In The Clean Coder, expert developer Robert C. Martin explains how to be a programming professional—an honorable, reliable employee who produces quality work (or takes responsibility for the rare times she doesn’t). Professionals’ most important responsibility is to meet their employer’s needs.
In this summary, you’ll learn about six qualities and skills of a professional coder and how to develop them.
The first quality of a professional is a commitment to professional development. The hours you put into your day job rarely contribute to your professional development because at work, you often perform tasks and skills you already know how to do. Therefore, to be a professional, you should spend 20 hours per week of personal time on improving your programming skills and learning new ones.
Use these hours to:
Professional quality #2 is discipline—a collection of rules and standards around the act of coding. Everyone’s discipline is personal and unique, and in this section, Martin shares his rules as inspiration.
Rule #1: Avoid doing damage, or when you can’t, take responsibility. To avoid doing damage:
Rule #2: Don’t code while you’re tired or worried. if you’re not in a mental space in which you can concentrate, you’re going to make mistakes and have to throw out most of your work. If you’re tired or worried:
Rule #3: Don’t wallow in writer’s block. When you’re feeling stuck, try the following techniques to get past the block:
Rule #4: Avoid or minimize time pressure. The best way to deal with pressure is to avoid it. To do this:
No matter how well you employ the above techniques, you’ve inevitably going to encounter pressure. When you are under pressure, you should:
Rule #5: Avoid the “zone” when you’re working. The “zone” is a state of mind that makes you feel focused, productive, and invincible. In reality, you’re not being more productive—the zone is just a meditative state in which parts of your brain shut off. You’ll write more code, but because you’ve got tunnel vision, you’ll probably have to revise what you’ve written so it fits into the larger structures. If you feel the zone approach, arrest its onset by taking a break or pair programming (you can’t get hyper-focused on your code if you have to talk to someone.)
Rule #6: Be careful with music. Some people find music helps them concentrate; for others, it pushes them into the zone or distracts them.
Rule #7: Finish properly. Completely finish all tasks before declaring them “done” and define “done” as “passed all tests” (for more on tests, see Quality #4). Don’t accept partial completion for any reason, including if you’re short on time.
Rule #8: Give and accept help. Programming is so hard it requires more than one brain. When people ask you for help, always give it, and if someone appears to be struggling, offer to pair program with her even if she doesn’t ask. Similarly, always accept help when it’s offered and ask for it when you’re stuck. It’s unprofessional to waste paid time staring at a screen when help is available.
Rule #9: Deal with interruptions efficiently and gracefully. You’ll inevitably be interrupted while coding. Here are some strategies to quickly refocus on your work after an interruption:
The third professional quality is honesty, especially in the face of estimates and deadlines. Whenever you’re programming something for someone, they always want to know when it will be done. Most of the time, you won’t know exactly how long something will take, so you’ll provide an estimate instead of a guaranteed commitment. Estimates aren’t promises, so missing them isn’t unprofessional, but professionals do make their estimates as accurate as possible.
To that end, estimates aren’t single numbers—they’re probability distributions. They factor in the following three numbers:
When giving estimations, you should mention all three numbers.
There’s always the possibility that people won’t like your estimates and will want something done faster. If this happens, you have three options, not all of which are professional:
1. Saying “no.” Saying no has a bad rap, but it’s the most professional thing to do in many situations. If it’s impossible to get something done properly (adhering to discipline) by a certain deadline, and you say anything other than no, you’re essentially lying.
2. Saying “try.” Never agree to try to do something in a time period shorter than your estimation. People often interpret “try” to mean “yes” or “maybe,” and both are lies because if you’re a professional, you’ve already been giving the project your full effort. There’s nothing more you can do that would make things go faster.
3. Saying “yes.” Only say yes when you know you can meet a deadline because a yes is a commitment. If it’s impossible to say yes to something in its current form, ask to change the parameters of the task so that you can say yes. For example, you might ask to reduce the scope of the project so that there’s less to do and you can finish in a shorter amount of time.
The fourth professional quality is communication, which is best done via testing. Tests ensure that a system works, but that’s a happy bonus, not their main purpose. The most important purpose of a test is to communicate, specify, and document how a system is supposed to work and how it actually works.
First, we’ll look at acceptance testing, which is the main type of testing used for communication. Then, we’ll look at how acceptance tests fit into the broader discipline of testing.
Acceptance tests are automatic tests that determine if the system behaves the way the business wants it to—in other words, these tests specify what the system is supposed to do. Therefore, acceptance tests are the most unambiguous way to communicate about system requirements—there’s no possibility of misunderstandings or inaccurate assumptions.
Acceptance tests are co-written by clients and testers or QA (Quality Assurance). The client will usually come up with the happy-path test and QA will write the unhappy-path tests that cover unusual scenarios. Then, it’s the developers’ job to add the tests to the system and build something that passes them.
There is a pyramid of testing that ensures a system works and that it behaves the way a business wants it to. We’ll start at the bottom and move up:
Level #1: Unit tests test “units”—small sections of code. They cover as much of the code as possible (at least 90%) and their purpose is to specify the system. They run continuously and they’re written before the code by developers using test-driven development (TDD).
There are three rules to TDD:
TDD comes with several advantages:
Level #2: Component tests (which include acceptance tests) test individual components and business rules. They cover 50% of the system and run continuously, just like unit tests.
Level #3: Integration tests assess how well different components communicate (only relevant in multi-component systems). They cover 20% of the system, execute periodically, rather than continuously (they’re time-consuming), and are written by the system’s lead designer or system architect.
Level #4: System tests are the highest form of integration tests and they evaluate the whole system. They cover 10% of the system, execute infrequently (they’re time-consuming), and are written by the technical leads or system architects.
Level #5: Manual exploratory tests are tests in which humans use the system to confirm how it works and report bugs. They cover 5% of the system, are executed infrequently (they’re expensive), and aren’t written (people explore the system however they like).
The fifth quality of professionals is that they manage their time well. There are three techniques professionals use for time management:
Technique #1: Attend meetings strategically. Meetings take up a lot of time and are expensive—they require renting a location and paying for the time of the attendees. Therefore, professionals strive to make the best use of meetings by:
1. Avoiding time-wasting meetings. Only go to meetings if you’ll gain information that’s important to your current project, your presence will help someone, the meeting is about something interesting and you have time, and/or the meeting has an agenda, schedule, and goal. If the meeting stops meeting these criteria partway through, ask to get back on topic or leave.
2. Running meetings efficiently. Many of the meetings you attend will be structured based on the Agile canon. (Shortform note: Agile is a collection of software development practices.) Here’s how to run the three types efficiently:
3. Keeping a handle on arguments. If an argument breaks out during a meeting and it lasts more than five to 30 minutes, further discussion isn’t productive. You can settle the argument either by gathering more data (likely no one can win because no one has convincing evidence) or asking meeting participants to voice.
Technique #2: Use the Pomodoro technique. Pomodoro is a way of reserving chunks of time for uninterrupted (and therefore productive) work. It works like this:
Technique #3: Avoid priority inversion. Priority inversion is when you avoid unpleasant work (work that’s dull, frightening, or uncomfortable) by doing a lower-priority task instead (and often invent some justification). Do your tasks in the real priority order.
Technique #4: Avoid and abandon dead ends and messes. Abandon a course of action as soon as you realize it’s going nowhere and try something else. Don’t get mired in a mess before you officially hit the dead end—turn back as soon as possible.
The final quality of professionals is the ability to work with others. We’ll cover two elements of collaboration:
Professionalism involves doing whatever produces the best possible work, and the majority of the time, the best work is achieved via collaboration. The best way to collaborate is to put together a permanent team that works on multiple projects together (versus making a new team for every new project) because:
Once a team is assembled, here are some techniques for effective collaboration:
1. Share code. Anyone should be able to make improvements to any part of the code. That way, people can work with each other and learn from each other.
2. Pair program. Not only is pair programming efficient, but it also allows people to share knowledge about both the system and the business, and familiarity with other people’s work allows team members to take over for each other in emergencies. Additionally, pair programming is the most efficient way to review code.
3. Work physically close to each other. Face each other when you’re sitting around a table, and be close enough to talk and read body language.
In addition to teamwork, collaborate by mentoring. It’s the professional and ethical duty of experienced programmers to mentor newbies, and it’s newbies’ duty to ask for mentorship. This is because inexperienced coders can cost a company a lot of money and do a lot of damage.
Mentoring teaches technical skills and professionalism, and instills craftsmanship—the mindset of attitudes, techniques, values, and disciplines required for coding. Mentoring is the only way to learn many of these skills—school and courses can teach theory but not practice.
Martin’s ideal mentoring system includes the following roles and responsibilities.
The level of mentorship required depends on experience. The less experienced an apprentice or journeywoman, the more supervision is required. Apprentices should have no autonomy, and experienced journeywomen should be peer-reviewed.
In The Clean Coder, expert developer Robert C. Martin explains how to be a programming professional—an honorable, reliable employee who produces quality work (or takes responsibility for the rare times she doesn’t). Professionals’ most important responsibility is to meet their employer’s needs.
Many people (including developers) don’t consider developers professionals, and this is partly because developers don’t act like professionals. Martin certainly didn’t, when he started his career—he missed deadlines, didn’t test code before releasing it, and was such a bad leader he got two people working under him fired. In this book, he shares the lessons learned the hard way, in the hopes that he can help you avoid making some of the same mistakes.
He’ll teach you about the six qualities and skills of a professional and how to develop them:
And at the end, in an appendix, you’ll learn about some of the tools and programs that will help you master the skills and qualities.
Note: The Clean Coder isn’t a how-to-code book; it’s a manual about how to behave on the job. While the book was written in 2011, its principles still apply—the tools of coding might have changed, but the actual work is largely the same.
The Clean Coder was originally organized in 14 chapters and an appendix. We've reorganized the chapters to be more concise and logical. As a reference, here's a mapping of our chapter numbers to the original book:
Because the book is written for coders who want to be more successful, the author assumes a certain level of knowledge about coding and doesn't define terms. This summary mostly follows the author's lead.
The first quality of a professional is a commitment to professional development. The tech industry moves quickly, and professionals realize that if they aren’t continually improving their existing skills and learning new ones, they’ll lose touch with the cutting edge, be unprepared for change, and narrow their resumes.
The hours you put into your day job rarely contribute to your professional development because at work, you often perform tasks and skills you already know how to do. Therefore, to be a professional, you should spend 20 hours per week of personal time on improving your programming skills and learning new ones.
Sometimes, your employer will contribute to your development, but you should consider this a favor, not something you’re entitled to.
Similarly, sometimes you need to learn something that would also benefit your employer. In this case, it’s reasonable to dedicate part or all of your 20 hours to it.
Putting in these extra hours won’t cause burnout—if you’re a software developer, you’re probably passionate about coding, so 20 hours of practice will feel like doing a fun hobby. (If you don’t want to put in this time, don’t call yourself a professional.)
A large part of improving your existing skills involves practicing them so you can perform them quickly and instinctively. The goal is to get the unconscious part of your mind to recognize a problem and your body to instinctively react to it (for example, by hitting a particular combination of keys). Then, the rest of your mind is free to focus on strategy and problem-solving.
Speed is particularly important these days. Decades ago, programmers didn’t need to be fast with their keystrokes or mouse movements because computers were the limiting factor—they took a long time to compile (transform human-readable code into machine-readable code) and debug. Today, computers are fast, and programmers are the holdup.
There are two venues for practicing:
The “coding dojo” is a collection of practice exercises that are inspired by martial arts (in martial arts, a dojo is a training space). Here are some of the exercises:
Exercise #1: Kata. In martial arts, a kata is a choreographed sequence of moves that would be one person’s side of a fight. The goal is to make the movements instinctive so that if you do get into a fight, your body does the sequence automatically.
Programming katas are similar—they're choreographed sequences of keystrokes and mouse movements that solve a particular coding problem. The goal isn’t to practice solving the problem (for most katas, you’ll already know the solution). Instead, it’s to practice the physical movements required for the solution and to train your mind to trigger the appropriate muscle memory when it identifies a specific problem.
Katas are good for learning:
You should do one kata in the morning and one in the evening, and each should take around 10 minutes to complete. You should vary which ones you practice to keep them all sharp and you can find many katas at Code Kata. When you get really comfortable, try setting a kata to music.
Exercise #2: Wasa. In jujitsu, wasa is a two-person drill in which one partner acts as the attacker and the other as the defender. Each person performs choreographed movements, and then they switch parts.
The programming version is ping-pong—two programmers practice together. One programmer writes a test, and the other writes code that will pass it. Then, they switch jobs.
This can be done with a kata or a new programming problem. If using a kata, the partners can critique each other’s memorization and execution of the physical movements. If it’s a new problem, the test writer can control the difficulty level.
Exercise #3: Randori. In jujitsu, randori is unchoreographed combat practice.
The coding version is more like group wasa. The first person writes a test. The next person writes code that will pass the test and writes a new test. And so on. This will help you learn about other people’s problem-solving methods.
Open-source projects provide a great opportunity for practice because they have real stakes. The project has a real-world application and someone else cares about it.
Once you’ve learned to improve your existing skills, it’s time to learn new ones. The best two ways to learn, in order of effectiveness, are:
1. Teaching. Teaching forces you to translate your knowledge into something you can communicate (like words), which in turn forces you to internalize the information. (For more on teaching, see Chapter 6.)
2. Collaborating. Collaborating means programming and practicing with another developer. You’ll learn from her and she’ll help you notice your mistakes. (For more on collaborating, also see Chapter 6.)
You can also learn by reading, attending conferences, and interviewing people.
Now that you know how to learn, what topics should you tackle? You should learn:
1. Industry history. You should learn all the techniques, ideas, jargon, tools, and niches of the last 50 years (almost all of which are still relevant). At a minimum, you should be familiar with:
2. New developments. Keep on top of the cutting edge of the industry. Learn new programming languages.
3. Your employer or customer’s business and field. When you’re programming a tool for a business in a particular field, you should know about the field yourself. (Shortform example: If you’re building a system for a law firm, then you need to learn something about law.) That way, if the business, unaware of the nitty-gritty of technology, requests a specification that doesn’t make sense or will be ineffective, you can advise. Think of the business’s problems as your problems—your goal is to come up with whatever solution will actually help, not just to follow instructions.
4. Humility. Programming comes with some inherent arrogance—when you create something, you’re playing god. You should take pride in your work and be confident, but also know that you’ll inevitably make mistakes because everyone does. If you fail, accept the consequences and laugh at yourself. Never attack other people for making mistakes.
5. Error sense. Error sense is becoming aware of when you make a mistake. The faster you can notice your errors, the faster you can learn from them.
Martin has practiced a 30-minute kata called The Bowling Game for years. He’s run through it so many times he “could do it in his sleep.” Over the years, he’s streamlined the exercise so he doesn’t use any more keystrokes than necessary and has finessed the algorithm structure and variable.
In the last chapter, we learned about the first quality of a professional—a commitment to learning. The second quality of a professional is discipline—professionals adhere to personal rules and standards around the act of coding. The rules aren’t always about the actual code; sometimes they’re about attitude and behavior while working.
Everyone’s rules will be different. In this chapter, Martin shares what works for him in case you’d like to adopt it, but he also encourages you to reflect on what else might work for you.
The first rule is to avoid doing damage, and if you do create damage, to take responsibility for it by apologizing and learning from the mistake.
A software developer can damage two things:
1. The working of the software. You damage the working by making a change that creates a bug that breaks the software. To avoid damage and take responsibility:
2. The structure of the software. You damage the structure by making the code difficult or expensive to change. To be professional and avoid damaging the structure, mercilessly and regularly refactor (edit) it to improve it.
Many people don’t like refactoring because they’re scared of breaking the code. If you test all of your code (as you need to do to avoid damaging the working), there’s no need to fear breaking anything. If something does go wrong, your tests will catch it.
The second rule is to avoid coding when you’re tired or worried. If you’re not in a mental space in which you can concentrate, you’re going to make mistakes and have to throw out most of your work because coding is hard. You have to do all of the following at the same time:
First, we’ll look at how to manage tiredness, and then, worry.
Here are some techniques to decrease your tiredness levels:
When you’re tired, you lose your ability to problem-solve and be creative. Once you’ve used up all your focus (you will probably physically feel it), you need to recharge by disengaging and spending at least an hour doing something that doesn’t require focus. Your unconscious mind will continue to mull over the problem in the background. To disengage, you might:
In the previous technique, we looked at what to do when you start to feel tired at work. Now, we’ll look at how to arrange your life so you can make your work time your most energetic time:
There’s one technique for decreasing worry:
If you’re worried about something, part of your brain will be occupied with the worry instead of thinking about your code. You might even physically feel the worry as a tightness in your chest or a sick feeling in your stomach.
To avoid being distracted by worry, devote some time (often an hour) to addressing the worry. Not all worries are solvable within an hour, but making some progress on them can reduce anxiety enough to let you work.
It’s most professional to schedule worry-addressing time at home so that when you arrive at the office, you’re ready to give your best. But if you’re unable to address something at home, and you can’t get anything done at work for thinking about it, it’s more productive to take an hour of office time to address the worry. If you try to push through, you’ll just write garbage.
The third rule is to avoid getting writer’s block. When you’re feeling stuck, try the following techniques to get past the block:
The fourth rule is to avoid or at least minimize time pressure—this is the best way to deal with it. To do this:
1. Adhere to your rules. You’ll be most efficient if you don’t break things, don’t get stuck behind writer’s block, and so on.
2. Use your crisis behaviors all the time. In a crisis, you’ll use the most effective and efficient method of doing something. To achieve crisis levels of efficiency all the time, use your crisis behaviors in non-crisis times too.
3. Say no to unreasonable deadlines. See Chapter 3 for more on this.
4. Watch out for manipulative client behaviors. If a client does any of the following, they might be gearing up to put unfair pressure on you:
No matter how well you employ the above techniques, you’ve inevitably going to encounter pressure. For example, someone on your team might quit at an inopportune time. When you are under pressure, you should:
The fifth rule is to avoid the “zone”—a state of mind that makes you feel focused, productive, and invincible. In reality, the zone is just a meditative state—parts of your brain shut off, which skews your sense of time passing and depresses your creativity. Being in the zone is useful when practicing, but not while working because you’re not actually more productive or on your game when you’re in the zone. You’ll write more code, but because you’ve got tunnel vision, you’ll probably have to revise what you’ve written so it fits into the larger structures.
If you feel the zone approaching, avoid it by:
The sixth rule is to deploy music carefully. Many people think that music helps them concentrate, but this isn’t universally the case. Sometimes, it even helps people enter the zone, which you learned is detrimental in the previous rule.
If listening to music does work for you, it’s fine to use it.
The seventh rule is to completely finish all tasks before declaring them “done” and to define “done” as “passed all tests” (for more on tests, see Chapter 4). Don’t accept partial completion for any reason, including if you’re short on time.
Breaking this rule leads to a slippery slope—you’ll declare things “done” earlier and earlier in the process. “Done” will become meaningless.
The eighth rule is to give and accept help—programming is so hard it requires more than one brain. Despite this fact, many programmers have trouble with collaboration—there’s some truth to the stereotype that programmers are big-headed introverts who get into the field because they’d rather talk to a predictable computer than a messy person with emotions. Even if you find collaboration hard, develop the discipline to follow this rule.
There are two ways to give help:
1. Respond when asked. If people have questions, you must answer them. It’s fine to schedule some alone or uninterrupted time, but you need to be available too.
2. Offer to pair program. If someone seems to be having difficulty, offer to pair program with her even if she hasn’t asked. Expect to spend at least an hour (it may not actually take this long, but if you budget this amount, you won’t make your partner feel rushed). Even if you’re not experienced with whatever she’s working on, you can always offer a fresh perspective.
There are two ways to receive help:
1. Accept it when it’s offered. Always accept help, even when you’re under pressure. If the person isn’t helping after half an hour, then thank them and excuse yourself.
2. Ask for help. It’s unprofessional to waste time banging your head against the wall when resources are available.
The last rule is to come up with a workflow for interruptions. You’ll inevitably be interrupted, sometimes by people asking for help, and as you learned in the last rule, it’s your responsibility to graciously help them. Therefore, you need to come up with some strategies for quickly getting back into your work after an interruption. Here are some options:
If you don’t like being interrupted because it pulls you out of the zone, remember rule #5: You’re not supposed to be in the zone in the first place.
When Martin was working for a start-up called Clear Communications, he broke rule #1: Don’t code when you’re tired. He was working 60-70 hour weeks, and one morning at 3 a.m. after 18 hours straight of work, he wrote an ugly solution to a timing problem. If he hadn’t been tired, he would have realized it was the wrong solution, but at 3 a.m., it was the only thing he could think of, and it looked good.
The solution was “sending mail”—Martin’s code sent a message to itself. This caused new timing errors, infinite mail loops, and plagued everyone else who worked on the system with problems for years.
Martin gives suggested rules for professional conduct, and rule #2 is to avoid coding when worried or tired.
If you start to feel tired at work, Martin advises you to take a break and recharge. What recharging activities appeal to you and why? (Walk, nap, listen to a podcast, and so on.)
If you’re worried, Martin advises you to spend some addressing the worry to quiet your anxiety so it becomes less distracting. Think of a recent worry. What might you have done to address it? (For example, if you discovered someone had stolen your wallet, you might take a few minutes to call your credit card company and cancel your cards so you don’t spend the day worrying about identity theft.)
In the last chapter, we looked at the discipline and rules all professionals adopt. The next quality of a professional is honesty, especially about estimates and deadlines.
Whenever you’re programming something for someone, they always want to know when it will be done. Most of the time, you won’t know exactly how long something will take, so you’ll provide an estimate instead of a commitment (guarantee). Estimates have the following qualities:
1. They aren’t promises (though businesses often interpret them as such, which is why there’s often conflict between programmers and businesspeople).
2. They aren’t single numbers—they’re probability distributions. They factor in the following three numbers:
Missing an estimate isn’t unprofessional because estimates aren’t guarantees. However, professionals make their estimates as accurate as possible using well-tested estimation methods.
There are many methods you can use to give your managers and clients an estimation, and we’ll cover three of the options.
The first estimation method is called wideband delphi and uses consensus to make estimations by pooling the experience and knowledge of several people.
Here are the steps:
1. Everyone discusses a task—what it involves, how to do it, and possible delays or hiccups.
2. Individually and privately, everyone estimates the nominal time. Be objective and honest about these dates—don’t factor in hope or miracles. Hope is dangerous because it leads people to create unrealistic schedules and then when things don’t work out, people’s reputations suffer.
3. Everyone reveals their estimate at the same time. This is so that no one’s estimate influences anyone else’s.
If there are any major discrepancies, the conversation continues.
4. After the discussion, repeat steps 2 and 3 until everyone reaches a consensus.
5. To determine the best-case estimate, repeat only steps #2 and #3. Take the lowest estimate.
6. To determine the worst-case estimate, repeat only steps #2 and #3 and take the highest estimate.
There’s another version of wideband delphi you might find useful for estimations:
1. Write all the tasks onto cards and spread the cards out randomly on a surface.
2. As a group (but without talking), everyone arranges the cards in order of how long they think each of the tasks will take. Anyone can move any card, and once a card has been moved a certain predetermined amount of times, it’s taken off the table and the group will discuss the task until they agree on an estimated time.
3. Sort the cards into approximate time frames. Usually, the buckets are 1, 2, 3, 5, 8, and these numbers can represent weeks, days, or points (units of complexity). (Shortform example: One complicated feature might be assigned 10 points, while a simpler feature would only be worth one).
The second estimation method is the program evaluation and review technique (PERT). While it doesn’t formally involve consulting others like wideband delphi, feel free to ask your teammates and the people around you to weigh in because their perspective might improve the accuracy.
Here are the steps:
1. Create your distribution by coming up with the best case, nominal, and worst-case numbers.
2. Describe the probability distribution using the following formula: (Best + (nominal*4) + worst)/6
Most of the time, this calculation will return a pessimistic-ish number because the right side of the distribution curve will be longer than the left.
3. Calculate the standard deviation (how much uncertainty there is) using this formula: (Worst - best)/6
4. Express the estimate as a range. The task will take the probability distribution amount of time plus or minus the standard deviation.
You’re rarely working on just one task at a time. You could estimate how long doing all your tasks would take by adding up all the nominal estimates, but there's a more accurate way that takes into account the uncertainty surrounding doing multiple tasks at once.
To do the calculation:
1. Follow steps 1-3 above for each of the individual tasks.
2. Add the probability distributions (calculated in step #2 of PERT) together.
3. Use the following formula to calculate the standard deviation of the group of tasks: √(Task A standard deviation^2 + Task B standard deviation^2 Task C standard deviation^2 …)
4. Express the estimate as the step #2 number plus or minus the step #3 number.
The law of large numbers states that if you break a big task into smaller chunks and estimate how long each chunk will take, adding up the chunk times will give you a more accurate estimate than simply estimating the big task as a whole. This is because the errors in small tasks compound when you do the math, which is more realistic, because uncertainty also compounds in real life.
Once you’ve calculated your estimates, it’s time to share them. Once you do, there’s always the possibility that people won’t like them and will want something done faster. If this happens, you have three options, not all of which are professional:
Saying no has a bad rap, but it’s the most professional thing to do in many situations. If it’s impossible to get something done properly (adhering to discipline) by a certain deadline, and you say anything other than no, you’re essentially lying.
Here are some of the situations where you might think you can’t say no, but in reality, it’s the right thing to do:
1. When it’s technically possible to get the job done, but only if you do it badly. Doing damage is unprofessional—remember, your first commitment should be to your standards. (Martin’s experience shows that breaking discipline is always less productive—when a hurried developer writes messy code, all the other developers are slowed down too as they navigate the mess.) If the only way to get something done is to skip testing or write messy code, say no.
2. When the adversary is your manager. Your job isn’t to follow your manager’s orders; it’s to defend your objective, which is to have enough time to do a professional job. Your manager expects defense from you.
3. When you want to be a team player. Being a team player means doing your part of the work well, helping others, and communicating truthfully. It doesn’t help your team to agree to do something impossible on their behalf. It also doesn’t help your team to let them fail because they’ve ignored your “no”—if they refuse to acknowledge your answer, speak to someone higher up.
4. When someone begs, cajoles, or casts you as a hero. Accolades and glory are tempting. You don’t have to swear off heroism, just swear off working unsustainable overtime. If you really want to be a hero, do the job properly—meet both a reasonable deadline and the budget.
5. When you’ve already said yes. Sometimes, you’ll say yes to a project that has hidden complications. Once you discover that the complications will affect your ability to do a job well, you can say no in light of the new information, even though you’d previously agreed.
It’s especially important to say no in high-stakes situations (such as if your company will fail if the software doesn’t work). This is because high-stakes situations are when managers most need accurate information and honesty.
You don’t need to explain why you’ve said no. What’s important and relevant is that something is impossible—your manager doesn’t need to know why to make decisions or rearrange a schedule. If your manager is reasonable and has a lot of technical knowledge, you can explain if you want to, which will usually produce one of the following reactions:
Never agree to “try” to do something in a time period shorter than your estimation. The word “try” has multiple definitions and implications, none of which is honest:
1. You will apply extra effort. If you agree to try to get something done faster, it implies that you haven’t been giving the project your full effort up until this point. You have an extra energy reserve, or a new plan, or a behavioral change you’ve been holding back. If you’re a professional, you’ve already been throwing everything you have at the project. Therefore, there is nothing else to try, so by promising to do so, you’re lying and making a commitment you won’t be able to keep.
2. You really mean “maybe.” If this is the case, you should be honest about your uncertainty. If someone insists on a yes or no, and you’re not sure, say no.
3. You really mean “yes.” The person who’s saying “try” rarely means “yes,” but it’s often what the listener hears.
If you say yes, you’re committing to getting something done by the date you promised, no matter what it takes (overtime, skipping family vacations, and so on). It’s unprofessional to say yes to something you’re not sure you can achieve because other people are going to plan around you. If you miss a commitment, it’s a huge blow to your reputation.
On the other hand, it is professional to ask to change the parameters of the task so that you can say yes. (You cannot say yes without something changing because you already considered every factor during your estimation.)
One of the parameters you might change is your working hours, but working overtime will tire you, so it has limitations:
Therefore, don’t agree to work overtime unless:
According to consultant Roy Oshervoe, there are three stages to saying yes and committing:
You can help yourself reach the last stage by paying attention to the language you use. Say “I will” instead of should, need, wish, hope, let’s (all of these words abdicate responsibility). Once you’ve said “I will,” you’re accountable—whoever you said it to will know that if it doesn’t happen, it’s your fault. Fault feels bad, so you’ll be motivated to do what you said you would.
Don’t commit to things you can’t control. If you can’t get something done without the help of someone else, don’t commit because you have no way of following through. Instead, commit to something that will get you closer to getting something done.
There will be times when you can’t make a commitment because life gets in the way. Everyone is late at some point in their lives, and the best way to manage this is to regularly assess and communicate:
1. Update your estimates every day and share them.
2. As soon as you realize you can’t make a commitment, tell everyone who’s depending on you. The earlier you tell them, the more time they have to come up with a backup plan. Someone else might be able to take over the commitment, the team might be able to reassess priorities, or you can make a new commitment.
However, if someone makes a commitment on your behalf (for example, your employer promises a customer something without talking to you about it first), professionalism requires you to help the promiser meet the commitment, but professionalism doesn’t require you to take ownership of the commitment. If you can’t meet the commitment, you’re not breaking it, the promiser is. She must take responsibility.
John worked for an employer that won a bid to make an app for a major retailer in two weeks. John said yes even though he knew two weeks wasn’t long enough to do the job properly. He broke discipline to try to get the project done faster—his code was messy and he didn’t test it because errors would demotivate him. He worked 20-hour days and “finished” the app by the deadline, but he’d done damage—the structure of the code was rigid and hard to change. When the client extended the deadline and requested a new feature, it was very hard to implement.
Program evaluation and review technique (PERT) is a method for estimating how long a task will take as a range.
Think of a task you’re currently working on. What are your best-case, nominal, and worst-case estimates for how long it will take you to do the task?
Describe the probability distribution using the following formula: (Best + (nominal*4) + worst)/6
Calculate the standard deviation (how much uncertainty there is) using this formula: (Worst - best)/6
What is your estimate, given as a range? (Add and subtract the standard deviation to the probability distribution. For example, if the probability distribution is 10 days and the standard deviation is 2 days, the range is 8 (10-2) to 12 (10+2) days.)
In the previous chapter, we looked at the third quality of professionals: honesty. Next, we’ll look at the fourth: communication, which is best done via testing.
Tests ensure that a system works, but that’s a happy bonus, not their main purpose. The most important purpose of a test is to communicate, specify, and document how a system is supposed to work and how it actually works.
In this chapter, we’ll first look at acceptance testing, which is the main type of testing used for communication. Then, we’ll look at how acceptance tests fit into the broader discipline of testing.
When clients speak with programmers, there are often miscommunications, especially about system requirements. This is because the businesses describe to programmers what they want (sometimes ambiguously), and the programmers estimate and build what they understand from the description (sometimes incorrectly). Ambiguity comes from two sources:
For example, a stakeholder might tell a programmer that log files need to be backed up but not provide information about when and how often they should be backed up, where they should be saved, or how long they should be kept. A programmer might think to ask some of these questions (and as a professional it’s your responsibility to make sure requirements are as clear as possible), but the conversation isn’t foolproof.
First, we’ll look at what doesn’t resolve ambiguity. Then, we’ll look at what does.
Both programmers and businesses often try to eliminate ambiguity by being more precise about requirements, but this doesn’t work because descriptions never match reality. When clients see a finished product, it provides them with new information. They often realize what they initially described wasn’t actually what they wanted, or what they see inspires a better idea.
As a programmer, you should avoid being precise until the last possible moment—until you’re just about to build it.
The only way to eliminate ambiguity is to create acceptance tests. Acceptance tests determine whether the system behaves the way the business wants it to—in other words, these tests specify what the system is supposed to do.
Acceptance tests are co-written by clients and testers or QA. Sometimes the clients can write the tests themselves, otherwise, QA should work with them to gather requirements and turn these into acceptance tests. The client will usually come up with the happy-path test (checking that default usage doesn’t throw errors) and QA will write the unhappy-path tests that cover unusual scenarios. The developer only gets involved after the test is written to add it to the system. There are two things to keep in mind with these relationships:
To avoid the trap of premature precision, developers shouldn’t start on a feature until the test is ready. The first acceptance tests should be ready the day work starts, and all the tests should be completed by the halfway point.
Perhaps writing these tests seems like extra work, but in fact, they’ll save both money and time:
There are two things you’re testing when it comes to the GUI:
As much as possible, test these two things separately. Otherwise, changes to one might break the tests to the others, which could become so frustrating you ignore your tests or stop changing the GUI, both of which are unprofessional. Keep in mind the single responsibility principle (SRP), which involves grouping elements by why they change.
To test the workings, test via an API instead of via the GUI (but use the same API that GUI uses).
To test the GUI, use stubs, or pieces of code to stand in for the business rules. Since the GUI changes a lot, don’t test it too much, or you run the risk of getting annoying and abandoning the tests altogether.
In the previous section, we learned about testing for communication. Now, we’ll learn about how acceptance testing fits into the other testing that ensures the system behaves properly.
Testing occurs at multiple levels and is arranged in a pyramid based on how much of the code and what level of detail it covers. We’ll start at the bottom and move up:
Unit tests test “units”—small sections of code. Their purpose is to specify the system and they:
Test-driven development (TDD) is a workflow in which you write the tests you’ll use on your code before you actually write the code.
There are three rules to TDD:
TDD comes with several advantages:
A couple of caveats:
Unit testing tools vary by language, but whichever tool you choose should have the following features:
Martin likes CPPUTest for C and C++, RSPEC for Ruby, NUNIT for .Net, Midje for Clojure, and JUNIT for Java.
For the continuous build, Martin uses Jenkins—it’s easy to learn, simple, and doesn’t take a lot of processing power.
The second level of the pyramid is component tests, which include acceptance tests. Component tests test individual components and business rules. Their purpose is to test whether the software does what the client wants it to and they:
You might want to use some of the following tools to test at the API level:
The third level is integration tests. Their purpose is to assess how well different components communicate (they’re only relevant in multi-component systems). They:
You can often use the component testing tools for integration testing, but not when it comes to UI tests or end-to-end tests. Martin likes Watir and Selenium for integration testing.
The fourth level is system tests, which are the highest form of integration tests. The purpose is to evaluate the whole system. They:
The highest level of the pyramid is manual exploratory tests—tests in which people (sometimes specialists, sometimes anyone in the company) use the system. Their purpose is to confirm that the system operates, note bugs that come up, and report how the system actually works. They:
While Martin was working at test-supplier company Teradyne, Tom, the manager of field service and installation, asked Martin to work with him on creating a trouble-ticket system. Initially, Tom just wanted Martin to teach him to use a text editor so Tom could build it himself, but both of them quickly realized this was too complicated, so Martin became the developer and Tom the client.
They didn’t use user acceptance tests—instead, Tom would describe what he wanted and Martin would build it in front of him. Sometimes, Martin would suggest doing something else that was easier and describe that. Tom might agree, but when Tom actually saw the feature, he’d reject it. It took a whole day to finish the simple application because the communication was ineffective.
In the last chapter, we looked at how professionals use tests to both communicate and ensure their code works. Now, we’ll look at the fifth quality of professionals: They manage their time well.
There are three techniques professionals use for time management:
Meetings take up a lot of time and are expensive—they require renting a location and paying for the time of the attendees. Therefore, professionals strive to make the best use of meetings, which they do by avoiding the ones that waste their time and ensuring the valuable ones are efficiently run.
There are two strategies to avoid wasting time in meetings:
You should only go to a meeting if it meets the following criteria:
If you need help determining if a meeting meets one of these criteria, or if a senior authority requests your presence, discuss your attendance with your team and manager. Your manager should be just as invested as you are in protecting your time.
If you go to a meeting and it stops meeting the criteria partway through (for example, someone adds something irrelevant to you to the agenda), do one of the following:
If a meeting does meet the criteria, you should attend it, and many of the valuable meetings you attend will be structured based on the Agile canon. (Shortform note: Agile is a collection of software development practices.)
There are three types of meetings that are part of Agile, and this is how they be should run efficiently:
1. Stand-up meetings. All participants must stand during the meeting, and everyone gets only 20 seconds to respond to each of the following questions:
2. Iteration planning meetings. The goal of these meetings is to choose which backlog tasks to include as part of the next iteration. The discussion of each task should only take five to 10 minutes and the total meeting time should be less than 5% of the time to complete the iteration. (If the iteration will take 40 hours, the meeting should take a maximum of two.) The following should already be determined before the meeting:
3. Iteration review. Hold these meetings at the end of every iteration. The goal is to talk about what went right and wrong (maximum of 20 minutes) and to demo the results of the iteration to stakeholders (maximum of 25 minutes).
If an argument breaks out during a meeting and it lasts more than five to 30 minutes, further discussion isn’t productive. You can settle the argument in two ways:
If you’re one of the arguers, avoid the following unprofessional behavior:
The second time-management technique is to use Pomodoro technique. Pomodoro is a way of reserving chunks of time for uninterrupted (and therefore productive) work.
It works like this:
The third technique is to avoid priority inversion, which is when you avoid unpleasant work (dull, frightening, or uncomfortable) by doing a lower-priority task instead (and often invent some justification).
Don’t let your emotions steer you—avoiding important tasks is unprofessional. Don’t engage in priority inversion.
The last technique is to abandon a course of action as soon as you realize it’s going nowhere and try something else. (No matter how much experience you have, you’ll inevitably find yourself working on a task that seemed like a good idea when you started it but turned out to be a mistake.)
There are two types of tasks to avoid and abandon:
1. Dead ends have no way forward.
2. Messes technically have a way forward, but the way will be slow and more effort than it’s worth. Messes are even more dangerous than dead ends because you’ll be tempted to continue on because you’ve already invested time. Every step you take forward will mire you deeper and make it harder to get out of the mess. Venturing into a mess is a form of priority inversion.
When Martin was working for Teradyne, he used the following time-management techniques to give his employer as much productivity as he could:
Meetings can be critical or time-wasting, so you must be strategic about how you approach them.
Think of an upcoming meeting you’ve been invited to. Does it meet the criteria for being worth your time? (It will give you important information; it’s about an interesting topic; it will allow you to help someone; it has an agenda, schedule, and goal?) How do you know?
Think of a meeting you attended that initially met the criteria but then devolved into a waste of time. Would it have been most appropriate to ask to change the agenda, to ask to speed things up, or to leave? Why?
Think of a meeting you attended that included an argument. What would have been the most effective way to address the argument, gather more data, or vote? Why?
In the previous chapter, we looked at the fifth quality professionals possess: time-management skills. Now, we’ll look at the final quality: the ability to work with others. First, we’ll look at teamwork, then mentoring.
Professionalism involves doing whatever produces the best possible work, and the best work is achieved via collaboration. (Even if you’re one of the rare people who works best alone, you hamstring your team’s work—and as a result, hurt your employer—when you refuse to collaborate.)
There are two approaches to putting together teams:
1. Build the team around a project. Assign programmers, analysts, testers, and a project manager to work on a project for a percentage of their time. The members can belong to other teams working on other projects at the same time.
2. Start with the team. Create a team of programmers, analysts, testers, and a project manager, and then assign the team to work on multiple projects together. Usually, this kind of team consists of 12 people: one project manager, two testers, two analysts, and seven programmers. Here are their jobs:
Approach #2, starting with a team, is the better option because:
Once a team is assembled, here are some techniques for effective collaboration:
1. Share code. Anyone should be able to make improvements to any part of the code. That way, people can work with each other and learn from each other.
2. Pair program. Pair programming is not only efficient, but also allows people to share knowledge about both the system and the business; familiarity with other people’s work allows team members to take over for each other in emergencies. Additionally, pair programming is the most efficient way to review code.
3. Work physically close to each other. Face each other when you’re sitting around a table, and be close enough to talk and read body language.
There are a few times when working alone is most appropriate:
In the previous section we discussed the importance of teamwork. Next, we’ll discuss another aspect of collaboration—mentoring. It’s the professional and ethical duty of experienced programmers to mentor newbies, and it’s newbies’ duty to ask for mentorship. This is because inexperienced coders can cost a company a lot of money and do a lot of damage.
Mentoring teaches technical skills and professionalism, and instills craftsmanship—the mindset of attitudes, techniques, values, and disciplines required for coding. (Craftsmanship is contagious, so when mentors lead by example, mentees pick it up.) Mentoring is the only way to learn many of these skills—school and courses can teach theory but not practice.
Martin’s ideal mentoring system includes the following roles and responsibilities.
The level of mentorship required depends on experience. The less experienced an apprentice or journeywoman, the more supervision they need. Apprentices should have no autonomy, and very experienced journeymen and women should be peer-reviewed.
When Martin was consulting for a company that made printers, each programmer worked on a separate part of the device (feeder, stapler, and so on). The programmers were possessive of their code and never shared it with their coworkers—they didn’t embrace teamwork. As a result, there was wasteful duplication in everyone’s code.
In the previous six chapters, we discussed the qualities and skills of professionals. In this appendix, we’ll explore some of the programming tools you can use as you work toward professionalism.
There are two main types of source control tools, open source and “enterprise.” Open source tools are usually better than “enterprise” ones because open source tools are built by developers (who know what features other developers need). Enterprise tools, on the other hand, are usually aimed to appeal to business people, and often they have extraneous features but lack the features developers require, especially speed.
Martin recommends the following open-source tools:
If your company has an enterprise system, you can still use an open-source system—use the open-source system during iterations, and check the source code into the enterprise system at the end of iterations.
IDEs all have their pluses and minuses:
Use issue tracking systems to keep track of both bugs and to-dos including new tasks. If your team is between five and 12 developers, you should have tens to hundreds of tasks and bugs, so you shouldn’t need anything particularly powerful. (If you have thousands of tasks or bugs, you don’t need a more powerful tracker, you need to go back and fix whatever got you into this situation.)
Martin recommends starting with a manual system first. For example, divide a bulletin board into labeled sections (for example, “not yet started,” “in progress,” “finished”) and write tasks on cards. Pin the cards in the relevant section and move them as the task progresses. This will help you figure out what kind of digital tool will best meet your needs.
Here are some of the options once you’re ready to move to a digital tool:
UML and MDA are tools that theoretically allow developers to build diagrams that an engine will translate into code, rather than writing the code directly. These tools don’t do this job effectively because the goal is to abstract away details, but removing detail is unhelpful for two reasons: