Without rules and standards, we would be living in total chaos, and if every programmer had the freedom to do or write whatever he wanted as code, we would probably still be in the time where computers could occupy an entire apartment š.
But fortunately, this is not the case š. There are rules and standards every programmer should know. If you didnāt know these standards, donāt worry, I was a bad programmer too, a very bad one, but now Iām better and Iām still improving. Now, if you already knew them I congratulate you. But read anyway until the end for peace of mind.
I wonāt really detail or give examples to these rules, as each of them requires at least a whole article with a lot of real cases examples, exceptions, or edge cases. Iāll just list them and cover each of them alone in its own article.
Take care of your code quality
It implies that you write readable code. Use styling rules related to your programming language or technology and be consistent about them (For instance in python, the coding style conventions are described in PEP 8 of the documentation). You can install a linting extension related to your programming language/technology in your IDE. It will enforce your code quality and give you good habits.Give meaningful names
Give a meaningful name to your variables, functions, class, and packages. It will help understand the big picture of your codebase without even reading the implementation details.Use the DRY (Don't Repeat Yourself) principle
Avoid as much as possible repeating your code. It will first reduce your codebase, and if for any reason you have to change or improve that code, you'll change it only once instead of applying the same changes at multiple places.Write short functions that handle specificĀ tasks
Keep your functions as short as possible and make them handle a single task. Plus, it will help for code reusability and code refactoring.Well document yourĀ code
Add useful comments and document your functions, classes, and packages as much as possible. Add description and type-hint for function parameters and return values. But, avoid obvious comments. It will also help to understand the big picture of your codebase without even reading the implementation details. And some of your IDE extensions could even help you automatically generate a documentation for your software if it's well documented.Avoid using Magic numbers or hardcoded values in yourĀ code
It's will save your life and contribute to your codebase maintainability.Limit code line length to a standard value (80 chars for instance)
It improves code readability as well.
Very Important
- Test your code. Write test (at least unit tests) cases as much as you can, especially when the feature is tricky or complex.
- Think big. Take care of scalability and performance matters. Don't code like if you'll be the only user of your website, even if it's a side project, or don't code like your software will just have 10 or 100 users, think big. Think about what will happen if it came that there are millions or billions of users using it. Won't this database request or loop take a while ? will this code still do the job ? Think about it while coding and improve your code as you go.
- Pay attention to code reviews. During code reviews you'll learn a lot and also share a lot with others. And the most important thing, during reviews you will catch earlier bugs, and that helps reduce the technical depts. So pay close attention to them.
- Avoid Hacks in your code. Avoid tinkering with code, finding a temporary quick fix to work around a problem or bug. That will probably break again later (maybe even in production). Instead, go to the source, take the time to understand the issue, and try to find the right final solution for good. If you found it by help, on a website like StackOverflow for instance, make sure you understand it before adding it to your codebase.
That is all for this article, If you have any pearls of wisdom that you think are missing, please let me know in the comment section. I may include them in another article.
I share what I know because:
The more I learn, the more I realize how much I don't know. (Einstein)
Top comments (32)
Regarding your "rules", most are very good. But #3 is horribly overused by people who think that everything in life is either a 1 or a 0. Most of the time a bit of repetition is better than too much abstraction. Practice the rule of least power: don't abstract until you must.
If you've done 1, 2, and 4 well -- and kept abstraction to a minimum -- then your code is its own documentation. There is no need to document further. Code should read just like your native language. Adding comments just contributes to confusion. Now you have two sources of truth: the one thing you should never allow copies of. And invariably they will get out of synch.
Just write great code and leave the comments for expressions of intent or general discussion of how the code is intended to be used. One exception is when you are forced to write a workaround. Always comment the workaround and explain why you did it. Otherwise you or the next person will look at the code, think WTF?, and change it, only to discover painfully why it was hacked in the first place.
By #6 I presume you mean that we should use constants to keep unexplained simple values out of our code. Good naming is especially important here, and put the declarations/assignments at the top of the file or in a separate constants file. Even if you only use a value once. That's part of making your code read like your native tongue. 96_485.332_12 is just a number. FARADAY_CONSTANT is not.
In disagreement with some of the other commenters here, I think 80 chars per line remains an excellent limit with very few exceptions. Yes, we have bigger screens and multiple screens, but I often have several files open side-by-side, and every time I've increased line length I've regretted it. Also, from an accessibility perspective, remember that not all coders and reviewers can read that tiny font you like. Monospace fonts are already horizontally greedy. Eighty chars is enough for anyone. Think vertical.
Remember the most important rule: always think of the next coder. Code is a conversation not just between you and the machine, but between you and the next human to look at the code. Think about their needs, too.
Finally, there are two kinds of anarchy: the anarchy of infants, which is violence and chaos, and the anarchy of adults, which is peace and harmony. That modern Western humans have been so conditioned by repressive governments to equate anarchy solely with violence and chaos is a triumph of authoritarianism and a recipe for perpetual infantility (leading, BTW, directly to the extinction of the species). So it would be nice if when you mean "chaos" you said "chaos" and did not besmirch anarchy out of ignorance.
Waow, this:
"Code is a conversation not just between you and the machine, but between you and the next human to look at the code.",
is soo beautiful, I new about it, but never read it that way,
it should be immortalized as a universal definition/quote for code ^_^.
It is certainly not original to me. I don't know who said it first. Maybe Ada Lovelace?
I trully agree, sometimes, we are forced to work around, like in python, when we are obliged to import inside a function instead of at the top to avoid circular import. Or in VueJS when we are obliged to access the child vm instance from the parent instead of using props. For those cases, we should leave a comment so others will know that it's not a bad code, just an edge case.
Those sound reasonable.
Hey, Charles, thanks a lot for your feed back. In the future I want to make a detailed article with examples, exceptions for each point, and concerning your suggestion on point 3 (Follow DRY as much as possible), if you could already provide me an example of exception (no matter of language, preferably python or javascript), in which the use of repetition is more judicious and allows to have a better code than to follow DRY, it would be really cool. Thanks in advance.
I don't really have a lot of spare time to dig up specific examples, but to be more clear, the trade off is between multiple components/functions/etc. (wet) and more configuration, or maybe layers of indirection and composition ("dry").
One app that I am occasionally forced to work on is abstracted to the point of absurdity. No component, no function, can be for a simple use. If there are ten components, then every bit of commonality must be factored out into another component and then reused. At each level as things are abstracted, they become, well, more abstract -- that is, more generic. This makes them simultaneously more powerful and less useful.
There have been times when I have needed to change one minor thing in that app, and have gone to the file where the actual component lives, only to find that it uses some more abstracted component to do the work. But on finding the file to that component, I find that it abstracts still further to another component. But then that component uses some utility -- say a GraphQL query -- and when I look up the query function, I find it wraps a function that wraps a function that sometimes wraps yet another function.
For a simple fix that should have taken a few seconds, I've now spent half an hour and tracked things back through a dozen files and I still don't understand what the hell all this code is supposed to do!
The actual problem was simple and could have been handled right in that component, but in an attempt to be ultra DRY, the coders made it so complex as to be unusable. And even the coders who made this mess complain about it.
In short, do things in your code as close as possible to where they are needed, and only abstract out functionality when it truly is duplicated and reusable -- and then only raise that abstraction to the level where the branches that use it meet. Except, of course, for general utilities such as
pipe
ornot
.Imagine this: Your front end uses components, no? So why not go all the way and have ONE component (call it
Component
) and just add a lot of optional props and branching code. Then you only ever have to write the component once, right? How dry is that?I hope that helps a little. But the easiest way to understand it is just to resist drying up your own code until it is obvious that you have to. You will be surprised how often you really didn't need it any drier.
Yep, I see your point. Too much lvels of abstractions will make the code difficult to comprehend and then to maintains, and simple code is most of the time better even if sometimes it seems to take more lines of code, or have few redundancies.
Exactly. The point of all programming is to take complex problems and break them down into progressively simpler chunks until they are understandable and easily solved. Then those bits are recombined to solve the larger problem.
Approaches that make the code more complex and difficult to understand are the precise antithesis of what programming should be. A variation on Occam's Razor is apropos: as simple as it can be and no simpler.
The majority of modern coding practices (IMO) start off with the right idea: making things simpler. But then they go off track trying to please everyone and soon they have become the problem rather than the cure.
Never write a line of code until you have to.
Never add a dependency except as a last resort.
Never abstract your code any more than absolutely necessary.
Not only will this keep your code simpler and more understandable, but it will save quite a bit of time once you learn the habit (until you learn it, plan on lots of refactoring as you realize you ain't gonna need it).
Yeah, I wanted to cover that as well when I'll detail the point 6 in it own article. Especially for constants that are really really coupled to their module or file and not used anywhere else, they can jsut stick at the top of the file module. But if they are very generic, or used at differents places or files accross the project, they need to be move into a settings or constant files (single point to manage them).
I look forward to your article.
And thanks for the correction about my use of the word
anarchy
. So I would have say,we would be living in total anarchy
.No, that's not any better. Total or incomplete, anarchy can mean either violence and chaos or peace and harmony. To use it with the assumption that it means chaos, whether total or not, is to deny the possibility of a mature, adult anarchy in which humans cooperate for the betterment and happiness of all. Those who wish to manipulate us for their own ends have a large stake in denying the possibility of a better world. If they can keep us at each other's throats -- or convince us that we will be if we don't give them superpowers of control and surveillance -- then we've lost all hope of a better world.
So if you mean chaos, just say chaos. It's clearer, too. No misunderstandings there.
I'll go for
chaos
. then, thanks.Nice checklist š I would recommend to not be too religious about the 80 character line length though. Sometimes splitting code across multiple lines makes it harder to understand. Long lines of code are an indicator that you might need to refactor your code though.
I think the last of the tips "Avoid Hacks in your code" should be the most important one! It's a massive headache when you have to fix someone elses code and it's full of these clever hacks. Please try not to be clever when coding! š
Sure, for the 80 chars rules you're right, I think some rules or best practices have rare exceptions or egde case that I'll try to cover in future posts.
Yeah, a real fixing code full of hacks will give long and painfull headache ^_^.
Thank you for putting this list together. I find it very helpful.
A follow-up question on Think Big: often, in order to scale you need to make certain software and hardware choices ahead of time. How do you go about deciding what is appropriate?
An example: in 2020 Signal gained huge popularity, which effectively "broke" the backend of the app - they didn't expect such a huge demand so quickly, so they hadn't optimized their backend.
What's the most sensible approach to avoid such a situation?
Hey Vic, thanks for your feeback. Very interesting question,
I would say that software is a bit like a building.
The basic architecture of the system, represents the foundations, there is a dimensioning, choices so that the building can perhaps evolve. You can for example build the foundation for a ground floor but the foundation can support a 2 storey duplex but not more. In fact, if the basic architecture is not made from the beginning to be scalable up to a certain level, trying to make it evolve beyond that level will probably lead to a collapse of the building. For software are a bit like that.
With one exception, a big one, the cloud.
with the cloud, we can scale our applications almost infinitely, horizontally or vertically, and even automatically depending on the demand.
So for me, either the system was already designed from the ground up to be really scalable (maybe using a microservices architecture), or else we can always see how to migrate to the cloud (PAAS or SAAS preferably), and pay the price.
Thank you for this explanation, Horace. I like the building analogy. It makes a lot of sense.
Nice post!
Thanks Aatmaj ^_^.
Testing isn't a bonus. It's the most important of all your suggestions.
You're also right, I might review a bit my article.
Super
thanks for letting us know this, this is very use ful
Thanks Tiwari. It's a pleasure.
Tanks
You're welcome Athif
Tanks sir your domain ples in programming
Didn't well understand. Want to know my skills or tech stacks ?
Teck stack
Python, Django, VueJS. Currently Masterging React and learning node.