II Principles
|
|
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—
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—
|
|
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—
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
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?
[e]xperts in their fields tend to be motivated by criticism.
Show your code to other developers and ask for feedback.
Expect, embrace, and evaluate criticism. If necessary, fix things.
Reflect on what happened.
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.
Egoless programming requires a significant change in mind set. It must start with yourself and your desire to become an expert developer.
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—
In short, make a point of finding contemporary “water coolers” and “printers.”
Or, if needed, create such places—
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—
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.—
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.
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 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—
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.
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.
Reading
Laurie Williams, Robert Kesler. Pair Programming Illuminated.
Addison-Wesley. 2002.—
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—
Since these various forms of inspection differ so much—
|
|
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.
|
|
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.
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).
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?
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?
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 head reader, who assumes the dual role of reader and moderator of the review effort;
an assistant reader, who may exclusively focus on reading the software and posing questions about it; and
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.
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.
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.
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.
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—
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—
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.—
Glen W. Russel. Experience with inspection in ultralarge-scale development. In
IEEE Software 8(1). 1991.—
Edward F. Weller. Lessons from three years of inspection data. In IEEE
Software. 10(9).—
NASA Office of Safety and Mission Assurance. Software Formal Inspections
Guidebook. Technical Report OFFICE NASA-GB-A302.—