Chapter 2: Principles of Programming and Software Engineering:
Given a programming assignment, most students put it off until the last minute and then they sit down by the computer to write the program. This method leads to numerous mistakes and frustration. To avoid such mistakes and frustrations, programming (like any other task in life) should be tackled differently.
We should tackle the problem in a more formal and serious manner – problem solving. Problem solving is taken to mean “taking the statement of the problem and developing a computer program that solves that problem.” It is a process that requires an iterative process of understanding the problem through designing a conceptual solution then developing a computer program for that solution. This conceptual solution is transferred into an algorithm (a step by step solution to a problem that is unambiguous and produces a result in a finite amount of time) that can solve the problem. One of the key components of developing an algorithm is to determine how to get the data (and keep it) needed to solve the problem and how to store the result – that is what data container (structure) to use. Different containers allow us to store data differently and so we must decided which container is best suited for a given problem solution. For example, if we don’t care about mixing the data type in a container, then we can use a vector and if we must store elements of a single data type, we may consider an array. So upon developing a solution to a problem we can use several different techniques to make the task easier but we must be careful that we get the solution to the given problem and not a misinterpretation of the problem.
The Life Cycle of Software:
Developing good software requires a lengthy and continuing process that begins with an initial idea to writing and debugging a program and maintaining and enhancing that program over the years. At the core of this development, implementation and maintenance is documentation – one of the most important aspects to good software development. This whole process is iterative and is broken down into 9 phases as shown in Figure 2-1, page 67.
Phase 1: Specification:
Give an initial statement of the purpose of the software; you need to specify all aspects of the problem clearly. The initial statement may not explain the goal of the software clearly because the people that need the software may not be computer scientists and so are unable to explain the problem precisely. The developers have to add precision to the problem statement and work out the specification – data types, inputs, type of interface (text based or GUI), error detection and recovery methods, etc. One good way to help with this is to develop a prototype.
Phase 2: Design:
Now you need to design a solution for the problem always bearing in mind that all
programs are developed on the basis of Input_Processing_Output_Storage (IPO’S). One
of the best ways to simplify a problem is to divide it into smaller and smaller problems until we can’t divide it any longer. Now we develop solutions for the smaller problems and back integrate them to provide a solution to the whole problem. The Object Oriented Paradigm (OOP) is ideal for this use because it allows us to break the solution into classes. Two ideas to consider when breaking the whole is hierarchy and peer distribution. All of those pieces (classes) that are dependent on each other and have a common set of variables allow us to create a hierarchy whereas those that shows independence will allow us to implement peer to peer relationship. Thus enable us to implement tight coupling (in the former case) and loose coupling (in the latter case). These dictate among other things, how data is passed between methods of the same class and between different classes. These are ideal objectives for the OOP.
Another major aspect of design is to write the contract(the relationship between the method and the calling code) of a method – the preconditions and the postconditions. The preconditions are the conditions that must exist at the beginning of a method and the postconditions are conditions at theend of the method. Upon writing preconditions, begin by describing the methods formal parameters, any class variables to be used and any assumptions that the method makes. And writing postconditions, describe the methods effect on its parameters – any changes, etc. and what exactly will happen by executing the code of this method.
Phase 3: Risk Analysis:
Building software always involves risks – some are easy to handle and some are very difficult. Also some risks are predictable and some are not.
Phase 4: Verification:
We can actually prove that a particular algorithm is correct – but not in this class. But looking at some means for verifying that our design (and eventually program is correct) – we can use assertions – a statement about a particular condition at a certain point in an algorithm. Preconditions and postconditions are assertions for conditions at the beginning and end of an algorithm. An invariant is an assertion about the condition that is always true at a particular point in an algorithm. Example, a loop invariant is a condition that is true at the beginning of a loop as well as for each iteration of the loop.
Phase 5: Coding:
Translating the design into a particular programming language, compiling the program to ensure it is working.
Phase 6: Testing:
During this phase, we test the software with the main purpose being to break it. This will
allow all errors to be removed including logical errors. We include valid data, boundary data as well as invalid data to test the software.
Phase 7: Refining the solution:
Phases 1 to 6 allow us to take a problem from the initial idea, design it and eventually coded it to provide a software. To go through this process, we sometimes simplify the problem thus finding the solution program for simpler but similar software. We now need to refine this software to make sure it actually provides a solution to our original problem. We now add additional features, more sophisticated input/output routines, better error checking methods, etc. Of course if the problem was not as difficult initially, we may not need this phase.
Phase 8: Production:
After the software is satisfactorily produced (accepted by the client), then it is time to distribute it to the intended users.
Phase 9: Maintenance:
Software will constantly need to be maintained especially when we consider the development of new computer technologies every day. As new technologies emerge, several refinements may be required, hence the need for maintenance. Also, as the software is being used, the user may constantly find new requirements that they may want to add to the software. And other factors also may lead to the need for maintenance.
1