HOME | Project Management Data Warehousing / Mining Software Testing | Technical Writing |
3. The Software Engineering Approach Based on the preceding discussions, we can say that the basic objective of software engineering is to: Develop methods and procedures for software development that can scale up for large systems and that can be used to consistently produce high quality software at low cost and with a small cycle time. That is, the key objectives are consistency, low cost, high quality, small cycle time, and scalability. The basic approach that software engineering takes is to separate the development process from the developed product (i.e., the software). The premise is that the development process, or the software process, controls the quality, scalability, consistency, and productivity. Hence to satisfy the objectives, one must focus on the soft ware process. Design of proper software processes and their control then becomes the primary goal of software engineering. It is this focus on process that distinguishes it from most other computing disciplines. Most other computing disciplines focus on some type of product-algorithms, operating system, databases, etc. while software engineering focuses on the process for producing the products. It is essentially the software equivalent of "manufacturing engineering." The software process must necessarily have components of project management, in addition to procedures for development. Otherwise, as we discussed, scalability will not be achieved. To better manage the development process and to achieve consistency, it is essential that the software development be done in phases. Hence, a phased development process is central to the software engineering approach. Besides having a phased development process, it is essential that monitoring of a project for quality and cost involve objective means rather than subjective methods. Otherwise, the scalability is limited: it is possible to handle a small project without measuring anything and 'using "gut-feel" type of management, but such methods are unlikely to work for projects that involve many people (possibly hundreds) and last many months. We briefly discuss these fundamental approaches here. The software process, being the central concept of software engineering, is discussed in detail in the next section. 3.1 Phased Development Process A development process consist of various phases, each phase ending with a de fined output. The phases are performed in an order specified by the process model being followed. The main reason for having a phased process is that it breaks the problem of developing software into successfully performing a set of phases, each handling a different concern of software development. This ensures that the cost of development is lower than what it would have been if the whole problem was tackled together. Furthermore, a phased process allows proper checking for quality and progress at some defined points during the development (end of phases). Without this, one would have to wait until the end to see what software has been produced. Clearly, this will not work for large systems. Hence, for managing the complexity, project tracking, and quality, all the development processes consist of a set of phases. A phased development process is central to the software engineering approach for solving the software crisis. Various process models have been proposed for developing software. In fact each organization that follows a process has its own version. We will discuss some of the common models in the next section. The different processes can have different activities. However, in general, we can say that any problem solving in software must consist of these activities: requirement specification for understanding and clearly stating the problem, design for deciding a plan for a solution, coding for implementing the planned solution, and testing for verifying the programs. For small problems, these activities may not be done explicitly, the start and end boundaries of these activities may not be clearly defined, and no written record of the activities may be kept. However, for large systems, where the problem-solving activity may last a couple of years and where many people are involved in development, performing these activities implicitly without proper documentation and representation will clearly not work, and each of these four problem solving activities has to be done formally. In fact, for large systems, each activity can itself be extremely complex, and methodologies and procedures are needed to perform it efficiently and correctly. Each of these activities is a major task for large software projects. These basic phases are briefly described here; each one of them will be discussed in more detail during the course of the guide (there is at least one section for each of these phases). Requirements Analysis Requirements analysis is done in order to understand the problem the software system is to solve. The problem could be automating an existing manual process, developing a new automated system, or a combination of the two. For large systems that have many features, and that need to perform many different tasks, understanding the requirements of the system is a major task. The emphasis in requirements analysis is on identifying what is needed from the system, not how the system will achieve its goals. This task is complicated by the fact that there are often at least two parties involved in software development-a client and a developer. The developer has to develop the system to satisfy the client's needs. The developer usually does not understand the client's problem domain, and the client often does not under stand the issues involved in software systems. This causes a communication gap, which has to be adequately bridged during requirements analysis. In most software projects, the requirements phase ends with a document describing all the requirements. In other words, the goal of the requirements specification phase is to produce the software requirements specification document (also called the requirements document). The person responsible for the requirements analysis is often called the analyst. There are two major activities in this phase: problem understanding or analysis and requirement specification. In problem analysis, the analyst has to understand the problem and its context. Such analysis typically requires a thorough understanding of the existing system, parts of which have to be automated. A dear understanding is needed of the important data entities in the system, major centers where action is taken, the purpose of the different actions that are performed, and the inputs and outputs. This requires interacting with clients and end users, as well as studying the existing manuals and procedures. With the analysis of the current system, the analyst can understand the reasons for automation and what effects the automated system might have. Understanding the existing system is usually just the starting activity in problem analysis, and it is relatively simple. The goal of this activity is to understand the requirements of the new system that is to be developed. Understanding the properties of a system that does not exist is more difficult and requires creative thinking. The problem is more complex because an automated system offers possibilities that do not exist otherwise. Consequently, even the client may not really know the needs of the system. The analyst has to make the client aware of the new possibilities, thus helping both client and analyst determine the requirements for the new system. Once the problem is analyzed and the essentials understood, the requirements must be specified in the requirement specification document. For requirement specification in the form of a document, some specification language has to be selected (e.g., English, regular expressions, tables, or a combination of these). The requirements document must specify all functional and performance requirements; the formats of inputs and outputs; and all design constraints that exist due to political, economic, environmental, and security reasons. In other words, besides the functionality required from the system, all the factors that may effect the design and proper functioning of the system should be specified in the requirements document. A preliminary user manual that describes all the major user interfaces frequently forms a part of the requirements document. Software Design The purpose of the design phase is to plan a solution of the problem specified by the requirements document. This phase is the first step in moving from the problem domain to the solution domain. In other words, starting with what is needed, design takes us toward how to satisfy the needs. The design of a system is perhaps the most critical factor affecting the quality of the software; it has a major impact on the later phases, particularly testing and maintenance. The output of this phase is the design document. This document is similar to a blueprint or plan for the solution and is used later during implementation, testing, and maintenance. The design activity is often divided into two separate phases-system design and detailed design. System design, which is sometimes also called top-level design, aims to identify the modules that should be in the system, the specifications of these modules, and how they interact with each other to produce the desired results. At the end of system design all the major data structures, file formats, output formats, and the major modules in the system and their specifications are decided. During detailed design, the internal logic of each of the modules specified in system design is decided. During this phase further details of the data structures and algorithmic design of each of the modules is specified. The logic of a module is usually specified in a high-level design description language, which is independent of the target language in which the software will eventually be implemented. In system design the focus is on identifying the modules, whereas during detailed design the focus is on designing the logic for each of the modules. In other words, in system design the attention is on what components are needed, while in detailed design how the components can be implemented in software is the issue. A design methodology is a systematic approach to creating a design by application of a set of techniques and guidelines. Most methodologies focus on system design. Coding Once the design is complete, most of the major decisions about the system have been made. However, many of the details about coding the designs, which often depend on the programming language chosen, are not specified during design. The goal of the coding phase is to translate the design of the system into code in a given programming language. For a given design, the aim in this phase is to implement the design in the best possible manner. The coding phase affects both testing and maintenance profoundly. Well-written code can reduce the testing and maintenance effort. Because the testing and maintenance costs of software are much higher than the coding cost, the goal of coding should be to reduce the testing and maintenance effort. Hence, during coding the focus should be on developing programs that are easy to read and understand, and not simply on developing programs that are easy to write. Simplicity and clarity should be strived for during the coding phase. An important concept that helps the understandability of programs is structured programming. The goal of structured programming is to linearize the control flow in the program. That is, the program text should be organized as a sequence of statements, and during execution the statements are executed in the sequence given in the program. For structured programming, a few single-entry-single-exit constructs should be used. These constructs include selection (if-then-else) and iteration (while-do, repeat-until, etc.). With these constructs it is possible to construct a program as a sequence of single-entry-single-exit constructs. Testing Testing is the major quality control measure used during software development. Its basic function is to detect errors, in the software. During requirements analysis and design, the output is a document that is usually textual and non-executable. After the coding phase, computer programs are available that can be executed for testing purposes. This implies that testing not only has to uncover errors introduced during coding, but also errors introduced during the previous phases. Thus, the goal of testing is to uncover requirement, design, and coding errors in the programs. Consequently, different levels of testing are used. The starting point of testing is unit testing. In this, a module is tested separately and is often performed by the coder himself simultaneously along with the coding of the module. The purpose is to exercise the different parts of the module code to detect coding errors. After this, the modules are gradually integrated into subsystems, which are then integrated to eventually form the entire system. During integration of modules, integration testing is performed to detect design errors by focusing on testing the interconnection between modules. After the system is put together, system testing is performed. Here the system is tested against the system requirements to see if all the requirements are met and if the system performs as specified by the requirements. Finally, acceptance testing is performed to demonstrate to the client, on the real-life data of the client, the operation of the system. Testing is an extremely critical and time-consuming activity. It requires proper planning of the overall testing process. Frequently the testing process starts with a test plan that identifies all the testing-related activities that must be performed and specifies the schedule, allocates the resources, and specifies guidelines for testing. The test plan specifies conditions that should be tested, different units to be tested, and the manner in which the modules will be integrated together. Then for different test units, a test case specification document is produced, which lists all the different test cases, together with the expected outputs. During the testing of the unit, the specified test cases are executed and the actual result compared with the expected output. The final output of the testing phase is the test report and the error report, or a set of such reports (one for each unit tested). Each test report contains the set of test cases and the result of executing the code with these test cases. The error report describes the errors encountered and the action taken to remove the errors. 3.2 Project Management and Metrics As stated earlier, a phased development process is central to the software engineering approach. However, a development process does not specify how to allocate [...] Some tools that have been used for evaluating the design, code, or testing of the case study are also available from the home page. The structure of most sections in this guide is similar. Most sections begin by discussing the fundamental concepts for that particular phase. Then the methods for performing the activity for that phase are discussed. This is followed by the verification methods used for that phase. Metrics relevant to the phase are discussed next, along with some discussion on how metrics can be used for monitoring and control activities for that phase. Most sections end with a discussion of the case study and a description of the case study outputs for that particular phase. Here we give a brief outline of each of the sections. As the concept of process is central to the software engineering approach, Section 2 is devoted to "Software Processes." First, the three major entities of software engineering -- processes, projects, and products -- are defined. The major component processes of a software process are then identified, along with the basic properties of a software process. Then each component process is discussed in some detail through the rest of the section. Various models that have been proposed for the development process are discussed. The role of metrics in the project management process and the process management process is also discussed. Section 3 is entitled "Software Requirements Analysis and Specification" and discusses the different aspects of this phase. The desirable qualities of the requirements document are discussed, along with the different aspects the document should specify. Different approaches for problem analysis and representation are covered, and a brief description of some of the tools available for requirements analysis is included. The validation methods and metrics of interest for this phase are described. The section ends with problem analysis and the requirements document for the case study. Section 4 is entitled "Planning a Software Project" and discusses the different issues relating to software development project planning. The topics covered are cost estimation, schedule and milestone plan, personnel plan, team structure, soft ware quality assurance plans, configuration management plans, project monitoring plans, and risk management. For cost and schedule planning, different models are described. In quality assurance plans, general methods of monitoring, including reviews, are discussed. For risk management, different activities for performing risk management are discussed. A project plan for the case study is then presented. Section 5 discusses "Function-Oriented Design." We consider design as a two level process combining system design and detailed design (detailed design is discussed in Section 7.). For system design, two major approaches have emerged function-oriented design and object-oriented design. In Section 5 we first discuss the basic principles of design, including problem partitioning, divide and conquer, top-down refinement, modularity and abstraction. We then describe one design technique: the structured design methodology, which is a widely used function-oriented design methodology. Different methods for verifying a system design, and metrics applicable for a function-oriented system design are also discussed. For the case study, we follow the structured design methodology and give the entire system design. We also demonstrate how metrics are used to improve the design of the case study. In Section 6 we discuss "Object-Oriented design." The basic principles behind the object-oriented design are first discussed, followed by a design methodology. Some metrics that can be applied to an object-oriented design are then described. The section ends with a complete description of the object-oriented design for the case study. In Section 7 we discuss the issue of "Detailed Design." The first step in designing a module is to specify the module formally and understand it clearly. We discuss some methods of formally specifying modules that support functional or data abstractions. For detailed design we discuss the method of stepwise refinement and the program design language (PDL). Different methods for verification and some metrics for complexity, cohesion, and coupling are discussed. Section 8, "Coding", discusses the issues relating to programming. The basic principles for developing programs are discussed. These include structured programming, information hiding, programming style, and intern al documentation. Many methods for verification exist for programs. In this section we discuss code reading, data flow analysis, symbolic execution, program proving, unit testing, code reviews and walkthroughs. Metrics discussed include size metrics and complexity analysis. Section 9, the last section, discusses "Testing." We first clarify the concepts of faults, errors, failures, and reliability. Different levels of testing that are usually used and their various purposes are defined. The importance of the psychology of testing is discussed, as are the two basic approaches to testing (functional testing and structural testing). Different heuristics for generating test cases for functional testing are described. For the structural testing approach, control flow-based testing, data flow-based testing, and mutation testing are discussed. The issues and techniques for testing object-oriented programs are described next. The basic metric we describe is reliability assessment, and we describe one model for reliability estimation. The test plan and the test case specifications for the case study are given. 1. Suppose a program for solving a problem costs C, and a programming product for solving that problem costs 9C. Where do you think this extra 8C cost is spent? Suggest a possible breakdown of this extra cost. 2. If the primary goal is to make software maintainable, list some of the things you will do and some of the things you will not do during 1) design, 2) coding, and 3) testing. 3. If you are given extra time to improve the reliability of the final product developing a software product, how would you distribute this extra time? 4. List some possible problems that can come up if the methods you use for developing small software are used for developing large software systems. 5. Suggest ways of reducing the cost due to rework. 6. Suggest some ways to detect software errors in the early phases (when implementation is not yet complete). 7. What are the major reasons for having a phased process? How does it help in project management? 8. If absolutely no metrics are used, can you manage, or even define, a project? What is the bare minimum set of metrics that you must use for a development project? |