8.14.0.4

II Principles🔗

    3 The Nature of Software Development

    4 Egoless Programming

    5 Pair Programming

    6 Software Inspections

 

 

What is software to its developer?

This question is at the heart of the conversation we must have about the software development process and its social context. Even if developers claim they are coding “for just money,” they still identify with their software to some degree. On one hand, this identification is important. A developer who identifies with his work is going to strive for high quality. On the other hand, identification with the product is an obstacle to a positive feedback cycle. A developer who identifies with his software may feel hurt when this product is subjected to intense criticism.

Modern software shops recognize this dilemma and put an impersonal intermediary between the developers and the reviewers, the github comment section and the like. It removes the necessity that the two people look at each other—look each other in the eye—and this makes the process less personal, less social, and less responsible. By contrast, this chapter of the book argues that, while this reduction in direct communication may result in eliminating some amount of conflict from developer teams, it does so by imposing a significant cost on the people who work with the software now and even more so on those who work on it in the future.

Instead software developers must learn to remove their ego from the process and turn negative feedback into positive actions. While nobody is born ready for negative feedback, learning from it is possible with explicit practice. Ideally, a developer can become so comfortable with criticism that it is solicited explicitly. Internalizing this attitude is ideal for a socially responsible software development process.

The following sections spell out how a developer might acquire a positive attitude toward negative feedback. The first step is to remove one’s ego from the product. The second is to embrace working in pairs. The final one is to solicit team-wide criticism via probing inspections.

3 The Nature of Software Development🔗

Software developers are artists, creators, designers, and inventors. The software systems they create are like books, compositions, paintings, poems, or sculptures. Like other creative people, developers labor and struggle to produce these artifacts.

When developers see other people successfully and easily use their software, they are, and should be, happy about their achievement. One developer may point out to her father which piece of an app’s interface is hers; and another may explain to his mother how his machine-learning software discovers suspicious patterns in a patient diagnosis file.

Similarly, developers are always happy when another developer remarks on the clarity of their code, its efficiency, its low memory footprint, and so on. If the other developer is a highly respected and highly experienced member of the team, the praise is particularly meaningful.

Like all creators, software developers inevitably identify themselves with their product and love to receive such praise for it or enjoy watching others use it. In other words, they invest a part of their ego in their creation. This investment—this identification—is neither surprising nor bad. Whenever people are deeply invested in a task, they are motivated to give their best, to make a respected product.

 

 

The problem is that all creative people must stomach criticism, too. Authors hate to read bad book reviews; composers don’t want the audience to leave the premiere early; painters prefer good-willed, “nice” people at their vernissages; and poets might be reluctant to read their works in public. Why? All creators fear negative criticism, because of their investment in the product, because of their identification with it. Deep down criticism of a creative product is considered criticism of the creator’s ego.

Developers are no different in this respect. End-users may criticize their software for being clunky, slow, or buggy. Worse, their colleagues may criticize them for style-guide violations, lack of elegance, a badly chosen data representation, and so on. While the former may hurt a bit, the latter stings really hard because these colleagues are professionals whose opinions count a lot, even if it is just within the developer’s team.

Poets, painters, and other artists can hide. Society will simply ignore a composition if newspapers pan it. Readers don’t buy a novel that consistently receives bad reviews. In short, the economic harm of such bad artistic creations is relatively small. None of this is true for software developers.

 

 

Bad software can inflict immediate harm on end-users. It may shut down an electricity grid, leaving millions stranded. It may cause financial harm. It may down an airplane. You name it, software can do it. The worst aspect is that software libraries and frameworks are migrated from one code base to another, and the original creator may never find out where code ends up.

Badly written software also affects current and future colleagues. One colleague may have left yesterday for a better-paying job at a competing company, and another one is assigned to his portion of the code base—and it turns out to be incomprehensible. The newly assigned colleague will have to work extra hours to catch up with the rest of the team—hours that, as mentioned in the preceding section, come at the expense of spouses, children etc. Similarly, imagine an intern who has just signed up for a six-months stint. She is pointed to a code base of some 100 file-modules and is told to resolve some error tickets. The code repository lacks any documentation of how to navigate the modules, which one serves which purpose, or how they are related. All design decisions are buried in commit messages, and there are thousands of small commits. How is she going to live up to the expectations of her mentor?

Think of the “Year 2000” problem already mentioned in The Death of Software, The Life of Software. Numerous programmers had to dig through huge volumes of decades-old software in the late 1990s to find all instances of two-digit date declarations and all their uses. They had to repair those systematically; they had to adjust how this repaired code connected to old databases; and they had to make sure that the code’s functionality remained the same. And sadly, there were few people left who actually knew the programming languages of the 1960s, which they had to teach others all while working on revisions.

In contrast to most artistic creators, though, developers are consistently paid a significant salary almost immediately after graduation. Furthermore, their software often has a potentially large value. So unlike artists, software developers “owe” their end-users and their colleagues. In particular, they owe them an attitude that welcomes criticism, welcomes negative feedback and turns those into positive changes to their products. Doing so means letting go of some ego.

4 Egoless Programming🔗

Shellenbarger at WSJ

In 2018, the Wall Street Journal’s Sue Shellenbarger wroteThe Rare Workers Who Thrive on Negative Feedback

Many people hate getting negative feedback and avoid dishing it out too, fearing it will spark anger, dejection or even tears.

But some people actually want and even seek out criticism at work. Who are these people?

in a column on workplace and family affairs. Further along she reveals that

[e]xperts in their fields tend to be motivated by criticism.

They solicit criticism because they have come to understand it as a way to improve themselves.

Decades before, in the 1970s, Gerald Weinberg already noted how programmers benefited tremendously from honest and frank feedback—if they could let go of the ego in their code. He coined the slogan egoless programming. The idea is easily expressed with three bullets:
  • Show your code to other developers and ask for feedback.

  • Expect, embrace, and evaluate criticism. If necessary, fix things.

  • Reflect on what happened.

Rinse, repeat, and never stop.

In essence, both of these authors just focus our mind on the essence of learning outside of school. Without sharing our work, without exposing ourselves to others, we cannot hope to discover problems with our thinking. This is especially true when this thinking turns into a message for current and future colleagues.

Implementing egoless programming is challenging:

Egoless programming requires a significant change in mind set. It must start with yourself and your desire to become an expert developer.

One consequence is that it can only be accomplished in a bottom-up manner, not via commands from managers, which might merely antagonize the team. Setting an example works well, and encouraging others to emulate the example helps spread the idea.

So, first you invest energy into programming but at the same time separate yourself from the resulting code. Then you need to find like-minded others who are willing to listen and reciprocate. In some teams, doing so might be straightforward. Your colleagues may already practice egoless programming and the critiquing techniques described here. In others, you may have to bring up the idea with your team, because nobody has thought of just doing it. You may find open minds, and everything will go well.

If nothing works, there are some old standbys of the olden days: “water coolers” and “vending machines.” Now these words are just metaphors for “a place where developers meet” during a break, to chat, to exchange gossip, and so on. When programming meant exploring the limits of computers, operating systems, and languages, people congregated around card readers—which read their programs—and printers—which produced the program’s outputs. There, while they waited, they discussed their programs and exchanged hints on basic programming problems.

In short, make a point of finding contemporary “water coolers” and “printers.” Or, if needed, create such places—real ones, not virtual ones. Then use these gatherings to learn from experienced developers, to show people what you’re working on and ask for criticism.

Let’s say you have found a partner and a review uncovers flaws. Your reaction is critical. Clarify to people that discovering flaws is good for you and good for the whole team. You can assess the flaw, evaluate your options, and improve your code. Doing so will help others, and your positive attitude about finding flaws in time may infect others.

Also take time to reflect and draw general conclusions for such mistakes. Sometimes it is possible to change habits based on a single example. Other times it may take several conversations to figure out the patterns of one’s problems. In all cases, you will improve your skills and your product—something that will make you happy.

Of course, you will also need to balance criticism with the ingrained perception of others that criticism reflects badly on you and your skills. It will take time to convince those skeptics, but if they notice improvements in your skill set, they will see how it improves at a faster rate than theirs. Then the time has come to suggest that they too can benefit from egoless programming, negative feedback, and turning it into positive energy.

Reading

Gerald M. Weinberg. The Psychology of Programming. Van Nostrand Reinhold Company. 1971.—The entire book is an excellent introduction to the topic, but if you don’t have time for the whole book, focus on . It directly addresses the idea of programming in a group, the principle of egoless programming, and the importance of “water cooler” conversations.

5 Pair Programming🔗

What happens when software developers program?

Obviously they write code. Before they can write code, they need to understand the purpose of their new code; the context in which it exists and how it interacts with this context; its minimal performance characteristics; and much more. “Understanding” means thinking, as in, thinking through someone’s requests and about existing code. It also means thinking while coding and reflecting on the code’s context.

Coding doesn’t always start from a blank page though. It is equally common that developers must modify existing code. They must read and comprehend code. They have to reconstruct the design rationale from comments and commit messages, which means understanding the thinking of their predecessors. When they finally edit the code, they must not break the existing functionality. They have to formulate new comments and new commit messages. And, if they wish to help their successors, they should leave behind documents about what they found out from reading the code. All of this just means more thinking.

Yet, coding isn’t just thinking either. It requires a bunch of mechanical tasks, like typing on a keyboard; selecting one of the identifiers when a completion menu shows up; searching for descriptions of classes, functions, and methods; managing code repositories; running tests; and meeting with people to discuss one thing or another. And this means that the developers’ thinking about code gets constantly interrupted.

We all know that thinking is hard and interrupted thinking is harder. Contrary to appearances, IDEs (interactive development environments) do not help (much) Soon machine learning AI will suggest completions of code snippets. Buyer beware. with thinking, though name completion, on-line parsing, and type checking are helpful in many ways. IDEs don’t help with thinking because despite all the progress of artificial intelligence (AI), software doesn’t really think. The only way to get immediate feedback on thoughts is to work with another person, which brings us to pair programming.

Ideally, pair programming works like this:
  • two people share one computer, one keyboard;

  • one of them acts as designated driver, the other as co-pilot;

  • the driver proposes ideas and creates code;

  • the co-pilot questions the code and requests explanations; and

  • after completing a unit of work, the two switch roles.

In a team setting it is also common that every member pairs up with everyone else on the team over the course of a project. It implies that the team members get to know each other, their thinking, and their coding habits.

In some settings, sharing a computer may not work. In some companies, the boundaries of coding are well-defined, including the commit to a version control system. In others, developers pick them as they see fit. Regardless, keeping the roles in mind is the point.

The immediate purpose of a co-pilot is obvious. It is about checking the spoken-out thinking of the driver to provide immediate and direct feedback. But, the co-pilot is also a representative of the rest of the team. In this light, it’s the co-pilot’s job to think “if I don’t understand it, I doubt my colleagues will understand it.” And if those colleagues don’t understand it, they cannot fix code without major effort when they find a bug and they cannot easily add features if needed.

By extension, the co-pilot also represents those colleagues that aren’t a part of the team yet. Those colleagues may still be in high school. They may not be born yet. In short, the co-pilot makes sure that the driver acts in a socially responsible manner, toward team members, new hires, and people who will maintain the code in five, ten, or twenty years from now.

 

 

Pair programming has several benefits for developers, their teams, and their company. Most importantly, one person’s thinking is immediately checked by another person. Thinking happens in our mind, and our mind doesn’t cross-check ideas easily. Hence, when we think just by ourselves for a long time, we may build up a complex construction of ideas on top of some misconception—bluntly Look up the term “rubber duck debugging.” put, we may get “off the rails.” Forcing ourselves to explain an idea to someone else may reveal such misconceptions directly, or the partner may discover them. Either way early discovery of thinking in the wrong direction is beneficial.

Joint work also has psychological benefits. While some complex mathematical problems may require long, hard solo work, software development rarely calls for this kind of deep thinking, this search for the creative spark. Yes, it requires thinking but some of the thinking is just tedious and error-prone for various reasons; it is not creative at the level of individual lines of code. Sharing makes it somewhat easier to perform such work.

Shared work also means shared knowledge. If a team member has to stay home one day due to sickness or a family emergency, past pair programming comes in handy. The other team members have partnered with the absent one and have thus acquired some understand of his code.

This benefit of shared knowledge of the entire project is even more important when a team member quits. From the company’s perspective, this benefit might be the most important one, directly affecting the bottom line of this cost center. All the money “sunk” into the member who’s leaving doesn’t translate into lost knowledge that someone else has to figure out. It is distributed over the entire team. A new hire can be assigned to the team, and she can pair-program with others to acquire this shared understanding of the code base.

After reading all these positives, you would think that companies are racing to implement pair programming across the board. Sadly, too many managers completely fail to understand the nature of programming and the benefits of pairing up. The most common objection is that “two people are doing the work of one.” To counter this nonsense takes careful and patient “managing up” with four effective arguments deployed and re-deployed time and again:
  • The software is going to run faster, use less space, and consume less energy. Managers love performance arguments.

  • Shared knowledge about the code base reduces inefficiencies when someone leaves. It turns programmers into replaceable assembly-line workers. Managers like this idea as much as performance arguments.

  • Continuous partnering ensures that the code will be accessible three or five year down the line after the product has become a profit center. The company will be able to add extensions quickly and cheaply. Cost reduction arguments almost always work, too.

  • Pair programming is also likely to get the software right faster than solo work. Since bugs often cost money, bugs mean loss of profit. If the cost motive doesn’t work, the profit idea will.

The key is to learn a manager’s language and to articulate advantages in those terms.

Reading

Laurie Williams, Robert Kesler. Pair Programming Illuminated. Addison-Wesley. 2002.—This short book collects in one place all that you need to know about pair programming: what works, what doesn’t, and how to “sell” it to your team and manager.

6 Software Inspections🔗

When two people stare at, and discuss, the same piece of software for long enough, they will convince each other that “it works.” To fight this form of unintentional collusion, teams must conduct design and code inspections, also known as design reviews and code walks. Colleagues with only peripheral involvement in the creation process inspect the software and critique it.

The idea of software inspection dates back to the 1970s, a time when large software companies began to understand that programming had turned into something akin to an engineering activity. While design reviews had been used in many engineering disciplines, adapting them to the engineering of software took some time. All forms of review meant face-to-face meetings, and many different forms emerged: code browsing, desk checking, peer review, and walk-through.

IBM’s formal code inspections come in the form of a rigorously defined process, based on rigorous investigations. The goal is to make the results of these inspections measurable, with a focus on the rate at which errors are detected. IBM and others who adopted this form of formal code inspection reported rather high error discovery rates, though everyone also admitted that the costs of following a strict protocol were high.

Over the past couple of decades, especially with the emergence of commenting interfaces to code repository software, the review of code has become common. These reviews rely on one set of developers to leave comments for another set of developers for a specific unit of code, often just a pull request. Not all, but many companies fortunately practice such platform-mediated reviews—though sadly, these practices leave behind many of the qualities of in-person inspections and conversations.

Since these various forms of inspection differ so much—and don’t aim for the same outcomes—this book uses the phrases code inspection for the informal in-person version and code review for the on-line version. Keep in mind that “inspection” as used here is not IBM’s formal inspection process, though it takes its inspiration from this work.

 

 

Let’s take a close look at the basic ideas behind in-person inspections and on-line reviews.

Code inspections make reviewers face developers, that is, the latter look at the former and vice versa as they discuss code. Having to face each other during the inspection and conversing in real time has some obvious advantages. When a reviewer expresses a criticism, a presenter can re-articulates the comment to clarify its meaning and a back and forth is likely to eliminate misunderstandings. These real-time clarifications may also become the basis for improvements to the software. A face-to-face conversation is typically friendlier than other forms of exchanges; just think how conversations on modern social networks can deteriorate rather quickly. Furthermore, a conversation naturally generates teaching situations in which reviewers can learn from presenters and vice versa.

Facing someone to express criticism can trigger stress in both parties, however. To reduce this stress, the inspection process needs to be properly managed. Specifically, “properly managed” means developers must know how to conduct inspections both as presenters and as reviewers. They must be prepared and trained. According to several studies, the training’s pay-off seems to be rather large. These studies show that this low-tech technique discovers many problems quickly and as a result saves a good amount of developer time and thus reduce stress.

    

platform-mediated reviews

    

in-person inspection

cost

    

a moderator may be needed

    

preparing the reviewer

efficiency

    

time for analysis & reflection

    

real-time conversations

stress

    

from quasi-anonymous posting

    

from face-to-face criticism

benefit

    

finds some bugs

    

finds bugs & design flaws,

    

    

improves readability, and

    

    

develops human resources

it’s like handing code over to a maintainer who ...

    

... joins in 10 years from now

    

... is an immediate colleague

teaching situations arise ...

    

N/A

    

... naturally

conversations develop the skill ...

    

rarely take place/work

    

... to reason about code,

    

    

which helps with coding

Figure 2: A comparison of the two dominant code inspection modes

By contrast, platform-mediated code reviews eliminate all direct interactions. Depending on the setting, an assigned developer or any developer in the world reads portions of the software and leaves comments. Reading means a reviewer can take time to sit back to analyze and reflect. It can thus produce well-thought and thorough comments. Spatial and temporal distance between the creator of the software and the reviewer simulates the situation of a developer who months or years later is asked to read, comprehend, and modify the code; this particular aspect directly contributes to the goal of social responsibility to “strangers.” By removing the potentially awkward personal encounter during critical sessions, on-line reviews seem to eliminate some stress. Some experience with such platforms suggests, however, that inviting quasi-anonymous reviewers can encourage rather aggressive commenting and can lead to forms of on-line harassment. In short, the cost isn’t as low as it seems in some situations.

Figure 2 provides a concise summary of this comparison. As even a cursory look suggests, there is no clear winner. But, in the spirit of putting the developer into the focus of the software development process, this book focuses on software inspections, especially because it is now the less common form practiced in industry.

 

 

As mentioned, running software inspections requires preparing and training developers for this task. This training must clarify the goals of inspections, the panels, and some mechanics. Not all setups work well; the one described in the remainder of this section has proven its worth over a couple of decades. When the prose speaks of “students,” the industrial reader should think “trainee.”

Goals Inspections have two goals:
  • understanding whether and how the software implements the specified functionality, and

  • understanding whether and how it is designed systematically and organized in way that facilitates reading and comprehending it.

Concisely put, inspections aim to find bugs and design flaws.

The first goal, meeting expectations, is all about finding functionality and performance errors. Usually the reviewers and the developers can easily agree that some code will not behave in the specified manner, and they can also easily settle whether an algorithm performs the desired task in quadratic time (O(n2) where n is the size of the input) when it could easily be linear (O(n), with n again the size of the input).

The second goal, being comprehensible, raises somewhat amorphous questions. Here are some examples:For programming principles and sample inspections, see Project.
  • Is the code organized into functionally coherent and clearly delineated units (modules, classes)? Are those reasonably small?

  • Does each basic building block (function, method) have a clear purpose? A purposeful name? A reasonable size?

  • Are the expressions and statements clear?

Each of these questions has an obvious negative variant, and those are the ones that reviewers will have in mind. Accordingly, the feedback will be about convoluted units of code, over-sized functions, and too-clever-by-half expressions.

Critique and Criticism So, inspections are about delivering critique, that is, constructive yet negative feedback. At some point in your life, you might have been told to deliver all negative feedback in a sandwiched manner: some nice feedback, the bad part, some more nice words. Don’t! During an inspection the bad parts get lost because for any piece of code worth inspecting, you will find a lot of mistakes. Packing every one of these in nice words drowns the important parts of the conversations. Don’t do it.

At the same time running a panel demands a lasor-sharp focus on the habits of egoless programming. The reviewers must keep in mind that the presenter may be stuck in ego-focused programming. It is thus imperative to ask questions about the software not questions in terms of “you, the programmer.” Here are two examples:

good

          

bad

How does this function account for the special case of 0?

          

How do you deal with 0 in this function?

Why does this class come with getters for all fields?

          

Why did you introduce getters for all fields?

Where does the exception get caught?

          

Where do you catch the exception?

Note how most questions make more sense when stated in terms of code rather than its creators.

In sum, panelists can bring out the best in presenters by emphasizing egoless programming as much as presenters can do so by separating their ego from the presented code.

The Panel An inspection confronts a pair of developers with a panel. The pair is jointly responsible for a particular piece of functionality. The panelists are typically members of the team, know the presenters, and have a basic understanding of the presenter’s task.

A panel has three members:
  1. a head reader, who assumes the dual role of reader and moderator of the review effort;

  2. an assistant reader, who may exclusively focus on reading the software and posing questions about it; and

  3. a secretary, who is primarily charged with taking notes about the problems that the panel finds. The secretary notes must suffice to write a report on the problems in a short period of time. They do not record the exchanges between the presenter and the panel.

Experience with this arrangement and IBM’s stringent protocol suggests that more people do not improve the quality of the code walk.

Preparation In general, the panelists should prepare themselves for an inspection session in two ways. First, they should study the problem and any existing specifications for the code to be inspected. Second, they should familiarize themselves with the inspection protocol. This second point is particularly important for panelists with little or no experience. Surprisingly, studies of code inspection have repeatedly found that reading the code in question ahead of an inspection session does not affect the outcome of reviews.

In a course context, the panelists are practicing code inspections after having been told about the principles. So their preparation should focus on how to run panels. By contrast, they do not need to prepare themselves otherwise. Since all students work on the same problem, they are intimately familiar with its nature, its context, and the overall plan. Indeed, because all students have worked out their own solutions by the time a panel meets, the real danger is that panelists try to superimpose their own solution instead of comprehending the presenters’ code. When this happens, instructors must redirect the panel’s inquiry.

In a professional context, the head reader should be an experienced panelist who can implicitly teach the assistant reader. Both may understand the role of panels, but they may not be as familiar with the problem itself. So their preparation might be more about reading up on the problem and the requirements rather than refreshing their knowledge about panels.

Evaluating Panels

Mechanics During a panel presentation, the head and assistant readers need to imagine themselves as developers who take over the presented software. When they do not understand any aspect of the software, they must question it. Some of those questions may merely clarify superficial aspects and receive immediate answers; others will uncover problems.

Although both readers can work with the presenter to figure out something, the head reader must assume the role of moderator. Specifically, the head reader must stop conversations that
  • cause cross-talk or pursue conflicting goals;

  • seem to go nowhere promising;

  • turn into defenses of design decisions both readers consider wrong;

  • discuss solutions.If a solution is obvious, the secretary adds it to the notes and mark it as such. Inspections should be mostly about problems; if presenters request a discussion of solutions, it is up to the head to decide whether doing so is fruitful.

In those cases, the head reader is responsible for getting the inspection back on track.

The third item of this list is particularly important. Defensiveness on either side means a person has investigated “ego” into the process. In such cases, it is the head’s task to remind everyone that questions are about the software product and that critiques are also about the software product—not any person.

Presenters While the presenters created the artifact as a pair, the advantages of pair programming are realized only when both partners can explain any piece of the presented code. To check on this state of knowledge about the code base, only one partner should present at any point in time. The other partner may navigate if it facilitates the discussion and should take additional notes about the problems. These notes will supplement what the pair receives from the secretary. It is also important to let the two partners know that they will need to switch at any moment during the code inspection.

 

 

At this point, it is also obvious that inspections are far more intense than platform-based code reviews and that they produce more interesting feedback. Like with pair programming, management may object to the seemingly high cost of spending a good portion of a team’s time on mutual code inspections. The discussion with management has to address the same elements as the ones for pair programming and must use the same managerial language. Although formal code reviews come with large, measurable, and reproducible advantages concerning error discovery—see readings below—it is not obvious that informal inspections have the same attributes. Even if they do, it is also well-known that management rarely reacts to data gathered elsewhere; the goal has to be to “sneak” mutual code inspections into the process and then to point to successes.

Readings

The following articles are about formal inspections, which differ in some ways from the code inspection described here. They are even more labor-intense than the ones presented here. In turn, they come with a high pay-off in terms of error detection. Reading some of the original literature may help clarify how much in-person inspections can accomplish and how to inject them into existing organizations.

Michael E. Fagan. Advances in software inspection. IEEE Transactions on Software Engineering. 12(7). 1986.—Code inspections are the brain child of Michael Fagan from IBM. He started investigating the idea in the 1970s and reported on his progress in several papers. This one is the most substantial report from this period.

Glen W. Russel. Experience with inspection in ultralarge-scale development. In IEEE Software 8(1). 1991.—This magazine article presents the interesting claims that (1) code inspections may save up to 33 hours of developer time per bug found and (2) code inspections find twice as many bugs as integration testing. Both claims have to be understood in the specific context of this experience (telecom switches, understanding of software development processes). The article also comes with extensive hints on how to introduce formal code inspections into a reluctant organization, ideas that probably apply to all forms of code inspection.

Edward F. Weller. Lessons from three years of inspection data. In IEEE Software. 10(9).—Weller’s article reports on experiences similar to those from Russel, but for a different context. The goal is again to inform readers how to manage their managers.

NASA Office of Safety and Mission Assurance. Software Formal Inspections Guidebook. Technical Report OFFICE NASA-GB-A302.—NASA has a large stake in getting all software correct: unmanned missions cost billions of dollars and for manned missions, lives depend on software as much as the surrounding hardware. This report is one of their first comprehensive guide on code inspections, though the agency and its contractors has had a long history of working in groups on mission software.