Code Complete (I)

Here’s what I wrote about the book elsewhere not long ago: “I recently started reading the book Code Complete by Steve McConnell. I’ve only read the first 100 pages so far (Kindle estimate of time remaining: 27 hours… – then again, it is ‎960 pages..) but I can already confidently say at this point that if you’re a software developer or programmer or similar, or plan to be, then you’ll want to read this book – it’s awesome. (…and even just reading the first 50 pages of this book would probably make you a better programmer, even if you read no more than that…)”

I enjoy reading it and I learn something new on many of the pages here, or perhaps get a new angle on a topic I have familiarity with – I’ve already come across multiple important insights that I’d really wish I’d have known about when involved in projects in the past, and I’m trying to share some of these learnings also with my coworkers. It’s just a good book. The fact that it’s already almost 20 years old of course means that there isn’t a great deal of coverage about, say, the topics touched upon in the lecture below this post, but a lot of this stuff is about fundamentals, concepts, and tradeoffs, which means that this aspect actually matters probably significantly less than you’d think. Not all suggestions made are the sort of suggestions I feel tempted to immediately follow/implement in my daily work, but most of them at the very least makes you think a bit more about the choices you might be making, often subconsciously – and as the quotes below should incidentally serve to illustrate it’s not just a book about coding.

I have added some sample quotes from the chapters I’ve read so far below.

“Construction is a large part of software development. Depending on the size of the project, construction typically takes 30 to 80 percent of the total time spent on a project. […] Construction is the central activity in software development. Requirements and architecture are done before construction so that you can do construction effectively. System testing (in the strict sense of independent testing) is done after construction to verify that construction has been done correctly. […] With a focus on construction, the individual programmer’s productivity can improve enormously. A classic study by Sackman, Erikson, and Grant showed that the productivity of individual programmers varied by a factor of 10 to 20 during construction (1968). Since their study, their results have been confirmed by numerous other studies (Curtis 1981, Mills 1983, Curtis et al. 1986, Card 1987, Valett and McGarry 1989, DeMarco and Lister 1999, Boehm et al. 2000). This book helps all programmers learn techniques that are already used by the best programmers.”

“As much as 90 percent of the development effort on a typical software system comes after its initial release, with two-thirds being typical (Pigoski, 1997).”
“It generally doesn’t make sense to code things you can buy ready-made.”
“Choosing the right tool for each problem is one key to being an effective programmer.”
“Good architecture makes construction easy. Bad architecture makes construction almost impossible.”
“Good software architecture is largely machine- and language-independent.”
“Part of a programmer’s job is to educate bosses and coworkers about the software-development process, including the importance of adequate preparation before programming begins.”

“Both building construction and software construction benefit from appropriate levels of planning. If you build software in the wrong order, it’s hard to code, hard to test, and hard to debug. It can take longer to complete, or the project can fall apart because everyone’s work is too complex and therefore too confusing when it’s all combined. Careful planning doesn’t necessarily mean exhaustive planning or over-planning. You can plan out the structural supports and decide later whether to put in hardwood floors or carpeting, what color to paint the walls, what roofing material to use, and so on. A well-planned project improves your ability to change your mind later about details. The more experience you have with the kind of software you’re building, the more details you can take for granted. You just want to be sure that you plan enough so that lack of planning doesn’t create major problems later.”

“The overarching goal of preparation is risk reduction: a good project planner clears major risks out of the way as early as possible so that the bulk of the project can proceed as smoothly as possible. By far the most common project risks in software development are poor requirements and poor project planning […] You might think that all professional programmers know about the importance of preparation and check that the prerequisites have been satisfied before jumping into construction. Unfortunately, that isn’t so. A common cause of incomplete preparation is that the developers who are assigned to work on the upstream activities do not have the expertise to carry out their assignments. The skills needed to plan a project, create a compelling business case, develop comprehensive and accurate requirements, and create high-quality architectures are far from trivial, but most developers have not received training in how to perform these activities. […] Some programmers do know how to perform upstream activities, but they don’t prepare because they can’t resist the urge to begin coding as soon as possible. […] It takes only a few large programs to learn that you can avoid a lot of stress by planning ahead. Let your own experience be your guide. A final reason that programmers don’t prepare is that managers are notoriously unsympathetic to programmers who spend time on construction prerequisites.”

“One of the key ideas in effective programming is that preparation is important. It makes sense that before you start working on a big project, you should plan the project. Big projects require more planning; small projects require less. […] Researchers at Hewlett-Packard, IBM, Hughes Aircraft, TRW, and other organizations have found that purging an error by the beginning of construction allows rework to be done 10 to 100 times less expensively than when it’s done in the last part of the process, during system test or after release […]. In general, the principle is to find an error as close as possible to the time at which it was introduced. The longer the defect stays in the software food chain, the more damage it causes further down the chain. Since requirements are done first, requirements defects have the potential to be in the system longer and to be more expensive. Defects inserted into the software upstream also tend to have broader effects than those inserted further downstream. That also makes early defects more expensive. […] for example, an architecture defect that costs $1000 to fix when the architecture is being created can cost $15,000 to fix during system test. […] The cost to fix a defect rises dramatically as the time from when it’s introduced to when it’s detected increases. This remains true whether the project is highly sequential (doing 100 percent of requirements and design up front) or highly iterative (doing 5 percent of requirements and design up front). […] Dozens of companies have found that simply focusing on correcting defects earlier rather than later in a project can cut development costs and schedules by factors of two or more […]. This is a healthy incentive to find and fix your problems as early as you can.”

“Accommodating changes is one of the most challenging aspects of good program design. The goal is to isolate unstable areas so that the effect of a change will be limited to one routine, class, or package. […] Business rules tend to be the source of frequent software changes. […] Business systems projects tend to benefit from highly iterative approaches, in which planning, requirements, and architecture are interleaved with construction, system testing, and quality-assurance activities. […] Iterative approaches tend to reduce the impact of inadequate upstream work, but they don’t eliminate it. […] Iterative approaches are usually a better option for many reasons, but an iterative approach that ignores prerequisites can end up costing significantly more than a sequential project that pays close attention to prerequisites. […] One common rule of thumb is to plan to specify about 80 percent of the requirements up front, allocate time for additional requirements to be specified later, and then practice systematic change control to accept only the most valuable new requirements as the project progresses. Another alternative is to specify only the most important 20 percent of the requirements up front and plan to develop the rest of the software in small increments, specifying additional requirements and designs as you go. […] One key to successful construction is understanding the degree to which prerequisites have been completed and adjusting your approach accordingly […] The extent to which prerequisites need to be satisfied up front will vary with the project type […], project formality, technical environment, staff capabilities, and project business goals. […] Software being what it is, iterative approaches are useful much more often than sequential approaches are. […] Some projects do too much up front; they doggedly adhere to requirements and plans that have been invalidated by down-stream discoveries, and that can also impede progress during construction.”

“[D]ata from numerous organizations indicates that on large projects an error in requirements detected during the architecture stage is typically 3 times as expensive to correct as it would be if it were detected during the requirements stage. If detected during coding, it’s 5–10 times as expensive; during system test, 10 times; and post-release, a whopping 10–100 times as expensive as it would be if it were detected during requirements development. On smaller projects with lower administrative costs, the multiplier post-release is closer to 5–10 than 100 (Boehm and Turner 2004). […] Specifying requirements adequately is a key to project success, perhaps even more important than effective construction techniques. […] Stable requirements are the holy grail of software development. With stable requirements, a project can proceed from architecture to design to coding to testing in a way that’s orderly, predictable, and calm. […] It’s fine to hope that once your customer has accepted a requirements document, no changes will be needed. On a typical project, however, the customer can’t reliably describe what is needed before the code is written. The problem isn’t that the customers are a lower life form. Just as the more you work with the project, the better you understand it, the more they work with it, the better they understand it. The development process helps customers better understand their own needs, and this is a major source of requirements changes […]. A plan to follow the requirements rigidly is actually a plan not to respond to your customer. How much change is typical? Studies at IBM and other companies have found that the average project experiences about a 25 percent change in requirements during development […], which accounts for 70 to 85 percent of the rework on a typical project […] Make sure everyone knows the cost of requirements changes. […] say, “Gee, that sounds like a great idea. Since it’s not in the requirements document, I’ll work up a revised schedule and cost estimate so that you can decide whether you want to do it now or later.” The words “schedule” and “cost” are more sobering than coffee and a cold shower […] Set up a change-control procedure. […] Having a built-in procedure for controlling changes makes everyone happy. You’re happy because you know that you’ll have to work with changes only at specific times. Your customers are happy because they know that you have a plan for handling their input.””Use development approaches that accommodate changes. Some development approaches maximize your ability to respond to changing requirements. An evolutionary prototyping approach helps you explore a system’s requirements before you send your forces in to build it. Evolutionary delivery is an approach that delivers the system in stages. You can build a little, get a little feedback from your users, adjust your design a little, make a few changes, and build a little more. The key is using short development cycles so that you can respond to your users quickly. […] Keep your eye on the business case for the project. Many requirements issues disappear before your eyes when you refer back to the business reason for doing the project. Requirements that seemed like good ideas when considered as “features” can seem like terrible ideas when you evaluate the “incremental business value.””

“The amount of time to spend on problem definition, requirements, and software architecture varies according to the needs of your project. Generally, a well-run project devotes about 10 to 20 percent of its effort and about 20 to 30 percent of its schedule to requirements, architecture, and up-front planning […]. These figures don’t include time for detailed design—that’s part of construction. […] If requirements are unstable and you’re working on a small, informal project, you’ll probably need to resolve requirements issues yourself. Allow time for defining the requirements well enough that their volatility will have a minimal impact on construction. If the requirements are unstable on any project — formal or informal — treat requirements work as its own project. Estimate the time for the rest of the project after you’ve finished the requirements. This is a sensible approach since no one can reasonably expect you to estimate your schedule before you know what you’re building. It’s as if you were a contractor called to work on a house. Your customer says, “What will it cost to do the work?” You reasonably ask, “What do you want me to do?” Your customer says, “I can’t tell you, but how much will it cost?” You reasonably thank the customer for wasting your time and go home.”

“When software-project surveys report causes of project failure, they rarely identify technical reasons as the primary causes of project failure. Projects fail most often because of poor requirements, poor planning, or poor management. But when projects do fail for reasons that are primarily technical, the reason is often uncontrolled complexity. The software is allowed to grow so complex that no one really knows what it does. When a project reaches the point at which no one completely understands the impact that code changes in one area will have on other areas, progress grinds to a halt. […] Managing complexity is the most important technical topic in software development. In my view, it’s so important that Software’s Primary Technical Imperative has to be managing complexity. […] The goal is to minimize the amount of a program you have to think about at any one time. […] The goal of all software-design techniques is to break a complicated problem into simple pieces. The more independent the subsystems are, the more you make it safe to focus on one bit of complexity at a time. Carefully defined objects separate concerns so that you can focus on one thing at a time. Packages provide the same benefit at a higher level of aggregation. Keeping routines short helps reduce your mental workload. Writing programs in terms of the problem domain, rather than in terms of low-level implementation details, and working at the highest level of abstraction reduce the load on your brain. The bottom line is that programmers who compensate for inherent human limitations write code that’s easier for themselves and others to understand and that has fewer errors. […] Once you understand that all other technical goals in software are secondary to managing complexity, many design considerations become straightforward.”

November 23, 2021 - Posted by | Books, Computer science

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: