|< Free Open Study >|
When we consider computer programming, we immediately think of writing a program for a computer to execute-the generation of code in some computer language. As a beginning student of computer science, you wrote programs that solved relatively simple problems. Much of your initial effort went into learning the syntax of a programming language such as C++: the language's reserved words, its data types, its constructs for selection (if-else and switch) and looping (while, do while, and for), and its input/output mechanisms (cin and cout).
You may have learned a programming methodology that took you from the problem description that your instructor handed out all the way through the delivery of a good software solution. Programmers have created many design techniques, coding standards, and testing methods to help develop high-quality software. But why bother with all that methodology? Why not just sit down at a computer and write programs? Aren't we wasting a lot of time and effort, when we could just get started on the "real" job?
If the degree of our programming sophistication never had to rise above the level of trivial programs (like summing a list of prices or averaging grades), we might get away with such a code-first technique (or, rather, lack of technique). Some new programmers work this way, hacking away at the code until the program works more or less correctly-usually less.
As your programs grow larger and more complex, however, you must pay attention to other software issues in addition to coding. If you become a software professional, someday you may work as part of a team that develops a system containing tens of thousands, or even millions, of lines of code. The activities involved in such a software project's whole "life cycle" clearly go beyond just sitting down at a computer and writing programs. These activities include
Problem analysis Understanding the nature of the problem to be solved
Requirements elicitation Determining exactly what the program must do
Requirements definition Specifying what the program must do (functional requirements) and any constraints on the solution approach (nonfunctional requirements such as what language to use)
High- and low-level design Recording how the program meets the requirements, from the "big picture" overview to the detailed design
Implementation of the design Coding a program in a computer language
Testing and verification Detecting and fixing errors and demonstrating the correctness of the program
Delivery Turning over the tested program to the customer or user (or instructor!)
Operation Actually using the program
Maintenance Making changes to fix operational errors and to add or modify the program's function
Software development is not simply a matter of going through these steps sequentially. Rather, many activities take place concurrently. We may code one part of the solution while we design another part, or define requirements for a new version of a program while we continue testing the current version. Often a number of people may work on different parts of the same program simultaneously. Keeping track of all these activities is not an easy task.
We use the term software engineering to refer to the discipline concerned with all aspects of the development of high quality software systems. It encompasses all variations of techniques used during the software life cycle plus supporting activities such as documentation and teamwork. A software process is a specific set of interrelated software engineering techniques, used by a person or organization to create a system.
Software engineering The discipline devoted to the design, production, and maintenance of computer programs that are developed on time and within cost estimates, using tools that help to manage the size and complexity of the resulting software products
Software process A standard, integrated set of software engineering tools and techniques used on a project or by an organization
What makes our jobs as programmers or software engineers challenging is the tendency of software to grow in size and complexity and to change at every stage of its development. A good software process uses tools to manage this size and complexity effectively. Usually a programmer takes advantage of several toolboxes, each containing tools that help to build and shape a software product.
Hardware One toolbox contains the hardware itself: the computers and their peripheral devices (such as monitors, terminals, storage devices, and printers), on which and for which we develop software.
Software A second toolbox contains various software tools: operating systems to control the computer's resources, text editors to help us enter programs, compilers to translate high-level languages like C++ into something that the computer can execute, interactive debugging programs, test-data generators, and so on. You've used some of these tools already.
Ideaware A third toolbox is filled with the shared body of knowledge that programmers have collected over time. This box contains the algorithms that we use to solve common programming problems as well as data structures for modeling the information processed by our programs. Recall that an algorithm is a step-by-step description of the solution to a problem. How we choose between two algorithms that carry out the same task often depends on the requirements of a particular application. If no relevant requirements exist, the choice may be based on the programmer's own style.
Algorithm A logical sequence of discrete steps that describes a complete solution to a given problem, computable in a finite amount of time
Ideaware contains programming methodologies such as top-down and object-oriented design and software concepts, including information hiding, data encapsulation, and abstraction. It includes aids for creating designs such as CRC (Classes, Responsibilities, and Collaborations) cards and methods for describing designs such as the UML (Unified Modeling Language). It also contains some tools for measuring, evaluating, and proving the correctness of our programs. We devote most this book to exploring the contents of this third toolbox.
Some might argue that using these tools takes the creativity out of programming, but we don't believe that to be true. Artists and composers are creative, yet their innovations are grounded in the basic principles of their crafts. Similarly, the most creative programmers build high-quality software through the disciplined use of basic programming tools.
Quality software entails much more than a program that somehow accomplishes the task at hand. A good program achieves the following goals:
It can be modified without excessive time and effort.
It is reusable.
It is completed on time and within budget.
It's not easy to meet these goals, but they are all important.
Goal 1: Quality Software Works The program must do the task it was designed to perform, and it must do it correctly and completely. Thus the first step in the development process is to determine exactly what the program is required to do. To write a program that works, you first need to have a definition of the program's requirements. For students, the requirements often are included in the instructor's problem description: "Write a program that calculates...." For programmers working on a government contract, the requirements document may be hundreds of pages long.
Requirements A statement of what is to be provided by a computer system or software product
Software specification A detailed description of the function, inputs, processing, outputs, and special requirements of a software product; it provides the information needed to design and implement the program
We develop programs that meet the user's requirements using software specifications. The specifications indicate the format of the input and the expected output, details about processing, performance measures (how fast? how big? how accurate?), what to do in case of errors, and so on. The specifications tell exactly what the program does, but not how it is done. Sometimes your instructor will provide detailed specifications; other times you may have to write them yourself, based on the requirements definition, conversations with your instructor, or guesswork. (We discuss this issue in more detail later in this chapter.)
How do you know when the program is right? A program must be complete (it should "do everything" specified) and correct (it should "do it right") to meet its requirements. In addition, it should be usable. For instance, if the program needs to receive data from a person sitting at a terminal, it must indicate when it expects input. The program's outputs should be readable and understandable to users. Indeed, creating a good user interface is an important subject in software engineering today.
Finally, Goal 1 means that the program should be as efficient as it needs to be. We would never deliberately write programs that waste time or space in memory, but not all programs demand great efficiency. When they do, however, we must meet these demands or else the programs will not satisfy the requirements. A space-launch control program, for instance, must execute in "real time"; that is, the software must process commands, perform calculations, and display results in coordination with the activities it is supposed to control. Closer to home, if a desktop-publishing program cannot update the screen as rapidly as the user can type, the program is not as efficient as it needs to be. In such a case, if the software isn't efficient enough, it doesn't meet its requirements; thus, according to our definition, it doesn't work correctly.
Goal 2: Quality Software Can Be Modified When does software need to be modified? Changes occur in every phase of its existence.
Software gets changed in the design phase. When your instructor or employer gives you a programming assignment, you begin to think of how to solve the problem. The next time you meet, however, you may be notified of a small change in the program description.
Software gets changed in the coding phase. You make changes in your program as a result of compilation errors. Sometimes you suddenly see a better solution to a part of the problem after the program has been coded, so you make changes.
Software gets changed in the testing phase. If the program crashes or yields wrong results, you must make corrections.
In an academic environment, the life of the software typically ends when a corrected program is turned in to be graded. When software is developed for real-world use, however, most of the changes take place during the "maintenance" phase. Someone may discover an error that wasn't uncovered in testing, someone else may want to include additional functions, a third party may want to change the input format, and a fourth person may want to run the program on another system.
As you see, software changes often and in all phases of its life cycle. Knowing this fact, software engineers try to develop programs that are modified easily. If you think it is a simple matter to change a program, try to make a "small change" in the last program you wrote. It's difficult to remember all the details of a program after some time has passed, isn't it? Modifications to programs often are not even made by the original authors but rather by subsequent maintenance programmers. (Someday you may be the one making the modifications to someone else's program.)
What makes a program easy to modify? First, it should be readable and understandable to humans. Before it can be changed, it must be understood. A well-designed, clearly written, well-documented program is certainly easier for human readers to understand. The number of pages of documentation required for "real-world" programs usually exceeds the number of pages of code. Almost every organization has its own policy for documentation. Reading a well-written program can teach you techniques that help you write good programs. In fact, it's difficult to imagine how anyone could become a good programmer without reading good programs.
Second, the program should readily be able to withstand small changes. The key idea is to partition your programs into manageable pieces that work together to solve the problem, yet remain relatively independent. The design methodologies reviewed later in this chapter should help you write programs that meet this goal.
Goal 3: Quality Software Is Reusable It takes time and effort to create quality software. Therefore, it is important to realize as much value from the software as possible.
One way to save time and effort when building a software solution is to reuse programs, classes, functions, and other components from previous projects. By using previously designed and tested code, you arrive at your solution sooner and with less effort. Alternatively, when you create software to solve a problem, it is sometimes possible to structure that software so it can help solve future, related problems. By doing so, you gain more value from the software created.
Creating reusable software does not happen automatically. It requires extra effort during the specification and design phases. To be reusable, software must be well documented and easy to read, so that a programmer can quickly determine whether it can be used for a new project. It usually has a simple interface so that it can easily be plugged into another system. It is also modifiable (Goal 2), in case a small change is needed to adapt it to the new system.
When creating software to fulfill a narrow, specific function, you can sometimes make the software more generally usable with a minimal amount of extra effort. In this way, you increase the chances that you can reuse the software later. For example, if you are creating a routine that sorts a list of integers into increasing order, you might generalize the routine so that it can also sort other types of data. Furthermore, you could design the routine to accept the desired sort order, increasing or decreasing, as a parameter.
Goal 4: Quality Software Is Completed on Time and Within Budget You know what happens in school when you turn in your program late. You probably have grieved over an otherwise perfect program that received only half credit-or no credit at all-because you turned it in one day late. "But the network was down five hours last night!" you protest.
Although the consequences of tardiness may seem arbitrary in the academic world, they are significant in the business world. The software for controlling a space launch must be developed and tested before the launch can take place. A patient database system for a new hospital must be installed before the hospital can open. In such cases, the program doesn't meet its requirements if it isn't ready when needed.
"Time is money" may sound trite but failure to meet deadlines is expensive. A company generally budgets a certain amount of time and money for the development of a piece of software. As a programmer, you are paid a salary or an hourly wage. If your part of the project is only 80% complete when the deadline arrives, the company must pay you-or another programmer-to finish the work. The extra expenditure in salary is not the only cost, however. Other workers may be waiting to integrate your part of the program into the system for testing. If the program is part of a contract with a customer, monetary penalties may be assessed for missed deadlines. If it is being developed for commercial sales, the company may be beaten to the market by a competitor and eventually forced out of business.
Once you have identified your goals, what can you do to meet them? Where should you start? Software engineers use many tools and techniques. In the next few sections of this chapter, we review some of these techniques to help you understand, design, and code programs.
No matter which programming design technique you use, the first steps are always the same. Imagine the following all-too-familiar situation. On the third day of class, you are given a 12-page description of Programming Assignment 1, which must be running perfectly and turned in by noon, one week from yesterday. You read the assignment and realize that this program is three times larger than any program you have ever written. What is your first step?
The responses listed here are typical of those given by a class of computer science students in such a situation:
Response 1 is a predictable reaction from students who have not learned good programming techniques. Students who adopt Response 3 will find their education progressing rather slowly. Response 2 may seem to be a good idea, especially considering the deadline looming ahead. Resist the temptation, though-the first step is to think. Before you can come up with a program solution, you must understand the problem. Read the assignment, and then read it again. Ask questions of your instructor (or manager, or client). Starting early affords you many opportunities to ask questions; starting the night before the program is due leaves you no opportunity at all.
The problem with writing first is that it tends to lock you into the first solution you think of, which may not be the best approach. We have a natural tendency to believe that once we've put something in writing, we have invested too much in the idea to toss it out and start over.
On the other hand, don't agonize about all the possibilities until the day before your deadline. (Chances are that a disk drive, network, or printer will fail that day!) When you think you understand the problem, you should begin writing your design.
Many writers experience a moment of terror when faced with a blank piece of paper-where to begin? As a programmer, however, you don't have to wonder about where to begin. Using the assignment description (your "requirements"), first write a complete definition of the problem, including the details of the expected inputs and outputs, the necessary processing and error handling, and all assumptions about the problem. When you finish this task, you have a detailed specification-a formal definition of the problem your program must solve, which tells you exactly what the program should do. In addition, the process of writing the specifications brings to light any holes in the requirements. For instance, are embedded blanks in the input significant or can they be ignored? Do you need to check for errors in the input? On which computer system(s) will your program run? If you get the answers to these questions at this stage, you can design and code your program correctly from the start.
Many software engineers work with user/operational scenarios to understand the requirements. In software design, a scenario is a sequence of events for one execution of the program. For example, a designer might consider the following scenario when developing the software for a bank's automated teller machine (ATM):
The customer inserts a bank card.
The ATM reads the account number on the card.
The ATM requests a PIN (personal identification number) from the customer.
The customer enters 5683.
The ATM successfully verifies the account number PIN combination.
The ATM asks the customer to select a transaction type (deposit, show balance, withdrawal, or quit).
The customer selects the show balance option.
The ATM obtains the current account balance ($1,204.35) and displays it.
The ATM asks the customer to select a transaction type (deposit, show balance, withdrawal, or quit).
The customer selects quit.
The ATM returns the customer's bank card.
Scenarios allow us to get a feel for the behavior expected from the system. Of course, a single scenario cannot show all possible behaviors. For this reason, software engineers typically prepare many different scenarios to gain a full understanding of the system's requirements.
You must know some details to write and run the program. Other details, if not explicitly stated in the program's requirements, may be handled according to the programmer's preference. Assumptions about unstated or ambiguous specifications should always be written explicitly in the program's documentation.
The detailed specification clarifies the problem to be solved. But it does more than that: It also serves as an important piece of written documentation about the program. There are many ways in which specifications may be expressed and a number of different sections that may be included, depending on the nature of the problem. Our recommended program specification includes the following sections:
Sample inputs with expected outputs
If special processing is needed for unusual or error conditions, it should be specified as well. Sometimes it is helpful to include a section containing definitions of terms used. Likewise, it may prove useful to list any testing requirements so that verifying the program is considered early in the development process.
|< Free Open Study >|
|Converted from CHM to HTML with chm2web Pro 2.85 (unicode)|