Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
– Martin Fowler
Writing clean, understandable, and maintainable code is a skill that is crucial for every developer to master.
When I say clean code I mean:
- Proper variable name, function name, class name, proper indentation, proper spacing, proper comment, and proper/unique code style throughout the team.
- Minimal number of lines of code, classes, functions, etc. Less code means less headache, fewer bugs, and less maintenance cost.
- No duplication of code. Duplication in your software shows bad software and lack of knowledge.
- It might seem contradictory to my previous point but too much abstraction is also bad. If your abstraction forces you to add more conditions and extra parameters in your method every time a new feature is introduced, it is a bad/wrong abstraction and you should follow the below things:
- Try to find a way so that every time you introduce a new feature, your abstraction should not be affected.
- Go back to duplication. You heard it right. Duplication is always better than wrong abstraction.
Well, I don't see this as a failure of abstraction. It's caused by some specific other failures.
a. Failure of people to understand data modeling, and the
difference between interface and implementation. "A new
requirement appears for which the current abstraction
is almost perfect. Just because the code is the same
doesn't mean it should use the same abstraction. The
data model is wrong, not the abstraction.
b. Failure of people to think of the entire system, when
making a change. The rookie mistake is to think that
adding one more conditional is always harmless, but, at
some point, you've got 3 tons of straw on that poor
camel's back. Adding just one more case may have been
the correct fix last week, but not this week.
- No magic numbers (A magic number is direct usage of a number in the code). Magic numbers are bad, not readable, hard to maintain and not reusable.
- Minimum/No hard coding. It is bad, not reusable, not testable, and not maintainable.
- Code should pass 100% of test cases(even 99% shows that you are screwed).
- Code is easy and cheap to maintain.
- Mature programmers know that the idea that everything is an object is a myth. Sometimes you really want simple data structures with procedures for your task. So you have to carefully think what to implement also thinking about the future perspective that what will be easy to update.
Always write concise documentation of your code( classes, functions, properties, etc.)
Tips to write clean code
- Variable, function, or class names should be descriptive. If it requires a comment to describe what the name does, it's a bad naming convention.
let s; // number of seconds ---> Bad naming convention
Good naming convention:
let numberOfSeconds, customerName, employeeName, mailMessage, mailFolder
- Do not include any redundant information/ noise words in naming. Some of noise words:
- Data
- Object
- Info
- Information
- Variable
- String
Bad naming convention:
userInfo, userData, userVariable, userObject, accountInformation, employeeString etc.
Good naming convention:
user, employee, account etc.
- Be consistent while naming variables of similar tasks. For example, while naming any variable which stores fetched data from an API call or Database use only one of these: get, retrieve, fetch. Don't use more than one as they do the same task.
Say you decide to follow get convention:
getUser, getName, getFile, getAccount etc. ==> Good convention
getUser, retrieveAccount, fetchName ===> Bad convention
- Don't use magic numbers(A magic number is a direct usage of a number in the code)
Bad convention:
if(age>=18) "eligible for voting"
Good Convention:
MINIMUM_AGE_FOR_VOTING=18;
if(age>=MINIMUM_AGE_FOR_VOTING) "eligible for voting"
Avoid leaving code inside comments because it makes other developers scary to remove them as they don't know whether it is for comment purposes or left to use later.
-
Always follow the coding style defined by the programming language which you are using. Few conventions in Typescript:
- Variable name should be in the camel case.
- Function name should be in the camel case.
- Class name should be in pascal case.
Try to follow the DRY (Don't Repeat Yourself) principle.
Function name should be a verb.
Class and variable name should be a noun.
Prefer to use code formatters such as Prettier for better code arrangement.
People often ask me, what should be maximum length of variable, function or class name. Well my answer to them:
If there's a shorter, but yet descriptive way to name the function, variable or class then your current variable, class or function name is long.
Conclusion
The skill of writing clean code comes from using it again and again in software development. It is the least you should follow while writing a software code.
Top comments (20)
I slightly disagree with No duplication of code. It's a good rule on general, but sometimes its better to have duplicate code if it keeps you from bad or premature abstractions. Readability over DRYness.
Well written Jan, to add few helpful quotes on top of this:
"A little copying is better than a little dependency." go-proverbs.github.io/
"duplication is far cheaper than the wrong abstraction." sandimetz.com/blog/2016/1/20/the-w...
it is common to see intermediate level developer writing complex code with high readability/maintainability cost just for the sake of DRYness
Yes Jan that's correct. Too much abstraction is also bad. Especially such abstractions which change every time you introduce new feature. At the end of day, it's you who should be aware of various scenarios while writing any abstraction. I always suggest people to write duplicate code for first and second time, for the third time if same thing arises, we can start refactoring. You can read my blog on Technical Debts and Refactoring.
The purpose of all of these rules is readability. There is nothing less readable than having a code base with needless needless amounts of functions and needless amounts of abstraction.. This notion that functions should only be 6 lines of code is silly and counter productive. As one of the other commenters mentioned, readability is most important.
Minimal number of lines of code, classes, functions etc. Less code means less headache, less bugs and less maintenance cost.
My purpose is to tell people not to write 100s of lines of code in the same function. At the end Readability and uniformity is what matters and same I am trying to convey here.
Less code does not mean less headache. Better to be more verbose and readable then too terse.
I'd say leaving code in comments is okay if it's accompanied with a comment to tell when to use the code. For example, you could have correct code in a comment but you have to use some kind of workaround while waiting the library maintainer to fix some bug in dependency. And you cannot code automatic switching because you're not sure which version will contain the fix.
However, in many cases you should prefer having a config variable to activate old or new logic for that part, even if the config were called CONFIG_WORKAROUND_FOO_BUG_53663.
But why would you leave a code like that and why do you need to design your software such as you need to comment and uncomment your code for different features. I can understand it is okay for testing but I don't think it is a good approach to follow for production ready code
I was thinking a case where logically you should use some code but due a problem in a library that you're using, you have to use some kind of workaround (with possibly worse runtime performance).
However, until the library maintainer has fixed the problem you cannot be sure if the correct code you are currently thinking is the actual final implementation because it could turn out that the library maintainer cannot fix the current API due backwards compatibility issues and you have to use a newly introduced function to get the fixed behavior for the use case you need. And if you use programming language such as C you cannot keep the "probably soon to be implemented code using currently non-existing API" visible to compiler so you have to hide it from the compiler. Putting the code in comments is one common way to do it.
Of course, you can also keep track of such future changes somewhere else but the actual source code. It really depends on how the whole project is implemented.
Great post, thanks for sharing. Another good practice might be to adopt an upper limit of characters for the function names. If your function name is to long that indicates that you should probably have to break it down.
@sp1thas thanks. Yes I will update the blog. I need to add more points to it.
Also proper line breaks, like those use by Prettier on long lines. Avoids having to scroll right and left to read reminder of statements. Having proper structured code goes a long way on readability as well.
Care to elaborate on the Magic Word thing? I don't get it. Also shouldn't it be >= instead of >?
Improved thanks. Magic number is nothing but using direct number in code:
if(name.length()>12){ ----} // here using 12 directly is bad.
Instead we should use
MAX_NAME_LENGTH=12;
if(name.length()>MAX_NAME_LENGTH) { ------ }
imo its typo, it should look like this -->
if(age >= MINIMUM_AGE_FOR_VOTING) "eligible for voting"
You were absolutely correct while saying to duplicate the code instead of adding too many abstraction level. As not only it makes code complicated for others to read but also a developer would find it little bit tricky to make changes in the same. And also person should avoid duplication in the 3rd time - not necessarily in the 2nd time with a bit of abstraction. A good article though with a perspective of clean coding !!
Thanks for uploading this kind of content.
I think there is a typo. You used "Varibale" instead "Variable". Is this an intended one?
Improved it. Thanks
Still many "varibale" typos in the article - try find to locate all.
hi, want to know more
Some comments have been hidden by the post's author - find out more