I have recently published an article called “10 commandments for creating good code“, in which the commandment number 8 says “Comments are evil”, well, as I was expecting this has created some controversy and a few comments have been written in dzone.com and news.ycombinator.com arguing about comments being evil, so I have decided to write this small post where I hope I can bring some light into what I really mean when I say “Comments are evil”.
Code quality scale
I believe most of the developers will agree with the following scale.
The worst code is: Bad code without comments.
Bad code is: Bad code with comments.
The average code is: Average code with comments.
Good code is: Good code with a few comments…
…but… Great code doesn’t need comments!!!
First commandment in the “10 commandments for creating good code” is DRY (Don’t repeat yourself), I believe this is the main guideline for a software developer, what most software developers don’t see is that every time a comment is written, you are repeating yourself! Now not only you will have to perform maintenance activities on the code, but you will also need to make sure that the comment keeps its synchronicity with the code. Not a big deal? Well, think in all the other principles you follow when you code, each of the small changes you perform in your code to make it better, like spending time to name a class, moving a method to a different class because it just feels right… are insignificant by themselves, is when you put all them together when you can tell that you have created a masterpiece of code.
Should we use comments at all?
Of course!!!!!!! My mistake was to name the commandment “Comments are evil”, is just a guideline, as any other principle you apply in software development, sometimes we just produce crappy code, for many reasons, we are under pressure, we don’t know the technology we are working with… Then for the love of god, use comments!! There are other times where we have prodcuded good code wich has a few comments, that’s fine, we cannot always look for the perfection. What “comments are evil” really means is that you should always push yourself to use as few comments as possible, not because you are lazy, but because they are not necessary.
1.- DRY: Don’t repeat yourself.
DRY is usually the easiest principle to understand, but it is quite harder to apply. It means that when finding similar code in two or more places, we should abstract them into a new method and change the previous code fragments so they will now call the new method with the appropriate parameters.
DRY is maybe the most universal coding principle, I have never found a developer who would argue that repeating code is good, but, I have found developers that forget about this principle when coding unit tests, as an example: imagine that you have changed the interface of a class which had lots of unit tests, if you haven’t used DRY, you will have to manually change the call to this class interface to match the new signatures to each test case.
2.- Write short methods.
There are three very good reasons for writing short methods.
- Your code will be easier to read.
- Your code will be easier to reuse (short methods are likely to produce loose coupling).
- Your code will be easier to test.
3.- Use good names for your classes, methods and variables.
There is nothing nicer than using some other developer code and not having to read its documentation because the names of the classes and the methods are telling us everything, so, make everyone’s life easier and take this approach, expend always a few seconds before naming any element in your code.
4.- Assign the right responsibility to each class.
One class, one responsibility, that will sound familiar to those who know about the SOLID principles, but not any responsibility, the right responsibility, so if we have the class Customer, we won’t assign to it the responsibility to create a new sales action, we will just assign it the responsibility to handle all the data related with a customer.
5.- Keep your code organized.
This organization is at two levels.
- Physical organization: Whatever the structure you are using, packages, namespaces, folders… Organize your classes in such a way that is easy and intuitive to find where the code is stored.
- Logical organization: Whatever belongs logically together should have access to each other members, but what belongs to a different logic structure has to access them by an interface. These logic groups are commonly implemented as layers, services…
6.- Create lots of unit tests.
The most tests you have, the better, they are our safety net for all the changes we will have to perform in the code in the future.
7.- Refactor often and sooner.
Software development is a continuous discovery process, in order to keep up to date with good code that matches the new/changing requirements is essential to refactor the code as we go. As this is a risky task there are 2 main preconditions to avoid entering new bugs into the system.
- Have lots of unit tests.
- Do small refactor steps at a time. In software development there are very few things more annoying than start refactoring 2000 lines of code to after 3 hours of work realize that is necessary to roll back to the original version because now nothing works and the track of which change is causing the problem is lost.
8.- Comments are evil.
This particular one is a bit controversial, most of us were taught that comments are good, and actually it’s better to have a comment in an obscure piece of code than just having the code by itself, what this point means is that: even better than having a comment for an obscure piece of code is to not to have that code at all, just refactor it until is a nice and readable piece of code. [EDIT] Please read this other post for a better explanation of what “comments are evil” means.
9.- Code to an interface, not to an implementation.
This is a classic one, coding to an interface will free us from the implementation details, we just define a contract and rely on calling the defined operations on the contract, expecting that the actual implementation will be passed to our code or decided at runtime.
10.- Have code reviews.
We all make mistakes, and there’s nothing better than asking some other person to have a quick and informal review in our code to find them, in order to make the reviews, it’s better not to wait until the code is completed, it’s better to ask for reviews whenever some important part of the code has been completed or when a few days have passed from the previous review.
There are two main reasons to refactor.
- To improve the code/design before building on it’s top: It’s really hard to come up with good code on the first attempt. The first try to implement any initial design will show us that we misinterpreted or forgot some logic.
- To adapt to changes in the requirements. Change happens in the software development; to be responsive to change is better to have a good code base.
We have two options for both scenarios, path the code or refactor it. Patching the code will lead us to unmaintainable code, and will increase our technical debt, it’s always better to refactor.
The sooner the better as is easier, faster and less risky to refactor over a recently refactored code rather than waiting to refactor for the code to be almost completed.
All the code and all the design are candidates for refactoring. An exception for not refactoring something could be a working piece of code which is quality is low, but due to be close to a deadline, we prefer to keep our technical debt rather than risking the planification.
There are two rules to never be broken when refactoring
- With lots of unit tests. This is going to give confidence to the developer that he is not breaking anything during the refactor.
- With consistency. There’s many ways to improve the code, but the underlying direction has to be always the same, for example: if you are always using error codes and not exceptions, keep using error codes… This will make sure that everyone is rowing in the same direction
Two persons should be in charge of the refactor.
- The developer who created the code. He will have the main role of the refactoring, he will perform all the changes.
- A senior developer. To supervise the refactoring, he will mainly keep an eye on consistency.
So, is refactoring good or is it bad?
Refactoring is the essence behind iterative development, but in order to turn it into a good practice you have to be very careful, again, it’s essential to have unit tests, and to refactor with consistency, if you do so refactoring will turn into a very powerful tool for your team.
The main reference about refactoring is the book “Refactoring: Improving the Design of Existing Code” by Martin Fowler, a must read for any software developer. Other references are:
There are many articles on Internet with tips on how to become a better developer, most of them focus on promoting learning attitudes like reading articles, books…
- Ryan Farley – Becoming a Better Developer
- Bil Simser – Being a Better Developer… in 6 months
- Justice Gray – How I am becoming a better developer, part 1 of infinity
- Rodrigo Diaz – How to be a better developer?
In this article I want to approach this subject from a different perspective I am going to present a few unusual tips which I believe will help you to become a better developer.
Be adaptable to any work environment (there is no “I” in team)
You may be a convinced agile practitioner or a waterfall one, but in the team where you are working they are not. Or you may be in a design session where you don’t agree with what has been decided…
You will always face conflicts, a good developer will know when it’s time for discussion and when it’s time to stick with the team and do as best as possible. The worst dynamic for a team, it’s when the people are not aligned in the same direction. (article from Jeff Atwood – codinghorror.com about this issue) .
This means that when a decision has been made you shouldn’t use every opportunity, every meeting, to remind your colleagues how wrong you think they are, you will be just mining the team confidence. One of the worst aspects I have observed from software developers is their ego, I’ve seen many times how attitudes like “If it’s not my way, no way” gets in the middle of getting things done.
This doesn’t mean that you don’t have to fight for your opinions and ideas, there is a time to make decisions and that’s when you have to bring all your ideas, after a decision is made, embrace it as if it was your decision, if you can’t is better that you just talk with your manager and you leave that team.
This doesn’t mean either that you have to give up if you see that the team goes in the wrong direction just because a decision has been already made, wait to have evidence that the team’s direction is not the right one, think on how to improve it and show it to your colleagues with a positive attitude
Understand that most of the times everyone is wrong
Drop the attitude “I’m right, You’re not”, both of you are wrong. In the software development industry I’ve seen very few times situations where someone holds all the truth about something, is very likely that in a software discussion all the parts involved are just partially right, a good software developer has to be able to recognize what can be bundle from everyone’s opinions in order to come up with the best possible solution.
Don’t get stressed. Enjoy what you are doing.
I keep reading articles about telling developers to read blogs, books, to code in your spare time, to write your own posts… And it’s not that I don’t think that it won’t help you to be a better software developer, of course it will, but it can also be really bad for you.
I actually wrote an article about how passion is the main difference between a good software developer and an average software developer, but if that passion is pushing you to the point where you are getting stressed, just take one step back.
- If you are not enjoying it, why are you doing it?
- If you are not enjoying it, you will eventually quit.
Meet Avery, the average Software Developer.
Let me introduce Avery; Avery is a programmer, he has been working in the IT department for a big non IT company for several years, he considers himself a Senior Developer, he has never questioned his approach to the software development, he doesn’t see coding as an art, he doesn’t believe that there is “ugly” code and “beautiful” code, he believes on the overall quality of the product rather on the quality of the code, he doesn’t like changes or new ideas about his code BUT he will eventually implement something that works. As you can see, Avery is the average programmer.
What’s the difference between an average Software Developer and a good Software Developer?
There is a major difference between an average Software Developer and a good Software Developer: Passion. Passion is what pushes developers to make good code rather than applications that just work; having good code it’s important because it makes the foundation for having a maintainable application.
In any case, passion is not enough to become a good Software Developer, it’s a good start, but it has to be combined with experience, perseverance and a bit of talent.
Are you an average Software Developer or a good Software Developer?
Is likely that if you are reading this article is because you read other programming articles, so my guess is that you have the passion, but are you a good Software Developer? To be honest I find that question very hard to answer with a closed definition, but there are a few symptoms of being a good developer.
- You are passionate about programming.
- Others consider you a good Software Developer.
- You want to become a better Software Developer. When you think you have reached the top of your profession is when you start going down and become an average Software Developer, there is always room for improvement and new things to learn.
- Your main motivation for being a good Software Developer is not money.
Can an average Software Developer be a Senior Developer?
The category of a Software Developer is mostly based on its revenue and experience, so YES an average programmer can effectively become a Senior Developer. For good Software Developers is sometimes frustrating to see that, but it is natural and right that companies base their decisions on plain figures, what is really important is that managers in the Development teams can see beyond that so they can reward good Software Developers somehow else like with better salaries, better hardware, letting them mentor the junior members, giving them proper credit…
So, is it bad to be an average Software Developer?
Not at all, being an average Software Developer is just fine, in the Software Development industry as in any other industry you will always find average professionals which will do a good job every day, being a good Software Developer is to be one from the small fraction of those professionals that take an extra step and become leaders.
Being a good developer is like being any other good professional, it’s all it’s about doing as much quality work as possible. There is a popular sentence that summarises it: “Do it. Do it right. Do it right now”.
1.- Have your own to do list for the day.
The best approach to complete complex activities is to break them down into simple activities. Do this every morning by breaking down the different activities you would like to complete for the day and assign them a schedule. This will help you to:
- Have a better understanding of the activity.
- Have a focused goal for the day
- Improve your estimating skills. After a few days you will find that you can predict how much work you can do in a day.
2.- Do one thing at a time.
It’s been proven by different studies and published in different media (ie CNN) that it is more productive to be focus only on one task than to do multitasking.
Work in short batches of intense work of about 25 minutes with a 5-10 minutes rest. There are popular techniques like the pomodoro technique to help you manage the time. There are also tools to help you measure the time you spent on the different tasks, my favorite one is CoolTimer.
3.- Do it right.
There are two keys to know if something is done right
- To be proud of the solution; it is not just any solution, it is a good solution. It follows the principles of the “Pyramid of the software quality“.
- The solution passes at least one review. Ask one of your colleagues that you respect as a good developer to review your solution and for his sincere opinion.
4.- Don’t finish something until it’s completely done.
We all know that if there’s still a glass to wash, we cannot say that we have done the dishes, the same applies for painting a wall or driving to a destination but in software development we don’t do that, we say that we are done even when we haven’t completed all the unit tests or when we haven’t checked if the implementation is correct with the customer, that’s a typical behavior from Hope Driven Development and that’s evil.
Something is only done when you are 100% sure that it won’t be necessary to work at all on that solution unless the requirements change.
5.- Better late than sorry BUT better sorry than never.
If it’s going to take you an extra day to complete the testing of some code, or to refactor a class which is unreadable, do it, that’s an investment in time for the future, but if you are stuck with something and you are delaying the project too much, just find an easier solution. It may not be as elegant as the one you are implementing, but at least you will have a solution. Make sure to document it as future risk for the project and something that will probably need to be revisited.
Would you go to war without a helmet? Would you drive without the seat belt? Then why do you develop software as if it shit doesn’t happen?
Meet Martin (an average developer) and John (a great developer) Martin is reviewing John’s code:
-Hey John, why do you validate the value of this parameter in your method?
-Well Martin, this is a public method and I’m making sure that its value it’s either “A” or “B” some other value will be invalid.
-I know John, but my class is the only one calling the method and I know I’m only passing “A” or “B”.
-Martin, have you ever heard about HDD?
The previous conversation is a fictitious one, but I’m sure you have been in a similar situation. HDD is the approach to software development where decisions and code are made based on assumptions and guessing
HDD does not only apply when coding, it applies to all the stages of software development, I remember been in a design meeting for a new interface to an external system, the documentation we had was minimal, so we didn’t really know what we were supposed to develop, what did we do? We just guessed what the implementation should be, so when we had to integrate with their system…. CRASH!!! Total disaster, we had to rewrite lots of code.
Everyone realizes HDD is bad, but we all still keep doing it, the only explanation I have for this is that Software Developers are extremely optimistic, is like when we have to give an estimate, 90% of the times our first estimation is: “It shouldn’t take more than one day or a few hours”, which is the same sentence you are going to repeat for the next week.
Most of the bugs I’ve seen During all the years I’ve been developing software were caused because HDD. I’ve come up with a list of symptoms to detect when HDD is being used and a list of tips to prevent it.
Symptoms that you are using HDD
- You use words like: “should”, “I think so”…
- You don’t have unit tests.
- You are more concerned about performance than your code quality. That’s one of the common traps, it’s usual to find developers arguing that they don’t want to add an additional validation, or some logic for error handling because that will cause bad performance, that’s wrong, what we should do is first make the best code as possible and then optimize it for performance, 9 out of 10 times the performance is not affected.
- You don’t have frequent demos/reviews with your product owner/team.
Tips to prevent HDD
- Every time you hear “should” or “think so” translate it to “I don’t have a clue”.
- If it doesn’t have unit tests, is not done.
- First care about your code quality, then improve the performance.
- Communicate, communicate and communicate.
What do you think?
So what would you do if you were John in the fictitious conversation above, what will you say after all:
a) HDD is just stupid, remove the validation, that’s unnecessary.
b) I see! We have to prevent HDD, let’s keep the validation.
Please let me know what you think in your comments, I’m looking forward for your opinions.
Pyramid Shapes. (Types of code)
Based on the previous article, we have seen that the code can be seen as pyramid where its base is formed by the characteristics that make the code robust and future-proof and the apex is represented by the amount of functionality and reliability of the code.
The shape of the pyramid can tell us a lot about the code behind it, there are three different types of pyramid shape or what is the same three different types of code:
1.-Code that needs refactor. The column pyramid.
This pyramid base size is too small for its height, the stability of the pyramid is at danger. This means that the code created to implement the specified inputs is not good enough to ensure the reliability of the software, it is also likely that when will like to make changes to the code they will be much complicated, unreliable and slow.
This code is typical from junior developers, developments under high pressure and unmotivated developers.
2.-Code that is fine as it is. The balanced pyramid.
This pyramid base has a good proportioned size for its high. The code is fine as it is, that’s we every single development should aim for.
This is the hardest code to obtain, it requires time, good leadership and good developers.
3.-Over engineered code. The flat pyramid.
This pyramid base size is bigger than necessary for its height. The code is 0ver engineered, is has more complexity than necessary.
This code is typical from senior developers when trying to create solutions too much flexible.
How to measure the dimensions of the code pyramid?
Unfortunately there isn’t any scientific approach to measure the testability, readability, extensibility and atomicity of the code, we can only draw a mental picture of the different vertex of the pyramid based on our own experience and then decide which one of the diferent three types of shape it is.
The quality of the code can be seen as pyramid where each of the 5 vertex are one characteristic of the code.
The pyramid has two parts the base, and the apex.
The base of the pyramid will be formed by the characteristics that make the code robust, future-proof. The apex is represented by the amount of functionality and reliability of the code.
The higher you want your apex to be (more functionality and reliability) the bigger the base has to be.
The base of the pyramid
This characteristic measures how easy is to read and understand the code and it’s purpose. The main factors that affect the readability are:
- Good comments
- Good naming of variables, functions, classes…
- Consistent coding standards
- Clean logic
The highest readability, the less time a new developer will need to understand what the current code is doing.
This characteristic measures how easy is to add new functionality, a good design will likely provide high extensibility. The highest extensibility, the less time for a developer to add new functionality as changes in the current code shouldn’t be necessary.
This characteristic measures how the different units of logic of the application are separated so that when a change is necessary it is only performed in one place in the current code. High atomicity is usually achieved following a few good principles when coding like:
- SOLID Principles
- Continuous refactoring
This characteristic measures how much automated and how much coverage the code tests have. This not only covers unit testing, but integration testing and E2E testing as well.
The apex of the pyramid
The apex of the pyramid measures how many things the code does, and how reliable it is.
Balancing the base and the apex.
The key for having a good pyramid is that the base is big enough for the required apex, in the next post we will discuss what different types of pyramid shapes we can find and which are adequate for every scenario, you can subscribe to get the second part of this article by following the RSS link on the top right hand side of the blog.
1.- The variable name has to be as descriptive as possible. Don´t use generic names.
Good example: daysDateRange, flightNumber, carColor.
Bad example: days, dRange, temp, data, aux…
There are a lot of developers who would prioritize short variable names over descriptive names because that will save time when typing the code, but who cares? It doesn’t help to improve the quality of the software, it only saves a few minutes per day (maximum) per developer, by the other hand, when having descriptive variable names, the overall quality of the software will increase because it will be easier to modify and read the code.
2.- The variable name has to be as short as possible.
This rule goes hand by hand with the first rule, the variable names should be as short as possible but as descriptive as possible.
This basically means that while we still try to come up with short names, we prioritize descriptive names over short names, we only pick the shorter one when they are as descriptive as the longer one.
Bad Examples: howLonDoesItTakeToOpenTheDoor, howBigIsTheMaterial…
Good Examples: timeToOpenTheDoor, MaterialSize.
3.- It´s OK to use abbreviations, but explain the abbreviation with a comment.
Sometimes to have a good descriptive name is necessary to make very long variable names, which is fine, but the variable size can be improved by using abbreviations, just make sure that when the variable is declared there’s a comment that explains the meaning.
4.- Use proper Hungarian notation when necessary.
There’s a great post from Joel on software that explains what the proper Hungarian notation is and how to use it. Basically it says that when coding a method where we have variables holding the same data, but with different types, the Hungarian notation can help us.
Example: Imagine a method that receives apples, then it classifies the apples depending in their color, and finally discards the ones that are not matured enough. We could use in this example the following variable names: incoming_apples, red_apples, yellow_apples, notMaturedYellow_apples, red_apples, maturedGreen_apples…
5.- Don´t use negative logic for your variable names.
Good Example: IsEnabled.
Bad Example: IsNotEnabled.
It’s always easier to read and undertand an statement that is expressed in a positive language that in a negative language.
6.- Be consistent.
If you have used a variable name called customer in a method, then don’t call it client in the next method, or if you use an abbreviation in one method, use it for all the methods the same.
7.- Map the application domain terminology with your names.
In different domains, different concepts have very specific and different meanings, for example, “order” doesn’t always mean the same in the different domains, try to map these specific concepts with your variable names so that when you name something with a concept from the business domain it means exactly the same.
Example. If your customer just considers “order” an “order” that has been approved, don’t call “order” to a non approved one in your code, call it “nonApprovedOrder”.
Golden rule.- Spend a few minutes thinking about your variable names.
If you find yourself writing variable names as soon as you need them in your code without even thinking on their name for a second, you are probably picking bad names for them.
If you always try to have good variable names, and you have found yourself thinking a couple of minutes for the best name for a variable, even if you don’t follow the other tips, you are likely to have pretty good variable names in your code.