Beginning Software Engineering - Rod Stephens - E-Book

Beginning Software Engineering E-Book

Rod Stephens

4,9
35,99 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

Discover the foundations of software engineering with this easy and intuitive guide In the newly updated second edition of Beginning Software Engineering, expert programmer and tech educator Rod Stephens delivers an instructive and intuitive introduction to the fundamentals of software engineering. In the book, you'll learn to create well-constructed software applications that meet the needs of users while developing the practical, hands-on skills needed to build robust, efficient, and reliable software. The author skips the unnecessary jargon and sticks to simple and straightforward English to help you understand the concepts and ideas discussed within. He also offers you real-world tested methods you can apply to any programming language. You'll also get: * Practical tips for preparing for programming job interviews, which often include questions about software engineering practices * A no-nonsense guide to requirements gathering, system modeling, design, implementation, testing, and debugging * Brand-new coverage of user interface design, algorithms, and programming language choices Beginning Software Engineering doesn't assume any experience with programming, development, or management. It's plentiful figures and graphics help to explain the foundational concepts and every chapter offers several case examples, Try It Out, and How It Works explanatory sections. For anyone interested in a new career in software development, or simply curious about the software engineering process, Beginning Software Engineering, Second Edition is the handbook you've been waiting for.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 1396

Veröffentlichungsjahr: 2022

Bewertungen
4,9 (16 Bewertungen)
14
2
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Table of Contents

COVER

TABLE OF CONTENTS

TITLE PAGE

INTRODUCTION

WHAT IS SOFTWARE ENGINEERING?

WHY IS SOFTWARE ENGINEERING IMPORTANT?

WHO SHOULD READ THIS BOOK?

APPROACH

WHAT THIS BOOK COVERS (AND WHAT IT DOESN'T)

WHAT TOOLS DO YOU NEED?

CONVENTIONS

ERRATA

IMPORTANT URLs

CONTACTING THE AUTHOR

DISCLAIMER

PART I: Software Engineering Step-by-Step

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

WHAT YOU LEARNED IN THIS CHAPTER

2 Before the Beginning

DOCUMENT MANAGEMENT

HISTORICAL DOCUMENTS

EMAIL

CODE

CODE DOCUMENTATION

APPLICATION DOCUMENTATION

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

3 The Team

TEAM FEATURES

TEAM ROLES

TEAM CULTURE

INTERVIEWS

PHYSICAL ENVIRONMENT

COLLABORATION SOFTWARE

OUTSOURCING

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

4 Project Management

EXECUTIVE SUPPORT

PROJECT MANAGEMENT

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

5 Requirements Gathering

REQUIREMENTS DEFINED

REQUIREMENT CATEGORIES

GATHERING REQUIREMENTS

REFINING REQUIREMENTS

RECORDING REQUIREMENTS

VALIDATION AND VERIFICATION

CHANGING REQUIREMENTS

DIGITAL TRANSFORMATION

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

6 High-Level Design

THE BIG PICTURE

WHAT TO SPECIFY

UML

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

7 Low-Level Design

DESIGN APPROACHES

OO DESIGN

DATABASE DESIGN

WHEN TO OPTIMIZE

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

8 Security Design

SECURITY GOALS

SECURITY TYPES

CYBERSECURITY

SHIFT-LEFT SECURITY

MALWARE MENAGERIE

PHISHING AND SPOOFING

SOCIAL ENGINEERING ATTACKS

CRAPWARE

PASSWORD ATTACKS

USER ACCESS

COUNTERMEASURES

CYBER INSURANCE

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

9 User Experience Design

DESIGN MINDSET

DESIGN GUIDELINES

FORM DESIGN

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

10 Programming

TOOLS

ALGORITHMS

TOP-DOWN DESIGN

PROGRAMMING TIPS AND TRICKS

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

11 Algorithms

ALGORITHM STUDY

ALGORITHMIC APPROACHES

ALGORITHM CHARACTERISTICS

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

12 Programming Languages

THE MYTH OF PICKING A LANGUAGE

LANGUAGE GENERATIONS

LANGUAGE FAMILIES

THE BEST LANGUAGE

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

13 Testing

TESTING GOALS

REASONS BUGS NEVER DIE

LEVELS OF TESTING

TESTING TECHNIQUES

TESTING HABITS

HOW TO FIX A BUG

ESTIMATING NUMBER OF BUGS

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

14 Deployment

SCOPE

THE PLAN

CUTOVER

DEPLOYMENT TASKS

DEPLOYMENT MISTAKES

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

15 Metrics

WRAP PARTY

DEFECT ANALYSIS

SOFTWARE METRICS

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

16 Maintenance

MAINTENANCE COSTS

TASK CATEGORIES

TASK EXECUTION

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

PART II: Process Models

17 Predictive Models

MODEL APPROACHES

PREREQUISITES

PREDICTIVE AND ADAPTIVE

WATERFALL

WATERFALL WITH FEEDBACK

SASHIMI

INCREMENTAL WATERFALL

V-MODEL

SOFTWARE DEVELOPMENT LIFE CYCLE

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

18 Iterative Models

ITERATIVE VS. PREDICTIVE

ITERATIVE VS. INCREMENTAL

PROTOTYPES

SPIRAL

UNIFIED PROCESS

CLEANROOM

COWBOY CODING

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

19 RAD

RAD PRINCIPLES

JAMES MARTIN RAD

AGILE

XP

SCRUM

LEAN

CRYSTAL

FEATURE-DRIVEN DEVELOPMENT

DISCIPLINED AGILE DELIVERY

DYNAMIC SYSTEMS DEVELOPMENT METHOD

KANBAN

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

PART III: Advanced Topics

20 Software Ethics

ETHICAL BEHAVIOR

RESPONSIBILITY

THOUGHT EXPERIMENTS

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

21 Future Trends

SECURITY

UX/UI

CODE PACKAGING

CLOUD TECHNOLOGY

SOFTWARE DEVELOPMENT

ALGORITHMS

TECH TOYS

SUMMARY

WHAT YOU LEARNED IN THIS CHAPTER

APPENDIX: Solutions to Exercises

CHAPTER 1

CHAPTER 2

CHAPTER 3

CHAPTER 4

CHAPTER 5

CHAPTER 6

CHAPTER 7

CHAPTER 8

CHAPTER 9

CHAPTER 10

CHAPTER 11

CHAPTER 12

CHAPTER 13

CHAPTER 14

CHAPTER 15

CHAPTER 16

CHAPTER 17

CHAPTER 18

CHAPTER 19

CHAPTER 20

CHAPTER 21

GLOSSARY

INDEX

COPYRIGHT

ABOUT THE AUTHOR

ABOUT THE TECHNICAL EDITOR

ACKNOWLEDGMENTS

END USER LICENSE AGREEMENT

List of Tables

Chapter 4

TABLE 4.1: Tasks for a zombie apocalypse bunker

TABLE 4.2: Classes and modules for

World of Z-Craft

Chapter 6

TABLE 6.1: Office supply purchasing sequence

TABLE 6.2: Class diagram visibility symbols

TABLE 6.3: Class diagram multiplicity indicators

TABLE 6.4: Activity diagram symbols

Chapter 7

TABLE 7.1: Weapons training signup sheet

TABLE 7.2: Ordered signup sheet

TABLE 7.3: Signup sheet with times

TABLE 7.4: Signup sheet with explicitly listed weapons

TABLE 7.5: Camp games schedule

TABLE 7.6: Counselors' favorite books

Chapter 15

TABLE 15.1: Attributes for projects Ruction and Fracas

TABLE 15.2: Normalized metrics for projects Ruction and Fracas

TABLE 15.3: CAV ratings

TABLE 15.4: Sample CAV ratings

TABLE 15.5: Number of programmers

TABLE 15.6: Lines of code and bugs

TABLE 15.7: Project Hydra progress

Chapter 19

TABLE 19.1: Release schedule for a three-month project

TABLE 19.2: FDD milestones

Appendix

TABLE A.1: Properties shared by ClassyDraw classes

TABLE A.2: Complexity adjustment factors for WordPad

TABLE A.3: Complexity adjustment factors for Microsoft Word

TABLE A.4: Normalized LOC and bugs

TABLE A.5: Percentage of LOC and time for previous projects

TABLE A.6: Percentage of LOC and time for project Hydra

List of Illustrations

Chapter 1

FIGURE 1.1: The circles represent possible mistakes at different stages of d...

Chapter 4

FIGURE 4.1: Each task's card should hold its name, duration, and predecessor...

FIGURE 4.2: Initially only the Start task is in the Ready pile.

FIGURE 4.3: After one round, the Start task is positioned and tasks A, F, an...

FIGURE 4.4: After two rounds, the Start task and tasks A, F, and H are posit...

FIGURE 4.5: After three rounds, the Start task and tasks A, F, H, and B are ...

FIGURE 4.6: After four rounds, only the Finish task is still in the Pending ...

FIGURE 4.7: This PERT chart shows the paths of execution of the project's ta...

FIGURE 4.8: The total time for each task is its expected time plus the large...

FIGURE 4.9: Task I's largest time predecessor is task B, so task I has a tot...

FIGURE 4.10: The complete zombie apocalypse bunker project has a total time ...

FIGURE 4.11: A Gantt chart shows task durations, start times, end times, and...

Chapter 5

FIGURE 5.1: The Mr. Bones application is a hangman word game for smartphones...

Chapter 6

FIGURE 6.1: An application can directly hold its own data.

FIGURE 6.2: In a two-tier architecture, the client is separate from the serv...

FIGURE 6.3: A three-tier architecture separates clients and servers with a m...

FIGURE 6.4: In a component-based architecture, components help decouple piec...

FIGURE 6.5: A data flow diagram shows how data such as a customer order flow...

FIGURE 6.6: Complicated data flows may take different paths depending on cir...

FIGURE 6.7: A class diagram describes the properties and methods of classes....

FIGURE 6.8: The relationship in this class diagram indicates that 1 student ...

FIGURE 6.9: A class diagram indicates inheritance with a hollow arrowhead.

FIGURE 6.10: An activity diagram is a bit like a flowchart showing how work ...

FIGURE 6.11: A use case diagram shows actors and the tasks they perform (pos...

FIGURE 6.12: This state machine diagram represents reading a floating-point ...

FIGURE 6.13: A sequence diagram shows the timing of messages between collabo...

FIGURE 6.14: A communication diagram emphasizes the objects participating in...

Chapter 7

FIGURE 7.1: People are naturally good at building inheritance hierarchies.

FIGURE 7.2: This hierarchy focuses on behavioral differences between classes...

FIGURE 7.3: Generalization creates the

Drawable

parent class.

FIGURE 7.6: This design is in first normal form (1NF). Lines connect related...

FIGURE 7.7: Moving the data that doesn't depend on

all

the table's key field...

FIGURE 7.8: Moving non-key fields that depend on other non-key fields into a...

Chapter 8

FIGURE 8.1: MFA is a conversation between a user and an application.

Chapter 9

FIGURE 9.1: Word's ribbon assumes the user is an eternal beginner.

FIGURE 9.2: Word uses verbose tooltips because the ribbon already includes d...

FIGURE 9.3: Visual Studio assumes the user is at least intermediate and poss...

Chapter 11

FIGURE 11.1: A decision tree represents combinations of decisions.

FIGURE 11.2: An algorithm can use backtracking to move back up a tree to exp...

FIGURE 11.3: The recursive Fibonacci calculation repeats the same calls many...

FIGURE 11.4: Dynamic programming removes many nodes from the call tree.

FIGURE 11.5: You can use a state diagram to model a login process.

FIGURE 11.6: Drawing a Mandelbrot set is embarrassingly parallel.

Chapter 13

FIGURE 13.1: When you're in the “getting close to zero” part of the graph, y...

Chapter 14

FIGURE 14.1: This schedule takes 11 workdays to migrate all 20 users to Adve...

Chapter 15

FIGURE 15.1: An Ishikawa (or fishbone) diagram shows causes leading to effec...

FIGURE 15.2: The exact format of an Ishikawa diagram doesn't matter as long ...

FIGURE 15.3: This graph shows the relationship between hours of code review ...

Chapter 17

FIGURE 17.1: In the waterfall model, each step follows the one before in a s...

FIGURE 17.2: In the waterfall with feedback model, you can go back to the pr...

FIGURE 17.3: In the sashimi model, development phases overlap.

FIGURE 17.4: In the incremental waterfall model, a series of waterfall casca...

FIGURE 17.5: This incremental waterfall project uses a series of sashimi wat...

FIGURE 17.6: In V-model, each of the tasks on the left corresponds to a task...

FIGURE 17.7: In the software development life cycle, project phases feed int...

Chapter 18

FIGURE 18.1: Iterative models use a series of development efforts to increme...

FIGURE 18.2: Different development approaches add features and increase fide...

FIGURE 18.3: The spiral process uses four phases.

FIGURE 18.4: In this project, the major risks were requirements, design, and...

FIGURE 18.5: In the Unified Process, construction takes more time and effort...

FIGURE 18.6: In the Unified Process, the amounts of different kinds of work ...

Chapter 19

FIGURE 19.1: In James Martin RAD, the user design and construction phases it...

FIGURE 19.2: In test-driven development, you write a test for each function ...

FIGURE 19.3: A project burndown chart shows the amount of work remaining for...

FIGURE 19.5: In FDD, the last two phases repeat for each feature iteration. ...

FIGURE 19.6: The DSDM life cycle includes four stages: study, functional mod...

FIGURE 19.7: The kanban board lets everyone see the status of the project's ...

Appendix

FIGURE A.1: Microsoft Word has revision-tracking tools that let you see who ...

FIGURE A.2: Google Docs also has revision-tracking tools that let you see wh...

FIGURE A.3: This PERT chart includes tasks needed to build a small part of a...

FIGURE A.4: The critical path for this piece of the zombie apocalypse game i...

FIGURE A.5: This Gantt chart shows this piece of the zombie apocalypse game ...

FIGURE A.6: GanttProject uses task data to generate a Gantt chart.

FIGURE A.7: Enter predecessor information on the Predecessors tab.

FIGURE A.8: This state machine diagram shows how a program could read a floa...

FIGURE A.9: This inheritance hierarchy represents shape classes in the Class...

FIGURE A.10: This inheritance hierarchy represents business classes.

FIGURE A.11: A hierarchy that combines the

Salaried

,

Manager

, and

VicePresid

...

FIGURE A.13: This Ishikawa diagram shows possible causes for New Hampshire n...

FIGURE A.16: This graph shows percent of LOC versus percent of elapsed time ...

FIGURE A.17: Project Hydra is generating code slowly compared to the previou...

FIGURE A.18: This flowchart shows the states through which most bugs pass.

FIGURE A.19: Users play a large role as requirements are created and refined...

FIGURE A.20: This diagram shows how waterfall tasks match up with Unified Pr...

Guide

Cover

Table of Contents

Title Page

Copyright

About the Author

Acknowledgments

Introduction

Begin Reading

Appendix: Solutions to Exercises

Glossary

Index

End User License Agreement

Pages

v

xxvii

xxviii

xxix

xxx

xxxi

xxxii

xxxiii

xxxiv

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

425

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

vi

vii

ix

686

BEGINNINGSoftware Engineering

 

Second Edition

 

 

Rod Stephens

 

 

 

 

 

PART ISoftware Engineering Step-by-Step

CHAPTER 1:

Software Engineering from 20,000 Feet

CHAPTER 2:

Before the Beginning

CHAPTER 3:

The Team

CHAPTER 4:

Project Management

CHAPTER 5:

Requirements Gathering

CHAPTER 6:

High-Level Design

CHAPTER 7:

Low-Level Design

CHAPTER 8:

Security Design

CHAPTER 9:

User Experience Design

CHAPTER 10:

Programming

CHAPTER 11:

Algorithms

CHAPTER 12:

Programming Languages

CHAPTER 13:

Testing

CHAPTER 14:

Deployment

CHAPTER 15:

Metrics

CHAPTER 16:

Maintenance

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 first 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 waterfall and V-model approaches, use detailed requirement specifications to exactly define the desired 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 other techniques, such as cowboy coding and extreme programming, sound more like action-adventure films than software development techniques. (I'll say more about these in Part II, “Process Models.”)

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 finished 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 and that's not true.

The chapters in the first 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 first 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.

1Software Engineering from 20,000 Feet

If you fail to plan, you are planning to fail.

—Benjamin Franklin

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 that are specific to software engineering. Later chapters in this book provide a lot more detail about these tasks.

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 first steps in a software project is figuring out the requirements. You need to find out what the customers want and what the customers need. Depending on how well-defined the user's needs are, this chore 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 finished 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 (usually) 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.

NOTE I refer to requirements a lot in this book. In general, when I say requirements, I mean the officially sanctioned requirements as recorded in the requirements documents and later carved in marble on the project's memorial. Anything else (such as customer suggestions, developer complaints, and management wishful thinking) are not part of the requirements until they are approved by the powers that be.

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 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 an iPhone, do they?”

In contrast, a company wouldn't ask an architectural firm 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 what interfaces with other systems to use (such as external purchasing systems or a payroll system hosted in the cloud).

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, Jockey, and Wager classes)

User interfaces (to enter Ostrich and Jockey data, enter race results, calculate odds, produce result reports, and create new races)

External interfaces (to send information and spam to participants and fans via email, text message, voicemail, pager, carrier pigeon, and anything else we can think of)

You should make sure 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 they don't need high-level designs.

Let's defer this argument until Chapter 6, “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 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 it 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 using proper first, second, and third normal forms. (You can argue about whether it needs higher levels of normalization.)

At this point you will also discover interactions between the different pieces of the project that may require changes here and there. For example, while working on the ostrich project's external interfaces, you may decide to add a new table to hold email, text messaging, and other information for fans. Or you may find that the printing module will be easier if you add a new stored procedure to the database design.

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 refining them into low-level designs, but development is the part that many programmers enjoy the most, so that's often where they think the “real” work begins.) The programmers continue refining 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 fixed 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.

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 fix 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 fixed it, right?

Unfortunately, fixing a bug often creates a new bug. Sometimes the bug fix is incorrect. Other times it breaks another piece of code that depended on the original buggy behavior. In that case, 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 fine, but you may get a nasty surprise the next time you take a shower.)

Anytime you change the code, whether by adding new code or fixing 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 find anything wrong, that doesn't mean there are no bugs; it just means 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 never detected, is it still a bug?)

The best you can do is test and fix 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.

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.)

If you detect the error during the requirements gathering phase, you need to fix 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?