Review Questions for Chapter 3: Project Management1. Draw a PERT chart for the tasks listed in Table 3-2 (p. 50, the required textbook). Include the tasks’
letters, predecessors, and expected times.
2. What techniques can you use to make accurate time estimates?
BEGINNING SOFTWARE ENGINEERING
INTRODUCTION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi
▸ PART I
SOFTWARE ENGINEERING STEP‐BY‐STEP
CHAPTER 1
Software Engineering from 20,000 Feet. . . . . . . . . . . . . . . . . . . . . . . 3
CHAPTER 2
Before the Beginning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
CHAPTER 3
Project Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
CHAPTER 4
Requirement Gathering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
CHAPTER 5
High‐Level Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
CHAPTER 6
Low‐Level Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
CHAPTER 7
Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
CHAPTER 8
Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
CHAPTER 9
Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
CHAPTER 10
Metrics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
CHAPTER 11
Maintenance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
▸ PART II
PROCESS MODELS
CHAPTER 12
Predictive Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
CHAPTER 13
Iterative Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
CHAPTER 14
RAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
APPENDIX
Solutions to Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
GLOSSARY
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
BEGINNIING
Software Engineering
Rod Stephens
Beginning Software Engineering
Published by
John Wiley & Sons, Inc.
10475 Crosspoint Boulevard
Indianapolis, IN 46256
www.wiley.com
Copyright © 2015 by John Wiley & Sons, Inc., Indianapolis, Indiana
Published simultaneously in Canada
ISBN: 978-1-118-96914-4
ISBN: 978-1-118-96916-8 (ebk)
ISBN: 978-1-118-96917-5 (ebk)
Manufactured in the United States of America
10 9 8 7 6 5 4 3 2 1
No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means,
electronic, mechanical, photocopying, recording, scanning or otherwise, except as permitted under Sections 107 or 108
of the 1976 United States Copyright Act, without either the prior written permission of the Publisher, or authorization
through payment of the appropriate per-copy fee to the Copyright Clearance Center, 222 Rosewood Drive, Danvers,
MA 01923, (978) 750-8400, fax (978) 646-8600. Requests to the Publisher for permission should be addressed to the
Permissions Department, John Wiley & Sons, Inc., 111 River Street, Hoboken, NJ 07030, (201) 748-6011, fax (201)
748-6008, or online at http://www.wiley.com/go/permissions.
Limit of Liability/Disclaimer of Warranty: The publisher and the author make no representations or warranties with
respect to the accuracy or completeness of the contents of this work and specifically disclaim all warranties, including
without limitation warranties of fitness for a particular purpose. No warranty may be created or extended by sales or
promotional materials. The advice and strategies contained herein may not be suitable for every situation. This work
is sold with the understanding that the publisher is not engaged in rendering legal, accounting, or other professional
services. If professional assistance is required, the services of a competent professional person should be sought. Neither
the publisher nor the author shall be liable for damages arising herefrom. The fact that an organization or Web site is
referred to in this work as a citation and/or a potential source of further information does not mean that the author or the
publisher endorses the information the organization or Web site may provide or recommendations it may make. Further,
readers should be aware that Internet Web sites listed in this work may have changed or disappeared between when this
work was written and when it is read.
For general information on our other products and services please contact our Customer Care Department within the
United States at (877) 762-2974, outside the United States at (317) 572-3993 or fax (317) 572-4002.
Wiley publishes in a variety of print and electronic formats and by print-on-demand. Some material included with
standard print versions of this book may not be included in e-books or in print-on-demand. If this book refers to
media such as a CD or DVD that is not included in the version you purchased, you may download this material at
http://booksupport.wiley.com. For more information about Wiley products, visit www.wiley.com.
Library of Congress Control Number: 2015930533
Trademarks: Wiley, the Wiley logo, Wrox, the Wrox logo, Programmer to Programmer, and related trade dress are
trademarks or registered trademarks of John Wiley & Sons, Inc. and/or its affi liates, in the United States and other
countries, and may not be used without written permission. All other trademarks are the property of their respective
owners. John Wiley & Sons, Inc., is not associated with any product or vendor mentioned in this book.
ABOUT THE AUTHOR
ROD STEPHENS started out as a mathematician, but while studying at MIT, he discovered how
much fun programming is and he’s been programming professionally ever since. During his career,
he has worked on an eclectic assortment of applications in such fields as telephone switching, billing,
repair dispatching, tax processing, wastewater treatment, concert ticket sales, cartography, and
training for professional football players.
Rod has been a Microsoft Visual Basic Most Valuable Professional (MVP) for more than a decade
and has taught introductory programming courses. He has written more than two dozen books
that have been translated into languages from all over the world, and he’s written more than
250 magazine articles covering Visual Basic, C#, Visual Basic for Applications, Delphi, and Java.
Rod’s popular VB Helper website (www.vb-helper.com) receives several million hits per month and
contains thousands of pages of tips, tricks, and example programs for Visual Basic programmers.
His C# Helper website (www.csharphelper.com) contains similar material for C# programmers.
You can contact Rod at RodStephens@CSharpHelper.com or RodStephens@vb-helper.com.
ABOUT THE TECHNICAL EDITOR
BRIAN HOCHGURTEL has been doing .NET development for over ten years, and actually started
his .NET experience with Rod Stephens when they wrote the Wiley book, Visual Basic.NET and
XML, in 2002. Currently Brian works with C#, SQL Server, and SharePoint in Fort Collins, CO.
CREDITS
EXECUTIVE EDITOR
Robert Elliott
PROFESSIONAL TECHNOLOGY & STRATEGY
DIRECTOR
Barry Pruett
PROJECT EDITOR
Adaobi Obi Tuiton
BUSINESS MANAGER
Amy Knies
TECHNICAL EDITOR
Brian Hochgurtel
ASSOCIATE PUBLISHER
Jim Minatel
PRODUCTION MANAGER
Kathleen Wisor
PROJECT COORDINATOR, COVER
Brent Savage
COPY EDITOR
San Dee Phillips
PROOFREADER
Sarah Kaikini, Word One
MANAGER OF CONTENT DEVELOPMENT &
ASSEMBLY
INDEXER
Mary Beth Wakefield
Johnna VanHoose Dinse
MARKETING DIRECTOR
COVER DESIGNER
David Mayhew
Wiley
MARKETING MANAGER
COVER IMAGE
Carrie Sherrill
©iStock.com/Chris Hepburn
p
ACKNOWLEDGMENTS
THANKS TO BOB ELLIOTT, Adaobi Obi Tulton, San Dee Phillips, Katie Wisor, and all the others who
worked so hard to make this book possible. (Adaobi was this book’s project manager. You’ll learn
what a project manager does in Chapter 3. It’s a bit different for writing a book but not as different
as you might think. As always, many thanks for your hard work, Adaobi!)
Thanks also to technical editor Brian Hochgurtel for giving me the benefit of his valuable
experience.
Special thanks to Mary Brodie at gearmark.blogs.com for letting me use her quote in Chapter 13,
“Iterative Models.”
CONTENTS
INTRODUCTION
xxi
PART I: SOFTWARE ENGINEERING STEP‐BY‐STEP
CHAPTER 1: SOFTWARE ENGINEERING FROM 20,000 FEET
Requirements Gathering
High‐Level Design
Low‐Level Design
Development
Testing
Deployment
Maintenance
Wrap‐up
Everything All at Once
Summary
CHAPTER 2: BEFORE THE BEGINNING
Document Management
Historical Documents
E‐mail
Code
Code Documentation
Application Documentation
Summary
CHAPTER 3: PROJECT MANAGEMENT
Executive Support
Project Management
PERT Charts
Critical Path Methods
Gantt Charts
Scheduling Software
Predicting Times
Get Experience
Break Unknown Tasks into Simpler Pieces
3
4
5
6
6
6
8
9
9
10
11
15
16
18
19
21
22
25
25
29
30
31
33
38
41
42
42
44
44
CONTENTS
Look for Similarities
Expect the Unexpected
Track Progress
Risk Management
Summary
CHAPTER 4: REQUIREMENT GATHERING
Requirements Defined
Clear
Unambiguous
Consistent
Prioritized
Verifiable
Words to Avoid
Requirement Categories
Audience‐Oriented Requirements
Business Requirements
User Requirements
Functional Requirements
Nonfunctional Requirements
Implementation Requirements
FURPS
FURPS+
Common Requirements
Gathering Requirements
Listen to Customers (and Users)
Use the Five Ws (and One H)
Who
What
When
Where
Why
How
Study Users
49
53
54
54
55
56
56
60
60
61
61
61
62
63
63
63
64
64
66
67
67
68
68
68
69
69
69
69
70
Refining Requirements
71
Copy Existing Systems
Clairvoyance
Brainstorm
71
73
74
Recording Requirements
76
UML
User Stories
xii
45
45
46
47
77
77
CONTENTS
Use Cases
Prototypes
Requirements Specification
Validation and Verification
Changing Requirements
Summary
CHAPTER 5: HIGH‐LEVEL DESIGN
The Big Picture
What to Specify
Security
Hardware
User Interface
Internal Interfaces
External Interfaces
Architecture
Monolithic
Client/Server
Component‐Based
Service‐Oriented
Data‐Centric
Event‐Driven
Rule‐Based
Distributed
Mix and Match
Reports
Other Outputs
Database
Audit Trails
User Access
Database Maintenance
Configuration Data
Data Flows and States
Training
UML
Structure Diagrams
Behavior Diagrams
Activity Diagrams
Use Case Diagram
State Machine Diagram
Interaction Diagrams
78
78
80
80
80
81
87
88
89
89
90
91
92
93
94
94
95
96
97
97
97
98
98
99
101
102
102
103
103
104
104
105
105
105
107
109
110
111
112
113
xiii
CONTENTS
Sequence Diagram
Communication Diagram
Timing Diagram
Interaction Overview Diagram
Summary
CHAPTER 6: LOW‐LEVEL DESIGN
OO Design
Identifying Classes
Building Inheritance Hierarchies
Refinement
Generalization
Hierarchy Warning Signs
Object Composition
Database Design
Relational Databases
First Normal Form
Second Normal Form
Third Normal Form
Higher Levels of Normalization
Summary
CHAPTER 7: DEVELOPMENT
Use the Right Tools
Hardware
Network
Development Environment
Source Code Control
Profilers
Static Analysis Tools
Testing Tools
Source Code Formatters
Refactoring Tools
Training
Selecting Algorithms
Effective
Efficient
Predictable
Simple
Prepackaged
Top‐Down Design
xiv
113
114
115
115
116
119
120
121
122
123
125
126
127
127
128
130
134
135
137
138
143
144
144
145
146
147
147
147
147
147
148
148
148
149
149
151
152
152
153
CONTENTS
Programming Tips and Tricks
Be Alert
Write for People, Not the Computer
Comment First
Write Self‐Documenting Code
Keep It Small
Stay Focused
Avoid Side Effects
Validate Results
Practice Offensive Programming
Use Exceptions
Write Exception Handers First
Don’t Repeat Code
Defer Optimization
Summary
CHAPTER 8: TESTING
Testing Goals
Reasons Bugs Never Die
Diminishing Returns
Deadlines
Consequences
It’s Too Soon
Usefulness
Obsolescence
It’s Not a Bug
It Never Ends
It’s Better Than Nothing
Fixing Bugs Is Dangerous
Which Bugs to Fix
Levels of Testing
Unit Testing
Integration Testing
Automated Testing
Component Interface Testing
System Testing
Acceptance Testing
Other Testing Categories
155
155
156
157
159
160
161
162
163
165
166
167
167
167
169
173
175
175
175
175
176
176
176
177
177
177
178
178
179
179
179
181
182
183
184
185
185
Testing Techniques
186
Exhaustive Testing
Black‐Box Testing
186
187
xv
CONTENTS
White‐Box Testing
Gray‐Box Testing
Testing Habits
Test and Debug When Alert
Test Your Own Code
Have Someone Else Test Your Code
Fix Your Own Bugs
Think Before You Change
Don’t Believe in Magic
See What Changed
Fix Bugs, Not Symptoms
Test Your Tests
How to Fix a Bug
Estimating Number of Bugs
Tracking Bugs Found
Seeding
The Lincoln Index
Summary
CHAPTER 9: DEPLOYMENT
Scope
The Plan
Cutover
Staged Deployment
Gradual Cutover
Incremental Deployment
Parallel Testing
189
189
189
190
192
193
193
193
194
194
194
195
195
197
197
198
203
204
204
206
206
206
208
209
Deployment Tasks
Deployment Mistakes
Summary
209
210
211
CHAPTER 10: METRICS
215
Wrap Party
Defect Analysis
Kinds of Bugs
Discoverer
Severity
Time Created
Age at Fix
Task Type
Ishikawa Diagrams
xvi
188
188
216
216
217
217
217
218
218
218
219
CONTENTS
Software Metrics
Qualities of Good Attributes and Metrics
Using Metrics
Process Metrics
Project Metrics
Things to Measure
Size Normalization
Function Point Normalization
Count Function Point Metrics
Multiply by Complexity Factors
Calculate Complexity Adjustment Value
Calculate Adjusted FP
Summary
CHAPTER 11: MAINTENANCE
Maintenance Costs
Task Categories
Perfective Tasks
Feature Improvements
New Features
The Second System Effect
Adaptive Tasks
Corrective Tasks
Preventive Tasks
Clarification
Code Reuse
Improved Flexibility
Bug Swarms
Bad Programming Practices
Individual Bugs
Not Invented Here
Task Execution
Summary
222
223
224
226
226
227
229
231
232
232
233
235
235
241
242
243
244
245
245
245
247
248
251
252
253
254
254
255
256
256
256
257
PART II: PROCESS MODELS
CHAPTER 12: PREDICTIVE MODELS
Model Approaches
Prerequisites
Predictive and Adaptive
Success and Failure Indicators
265
266
267
267
268
xvii
CONTENTS
Advantages and Disadvantages
268
Waterfall
Waterfall with Feedback
Sashimi
Incremental Waterfall
V‐Model
Systems Development Life Cycle
Summary
270
271
272
273
275
276
280
CHAPTER 13: ITERATIVE MODELS
283
Iterative Versus Predictive
Iterative Versus Incremental
Prototypes
Types of Prototypes
Pros and Cons
Spiral
288
289
290
Clarifications
Pros and Cons
293
294
Unified Process
295
Pros and Cons
Rational Unified Process
Cleanroom
Summary
CHAPTER 14: RAD
RAD Principles
James Martin RAD
Agile
Self‐Organizing Teams
Agile Techniques
Communication
Incremental Development
Focus on Quality
XP
XP Roles
XP Values
XP Practices
Have a Customer On Site
Play the Planning Game
Use Standup Meetings
Make Frequent Small Releases
xviii
284
286
287
296
297
298
299
303
305
308
309
311
313
313
314
316
317
318
319
319
320
320
321
322
CONTENTS
Use Intuitive Metaphors
Keep Designs Simple
Defer Optimization
Refactor When Necessary
Give Everyone Ownership of the Code
Use Coding Standards
Promote Generalization
Use Pair Programming
Test Constantly
Integrate Continuously
Work Sustainably
Use Test‐Driven and Test‐First Development
Scrum
Scrum Roles
Scrum Sprints
Planning Poker
Burndown
Velocity
Lean
Lean Principles
Crystal
Crystal Clear
Crystal Yellow
Crystal Orange
Feature‐Driven Development
FDD Roles
FDD Phases
Develop a Model
Build a Feature List
Plan by Feature
Design by Feature
Build by Feature
FDD Iteration Milestones
Agile Unified Process
Disciplined Agile Delivery
DAD Principles
DAD Roles
DAD Phases
Dynamic Systems Development Method
DSDM Phases
DSDM Principles
DSDM Roles
322
322
322
323
323
324
324
324
324
325
325
325
327
327
328
329
330
331
332
332
333
335
336
337
338
338
340
340
340
341
341
342
342
343
345
346
346
347
348
348
349
350
xix
CONTENTS
Kanban
Kanban Principles
Kanban Practices
Kanban Board
Summary
xx
351
352
353
353
355
APPENDIX: SOLUTIONS TO EXERCISES
361
GLOSSARY
417
INDEX
437
INTRODUCTION
Programming today is a race between software engineers striving to build bigger
and better idiot‐proof programs, and the universe trying to build bigger and
better idiots. So far the universe is winning.
—Rick Cook
With modern development tools, it’s easy to sit down at the keyboard and bang out a working
program with no previous design or planning, and that’s fi ne under some circumstances. My VB
Helper (www.vb‐helper.com) and C# Helper (www.csharphelper.com) websites contain thousands
of example programs written in Visual Basic and C#, respectively, and built using exactly that
approach. I had an idea (or someone asked me a question) and I pounded out a quick example.
Those types of programs are fi ne if you’re the only one using them and then for only a short while.
They’re also okay if, as on my websites, they’re intended only to demonstrate a programming
technique and they never leave the confi nes of the programming laboratory.
If this kind of slap‐dash program escapes into the wild, however, the result can be disastrous. At
best, nonprogrammers who use these programs quickly become confused. At worst, they can wreak
havoc on their computers and even on those of their friends and coworkers.
Even experienced developers sometimes run afoul of these half‐baked programs. I know someone
(I won’t give names, but I also won’t say it wasn’t me) who wrote a simple recursive script to delete
the files in a directory hierarchy. Unfortunately, the script recursively climbed its way to the top of
the directory tree and then started cheerfully deleting every file in the system. The script ran for only
about five seconds before it was stopped, but it had already trashed enough files that the operating
system had to be reinstalled from scratch. (Actually, some developers believe reinstalling the operating
system every year or so is character‐building. If you agree, perhaps this approach isn’t so bad.)
I know another experienced developer who, while experimenting with Windows system settings,
managed to set every system color to black. The result was a black cursor over a black desktop,
displaying black windows with black borders, menus, and text. This person (who wasn’t me this
time) eventually managed to fi x things by rebooting and using another computer that wasn’t color‐
impaired to walk through the process of fi xing the settings using only keyboard accelerators. It was
a triumph of cleverness, but I suspect she would have rather skipped the whole episode and had her
two wasted days back.
For programs that are more than a few dozen lines long, or that will be given to unsuspecting end
users, this kind of free‐spirited development approach simply won’t do. To produce applications that
are effective, safe, and reliable, you can’t just sit down and start typing. You need a plan. You need
… … software engineering.
This book describes software engineering. It explains what software engineering is and how it helps
produce applications that are effective, flexible, and robust enough for use in real‐world situations.
This book won’t make you an expert systems analyst, software architect, project manager, or
programmer, but it explains what those people do and why they are necessary for producing
INTRODUCTION
high‐quality software. It also gives you the tools you need to start. You won’t rush out and lead a
1,000‐person effort to build a new air traffic control system for the FAA, but it can help you work
effectively in small‐scale and large‐scale development projects. (It can also help you understand
what a prospective future boss means when he says, “Yeah, we mostly use Scrum with a few extra
XP techniques thrown in.”)
WHAT IS SOFTWARE ENGINEERING?
A formal defi nition of software engineering might sound something like, “An organized, analytical
approach to the design, development, use, and maintenance of software.”
More intuitively, software engineering is everything you need to do to produce successful software.
It includes the steps that take a raw, possibly nebulous idea and turn it into a powerful and intuitive
application that can be enhanced to meet changing customer needs for years to come.
You might be tempted to restrict software engineering to mean only the beginning of the process,
when you perform the application’s design. After all, an aerospace engineer designs planes but
doesn’t build them or tack on a second passenger cabin if the fi rst one becomes full. (Although I
guess a space shuttle riding piggyback on a 747 sort of achieved that goal.)
One of the big differences between software engineering and aerospace engineering (or most
other kinds of engineering) is that software isn’t physical. It exists only in the virtual world of the
computer. That means it’s easy to make changes to any part of a program even after it is completely
written. In contrast, if you wait until a bridge is fi nished and then tell your structural engineer that
you’ve decided to add two extra lanes, there’s a good chance he’ll cackle wildly and offer you all
sorts of creative but impractical suggestions for exactly what you can do with your two extra lanes.
The flexibility granted to software by its virtual nature is both a blessing and a curse. It’s a blessing
because it lets you refine the program during development to better meet user needs, add new features
to take advantage of opportunities discovered during implementation, and make modifications to meet
evolving business needs. It even allows some applications to let users write scripts to perform new tasks
never envisioned by developers. That type of flexibility isn’t possible in other types of engineering.
Unfortunately, the flexibility that allows you to make changes throughout a software project’s life
cycle also lets you mess things up at any point during development. Adding a new feature can break
existing code or turn a simple, elegant design into a confusing mess. Constantly adding, removing,
and modifying features during development can make it impossible for different parts of the system
to work together. In some cases, it can even make it impossible to tell when the project is fi nished.
Because software is so malleable, design decisions can be made at any point up to the end of the
project. Actually, successful applications often continue to evolve long after the initial release.
Microsoft Word, for example, has been evolving for roughly 30 years. (Sometimes for the better,
sometimes for the worse. Remember Clippy? I’ll let you decide whether that change was for the
better or for the worse, but I haven’t seen him in a while.)
The fact that changes can come at any time means you need to consider the whole development
process as a single, long, complex task. You can’t simply “engineer” a great design, turn the
xxii
INTRODUCTION
programmers loose on it, and walk off into the sunset wrapped in the warm glow of a job well done.
The biggest design decisions may come early, and software development certainly has stages, but
those stages are linked, so you need to consider them all together.
WHY IS SOFTWARE ENGINEERING IMPORTANT?
Producing a software application is relatively simple in concept: Take an idea and turn it into a
useful program. Unfortunately for projects of any real scope, there are countless ways that a simple
concept can go wrong. Programmers may not understand what users want or need (which may be
two separate things), so they build the wrong application. The program might be so full of bugs that
it’s frustrating to use, impossible to fi x, and can’t be enhanced over time. The program could be
completely effective but so confusing that you need a PhD in puzzle‐solving to use it. An absolutely
perfect application could even be killed by internal business politics or market forces.
Software engineering includes techniques for avoiding the many pitfalls that otherwise might
send your project down the road to failure. It ensures the final application is effective, usable, and
maintainable. It helps you meet milestones on schedule and produce a finished project on time and
within budget. Perhaps most important, software engineering gives you the flexibility to make changes
to meet unexpected demands without completely obliterating your schedule and budget constraints.
In short, software engineering lets you control what otherwise might seem like a random whirlwind
of chaos.
WHO SHOULD READ THIS BOOK?
Everyone involved in any software development effort should have a basic understanding of software
engineering. Whether you’re an executive customer specifying the software’s purpose and features,
an end user who will eventually spend time working with (and reporting bugs in) the fi nished
application, a lead developer who keeps other programmers on track (and not playing too much
Flow Free), or the guy who fetches donuts for the weekly meeting, you need to understand how all
the pieces of the process fit together. A failure by any of these people (particularly the donut wallah)
affects everyone else, so it’s essential that everyone knows the warning signs that indicate the project
may be veering toward disaster.
This book is mainly intended for people with limited experience in software engineering. It doesn’t
expect you to have any previous experience with software development, project management,
or programming. (I suspect most readers will have some experience with donuts, but that’s not
necessary, either.)
Even if you have some familiarity with those topics, particularly programming, you may still fi nd
this book informative. If you’ve been focusing only on the pieces of a project assigned to you, you
still need to learn about how the pieces interact to help guide the project toward success.
For example, I had been working as a programmer for several years and even taken part in some
fairly large development efforts before I took a good look at the development process as a whole. I
knew other people were writing use cases and deployment plans, but my focus was on my piece of
xxiii
INTRODUCTION
the project. It wasn’t until later, when I started taking a higher‐level role in projects that I actually
started to see the entire process.
This book does not explain how to program. It does explain some techniques programmers can use
to produce code that is flexible enough to handle the inevitable change requests, easy to debug (at
least your code will be), and easy to enhance and maintain in the future (more change requests), but
they are described in general terms and don’t require you to know how to program.
If you don’t work in a programming role, for example if you’re an end user or a project manager,
you’ll hopefully find that material interesting even if you don’t use it directly. You may also find some
techniques surprisingly applicable to nonprogramming problems. For example, techniques for generating
problem‐solving approaches apply to all sorts of problems, not just programming decisions. (You can
also ask developers, “Are you using assertions and gray‐box testing methods before unit testing?” just
to see if they understand what you’re talking about. Basically, you’re using gray‐box testing to see if the
developers know what gray‐box testing is. You’ll learn more about that in Chapter 8, “Testing.”)
APPROACH
This book is divided into two parts. The fi rst part describes the basic tasks you need to complete
and deliver useful software. Things such as design, programming, and testing. The book’s second
part describes some common software development models that use different techniques to perform
those tasks.
Before you can begin to work on a software development project, however, you need to do some
preparation. You need to set up tools and techniques that help you track your progress throughout
the project. Chapter 1, “Software Engineering from 20,000 Feet,” describes these “before‐the‐
beginning” activities.
After you have the preliminaries in place, there are many approaches you can take to produce
software. All those approaches have the same goal (making useful software), so they must handle
roughly the same tasks. These are things such as gathering requirements, building a plan, and
actually writing the code. The fi rst part of this book describes these tasks. Chapter 1 explains those
tasks at a high level. Chapters 2 through 11 provide additional details about what these tasks are
and how you can accomplish them effectively.
The second part of the book describes some of the more popular software development approaches.
All these models address the same issues described in the earlier chapters but in different ways.
Some focus on predictability so that you know exactly what features will be provided and when.
Others focus on creating the most features as quickly as possible, even if that means straying
from the original design. Chapters 12 through 14 describe some of the most popular of these
development models.
That’s the basic path this book gives you for learning software engineering. First learn the tasks you
need to complete to deliver useful software. Then learn how different models handle those tasks.
However, many people have trouble learning by slogging through a tedious enumeration of facts. (I
certainly do!) To make the information a bit easier to absorb, this book includes a few other elements.
xxiv
INTRODUCTION
Each chapter ends with exercises that you can use to see if you were paying attention while you read
the chapter. I don’t like exercises that merely ask you to repeat what is in the chapter. (Quick, what
are some advantages and disadvantages of the ethereal nature of software?) Most of the exercises
ask you to expand on the chapter’s main ideas. Hopefully, they’ll make you think about new ways to
use what’s explained in the chapter.
Sometimes, the exercises are the only way I could sneak some more information into the chapter
that didn’t quite fit in any of its sections. In those cases, the questions and answers provided in
Appendix A are like extended digressions and thought experiments than quiz questions.
I strongly recommend that you at least skim the exercises and think about them. Then ask
yourself if you understand the solutions. All the solutions are included in Appendix A,
“Solutions to Exercises.”
WHAT THIS BOOK COVERS (AND WHAT IT DOESN’T)
This book describes software engineering, the tasks that you must perform to successfully complete
a software project, and some of the most popular developer models you can use to try to achieve
your goals. It doesn’t cover every last detail, but it does explain the overall process so that you can
figure out how you fit into the process.
This book does not explain every possible development model. Actually, it barely scratches the
surface of the dozens (possibly hundreds) of models that are in use in the software industry.
This book describes only some of the most popular development approaches and then only
relatively briefly.
If you decide you want to learn more about a particular approach, you can turn to the hundreds
of books and thousands of web pages written about specific models. Many development models
also have their own organizations with websites dedicated to their promotion. For example, see
www.extremeprogramming.org, agilemanifesto.org, and www.scrum.org.
This book also isn’t an exhaustive encyclopedia of software development tricks and tips. It describes
some general ideas and concepts that make it easier to build robust software, but its focus is on
higher‐level software engineering issues, so it doesn’t have room to cover all the clever techniques
developers use to make programs better. This book also doesn’t focus on a specific programming
language, so it can’t take advantage of language‐specific tools or techniques.
WHAT TOOLS DO YOU NEED?
You don’t need any tools to read this book. All you need is the ability to read the book. (And
perhaps reading glasses. Or perhaps a text‐to‐speech tool if you have an electronic version that you
want to “read.” Or perhaps a friend to read it to you. Okay, I guess you have several options.)
To actually participate in a development effort, you may need a lot of tools. If you’re working
on a small, one‐person project, you might need only a programming environment such as Visual
Studio, Eclipse, RAD Studio, or whatever. For larger team efforts you’ll also need tools for project
xxv
INTRODUCTION
management, documentation (word processors), change tracking, software revision tracking, and
more. And, of course, you’ll need other developers to help you. This book describes these tools, but
you certainly don’t need them to read the book.
CONVENTIONS
To help you get the most from the text and keep track of what’s happening, I’ve used several
conventions throughout the book.
SPLENDID SIDEBARS
Sidebars such as this one contain additional information and side topics.
WARNING Boxes like this one hold important information that is directly
relevant to the surrounding text. There are a lot of ways a software project can
fail, so these warn you about “worst practices” that you should avoid.
NOTE These boxes indicate notes, tips, hints, tricks, and asides to the current
discussion. They look like this.
As for styles in the text:
➤
Important words are highlighted
d when they are introduced.
➤
Keyboard strokes are shown like this: Ctrl+A. This one means you should hold down the Ctrl
key (or Control or CTL or whatever it’s labeled on your keyboard) and press the A key.
➤
This book includes little actual program code because I don’t know what programming
languages you use (if any). When there is code, it is formatted like the following.
// Return true if a and b are relatively prime.
private bool AreRelativelyPrime(int a, int b)
{
// Only 1 and -1 are relatively prime to 0.
if (a == 0) return ((b == 1) || (b == -1));
if (b == 0) return ((a == 1) || (a == -1));
int gcd = GCD(a, b);
return ((gcd == 1) || (gcd == -1));
}
(Don’t worry if you can’t understand the code. The text explains what it does.)
xxvi
INTRODUCTION
➤
Filenames, URLs, and the occasionally piece of code within the text are shown like this:
www.csharphelper.com.
ERRATA
I’ve done my best to avoid errors in this book, and this book has passed through the word processors
of a small army of editors and technical reviewers. However, as you’ll learn several times in this
book, no nontrivial project is ever completely without mistakes. The best I can hope for is that any
remaining errors are small enough that they don’t distract you from the meaning of the text.
If you fi nd an error in one of my books (like a spelling mistake, broken piece of code, or something
that just doesn’t make sense), I would be grateful for your feedback. Sending in errata may save
other readers hours of frustration. At the same time, you’ll be helping me provide even higher
quality information.
To fi nd the errata page for this book, go to www.wrox.com/go/beginningsoftwareengineering.
Then, on the book details page, click the Book Errata link. On this page you can view all the errata
submitted for this book and posted by Wrox editors. A complete book list including links to each
book’s errata is also available at www.wrox.com/misc‐pages/booklist.shtml.
If you don’t spot “your” error on the Book Errata page, go to www.wrox.com/contact/
techsupport.shtml and complete the form there to submit the error you found. Highly trained
editors will spring into action and check the information (by sending me an e‐mail). If appropriate,
they will then post a message to the book’s errata page and fi x the problem in subsequent editions of
the book.
p2p.wrox.com
Another excellent way to submit feedback and ask questions about the book is through the P2P
forums at p2p.wrox.com. (P2P stands for “Programmer to Programmer,” but because this book
isn’t just for programmers, I hereby declare that P2P stands for “Person to Person” in this context.)
These forums are a web‐based system for you to post messages relating to Wrox books and related
technologies, and to interact with other readers, technology users, and authors (like me). The
forums offer a subscription feature to e‐mail you topics of interest of your choosing when new
posts are made to the forums. Wrox authors, editors, other industry experts, and readers are
present on these forums.
To join the forums, just follow these steps:
1.
2.
3.
Go to p2p.wrox.com and click the Register link.
4.
You will receive an e‐mail with information describing how to verify your account and
complete the joining process.
Read the terms of use and click Agree.
Complete the required information to join as well as any optional information you want to
provide and click Submit.
xxvii
INTRODUCTION
JOIN THE FUN
You can read messages in the forums without joining P2P, but to post your own
messages, you must join. If you join, Wrox won’t spam you. (At least they never
have in the past.) They just want to make sure Internet trolls don’t make posts in
your name.
After you join, you can post new messages and respond to messages the other readers post. You can
read messages at any time on the web. If you would like to have new messages from a particular
forum e‐mailed to you, click the Subscribe to this Forum icon by the forum name in the forum
listing.
Be sure to read the P2P FAQs for answers to questions about how the forum software works as well
as many common questions specific to P2P and Wrox books. To read the FAQs, click the FAQ link
on any P2P page.
Using the P2P forums allows other readers to benefit from your questions and any answers they
generate. I monitor my books’ forums and respond whenever I can help.
IMPORTANT URLS
Here’s a summary of important URLs related to this book:
➤
www.wrox.com/go/beginningsoftwareengineering—This book’s web page.
➤
p2p.wrox.com—Wrox P2P forums.
➤
www.wrox.com—The Wrox website. Contains errata and other information. Search for books
by title or ISBN.
➤
RodStephens@CSharpHelper.com—My e‐mail address. I hope to hear from you!
➤
www.CSharpHelper.com—My C# website. Contains thousands of tips, tricks, and examples
for C# developers.
➤
www.vb‐helper.com—My Visual Basic website. Contains thousands of tips, tricks, and
examples for Visual Basic developers.
CONTACTING THE AUTHOR
If you have questions, suggestions, comments, just want to say “Hi,” want to exchange cookie
recipes, or whatever, e‐mail me at RodStephens@CSharpHelper.com. I can’t promise that I’ll be able
to help you with every problem, but I do promise to try.
xxviii
INTRODUCTION
DISCLAIMER
Software engineering isn’t always the most exciting topic, so in an attempt to keep you awake, I
picked some of the examples in this book for interest or humorous effect. (If you keep this book on
your nightstand as a last‐ditch insomnia remedy, then I’ve failed.)
I mean no disrespect to any of the many talented software engineers out there who work long weeks
(despite the call for sustainable work levels) to produce top‐quality applications for their customers.
(As for the untalented software engineers out there, their work can speak for them better than I can.)
I also don’t mean to discount any of the development models described in this book or the people
who worked on or with them. Every one of them represents a huge amount of work and research,
and all of them have their places in software engineering, past or present.
Because this book has limited space, I had to leave out many software development methodologies
and programming best practices. Even the methodologies that are described are not covered in full
detail because there just isn’t room.
If you disagree with anything I’ve said, if you want to provide more detail about a topic, or if you
want to describe the techniques and variations that you use to build software, I beg you to join
this book’s Wrox P2P forum and tell everyone all about it. The people on that forum are trying to
improve their development skills, so we’d all love to hear what you have to say. (In fact, learning and
improving the development process is a stated requirementt for many agile methodologies, so joining
the forum is practically mandatory!)
Finally I mean no disrespect to people named Fred, or anyone else for that matter. (Except for one
particular Fred, who I’m sure retired from software development long ago.)
So get out your reading glasses, grab your favorite caffeinated beverage, and prepare to enter the
world of software engineering. Game on!
xxix
PART I
Step‐by‐Step
y
▸ CHAPTER 1: Software Engineering from 20,000 Feet
▸ CHAPTER 2: Before the Beginning
▸ CHAPTER 3: Project Management
▸ CHAPTER 4: Requirement Gathering
▸ CHAPTER 5: High‐Level
Hi h L
l Design
D i
▸ CHAPTER 6: Low‐Level Design
▸ CHAPTER 7: Development
▸ CHAPTER 8: Testing
▸ CHAPTER 9: Deployment
▸ CHAPTER 10: Metrics
▸ CHAPTER 11: Maintenance
2
❘
CHAPTER 3
SOFTWARE ENGINEERING STEP-BY-STEP
Software and cathedrals are much the same. First we build them, then we pray.
—Samuel Redwine
In principle, software engineering is a simple two‐step process: (1) Write a best‐selling program,
and then (2) buy expensive toys with the profits. Unfortunately, the fi rst step can be rather difficult.
Saying “write a best‐selling program” is a bit like telling an author, “Write a best‐selling book,” or
telling a baseball player “triple to left.” It’s a great idea, but knowing the goal doesn’t actually help
you achieve it.
To produce great software, you need to handle a huge number of complicated tasks, any one of
which can fail and sink the entire project. Over the years people have developed a multitude of
methodologies and techniques to help keep software projects on track. Some of these, such as the
waterfalll and V‐modell approaches, use detailed requirement specifications to exactly defi ne the
wanted results before development begins. Others, such as Scrum and agile techniques, rely on
fast‐paced incremental development with frequent feedback to keep a project on track. (Still others
techniques, such as cowboy coding
g and extreme programming
g, sound more like action adventure
fi lms than software development techniques.)
Different development methodologies use different approaches, but they all perform roughly the
same tasks. They all determine what the software should do and how it should do it. They generate
the software, remove bugs from the code (some of the bugs, at least), make sure the software does
more or less what it should, and deploy the fi nished result.
NOTE I call these basic items “tasks” and not “stages” or “steps” because
different software engineering approaches tackle them in different ways and at
different times. Calling them “stages” or “steps” would probably be misleading
because it would imply that all projects move through the stages in the same
predictable order.
The chapters in the fi rst part of this book describe those basic tasks that any successful software
project must handle in some way. They explain the main steps in software development and describe
some of the myriad ways a project can fail to handle those tasks. (The second part of the book
explains how different approaches such as waterfall and agile handle those tasks.)
The fi rst chapter in this part of the book provides an overview of software development from a high
level. The subsequent chapters explain the pieces of the development process in greater detail.
1
There are two ways of constructing a software design. One way is to make
it so simple that there are obviously no deficiencies. The other way is to
make it so complicated that there are no obvious deficiencies. The first
method is far more difficult.
—C.A.R. Hoare
WHAT YOU WILL LEARN IN THIS CHAPTER:
➤
The basic steps required for successful software engineering
➤
Ways in which software engineering differs from other kinds of
engineering
➤
How fixing one bug can lead to others
➤
Why it is important to detect mistakes as early as possible
In many ways, software engineering is a lot like other kinds of engineering. Whether you’re
building a bridge, an airplane, a nuclear power plant, or a new and improved version of
Sudoku, you need to accomplish certain tasks. For example, you need to make a plan, follow
that plan, heroically overcome unexpected obstacles, and hire a great band to play at the
ribbon‐cutting ceremony.
The following sections describe the steps you need to take to keep a software engineering
project on track. These are more or less the same for any large project although there are
some important differences. Later chapters in this book provide a lot more detail about
these tasks.
4
❘
CHAPTER 1
SOFTWARE ENGINEERING FROM 20,000 FEET
REQUIREMENTS GATHERING
No big project can succeed without a plan. Sometimes a project doesn’t follow the plan closely, but
every big project must have a plan. The plan tells project members what they should be doing, when
and how long they should be doing it, and most important what the project’s goals are. They give
the project direction.
One of the fi rst steps in a software project is figuring out the requirements. You need to fi nd out
what the customers want and what the customers need. Depending on how well defi ned the user’s
needs are, this can be time‐consuming.
WHO’S THE CUSTOMER?
Sometimes, it’s easy to tell who the customer is. If you’re writing software for
another part of your own company, it may be obvious who the customers are. In
that case, you can sit down with them and talk about what the software should do.
In other cases, you may have only a vague notion of who will use the fi nished
software. For example, if you’re creating a new online card game, it may be hard to
identify the customers until after you start marketing the game.
Sometimes, you may even be the customer. I write software for myself all the time.
This has a lot of advantages. For example, I know exactly what I want and I know
more or less how hard it will be to provide different features. (Unfortunately, I also
sometimes have a hard time saying “no” to myself, so projects can drag on for a lot
longer than they should.)
In any project, you should try to identify your customers and interact with them as
much as possible so that you can design the most useful application possible.
After you determine the customers’ wants and needs (which are not always the same), you can turn
them into requirements documents. Those documents tell the customers what they will be getting,
and they tell the project members what they will be building.
Throughout the project, both customers and team members can refer to the requirements to see
if the project is heading in the right direction. If someone suggests that the project should include
a video tutorial, you can see if that was included in the requirements. If this is a new feature, you
might allow that change if it would be useful and wouldn’t mess up the rest of the schedule. If that
request doesn’t make sense, either because it wouldn’t add value to the project or you can’t do it
with the time you have, then you may need to defer it for a later release.
CHANGE HAPPENS
Although there are some similarities between software and other kinds of
engineering, the fact that software doesn’t exist in any physical way means there are
some major differences as well. Because software is so malleable, users frequently
ask for new features up to the day before the release party. They ask developers
High‐Level Design
to shorten schedules and request last‐minute changes such as switching database
platforms or even hardware platforms. (Yes, both of those have happened to me.)
“The program is just 0s and 1s,” they reason. “The 0s and 1s don’t care whether
they run on an Android tablet or a Windows Phone, do they?”
In contrast, a company wouldn’t ask an architectural fi rm to move a new
convention center across the street at the last minute; a city transportation
authority wouldn’t ask the builder to add an extra lane to a freeway bridge right
after it opens; and no one would try to insert an atrium level at the bottom of a
newly completed 90‐story building.
HIGH‐LEVEL DESIGN
After you know the project’s requirements, you can start working on the high‐level design. The
high‐level design includes such things as decisions about what platform to use (such as desktop,
laptop, tablet, or phone), what data design to use (such as direct access, 2‐tier, or 3‐tier), and
interfaces with other systems (such as external purchasing systems).
The high‐level design should also include information about the project architecture at a relatively
high level. You should break the project into the large chunks that handle the project’s major areas
of functionality. Depending on your approach, this may include a list of the modules that you need
to build or a list of families of classes.
For example, suppose you’re building a system to manage the results of ostrich races. You might
decide the project needs the following major pieces:
➤
Database (to hold the data)
➤
Classes (for example, Race, Ostrich, and Jockey classes)
➤
User interfaces (to enter Ostrich and Jockey data, enter race results, produce result reports,
and create new races)
➤
External interfaces (to send information and spam to participants and fans via e‐mail, text
message, voice mail, and anything else we can think of)
You should make sure that the high‐level design covers every aspect of the requirements. It should
specify what the pieces do and how they should interact, but it should include as few details as
possible about how the pieces do their jobs.
TO DESIGN OR NOT TO DESIGN, THAT IS THE QUESTION
At this point, fans of extreme programming, Scrum, and other incremental
development approaches may be rolling their eyes, snorting in derision and
muttering about how those methodologies don’t need high‐level designs.
continues
❘ 5
6
❘
CHAPTER 1
SOFTWARE ENGINEERING FROM 20,000 FEET
(continued)
Let’s defer this argument until Chapter 5, “High‐Level Design,” which talks
about high‐level design in greater detail. For now, I’ll just claim that every design
methodology needs design, even if it doesn’t come in the form of a giant written
design specification carved into a block of marble.
LOW‐LEVEL DESIGN
After your high‐level design breaks the project into pieces, you can assign those pieces to groups
within the project so that they can work on low‐level designs. The low‐level design includes
information about how that piece of the project should work. The design doesn’t need to give every
last nitpicky detail necessary to implement the project’s major pieces, but they should give enough
guidance to the developers who will implement those pieces.
For example, the ostrich racing application’s database piece would include an initial design for the
database. It should sketch out the tables that will hold the race, ostrich, and jockey information.
At this point you will also discover interactions between the different pieces of the project that may
require changes here and there. The ostrich project’s external interfaces might require a new table to
hold e‐mail, text messaging, and other information for fans.
DEVELOPMENT
After you’ve created the high‐ and low‐level designs, it’s time for the programmers to get to work.
(Actually, the programmers should have been hard at work gathering requirements, creating the
high‐level designs, and refi ning them into low‐level designs, but development is the part that most
programmers enjoy the most.) The programmers continue refi ning the low‐level designs until they
know how to implement those designs in code.
(In fact, in one of my favorite development techniques, you basically just keep refining the design to give
more and more detail until it would be easier to just write the code instead. Then you do exactly that.)
As the programmers write the code, they test it to make sure it doesn’t contain any bugs.
At this point, any experienced developers should be snickering if not actually laughing out loud.
It’s a programming axiom that no nontrivial program is completely bug‐free. So let me rephrase the
previous paragraph.
As the programmers write the code, they test it to find and remove as many bugs as they reasonably can.
TESTING
Effectively testing your own code is extremely hard. If you just wrote the code, you obviously didn’t
insert bugs intentionally. If you knew there was a bug in the code, you would have fi xed it before
you wrote it. That idea often leads programmers to assume their code is correct (I guess they’re just
naturally optimistic) so they don’t always test it as thoroughly as they should.
Testing
❘ 7
Even if a particular piece of code is thoroughly tested and contains no (or few) bugs, there’s no
guarantee that it will work properly with the other parts of the system.
One way to address both of these problems (developers don’t test their own code well and the pieces
may not work together) is to perform different kinds of tests. First developers test their own code. Then
testers who didn’t write the code test it. After a piece of code seems to work properly, it is integrated
into the rest of the project, and the whole thing is tested to see if the new code broke anything.
Any time a test fails, the programmers dive back into the code to figure out what’s going wrong and
how to fi x it. After any repairs, the code goes back into the queue for retesting.
A SWARM OF BUGS
At this point you may wonder why you need to retest the code. After all, you just
fi xed it, right?
Unfortunately fi xing a bug often creates a new bug. Sometimes the bug fi x is
incorrect. Other times it breaks another piece of code that depended on the original
buggy behavior. In the known bug hides an unknown bug.
Still other times the programmer might change some correct behavior to a different
correct behavior without realizing that some other code depended on the original
correct behavior. (Imagine if someone switched the arrangement of your hot and
cold water faucets. Either arrangement would work just fi ne, but you may get a
nasty surprise the next time you take a shower.)
Any time you change the code, whether by adding new code or fi xing old code, you
need to test it to make sure everything works as it should.
Unfortunately, you can never be certain that you’ve caught every bug. If you run your tests and
don’t fi nd anything wrong, that doesn’t mean there are no bugs, just that you haven’t found them.
As programming pioneer Edsger W. Dijkstra said, “Testing shows the presence, not the absence of
bugs.” (This issue can become philosophical. If a bug is undetected, is it still a bug?)
The best you can do is test and fi x bugs until they occur at an acceptably low rate. If bugs don’t bother
users too frequently or too severely when they do occur, then you’re ready to move on to deployment.
EX AMPLE
Counting Bugs
Suppose requirements gathering, high‐level design, low‐level design, and development works like this:
Every time you make a decision, the next task in the sequence includes two more decisions that depend
on the first one. For example, when you make a requirements decision, the high‐level design includes
two decisions that depend on it. (This isn’t exactly the way it works, but it’s not as ridiculous as you
might wish.)
Now suppose you made a mistake during requirements gathering. (The customer said the application
had to support 30 users with a 5‐second response time, but you heard 5 users with a 30‐second
response time.)
8
❘
CHAPTER 1
SOFTWARE ENGINEERING FROM 20,000 FEET
If you detect the error during the requirements gathering phase, you need to fi x only that one error. But
how many incorrect decisions could depend on that one mistake if you don’t discover the problem until
after development is complete?
The one mistake in requirements gathering leads to two decisions in high‐level design that could be
incorrect.
Each of the two possible mistakes in high‐level design leads to
two new decisions in low‐level design that could also be wrong,
giving a total of 2 × 2 = 4 possible mistakes in low‐level design.
Each of the four suspicious low‐level design decisions lead to
two more decisions during development, giving a total of 4 × 2
= 8 possible mistakes during development.
Adding up all the mistakes in requirements gathering, high‐level
design, low‐level design, and development gives a total of 1 + 2 +
4 + 8 = 15 possible mistakes. Figure 1-1 shows how the potential
mistakes propagate.
Requirements
High-level Design
Low-level Design
Development
FIGURE 1-1: The circles represent
possible mistakes at different stages of
development. One early mistake can
lead to lots of later mistakes.
In this example, you have 15 times as many decisions to track down, examine, and possibly fi x than
you would have if you had discovered the mistake right away during requirements gathering. That
leads to one of the most important rules of software engineering. A rule that is so important, I’ll
repeat it later in the book:
The longer a bug remains undetected, the harder it is to fi x.
Some people think of testing as something you do after the fact to verify that the code you wrote is
correct. Actually, testing is critical at every stage of development to ensure the resulting application
is usable.
DEPLOYMENT
Ideally, you roll out your software, the users are overjoyed, and everyone lives happily ever after. If
you’ve built a new variant of Tetris and you release it on the Internet, your deployment may actually
be that simple.
Often, however, things don’t go so smoothly. Deployment can be difficult, time‐consuming, and
expensive. For example, suppose you’ve written a new billing system to track payments from your
company’s millions of customers. Deployment might involve any or all of the following:
➤
New computers for the back-end database
➤
A new network
➤
New computers for the users
➤
User training
Wrap‐up
➤
On-site support while the users get to know the new system
➤
Parallel operations while some users get to know the new system and other users keep using
the old system
➤
Special data maintenance chores to keep the old and new databases synchronized
➤
Massive bug fixing when the 250 users discover dozens or hundreds of bugs that testing
didn’t uncover
➤
Other nonsense that no one could possibly predict
WHO COULD HAVE PREDICTED?
I worked on one project that assigned repair people to fi x customer problems for a
phone company. Twice during live testing the system assigned someone to work at
his ex‐wife’s house. Fortunately, the repair people involved recognized the address
and asked their supervisors to override the assignments.
If psychics were more consistent, it would be worth adding one to every software
project to anticipate these sorts of bizarre problems. Failing that or a working
crystal ball, you should allow some extra time in the project schedule to handle
these sorts of completely unexpected complications.
MAINTENANCE
As soon as the users start pounding away on your software, they’ll fi nd bugs. (This is another
software axiom. Bugs that were completely hidden from testers appear the instant users touch the
application.)
Of course, when the users fi nd bugs, you need to fi x them. As mentioned earlier, fi xing a bug
sometimes leads to another bug, so now you get to fi x that one as well.
If your application is successful, users will use it a lot, and they’ll be even more likely to fi nd bugs.
They also think up a slew of enhancements, improvements, and new features that they want added
immediately.
This is the kind of problem every software developer wants to have: customers that like an
application so much, they’re clamoring for more. It’s the goal of every software engineering project,
but it does mean more work.
WRAP‐UP
At this point in the process, you’re probably ready for a break. You’ve put in long hours of
planning, design, development, and testing. You’ve found bugs you didn’t expect, and the users are
keeping you busy with bug reports and change requests. You want nothing more than a nice, long
vacation.
❘ 9
10
❘
CHAPTER 1
SOFTWARE ENGINEERING FROM 20,000 FEET
There’s one more important thing you should do before you jet off to Cancún: You need to
perform a post‐mortem. You need to evaluate the project and decide what went right and what
went wrong. You need to figure out how to make the things that went well occur more often in
the future. Conversely, you need to determine how to prevent the things that went badly in the
future.
Right after the project’s completion, many developers don’t feel like going through this exercise,
but it’s important to do right away before everyone forgets any lessons that you can learn from the
project.
EVERYTHING ALL AT ONCE
Several famous people have said, “Time is nature’s way to keep everything from happening all at
once.” Unfortunately, time doesn’t work that way in software engineering. Depending on how big
the project is and how the tasks are distributed, many of the basic tasks overlap—and sometimes in
big ways.
Suppose you’re building a huge application that’s vital to national security interests. For example,
suppose you want to optimize national energy drink ordering, distribution, and consumption. This
is a big problem. (Really, it is.) You might have some ideas about how to start, but there are a lot of
details that you’ll need to work out to build the best possible solution. You’ll probably need to spend
quite a while studying existing operations to develop the user requirements.
You could spend several weeks peppering the customers with questions while the rest of the
development team plays Mario Cartt and consumes the drinks you’re studying, but that would be
inefficient.
A better use of everyone’s time would be to put people to work with as much of the project that
is ready to roll at any given moment. Several people can work with the customers to defi ne the
requirements. This takes more coordination than having a single person gather requirements, but on
big projects it can still save you a lot of time.
After you think you understand some of the requirements, other team members can start working
on high‐level designs to satisfy them. They’ll probably make more mistakes than they would if you
waited until the requirements are fi nished, but you’ll get things done sooner.
As the project progresses, the focus of work moves down through the basic project tasks. For
example, as requirements gathering nears completion, you should fi nalize the high‐level designs, so
team members can move on to low‐level designs and possibly even some development.
Meanwhile, throughout the entire project, testers can try to shoot holes in things. As parts of
the application are fi nished, they can try different scenarios to make sure the application can
handle them.
Depending on the testers’ skills, they can even test things such as the designs and the requirements.
Of course, they can’t run the requirements through a compiler to see if the computer can make sense
of them. They can, however, look for situations that aren’t covered by the requirements. (“What
if a shipment of Quickstart Energy Drink is delayed, but the customer is on a cruise ship and just
crossed the International Date Line! Is the shipment still considered late?”)
Summary
❘ 11
Sometimes tasks also flow backward. For example, problems during development may discover
a problem with the design or even the requirements. The farther back a correction needs to flow,
the greater its impact. Remember the earlier example where every problem caused two more? The
requirements problem you discovered during development could lead to a whole slew of other
undiscovered bugs. In the worst case, testing of “fi nished” code may reveal fundamental flaws in the
early designs and even the requirements.
REQUIREMENT REPAIRS
The fi rst project I worked on was an inventory system for NAVSPECWARGRU
(Navy Special Warfare Group, basically the Navy SEALs). The application let you
defi ne equipment packages for various activities and then let team members check
out whatever was necessary. (Sort of the way a Boy Scouts quartermaster does
this. For this campout, you’ll need a tent, bedroll, canteen, cooking gear, and M79
grenade launcher.)
Anyway, while I was building one of the screens, I realized that the requirements
specifications and high‐level design didn’t include any method for team members
to return equipment when they were done with it. In a matter of weeks, the
quartermaster’s warehouse would be empty and the barracks would be packed to
the rafters with ghillie suits and snorkels!
This was a fairly small project, so it was easy to fi x. I told the project manager,
he whipped up a design for an inventory return screen, and I built it. That kind of
quick correction isn’t possible for every project, particularly not for large ones, but
in this case the whole fi x took approximately an hour.
In addition to overlapping and flowing backward, the basic tasks are also sometimes handled in very
different ways. Some development models rely on a specification that’s extremely detailed and rigid.
Others use specifications that change so fluidly it’s hard to know whether they use any specification
at all. Iterative approaches even repeat the same basic tasks many times to build ever‐improving
versions of the fi nal application. The chapters in the second part of this book discuss some of the
most popular of those sorts of development approaches.
SUMMARY
All software engineering projects must handle the same basic tasks. Different development models
may handle them in different ways, but they’re all hidden in there somewhere.
In fact, the strengths and weaknesses of various development models depend in a large part on
how they handle these tasks. For example, agile methods and test‐driven development use frequent
builds to force developers to perform a lot of tests early on so that they can catch bugs as quickly as
possible. (For a preview of why that’s important, see the “Counting Bugs” example earlier in this
chapter and Exercise 4.)
12
❘
CHAPTER 1
SOFTWARE ENGINEERING FROM 20,000 FEET
The chapters in Part II, “Development Models,” describe some of the most common development
models. Meanwhile the following chapters describe the basic software engineering tasks in greater
detail. Before you delve into the complexities of requirements gathering, however, there are a few
things you should consider.
The next chapter explains some basic tools that you should have in place before you consider a new
project. The chapter after that discusses project management tools and techniques that can help you
keep your project on track as you work through the basic software engineering tasks.
EXERCISES
1.
What are the basic tasks that all software engineering projects must handle?
2.
Give a one sentence description of each of the tasks you listed for Exercise 1.
3.
I have a few customers who do their own programming, but who occasionally get stuck and
need a few pointers or a quick example program. A typical project runs through the following
stages:
a.
The customer sends me an e‐mail describing the problem.
b.
I reply telling what I think the customer wants (and sometimes asking for clarification).
c.
The customer confirms my guesses or gives me more detail.
d.
I crank out a quick example program.
e.
I e‐mail the example to the customer.
f.
The customer examines the example and asks more questions if necessary.
g.
I answer the new questions.
Earlier in this chapter, I said that every project runs through the same basic tasks. Explain
where those tasks are performed in this kind of interaction. (For example, which of those steps
includes testing?)
4.
List three ways fixing one bug can cause others.
5.
List five tasks that might be part of deployment.
Summary
❘ 13
▸ WHAT YOU LEARNED IN THIS CHAPTER
➤
All projects perform the same basic tasks:
1.
2.
3.
4.
5.
6.
7.
8.
Requirements Gathering
High‐level Design
Low‐level Design
Development
Testing
Deployment
Maintenance
Wrap‐up
➤
Different development models handle the basic tasks in different ways, such as making some
less formal or repeating tasks many times.
➤
The basic tasks often occur at the same time, with some developers working on one task
while other developers work on other tasks.
➤
Work sometimes flows backward with later tasks requiring changes to earlier tasks.
➤
Fixing a bug can lead to other bugs.
➤
The longer a mistake remains undetected, the harder it is to fix.
➤
Surprises are inevitable, so you should allow some extra time to handle them.
2
It’s not whether you win or lose, it’s how you place the blame.
—Oscar Wilde
WHAT YOU WILL LEARN IN THIS CHAPTER:
➤
The features that a document management system provides
➤
Why documentation is important
➤
How you can easily archive e‐mails for later use
➤
Typical types of documentation
Before you start working on a software project, even before you dig into the details of what
the project is about, there are preparations you should make. In fact, some of these can be
useful even if you’re not considering a software project.
These tools improve your chances for success in any complicated endeavor. They raise the
odds that you’ll produce something that will satisfy the application’s customers. They’ll also
help you survive the process so that you’ll still be working on the project when the accolades
start rolling in.
Typically, you’ll use these tools and techniques throughout all of a project’s stages. You’ll
use them while you’re gathering requirements from the customer, during the design and
programming phases, and as you roll out the final result to the users. You’ll even use them
after you’ve fi nished releasing an application and you’re considering enhancements for the next
version.
The following sections describe some beginning‐to‐end tools that you can use to help keep
team members focused and the project on track.
16
❘
CHAPTER 2 BEFORE THE BEGINNING
DOCUMENT MANAGEMENT
A software engineering project uses a lot of documents. It uses requirements documents, use cases,
design documents, test plans, user training material, lunch menus for team‐building exercises,
resumes if the project doesn’t go well, and much more. (I’ll describe these kinds of documentation in
later chapters.) Even a relatively modest project could have hundreds or even thousands of pages of
documentation.
To make matters more confusing, many of those are “living” documents that evolve over time. In
some projects, the requirements are allowed to change as the project progresses. As developers get a
better sense for which tasks will be hard and which will be easy, the customers may want to revise
the requirements to include new, simple features and eliminate old, complicated features.
As the project progresses, the customers will also get a better understanding of what the system
will eventually do and they may want to make changes. They may see some partially implemented
feature and decide that it isn’t that useful. They may even come up with new features that they just
plain forgot about at the beginning of the project. (“I know we didn’t explicitly say you need a way
to log into the system, but I’m quite sure that’s going to be necessary at some point.”)
CHANGE CONTROL
If you let everyone make changes to the requirements, how can you meet them?
Just when you satisfy one requirement, someone can change it, so you’re not done
after all. (Imagine running after the bus in the rain while the driver cackles evilly
and checks the side mirror to make sure he’s going just a little faster than you’re
running.) Eventually, the requirements need to settle down so that you can achieve
them.
Allowing everyone to change the requirements can also result in muddled,
confl icting, and confusing goals and designs. This is more or less how laws and
government spending bills are written, so it shouldn’t be a surprise that the results
aren’t always perfect. (“Yes, you can have a $3,000 study to decide whether people
should carry umbrellas in the rain if I can have my $103,000 to study the effects
of tequila and gin on sunfish.” Someone really should spend a few dollars to study
whether that kind of budget process is efficient.)
To keep changes from proliferating wildly and becoming hopelessly convoluted,
many projects (particularly large ones) create a change control board
d that reviews
and approves (or rejects) change requests. The board should include people who
represent the customers (“We really need
d to log in telepathically from home”) and
the development team (“The best we can do is let you log in on your cell phone”).
Even on small projects, it’s usually worthwhile to assign someone as the fi nal
arbiter. Often that person is either a high‐ranking customer (such as the executive
champion) or a high‐ranking member of the development team (such as the
project lead).
Document Management
❘ 17
During development, it’s important to check the documentation to see what you’re supposed
to be doing. You need to easily fi nd the most recent version of the requirements to see what the
application should do. Similarly, you need to fi nd the most recent high‐level and low‐level designs to
see if you’re following the plan correctly.
Sometimes, you’ll also need to fi nd older versions of the documentation, to fi nd out what changes
were made, why they were made, and who made them.
FONT FIASCO
To understand the importance of historical documentation, suppose your
application produces quarterly reports showing projected root beer demand. At
some point the requirements were changed to require that the report be printed in
landscape mode with a 16‐point Arial font.
Now suppose you’re working on the report to add new columns that group
customers by age, weight, ethnic background, car model, and hat size. That’s easy
enough, but now the report won’t fit on the page. If you could bump the font size
down to 14‐point, everything would fit just fi ne, but the 16‐point Arial requirement
is killing you.
At this point, you should go back to the requirements documents and fi nd out why
the font requirement was added. If the requirement was added to make it easier to
include reports in PowerPoint slides, you may be able to reduce the font size and
your boss can live with slightly more crowded slides during his presentations to the
VP of Strategic Soft Drink Engineering.
Another option might be to continue producing the original report for
presentations and create a new expanded report that includes the new columns for
research purposes.
It’s even possible that the original issue was that some developers were printing
reports with the Comic Sans font. Management didn’t think that looked
professional enough, so it made a font requirement. They never actually cared
about the font size, just the typeface. In that case, you could probably ask to change
the requirement again to let you use a smaller font, as long as you stick with Arial.
Unless you have a good document history, you may never know why and when the
requirement was changed, so you won’t know whether it’s okay to change it again.
Meanwhile, as you’re changing the font requirement to allow 12‐point Arial, one of your coworkers
might be changing some other part of the same requirement document (perhaps requiring that all
reports must be printed in renewable soy ink on 100% post‐consumer recycled paper). If you both
open the document at the same time, whichever change is saved second will overwrite the other
change, and the fi rst change will be lost. (In programming terms, this is a “race condition” in which
the second person wins.)
18
❘
CHAPTER 2 BEFORE THE BEGINNING
To prevent this type of conflict, you need a document control system that prevents two people from
making changes to the same document at the same time.
To handle all these issues, you need a good document management system. Ideally, the system
should support at least the following operations:
➤
People can share documents so that they can all view and edit them.
➤
Only one person can edit a document at a given time.
➤
You can fetch the most recent version of a document.
➤
You can fetch a specific version of a document by specifying either a date or version number.
➤
You can search documents for tags, keywords, and anything else in the documents.
➤
You can compare two versions of a document to see what changed, who changed it, and
when the change occurred. (Ideally, you should also see notes indicating why a change was
made; although, that’s a less common feature.)
Following are some other features that are less common but still useful:
➤
The ability to access documents over the Internet or on mobile devices.
➤
The ability for multiple people to collaborate on documents (so they can see each other
making changes to a shared document).
➤
Integration into other tools such as Microsoft Office or project management software.
➤
Document branches so that you can split a document into two paths for future changes. (This
is more useful with program code where you might need to create two parallel versions of the
program. Even then it can lead to a lot of confusion.)
➤
User roles and restricted access lists.
➤
E‐mail change notification.
➤
Workflow support and document routing.
Some document management systems don’t include all these features, and some of these aren’t
necessary for smaller projects, but they can be nice to have.
The following sections describe some special features of different kinds of documentation that you
should save.
HISTORICAL DOCUMENTS
After you’ve installed some sort of document management system, you may wonder what documents
you should put in it. The answer is: everythingg. Every little tidbit and scrap of intelligence dealing
with the project should be recorded for posterity. Every design decision, requirements change, and
memo should be tucked away for later use.
If you don’t have all this information, it’s too easy for project meetings to devolve into
fi nger‐pointing sessions and blame-game tournaments. Let’s face it; people forget things.
E‐mail
❘ 19
(I’m writing Chapter 2 and I’ve already forgotten what Chapter 1 was about.) Not every
disagreement has the vehemence of a blood feud between vampires and werewolves, but some can
grow that bad if you let them. If you have a good, searchable document database, you can simply
fi nd the memo where your customer said that all the monitors had to be pink, pick the specific
shade, and move on to discuss more important matters.
Collecting every scrap of relevant information isn’t quite as big a chore as you might think. Most
of the information is already available in an electronic form, so you just need to save it. Whenever
someone sends an e‐mail about the project, save it. Whenever someone makes a change request, save
it. If someone creates a new document and doesn’t put it in the document repository, put it there
yourself or at least e‐mail it to yourself so that there’s a record.
The only types of project activity that aren’t usually easy to record electronically are meetings and
phone calls. You can record meetings and phone calls if you want a record of everything (subject
to local law), but on most projects you can just type up a quick summary and e‐mail it to all the
participants. Anyone who disagrees about what was covered in the meeting can send a follow‐up
e‐mail that can also go into the historical documents.
It’s also well worth your effort to thrash through any disagreements as soon as possible, and sending
out a meeting summary can help speed that process along. The biggest purpose of documentation is
to ensure that everyone is headed in the same direction.
E‐MAIL
Memos, discussions about possible change requests, meeting notes, and lunch orders are all easy to
distribute via e‐mail. Storing those e‐mails for historical purposes is also easy: Simply CC a selected
e‐mail address for every project e‐mail. For example, you could create an e‐mail address named after
the project and copy every project message to that account.
Suppose you’re working on project CLASP (CLeverly Acronymed Software Project). Then you would
create an e‐mail account named CLASP and send copies of any project e‐mail to that account.
TIP I’ve had project managers who extracted every project e‐mail into text files
and tucked them away in a folder for later use. That lets you perform all sorts
of other manipulations that are tricky inside an e‐mail system. For example,
you could write a program to search the files for messages from the user Terry
that include the words “sick” and “Friday.” I’ve even had project managers
who printed out every e‐mail; although, that seems a bit excessive. Usually just
having the e‐mails saved in a project account is good enough.
Sometimes, it’s hard for team members to easily fi nd project‐related e‐mails in the daily
spamalanche of offers for cheap Canadian prescriptions, low interest rates guaranteed by the
“U.S. National Bank,” letters from your long lost Nigerian uncle, and evacuation notices from your
Building Services department.
20
❘
CHAPTER 2 BEFORE THE BEGINNING
To make fi nding project e‐mails easier, you can prefi x their subjects with an identifier. The following
text might show the subject line for an e‐mail about the CLASP project.
[CLASP] This week’s meeting canceled because all tasks are ahead of schedule
Of course, if you receive an e‐mail with this subject, you should suspect it’s a hoax because all tasks
have never been ahead of schedule in the entire history of software engineering. I think the day the
term “software engineering” was coined, its defi nition was already a week overdue.
You can further refine the subject identifier by adding classes of messages. For example, [CLASP.Design]
might indicate a message about design for the CLASP project. You can invent any message classes that
you think would be useful. Following is a list of a few that may come in handy.
➤
Admin—Administration
➤
Rqts—Requirements
➤
HLDesign—High‐level design
➤
LLDesign—Low‐level design
➤
Dvt—Development
➤
Test—Testing
➤
Deploy—Deployment
➤
Doc—Documentation
➤
Train—Training
➤
Maint—Maintenance
➤
Wrap—Wrap‐up
TIP It doesn’t matter what subject line tags you use, as long as you’re
consistent. Make a list at the beginning of the project and make sure everyone
uses them consistently.
You could even break the identifier further to indicate tasks within a message class. For example, the
string [CLASP.LLDesign.1001] might indicate a message regarding low‐level design task 1001.
TIP Some e‐mail systems can even use rules to route particular messages to
different folders. For example, the system might be able to copy messages with
the word CLASP in the title into a project e‐mail folder. (Just don’t spend more
time programming your e‐mail system than on the actual project.)
If team members use those conventions consistently, any decent e‐mail system should make it easy
to fi nd messages that deal with a particular part of the project. To fi nd the test messages, you can
search for [CLASP.Test. To fi nd every CLASP e‐mail, search for [CLASP.
Code
❘ 21
An alternative strategy is to include keywords inside the message body. You can use a naming
convention similar to the one described here, or you can use something more elaborate if you need
to. For example, a message might begin with the following text to flag it as involving the testing,
bug reports, and login screen.
Key: Test
Key: Bugs
Key: Login
Now you can search for strings like Key: Bugs to fi nd the relevant messages.
In addition to making e‐mails easy to fi nd, you should take steps to make them easy to distribute.
Create some e‐mail groups so that you can distribute messages to the appropriate people. For
example, you may want groups for managers, user interface designers, customers, developers,
testers, and trainers—and, of course, a group for everyone.
Then be sure you use the groups correctly! Customers don’t want to hear the developers argue
over whether a b+tree is better than an AVL‐tree, and user interface designers don’t want to hear
the testers dispute the fi ne points of white‐box versus beige‐box testing. (In one project I was on, a
developer accidentally included customers in an e‐mail that described them in less than flattering
terms. Basically, he said they didn’t really know what they needed. It was true, but they sure didn’t
like hearing it!)
CODE
Program source code is different from a project’s other kinds of documents. Normally, you expect
requirements and design documents to eventually stabilize and remain mostly unchanged. In
contrast, code changes continually, up to and sometimes even beyond the project’s official ending
date.
That gives source code control systems a slightly different flavor than other kinds of document
control systems. A requirements document might go through a dozen or so versions, but a code
module might include hundreds or even thousands of changes. That means the tools you use to store
code often don’t work particularly well with other kinds of documents and vice versa.
Source code is also generally line‐oriented. Even in languages such as C# and Java, which are
technically not line‐oriented, programmers insert line breaks to make the code easier to read. If you
change a line of source code, that change probably doesn’t affect the lines around it. Because of that,
if you use a source code control system to compare two versions of a code fi le, it flags only that one
line as changed.
In contrast, suppose you added the word “incontrovertibly” to the beginning of the preceding
paragraph. That would make every line in the paragraph wrap to the following line, so every
line in the paragraph would seem to have been changed. A document revision system, such as
those provided by Microsoft Word or Google Docs, correctly realizes that you added only a
single word. A source code control system might decide that you had modifi ed every line in the
paragraph.
22
❘
CHAPTER 2 BEFORE THE BEGINNING
What this means is that you should use separate tools to manage source code and other kinds of
documents. This usually isn’t a big deal, and it’s easy to find a lot of choices online. (In fact, picking
one that every developer can agree on may be the hardest part of using a source code control system.)
Ideally, a source code control system enables all the developers to use the code. If a developer needs
to modify a module, the system checks out the code to that developer. Other developers can still use
the most recently saved version of the code, but they can’t edit that module until the fi rst developer
releases it. (This avoids the race condition described earlier in this chapter.)
Some source code control systems are integrated into the development environment. They make
code management so easy even the most advanced programmers don’t mess it up too often.
CODE DOCUMENTATION
Something that most nonprogrammers (and quite a few programmers) don’t understand is that code
is written for people, not for the computer. In fact, the computer doesn’t execute the source code.
The code must be compiled, interpreted, and otherwise translated into a sequence of 0s and 1s that
the computer can understand.
The computer also doesn’t care what the code does. If you tell it to erase its hard disk (something I
don’t recommend), the computer will merrily try to do just that.
The reason I say source code is written for people is that it’s people who must write, understand,
and debug the code. The single most important requirement for a program’s code is that it be
understandable to the people who write and maintain it.
Now I know I’m going to get a lot of argument over that statement. Programmers have all sorts of
favorite goals like optimizing speed, minimizing bugs, and including witty puns in the comments.
Those are all important, but if you can’t understand the code, you can’t safely modify it and fi x it
when it breaks.
Without good documentation, including both design documents and comments inside the code, the
poor fool assigned to fi x your code will stand little or no chance. This is even more important when
you realize that the poor fool may be you. The code you fi nd so obvious and clever today may make
no sense at all to you in a year or even a few months. (In some cases, it may not make sense a few
hours later.) You owe it to posterity to ensure that your genius is properly understood throughout
the ages.
To that end, you need to write code documentation. You don’t need to write enormous tomes
explaining that the statement numInvoicesLost = numInvoicesLost + 1 means you are adding 1
to the value numInvoicesLost. You can probably figure that out even if you’ve never seen a line of
code before. However, you do need to give yourself and others a trail of breadcrumbs to follow on
their quest to figure out why invoices are being sent to employees instead of customers.
Code documentation should include high‐ and low‐level design documents that you can store in the
document repository with other kinds of documentation. These provide an overview of the methods
the code is using to do whatever it’s supposed to do.
Code documentation should also include comments in the code to help you understand what the
code is actually doing and how it works. You don’t need to comment every line of code (see the
Code Documentation
numInvoicesLost example again), but it should provide a fairly detailed explanation that even
the summer intern who was hired only because he’s the boss’s nephew can understand. Debugging
code should be an exercise in understanding the code and figuring out why it isn’t doing what it’s
supposed to do. It shouldn’t be an IQ test.
JBGE
There’s a school of thought in software engineering that says you should provide
code documentation and comments that are “just barely good enough” ( JBGE).
The idea is that if you provide too much documentation, you end up wasting a lot
of time updating it as you make changes to the code.
This philosophy can reduce the amount of documentation you produce, but it’s
an idea that’s easy to take too far. Most programmers like to program (that’s why
they’re not lawyers or doctors) and writing and updating documentation and
comments doesn’t feel like writing code, so sometimes they skip it entirely.
A software engineering joke says, “Real programmers don’t comment their code.
If it was hard to write, it should be hard to understand and harder to modify.”
Unfortunately I’ve seen plenty of code that proves the connection between poor
documentation and difficult modification.
I worked on one project that included more than 55,000 lines of code and fewer
than 300 comments. (I wrote a program to count them.) And if there were design
documents, I never heard about them. I’m sure the code made sense when it was
written, but modifying it was next to impossible. I sometimes spent 4 or 5 days
studying the code, trying to figure out how it worked before changing one or two
lines. Even after all that time, there was a decent chance I misunderstood something
and the change added a new bug. Then I got to remove the change and start over.
I worked on another project that included tons of comments. Probably more than
80 percent of the lines of code included a comment. They were easy to ignore most
of the time, but they were always there if you needed them.
After we transferred the project to the company’s maintenance organization, the
folks in the organization went on a JBGE bender and removed every comment that
they felt wasn’t absolutely necessary to understand the code. A few months later,
they admitted that they couldn’t maintain the code because —…drumroll…— they
couldn’t understand it. In the end, they put all the comments back and just ignored
them when they didn’t need them.
Yes, excessive code documentation and comments are a hassle and slow you down, so
you can’t rush off to the next task, but suck it up and write it down while it’s still fresh
in your mind. You don’t need to constantly update your comments every time you
change a line of code. Wait until you finish writing and testing a chunk of code. Then
write it up and move on with a clear conscience. Comments may slow you down a bit,
but I’ve never seen a project fail because it contained too many comments.
❘ 23
24
❘
CHAPTER 2 BEFORE THE BEGINNING
JBGE, REDUX
JBGE is mostly applied to code documentation and comments, but you could apply
the same rule to any kind of documentation. For example, you could write barely
enough documentation to explain the requirements. That’s probably an even bigger
mistake than skimping on code comments.
Documentation helps keep the whole project team working toward the same
goals. If you don’t spell things out unambiguously, developers will start working
at cross‐purposes. At best you’ll lose a lot of time arguing about what the
requirements mean. At worst you’ll face a civil war that will destroy your team.
As is the case with code documentation and comments, you don’t need to turn the
requirements into a 1,200‐page novel. However, if the requirements are ambiguous
or confusing, pull out your thesaurus and clarify them.
JBGE is okay as long as you make sure your documentation actually is GE.
You can extend the JBGE idea even further and create designs that are just
barely good enough, write code that’s just barely good enough, and perform
tests that are just barely good enough. I’m a big fan of avoiding unnecessary
work, but if everything you do is just barely good enough, the result probably
won’t be anywhere near good enough. (Not surprisingly, no one advocates
that approach. The JBGE philosophy seems to be reserved only for code
comments.)
Some programming languages provide a special kind of comment that is intended to be pulled out
automatically and used in text documentation. For example, the following shows a snippet of C#
code with XML comments:
///
/// Deny something bad we did to the media.
///
/// What we did (Bug, Virus, PromisedBadFeature, etc.)
/// High, Medium, or Low
/// One or more of Blog, Facebook, Friendster, etc.
private void PostDenial(DenialType type, UrgencyType urgency, MediaType media)
{
…
}
The comment’s summary token explains the method’s purpose. The param tokens describe the
method’s parameters. The Visual Studio development environment can automatically extract these
comments into an XML fi le that you can then process to produce documentation. The result doesn’t
explain how the code works, but if you do a good job writing the comments, it does explain the
Summary
❘ 25
interface that the method displays to other pieces of code. (Visual Studio also uses these comments
to provide help pop‐ups called IntelliSense to other developers who call this code.)
As is the case when you write code documentation and other comments, you don’t need to
constantly update this kind of information as you work on a method. Finish the method, test it, and
then write the comments once.
APPLICATION DOCUMENTATION
All the documentation described so far deals with building the application. It includes such items as
requirements and design documents, code documentation and comments, meeting and phone call
notes, and memos.
At some point you also need to prepare documentation that describes the application. Depending
on the eventual number and kinds of users, you may need to write user manuals (for end users,
managers, database administrators, and more), quick start guides, cheat sheets, user interface maps,
training materials, and marketing materials. You may even need to write meta‐training materials to
teach the trainers how to train the end users. (No kidding, I’ve done it.)
In addition to basic printed versions, you may need to produce Internet, screencast, video, and
multimedia versions of some of those documents. Producing this kind of documentation isn’t all
that different from producing requirements documents. You can still store documents in an archive.
(Although you may not be able to search for keywords in a video.)
Although creating this material is just another task, don’t start too late in the project schedule. If
you wait until the last minute to start writing training materials, then the users won’t be able to use
the application when it’s ready. (I remember one project where the requirements and user interface
kept changing right up until the last minute. It was somewhat annoying to the developers, but it
practically drove our lead trainer insane.)
SUMMARY
Documentation is produced throughout a project’s lifespan, starting with early discussions of
the project’s requirements, extending through design and programming, continuing into training
materials, and lasting even beyond the project’s release in the form of comments, bug reports,
and change requests. To get the most out of your documentation, you need to set up a document
tracking system before you start the project. Then you can effectively use the project documents to
determine what you need to do and how you should do it. You can also figure out what was decided
in the past so that you don’t need to constantly rehash old decisions.
Document control is one of the fi rst tools you should set up when you’re considering a new project.
You can use it to archive ideas before you know what the project will be about or whether there will
even be a project. Once you know the project will happen, you should start tracking the project with
project management tools. The next chapter describes project management in general and some of
the tools you can use to help keep a project moving in the right direction.
26
…