Software design principles and software structures in the IT Systems Development Life Cycle
Software design principles and software structures in the IT Systems Development Life Cycle
Published on 8 May, 2012
This blog post will explain the role of software design principles and software structures in the IT systems development life cycle. It will also explain the importance of the quality of code that includes the readability, robustness, efficiency among other characteristics.
Stages of Development Life Cycle:
There are 8 known stages during the software development cycle; these are as follows (in chronological order):
1. Determining the problem scope
2. Gathering the requirements
3. Writing the specification
4. Designing the solution
5. Coding and design
6. Testing the program code
7. Writing the documentation
8. Reviewing and maintaining the solution
These 8 stages together form the software development cycle from the initial finding of the problem, to the maintaining of the solution, be it by the primary developer, or by someone alien to it through the use of the documentation created. This 8 stage model can easily be implemented into a development cycle such as rapid application development, spiral model, or waterfall model.
Scope – Stage 1:
The first stage is to determine the boundaries of the problem. By first figuring out the scope of the problem, you can effectively start thinking of what the solution will have to interface with. The problem scope includes the core problem, as well as all other issues that may arise due to the problem, even if it is a long connection link between the causation of the issue. If the creator of the solution is unable to fully understand the problem, or not take into account the entire scope of the issue, then their solution could potentially break other parts of the system that were working previously. If it is a new solution being built from scratch then they should also take into consideration on future advances/upgrades within the system so that during the maintenance stage minimal work is required to upgrade the system.
Gathering Requirements – Stage 2:
Once the solution scope has been determined, it is then necessary to gather all the desired requirements. This information is usually gathered from the body that currently has the problem with their system. This document is not very technical, as it should cover what the solution should do in layman’s terms, as a brief over view of the underlying problem, and the requirements for the final outcome. There are various ways to gather information, this includes questionnaires, interviews, and through observation.
Questionnaires is an effective method of gathering information from a client relating to simple questions regarding the issue and possible solution. The questions listed will often be fairly simple, either “yes” and “no” answers (closed questions) or offer some degree of opinion for the input (open questions). A questionnaire is an effective manner as it can gather mass amounts of results in a short time. Questionnaires however only provide limited information, to gather more information rish material, an interview could be taken place.
An interview allows a much more indepth analysis of the problem, and gives the opportunity to gather information on how the solution should work, this includes input methods processing and the output methods that the solution should provide. An interview can be made with one person, or within a group, and can also get the opinions of both the managing director who has the problem, while also gaining the opinion of the lower tier workers who handle the data. This is a benefit as it gives a better understand and specific requests on how the solution should handle the problem. An interview can also provide an open discussion with the technical board who originally setup the system that needs a solution.
Another method of gathering information is through observation of the current situation where the problem occurs. This allows the obsever to see errors in the system as they take place realtime, documenting them which will provide better understanding of the problem, and also aid in the designing of the solution to create a more efficient solution. The observer may also be able to look at current documents related to the problem such as examples of input to be processed and the output produced, which can be used to compare and contrast in the design of the new input and output methods.
Specification – Stage 3:
The next step is to start writing on the specification. The specification is a technical document that covers the specific desired outcome of the solution, as well as how the software is to run and interact with the user/other interfaces. This document usually accompanies with the requirements document in stage 2.
This document will include exact specifics of the solution, and is used as a mark-up scheme to determine when the solution is complete. The document can potentially hold a limitless amount of specifications of minute detail (which is to be advised when creating the document) including what the solution is to be able to run on (operating system/hardware).Whether the solution is to be cross platform between UNIX/Windows, the hardware limits such as CPU speed, available RAM and disk space.
Naturally software should be written with efficiency in mind; however when there are limits on hardware, extra care has to be taken so that these limits are kept without bound. A classic example is when older systems have small amounts of RAM, and the desired outcome is to operate on a file larger than what can be stored in the RAM, then the solution would have to be able to break up the byte code of the file into small enough chunks to fit in the RAM to operate on. The same can apply to the processing power of a CPU in the specification, often more lower level programming languages are to be used to capitalise on processing power, removing dependencies on the system such as the CLR (common language runtime) which requires more resources to run a solution written in (for example) Java or C#, where as if the solution is to be written in C/C++ (or in some cases assembly) then more resources of the system can be used for the solution.
Other factors that should be taken into consideration during the creation of this document are the time limit and financial costs. A solution should be able to be made around these boundaries, and also allows the developer to make clear priorities on the separate tasks within the solution. Common practice is for a programmer/team to create an elements list that contains all the tasks to produce a solution, and then assign each task a complexity value, and work on the hardest/most time consuming task first, then work down through the list.
Other parts of the document may include a data input dictionary and a data processing dictionary. This part of a document is usually a tabular structure that shows a variable name, what type of value that variable will hold, what the format of the variable is, and the value if it’s the data input dictionary, or a process instruction for the data processing dictionary.
This following table is an example of a data input dictionary:
Identifier Name Data Type Format Value
user_input_conductor_id Character
user_input_ticket_type Character
TOTAL_STATIONS_CENTRAL_LINE Integer 24
STATIONS_CENTRAL_LINE Character *LIST OF TRAM STATION NAMES*
MINIMUM_FARE Real 2 Decimal Places 0.25
OAP_FARE Real 2 Decimal Places 0.00
INPUT_CHAR_LIMIT Integer 30
INPUT_CHAR_LIMIT_NUMBER Integer 5
This following table is an example of a data process dictionary:
Indentifier Name Data Type Format Calculations
adult_cost Real 2 Decimal Places no_of_adults * no_of_stops * ticket_type_value
number_of_oaps integer number_of_oaps + 1
stops_travelled integer user_input_station_destination_number – user_input_station_departure_number
young_children_cost Real 2 Decimal Places ( ( stops_travelled * YOUNG_CHILDREN_FARE ) * ticket_type_formula ) * number_of_young_children
children_cost Real 2 Decimal Places ( ( ( stops_travelled * CHILDREN_FARE ) * ticket_type_formula ) + MINIMUM_FARE ) * number_of_children
Both these tables share the same variable names to create a direct correlation and help understand what variables mean and how they are to be interpreted in the solution.
Solution Design – Stage 4:
Designing the solution is a crucial element during the creation. The design can be done in a variety of ways, and can be understood/created by a party that does not need to know how to program, as long as their design is logical and efficient, the programmers are able to decipher the design and translate it into a working solution.
There are limitless types of designing a solution, although the most popular types of design are through flowcharts or Jackson structure diagram. These 2 design techniques can easily determine the hierarchy and structure of how the solution should be programmed, providing clear relationships between differing components and scopes that reside within the problem. It can also be used to solve design problems before programming can even begin.
With efficient design, it can be used to allocate tasks to certain team members/programmers that are more situated for the job. For example this type of encapsulation can be used to allocate a task of database querying and entry to some one more experienced, while another member is able to work on the algorithms. As both programmers are working from the same solution design, their work can be merged together easily.
Below is the example of a Jackson structure diagram:
Below is an example of a flowchart diagram:
Coding – Stage 5:
Once the solution design is complete, work can then commence on the programming of the solution. The solution should be professionally programmed to be sufficient for the solution. This includes making sure that the specification is strictly followed and that all the inputs and outputs are valid and accurate. Not only should the program work, but it should also contain fail safes within the source code to prevent against errors such as illegal user input, making sure that the program does not crash or potentially corrupt any data already on the system which may be irreversible.
The source code itself should be of a satisfactory quality in the sense that other programmers in the future are able to modify/append to the solution to accompany any new requested features or bug fixes. This quality can be assured that the source code follows basic standards such as robustness, efficiency, reliability, usability, portability, maintainability and readability; all of which will be discussed later within this document.
Testing – Stage 6:
Testing the solution for bugs within the code is a vital point within the solution development cycle. It is a key stage where the program should be vigorously tested for errors, and to deliberately try to crash the program, or make it behave in a way that is not desired/intended. It is common for a majority of bugs to be tested during the previous programming stage, as the programmer is compiling code; errors are bound to show up. Depending on the integrated development environment (IDE) there are various tools at the programmer’s disposal to fix bugs within their code. Such features include breakpoints, tracers, and variable watching.
Breakpoints allow the programmer to explicitly stop all execution of a program once a certain line of source code is reached. This allows the programmer to jump into the source code during program execution and probe at variables on the stack to check their value. They are then able to run each statement line by line to determine where the exact error is being generated from. During this line statement by line statement interactivity, they can then trace calls within the program to understand the exact functioning of the program. This tracing is useful to follow the flow of code, and variables being passed.
Outside of the IDE however, testing for bugs within a program requires a more vigorous approach; this is the stage that is commonly referred to black box/white box testing. This type of testing is done by creating a table listing of inputs at a specific location within the program execution, the desired outputs, and the actual outputs. Black box testing can be done by anyone, as they do not need to know the actual inner workings of the program itself. The test strategy includes going through each location within the program testing it multiple times with a wide range of input types to report back to the programmer to fix, potentially increasing the robustness of program when they are fixed. For example when the program asks for a name, the individual testing the application should try inputting various entries such as their actual name, a numeric value, blank text, an exceptionally long string of text, special characters, among other inputs, and document what happens to the program after each input. This document is then passed back to the programmers to implement a fix for the issues. The programmer should decide on an appropriate course of action to fix the bug, it is common that some input bugs (such as only requesting a 7 character length of numerals) can be fixed by implementing an out of range exception if any more or less digits are inserted, and requesting the input again.
Below is an example of white box/black box testing:
Test No. Test Purpose Test Data Expected Results Actual Results Action
1 Check if 7 digits is a valid ID. 1234567 Valid ID, accept and continue Accepts input and continues
4 Check if 7 non digits are valid ID. abcdefg Invalid ID, decline and request again Declines input and requests again
5 Check if name in for format “A.Aa” is a valid name. J.Sharpe Valid Name, accept and continue Accepts input and continues
10 Check if name in for format “*.*” is a valid name. where ‘*’ is a special character. :.@#{}& Invalid Name, decline and request again Declines input and requests again
11 Check if date day is equal to 1 or more, and less than or equal to 31 11 Valid date day, accept and continue Accepts input and continues
12 Check if date day is equal to 1 or more, and less than or equal to 31 -30 Invalid date day, decline and request again Declines input and requests again
Testing for bugs can potentially take an infinite time scale, so it is important that bugs are properly prioritised, such as program crashing being top tier, while small problems such as GUI alignment are lower tier.
Documentation – Stage 7:
There are 3 types of documentation that are to be created after the solution is made. These are:
• Internal documentation
• Technical documentation
• User documentation
The internal documentation is implicitly expressed through the source code itself. This is done by the use of appropriate variable, function names, including well commented sections on what each function does (briefly). The common rule of thumb in source code comments is to document why something is being done, as opposed to how it is done. This is because the source code itself shows how something is done, but why that method of choice is made is unknown unless a comment on why is present. There are also other factors to take into consideration such as indentation, and following the house style to aid in the reader to understand the flow of the source code; this will be discussed in further depth later within this document.
Below is a code snippet showing how comments can express what is happening within the code:
Selec All Code:
//Calculate the relevant costs for each individual on the bus.
young_children_cost = ( ( stops_travelled * YOUNG_CHILDREN_FARE ) ) * number_of_young_children;
children_cost = ( ( ( stops_travelled * CHILDREN_FARE ) ) + MINIMUM_FARE ) * number_of_children;
adults_cost = ( ( ( stops_travelled * ADULT_FARE ) ) + MINIMUM_FARE ) * number_of_adults;
oaps_cost = ( ( ( stops_travelled * OAP_FARE ) ) + MINIMUM_FARE ) * number_of_oaps;
//The above variables will be used in the display of the receipt.
The technical documentation is focused for future developers of the solution, so that they can understand all the clear works on the program itself. The following should be included within the documentation:
• Purpose of solution
• User requirements
• Input, output and processing requirements
• Test plan (white box/black box testing)
• Solution design (flow charts, structure model)
• Hardware and software requirements
• Class schemer
• Complete source code
• Future recommendations
Technical documentation is vital for another team of programmers to pick up the project and carry on with work fluently. This not only reduces production times, but also makes sure that everyone new to the project can also get onto the same level of knowledge as to what is to be expected. The technical documentation can also be used by system admins and engineers when installing the solution, making sure that everything is setup correctly and that all components are compatible and adjust current configurations to fit the solution.
The final user documentation is designed for the end user, who may not be as technologically knowledgeable on the solutions inner workings, and only needs to know basic installation, how to start the program, and over view on how to use the program effectively. This includes:
• Instructions on how to install
• How to use the program (including screenshots)
• An explanation of error messages
• Contact details for technical support
Maintaining – Stage 8:
The final stage of the solution is to review it and maintain it. The reviewing process is just a matter of evaluating the solution, comparing it to the initial user requirements that were documented during the requirements and specification stages. Ensuring that all the criteria are met and that the program is working as planned within the intended system. The reviewing stage is also an opportunity to document potential improvements to the code for a future release.
Maintaining the code is an on-going task that has the time span of the entire solutions life time. It involves, not only fixing future bugs that are found, but also manipulating the code to work with new future hardware/software upgrades on the system that the solution interacts with. Maintenance does not necessarily have to be done by the original authors of the solution, as the technical documentation will also be available at this stage.
Readability of code:
The readability of code ties into multiple areas, more importantly for the internal documentation and the maintenance stages. As mentioned previously, source code can have an increased readability by using basic techniques such as applying indentation, appropriate variable names, following house style, and commenting the source code.
Code should initially be written to be self-explanatory, reducing the need for comments. This can be done by declaring explicit variable names, that is human readable and that can easily be translated to what the value of that variable may hold. A simple example is for each for loop, use a variable called counter which is the iterator value that gets updated every run through the loop. It is common to see this variable be called something such as “i”; however this does not convey a meaning in the code to a human reading it at a glance.
Another technique is to not abbreviate variable or function names, unless of course it would break up human readability. When source code is compiled to machine code, the variables name can no longer be extracted. This can be achieved by breaking up words with an underscore like so:
Selec All Code:
int station_departure_number;
With the exception of the variable name:
Selec All Code:
int number_of_oaps;
Where an unabbreviated version would be:
Selec All Code:
int number_of_old_age_pensioners;
Which could arguably be considered an unnecessary long variable name.
However in some cases such as in scripting languages, it is common to have 2 versions of source code. One version being the fully documented copy, and another being minified and compressed. This is very common in JavaScript files that the end user of a website downloads. As they do not require all the comments and full length variable names. Take for example jQuery [http://jquery.com/], a JavaScript library containing many functions for developers to use. There is a minified version that is 32KB file size, used for publishing, and a development release of 247KB which contains all the same functionality, however has more meaningful variable names and comments.
By applying indentation to source code, it also improves the readability, specifically for the quick determination of where a scope ends and begins. Take for example this generated image that highlights different scopes with different colours, each new scope is given an extra indent:
It is visibly clear through the use of indentation the scope of various statements. Rather than if all the source code was written on the same vertical line.
Making sure the all programmers within the solution also follow a particular house style, allows each other to easily look at code and instantly decipher it. This keeps consistency with source code for when reading it.
Quality of code:
The quality of code can include a range of characteristics, although the most important aspects of the code are to be robust, efficient, reliable, usable, portable, and maintainable.
Robust, efficient, and reliable can all fall into the same category when writing source code. It is vital that the program being created is not prone to errors, faults, and can be relied upon to produce results when being run. The robustness can be determined through test cases on trying to deliberately crash the program in any possible way, and then to fix any of those bugs. Common problems could be allowing illegal input which could corrupt memory of the application within RAM, which in turn holds a high chance of problems to occur when that data is being accessed again.
The efficiency of source code can be determined by how much computer resources the program uses when it is being run. Having source code that does unnecessary calculations, or takes an unnecessary long time to run can be considered to be inefficient. A good example is when sorting algorithms are created. An efficient algorithm is able to sort a series of items in a time scale of O(n log n), however a bad sorting algorithm would sort the items in O(n2) time scale; known as Big O Notation. Thus if the program was to sort a series of shipping items from largest serial number to smallest, as more shipping items are added to the list, it causes the time scale to sort it logarithmically. Some sorting algorithms will be able to sort a list of 100,000 items in just a few milliseconds, however if the source code does unnecessary calculations, the time to sort could soon increase to minutes; thus efficiency is a key factor to take into consideration during the code run time.
The reliability of the program is to make sure that the same results are to be produced every time when given the same input values. This can be tested through test cases, where an input can be given to the program and to a human to solve, and comparing the results multiple times, with multiple inputs for both the human and the computer program. This will offer high validity that the program calculates the correct values using the same algorithm used. If a program does not always output the same answer, then invalid data could be introduced to the system, which could potentially corrupt the data and worse cause, cause database errors. This is extremely important in situations such as handling finances (such as in a bank), making sure that all calculations are correct.
Usability and portability can fall into the same category. When writing a program that does the same task multiple times at different stages, it would be wise to have that task written out once, and then keep reusing it. In programming this is often called creating a function or procedure. By the creating of functions and procedures it allows programmers to divide and conquer a problem. At later dates it will also allow the portability of the code to other platforms/systems as the functions can be reused or may only need slight alterations. If the programmer does not take this into account when writing the source code then they are potentially creating a vender specific solution, which could cause problems in the future if the system ever has to change slightly.
The maintainability of code is important so that in the future, bug fixes can be produced and also extra features can be implemented easily. Although the maintainability of code is not source code specific, as it also requires clear technical documentation to be present as well. For some older legacy applications or open source programs, this is not the case as either the documentation is missing, or is not professionally created and of limited use. It is then up to the programmer to be able to decipher the source code to understand what is going on. As mentioned previously this can be easily achieved by using simple techniques such as indentation and commenting.
Filed in Programming | No replies