Software engineering is the profession which is likely to replace programming and systems analysis over the next ten years. The objectives of software engineering are as stated above: the development of very large, complex, software items, which satisfy strict standards of performance and correctness, in a controlled, scheduled, budgeted and cost-effective way. Software engineers require, in addition to a proficiency in programming, a knowledge of formal mathematics and logic, computing science, economics and management.
Software engineering is carried out by teams of people. When a software development project is started, the teams are set up with a management structure corresponding to the structure of the software itself. A schedule is drawn up for the project, and costs are allocated to the various portions and stages. Each team has a team leader, whose task is to make sure that the software developed by the team is correct, properly structured, has the right interfaces to the software being developed by the other teams, and is on schedule and within budget. This is a very difficult task, which requires a wide range of technical and management skills.
Software engineering is concerned with the entire lifecycle of a software project: design. development, testing, use and maintenance. All the work done is aimed at the highest possible standards at the lowest possible costs throughout this lifecycle.
Program structure
It is now quite clear that the only way of achieving the required standards of correctness, performance and reliability of software is through the very careful design of the structure of a program. A well-structured program must satisfy the following conditions:
• The program must have a clear overall structure in terms of modules, with each module carrying out a specific task. Modules may be implemented as functions, procedures or segments, depending on the programming language used.
• There must be a clearly defined interface between modules. This is particularly important when interfaces are between modules written by different software engineers.
• Each module should be a simple combination of the elementary constructions of the programming language. Modules should be easy to read by people other than their original programmer.
• There must be a close correspondence between the structure of a module and the structure of the data on which it operates.
• Each module should leave the data structures on which it operates in a state which is consistent with their defining properties. This is particularly important with pointers: they should not be left 'hanging loose' by one module, on the assumption that another module will tidy them up.
• A module must have no side effects: it must not make any changes to data values, or to the state of the program, apart from those it is intended to make.
Achieving a program structure which satisfies these conditions is a very difficult task. Some help is given by the program structuring properties of the language. New programming languages are being developed which will give even greater assistance, particularly with the last two requirements of a structured program.
Program design
Program design is the means by which proper program structure is achieved. It is the technique for going from the initial statement of the requirements of a program, which is generally vague, incomplete and contradictory, to the final structured, tested and approved code. It is a long and difficult process, made more so by the lack of widely-accepted, tested techniques of program design. However, a number of methods of program design do exist, and their use is increasing all the time. In the foreseeable future, it is likely that all software development will be based on а formal technique of program design.
The simplest and one of the most popular methods of program design is stepwise refinement. It is based on the use of algorithms, which are written in a language somewhere between English and a programming language such as Pascal. The process itself may be described by an algorithm of this nature:
State the overall steps of a program in a brief, top-level algorithm.
Repeat
Expand each statement of the algorithm as a detailed algorithm which
describes the steps required to implement the statement.
Until the task has been specified in sufficient detail for the code of the program to be written.
Stepwise refinement is a top-down process, with details being added in an orderly fashion as the design progresses. If an algorithm turns out to be incorrect, it can be 'unplugged' and replaced by another without too much effect on the program structure as a whole.
Although stepwise refinement can bring about a great improvement in the structure of a program, it is not formal enough for many applications. In particular, there is no guarantee that data structures are left in a consistent state by the various modules. lt is very difficult to prove the correctness of program module developed in this way.
A number of more formal methods of program design are coming into use, the most popular being functional decomposition. Like stepwise refinement, functional decomposition is a top-down method, starting with the overall requirements of a program, and adding detail in an orderly way. The difference is that at every stage, the essential properties of the data structures are specified, and each algorithm is expressed as a mathematical function which transforms these data structures. Each algorithm can be tested by various mathematical techniques, in order to prove that the properties of the data structures are not altered by the operations it performs on the data. Functional decomposition is particularly suited to some of the new functional programming languages which are being developed for fifth generation computers.