While You Are Coding

We should avoid programming by coincidence—relying on luck and accidental successes—in favor of programming deliberately.

Always be aware of what you are doing. If you're not sure why it works, you won't know why it fails. Proceed from a plan, but be ready to change the plan if the environment changes. Prioritize your effort. Spend time on the important aspects.

Test your assumptions.

Document your assumptions, and also test your assumptions. If your assumption is right, you can make better, informed choice. If your assumption was wrong, well, be glad you tested it.

Don’t let existing code dictate future code. All code can be replaced if it is no longer appropriate. Even within one program, don’t let what you’ve already done constrain what you do next—be ready to refactor

Prioritize

If you don't have fundamentals or infrastructure correct, brilliant bells and whistles will be irrelevant. Prioritize your effort. Spend time on the important aspects.

Why Write Tests

Testing is part of programming. To write good tests, you have to understand the code you are writing the tests for. That's a huge benefit of writing tests. We usually work with a slight understanding of the code and think that we will worry about the edge cases, or error handling later, and never come to it.

Naming Things

Things should be named according to the role they play in your code. When you consider the role of a variable or function, you’re thinking about what is special about it, about what it can do, and what it interacts with. Rename and refactor when your understanding of a thing changes. Avoid misleading names.

Requirements: No one knows exactly what they want

Requirements rarely lie on the surface. Normally, they’re buried deep beneath layers of assumptions, misconceptions, and politics. Even worse, often they don’t really exist at all.

The typical client comes to us with a need. A response to a current problem. The need may be for a change to an existing system or it may ask for something new, can be either expressed in business terms or in technical ones. The mistake new developers make is to take this need and implement a solution for it. Good programmers help the clients understand what exactly they want.

Requirements are learned in a feedback loop. Your job is to help the client understand the consequences of their stated requirements. You do that by generating feedback, and letting them use that feedback to refine their thinking. 

Even at the end of a project we’re still interpreting what our client wants. In fact, by that point we’re likely to have more clients: the QA people, operations, marketing, and maybe even test groups of customers.

Maintain a glossary.

As soon as you start discussing requirements, users and domain experts will use certain terms that have specific meaning to them. Create and maintain a project glossary—one place that defines all the specific terms and vocabulary used in a project. All participants in the project, from end users to support staff, should use the glossary to ensure consistency. This implies that the glossary needs to be widely accessible—a good argument for online documentation.

Solving Impossible Puzzles

Identify the real (not imagined) constraints, and find a solution therein. Some constraints are absolute; others are merely preconceived notions. Absolute constraints must be honored, however distasteful or stupid they may appear to be.

The key to solving hard problems is both to recognize the constraints placed on you and to recognize the degrees of freedom you do have, for in those you’ll find your solution.

Go for a walk, work on something different. Let your unconscious brain work on the problem in the background. However, in order to have those eureka! moments, your nonconscious brain needs to have plenty of raw material; prior experiences that can contribute to an answer.  Or, explain the problem to someone, or even a rubber duck.

Ask questions. Why are you solving this problem? Do you really need to solve it? Has it been solved before? Is there a simpler problem you can solve, instead?  Continuously get feedback on what works and what doesn’t work as you do your daily job.

Were you handed a set of constraints when you signed on to yourcurrent project? Are they all still applicable, and is the interpretation of them still valid?

The Essence of Agile
  • Work out where you are.
  • Make the smallest meaningful step towards where you want to be. 
  • Evaluate where you end up, and fix anything you broke. 
  • Repeat until done. 

Context Matters

Have you or your team fallen in this trap? Ask yourself, why are you even using that particular development method? Or that framework? Or that testing technique? Is it actually well-suited for the job at hand? Does it work well for you? Or was it adopted just because it was being used by the latest internet-fueled success story?

Do What Works, Not What's Cool or Fashionable

There’s a current trend to adopt the policies and processes of successful companies such as Spotify, Netflix, Stripe, GitLab, and others. Each have their own unique take on software development and management. But consider the context: are you in the same market, with the same constraints and opportunities, similar expertise and organization size, similar management, and similar culture? Similar user base and requirements?

The Real Goal

The goal of course isn’t to “do Scrum,” “do agile,” “do Lean,” or what-have-you. The goal is to be in a position to deliver working software that provides value to your users by giving them more capability. 

 Civilization advances by extending the number of important operations we can perform without thinking. 

Ruthless and Continuous Testing

Many developers test gently, subconsciously knowing where the code will break and avoiding the weak spots. Pragmatic Programmers are different. We are driven to find our bugs now, so we don’t have to endure the shame of others finding our bugs later. Test Early, Test Often, Test Automatically.

Testing Thoroughly

How do you know if you have tested the code base thoroughly enough? The short answer is “you don’t,’’ and you never will.

Find Bugs Once, Fix them twice

Once a human tester finds a bug, it should be the last time that bug occurs, no matter how rare you think it is. Because it will happen again. And we just don’t have the time to go chasing after bugs that the automated tests could have found for us. We have to spend our time writing new code—and new bugs. 

So fix the bug as soon as you or QA find it, and immediately put a system in place so that that bug never happens again. 

Delight Your Users

Our goal as developers is to delight users, not just delivering working software in a timely manner, but to actually make our users happy when they use our software.

Users have a problem that needs solving within the context of their objectives and budget. It’s these expectations of business value that really count—not just the software project itself. The software is only a means to these ends.

Make sure you know about your users' expectations before you start working on a project. Continue to think about them as you progress, and try to not only meet them, but exceed them when you finish.

Talk to other departments

As our knowledge of the domain increases, we’re better able to make suggestions on other things that could be done to address the underlying business issues. Developers, who are exposed to many different aspects of an organization, can often see ways of weaving different parts of the business together that aren’t always obvious to individual departments.

Sign Your Work

Take pride in your work. “I wrote this, and I stand behind my work.” Your signature should come to be recognized as an indicator of quality. People should see your name on a piece of code and expect it to be solid, well written, tested, and documented. A really professional job. Written by a professional.

A Pragmatic Programmer.