What makes a good programmer? It’s an interesting question to ask yourself. It makes you reflect on the craft of software development. It is also a good question to ask your colleagues. It can trigger some interesting discussions on how you work together. Here are five skills I think are crucial to have in order to be a good programmer.
1. Problem Decomposition
Programming is about solving problems. But before you write any code, you need to be clear on how to solve the problem. One skill good programmers have is the ability to break the problem down in smaller and smaller parts, until each part can be easily solved. But it is not enough simply to find a way to solve the problem. A good programmer finds a way to model the problem in such a way that the resulting program is easy to reason about, easy to implement and easy to test.
Some of the most complicated programs I have worked on were complicated in part because the implementation did not fit the problem very well. This led to code that was hard to understand. When the problem is well modeled, I agree with Bernie Cosell (interviewed in the excellent Coders at Work):
“…there are very few inherently hard programs. If you are looking at a piece of code and it looks very hard – if you can’t understand what this thing is supposed to be doing – that’s almost always an indication that it was poorly thought through. At that point you don’t roll up your sleeves and try to fix the code; you take a step back and think it through again. When you’ve thought it through enough, you’ll find out that it’s easy“.
2. Scenario Analysis
Good developers have the ability to consider many different scenarios for the program. This applies both to the logic in the program, and to the internal and external events that can occur. To consider the different paths in the logic, they ask questions like: What happens if this argument is null? What if none of these conditions are true? Is this method thread-safe? To discover what types of events the software needs to handle, they will ask questions like: What if this queue becomes full? What if there is no response to this request? What if the other server restarts while this server is restarting?
The good programmers ask themselves: How can this break? In other words, they have the ability to think like testers. In contrast, inexperienced programmers mostly only consider the “happy path” – the normal flow of control when everything goes as expected (which it does most of the time). But of course, the unexpected inevitably happens, and the program needs to be able to cope with that.
Programming consists to a large degree of naming things: classes, methods and variables. When done well, the program becomes largely self-documenting, meaning that the function of the program is quite clear just from reading the source code. One effect of self-documenting code is that it naturally leads to many smaller methods, rather than a few large ones, simply because then you have more places to put meaningful names (there are other reasons why many small methods are good too).
Coming up with good names is much harder than it sounds. I like this quote (from Phil Karlton): “There are only two hard things in Computer Science: cache invalidation and naming things.” Partly naming is hard because it needs to be clear in your mind what each name represents. Sometimes that is not immediately clear, but only becomes apparent as the development proceeds. Therefore, renaming is just as important as naming.
Naming things well also includes coming up with concepts to be used, and what these concepts should be called. By having well-thought out, distinctly named concepts that are used consistently (in the program, and when discussing the domain with programmers and non-programmers), writing the program becomes much easier.
Perhaps the biggest challenge in programming is managing complexity. Consistency is one way to combat complexity. It reduces some of the complexity by allowing us to see patterns and infer how things are named, used and handled. With consistency, we don’t need to use brain power to remember exceptions and random variations. Instead we can concentrate on essential complexity, not accidental complexity.
Consistency is important across the board. It applies to variable names and grouping, method naming, the division into modules, the directory structure, the GUI, error handling, logging, documentation etc. For example, if some variables are related and appear together (in declarations, method calls or as columns in the database) then always use them in the same order. Then it becomes easier to see if one is missing, or if they have been mixed up. For an operation, if it is called delete in one place, don’t call it remove in another place – stick with the same name. Steve McConnell also has some good advice on using opposites precisely in Code Complete. For example, begin/end are opposites, as are start/stop. Don’t mix names from different pairs (for example using begin/stop) when dealing with opposites.
Inconsistencies can get introduced when modifying a program. Sloppy programmers don’t pay attention to if what they add is consistent with the existing code or not. Good programmers are relentless in ensuring that seemingly small details are just right. They know how important consistency is in the overall fight against complexity.
As a software developer, you are constantly learning. Before adding a new feature, you have to understand what it is supposed to do. Before adding code to an existing program, you usually have to learn what the existing code does, in order fit the new functionality in properly. You also have to learn about the surrounding systems, in order to interface with them correctly. The ability to learn fast therefore makes you a much more effective developer.
Furthermore, because the pace of development in the software engineering field is so high, there is a steady stream of new languages, tools, techniques and frameworks to learn about. You can view this as good or bad. Fred Brooks lists learning as one of the joys of the craft, and I agree. Learning new things is satisfying in itself. It also means that life as a developer never is boring.
All of the above skills are generic – none of them are specific to any one language, framework or technology. If you have them, you can quickly learn a new language or tool, and write good software in that environment. Furthermore, because they are general in nature, they will not become obsolete in a couple of years.
These are my answers for what makes a good programmer. What do you think makes a good programmer? Let me know in the comments.
You forgot the three most important skills a programmer needs: communication, communication and communication.
I agree, communication is crucial! I think both “naming” and “consistency” can be thought of as communication (through code).
I was actually referring to communication with stakeholders. The ability to understand what they want; being able to clearly communicate the possibilities, limitations and alternatives… Those are usually much more valuable skills than coding. And I say this with some sorrow, because it’s the aspect of my job that I like the least. 😦
Usually what happens for me before I start coding is that there are several cases (from the scenario analysis) that haven’t been specified by the stakeholders. So then I talk to them, and we work out what should happen. This is usually quite enlightening for all parties, and the problem becomes more clearly defined. I actually enjoy that part quite a lot, because it makes me learn more about the domain.
I don’t think it’s just communication with stakeholders either. The best programmers have an ability to really communicate with other programmers. Problem Decomposition and Scenario Analysis in particular are rarely done solo but as part of a team. The best programmers, and specifically the best teams of programmers, are best at doing these things together and communicating well with each other.
Discussion on Reddit: http://redd.it/29gd33
Glad I found this post on Google+. I’m a fairly inexperienced programmer, but really looking to get into programming much more heavily. I’m going to encourage myself to implement these 5 skills in all programs I create.
I’ve been programming computers for 40 years…old computers…new computers…big…small…
you name it.
I agree with everything you’ve written.
The only thing I would add would be good visualization skills.
I’ve been blessed (or cursed) with the ability to get a “picture” in my head as to how I’m going to solve a programming problem and that “picture” guided my code as kind of a blueprint to get the job done.
Great comment! I also think about my programs in pictures a lot.
Since a large portion of the brain is used in vision it makes sense that effective programmers would visualize their solutions. I find one big difference between junior and senior developers is their ability to “see” how their code fits into the rest of the system. I think the author addressed that in points 1 and 2.
I think the most important one (not listed) is knowing what the problem is.
no, a Good developer Doesn’t have to know what the problem IS,
he has to have the ability to know how to search and find a solution for it!
if you have that skill, then that turns into existing knowledge, also known as experience! but this comes AFTER the search! 😉
I think the author wrote specifically about that when he said that unnecessarily complicated code comes from misunderstanding the problem. It’s a very good reason to be constantly learning so that every problem doesn’t look like a nail because all we know how to use is a hammer! Metaphorically speaking of course. 🙂
I think we have to consider a way back to change last thoughts and actions. A simple problem suddenly or gradually becomes hard, often.
Decomposition is critical. While learning a new programming language a fellow student calculated a problem would take 6 months on the computers we were using. 1. Seemed long. 2. Seemed suspicious. Came up with my own solution, hadn’t the faintest how to estimate how long it would take because I’d be using deterministic logic. (Use logic to evaluate a step before advancing to the next step) Solves in 2 minutes on my machine so should solve in 8 minutes on the old computers we were on. (I can alter the deterministic logic so it will solve in 8 minutes. I can alter the problem so it solves in milliseconds.) I also came up with the worst design I could think of and that one I could estimate at a quintillion years.
After the ability to deliver high value solutions, and I do agree with the points raised from that perspective; rate and reliability of delivery surely follow as the multiplier to single out the truly excellent.
Among the characteristics tending to differentiate such developers are:
– excellent memory
– attention to detail
– consistently methodical
– self disciplined
The greater the mastery of these, the sooner and more reliably goals are reached.
Employers value a consistent (reliable) high rate of delivery with good quality and minimal defects.
While other factors play their part, personality and teamwork for example, for the individual developer these are key. The skills in the article seem that they may be learned more easily than these more deeply ingrained traits, particularly memory; making these rarer and thus more highly prized.
It’s easy to overlook these simple qualities in a developer, they are comparative and require time to assess while the skills stated in the article though hard to quantify are surprisingly evident under brief examination of a masterful lead developer.
Managing risk and ensuring consistent delivery pays a big part in managing software projects. Ultimately who would you choose to go on your team? Life is difficult enough.
It could probably be included in consistency, but I find formatting an important ingredient. Code is so much easier to read if it all lines up.
Again, while I agree it’s important to get your developers to apply your project standards, could not tooling and effective code reviews rectify that?
Excellent article (speaking with 30 years programming experience behind me ;-))
There is however one fundamental word that is missing: *abstraction*
“Good programming is the art of discovering the best abstractions to solve a problem and capitalize later on it.”. Then you need to name them properly, expose them, etc…
That’s what I have found out when looking at code from “good programmers”.
Thanks for commenting. I agree on the importance of abstractions – ideally, good problem decomposition leads to good abstractions.
Pingback: Qu’est-ce qui fait un bon développeur ? | Fier d'être développeur
How about sizing? The ability to size the problem that needs to be solved. I would say that belongs in the top 5 skills to be a good programmer. Nothing more frustrating than a programmer that can’t size his work, and either under/over delivers.
Pingback: Links – July 2014 | Ninad's Blog
Thank you for this great post; It’s insightful and gives a lot of food for thought.
What I found most insightful was the part where you said “A good programmer finds a way to model the problem in such a way that the resulting program is easy to reason about, easy to implement and easy to test.”
I think if we are able to internalise just this as a result of reading your post we’ll have taken a great leap forwards in our careers. What do you think?
An addition from your readership which I also loved was “good visualisation skills”. Since we have to deal with so many abstract concepts, it’s an important skill to have.
A video which explains this very powerfully and which I will recommend to you and your readers is: Bret Victor’s Inventing on Principle
which inspired the conception of this open-source IDE:
Now, I’ll be taking notes and teaching these ideas to fellow programmers!
Indirectly speaking of programmers, I like programs that read very linearly, have few paths, have a few hiararchy levels, use long variable names and good abbreviations for themes that reflect the business situation where the program is used. I like programs that push to lower levels all that is not expected by the “main line”. I like programs that are easy to “clone” to handle a variation of the input or a variation of the output. And the thing that I like the least of programs is overloading variables and procedures.
Pingback: Programming blogs that don't suck - Methodical Programmer
Hi, programming is not much tough. Simply follow the instructions, and it will be very easy and very interesting in Programming. Programming is all about logic. Every programmer writes different types of logics to solve a problem. So, it completely depend upon the thinking ability of the programmer.
Great Programmers automate and make complex things look very very simple..
Other Reddit discussion: https://redd.it/5gy5ll
Great and insightful article!
These are some skills which have to be in programmers which makes them better one, some skills you can add to this are like ‘ patience, practice, passion etc’. I am trying to adapt some of them as good programmer. Thanks for sharing this article!
I think that there are many traits that can be added to the list of good developer traits – good problem solving and debugging skills, the ability to solve “relatively” or “very” complex problems, meeting “reasonable” deadlines, maintainability, and being able to write code with better performance are some that I consider to be primary. You can even add things like understanding hardware internals, OS internals, DB internals, and having a deep understanding of data structures AND APPLYING THAT KNOWLEDGE TO YOUR CODE if you are talking about the “bonus” traits that distinguish the good from the great. Many bloggers list their own traits that they think a good developer has, and perhaps many people are thinking of their own traits when making these lists. If we considered every bloggers’ traits to be absolute traits that good developers must have then naturally there would be NO GOOD DEVELOPERS AT ALL because many bloggers even list non-technical traits as characteristics. It is fun to name traits to reflect on how we can improve, but it is important to take into consideration the programmer as a whole. For example, I am very good at debugging and feel like problem solving that others consider difficult or even impossible is actually easy- but I am still struggling to make my code simple and maintainable, and because I am a fast coder, bugs unexpectedly occur. I always solve the bugs quickly but my point is I am not as rigorous a tester as I should be. Does it mean that I am not not good? I don’t think so. I am a good programmer who knows my shortcomings and has room to grow. Before I couldn’t meet deadlines and struggled with problem solving, but now I solve everything I am handed, maybe just not always in the best way, even though I put some effort into that. But the work I work on now is harder than what most professionals work on. Are good programmers all humble? I say emphatically NO. Along with good skills, ego naturally arises. But keeping one’s ego in check is important because it helps one to recognize their shortcomings so as to improve. There is always room for improvement and “good programmer vs. bad programmer” is not a matter of absolutes in my opinion.
Thanks for commenting James. I agree that there are no absolutes, and that there is always room for improvement. That’s one of the reasons I like programming so much – you are never done learning, and you can always improve.