The original article is reprinted from Antirez

Translation: Jiang Hong

According to programming lore, a 10x programmer can do ten times as much work as the average programmer. The average programmer is, conceivably, someone who is good at his or her job, but doesn’t have the magical abilities of a 10X programmer. A better description of “average programmer” is that it represents the average level of programming output among professional programmers.

The programming community is divided on whether the animal exists: some say it doesn’t exist at all, while others argue that not only do 10x programmers exist, but 100x programmers can be found if you know how to look for them.

If you think of programming as a “linear” discipline, it’s clear that the possibility of 10x programmers does seem illogical. How can a runner be 10 times faster than another runner? Or how can a construction worker do ten times as much work as someone else in the same amount of time? However, programming is a very special design discipline, and even when programmers are not involved in the actual design of the architecture, they still need to design the implementation strategy when implementing a product.

So if the design and implementation of programs are not linear capabilities, then it seems to me that work experience, programming ability, knowledge base, ability to identify useless components, etc. are non-linear advantages that come into play in product development as a product. Of course, when programmers are responsible for both the design and implementation of the software, this phenomenon is even more common. The more “goal oriented” a task is, the more room a potential 10x programmer has to use her/his abilities to achieve the goal with much less effort than others. The ability of 10X programmers to get more done in less time is reduced when the tasks at hand are more rigid and there are many restrictions on development tools and implementation: It is still possible to do better with control of the “local” design, but it cannot fundamentally change the path to the goal, including removing parts of the design specification completely to achieve much the same goal with much less work.

In my 20 years of working as a programmer, I have observed many of the programmers I have worked with and mentored to achieve certain goals, such as providing patches for Redis and other projects. It is during these collaborations that many people consider me to be a highly effective programmer. Since I’m far from a workaholic, I’ll use myself as a reference to talk about how to develop fast.

Here are a few traits that I think have the biggest impact on programming effectiveness.

Pure programming ability: Complete subtasks

The most obvious strengths and weaknesses of programmers are the subtasks that implement a part of a program, including the implementation of functions, algorithms, or anything else. Surprisingly, in my experience, the ability to use basic instruction programming tools very effectively to achieve something is not as common as most people think. On a team, I’ve sometimes observed very incompetent programmers who don’t even know simple sorting algorithms get more done than college graduates who should be strong in theory but weak in practice.

Lesson learned: Pattern matching

By experience I mean a set of repetitive task solutions that have been explored. Experienced programmers eventually learn how to handle each subtask. This not only improves efficiency, but is also a powerful weapon against design errors, which are often the biggest enemy of simplified design.

Important: Actual time vs. assumed time

It makes no sense to look at the programming time without looking at the quality. Both internal and external factors can affect your level of concentration. Internal factors include procrastination, lack of interest in projects (you must not be fully engaged in what you don’t like), lack of exercise, poor or little sleep. External factors are frequent meetings, a poor work environment, frequent interruptions by colleagues, etc. Naturally, increased focus and reduced interruptions have a significant impact on development productivity. Sometimes extreme measures are needed to stay focused. I, for example, usually only send and receive emails at set times and only respond to important parts.

Learn trade-offs: Get 90% by killing 5%

Complexity arises when there is an unwillingness to acknowledge that a non-essential goal is responsible for a large part of the design’s complexity, or when more important goals are difficult to achieve because of trade-offs between an essential feature and a non-essential feature. It is important for designers to recognize the parts of a design that are difficult to achieve, that is, the effort is not always proportional to the benefit. In order to get the most bang for your buck on a project, you need to focus on the most important things that can be done in a limited amount of time. For example, when designing the message broker Disque, I realized that other aspects of the project could be substantially improved: usability, query language, and client interaction, simplicity, and performance, for example, by only making an effort (not an absolute effort) to ensure the order of messages.

simplicity

This is an obvious point, which is crucial. To understand simplicity, it is necessary to examine how complexity arises. I believe that the two main drivers of complexity are the unwillingness to make design sacrifices and the accumulation of errors in design activities.

Think carefully about the design process, and every wrong choice takes us further away from the optimal solution. An initial error, when encountered by the wrong person, does not lead to a redesign of the system, but to the design of a more complex solution to deal with the error, so the project becomes more complex and inefficient with each error.

Simplicity can be achieved by performing “proof of concept” reasoning in your head, which allows the programmer to imagine a large number of concise designs, then implement the one that seems most feasible and straightforward, then refine the design with experience and personal design skills, and find a reasonable solution for sub-designs.

However, whenever a complex solution is required, it is necessary to spend a lot of time thinking about how to avoid complexity, only to continue in that direction after considering various alternatives and finding no better one.

Perfectionism, or how to sacrifice productivity and introduce design bias

There are two types of perfectionism: an engineering culture that optimizes the quantifiable performance of programs, and personality traits. In both cases, I think perfectionism is the biggest barrier to fast delivery for programmers. Perfectionism and fear of others’ judgment can lead to design biases that lead to poor choices, and design improvements based solely on psychological or irrelevant quantifiable metrics, without any consideration for things like robustness, simplicity, and just-in-time delivery.

Knowledge: Some theory can help

When dealing with complex tasks, knowledge about data structures, the fundamental limitations of computation, and important algorithms for a particular task will have an impact on the ability to find the right design. It is not necessary to be a super-expert at everything, but it is necessary to know multiple potential solutions to a problem. For example, accepting a design sacrifice (accepting a certain error rate) and knowing how to estimate the size of a set with high probability can avoid designing a complex, slow, and memory intensive scheme to calculate the number of unique elements from streaming data.

Bottom line: Know the machine

Even in high-level languages, a lot of programming problems are caused by misunderstandings about how a computer does a particular task. This may even result in a project needing to be redesigned and implemented from scratch because of fundamental problems with the tools or algorithms used. A good command of C, understanding how the CPU works and how the kernel works and how system calls are implemented can prevent serious surprises later on.

Debugging technique

It’s not uncommon to spend a lot of time looking for bugs. If you’re good at picking up Bug status step by step so that you can fix it in a rational way, and writing code that’s as simple as possible to minimize bugs, you’ll be much more efficient.

It’s not surprising to me that these traits have a tenfold impact on output. They allow good implementations to start with a workable model and a design that is several times simpler than the alternatives. There is an approach that emphasizes simplicity that I like to call “opportunistic programming” : At each step of development, choose to implement the features that will have the greatest impact on users and require the least effort.