How to write code?
Writing code doesn’t mean creating a single feature when needed or learning the programming language rules only. It’s a more holistic approach to the project. Writing code in high-quality includes:
- Thinking about possible solutions,
- Combining all needed features,
- Testing the code,
- Thinking about the future of the project,
- Documenting changes and the essential parts,
- Discovering new solutions,
- Resolving problems,
- Using existing dependencies;
To make development easier, more pleasant, and efficient, developers should apply some rules in their minds and understand the consequences of non-compliance.
Think -> Try -> Project -> Code
Every line of code should be thought through. It is important to know which approach/tool/library is the proper one to solve the problem and how the final version of the product will look like before the start. Otherwise, it’s easy to end up in a dead spot with no chance to move forward. It’s easier to prevent it than changing the whole approach in the advanced stage of works. The team’s time ends up being wasted, the task is getting delayed, and overall nothing is going as expected. There is no fun in that.
Of course, developers should try to check if particular solutions are appropriate and can be helpful, but these attempts should be as simple as possible (to be precise: these attempts should reject useless solutions – in the first stage of the development process).
The whole process related to the task should be estimated – the task doesn’t consist of the coding part only. The time needed for research, thinking, writing code or testing should be included in the evaluation. Of course, a problem may occur, making the task more time-consuming. In this case, developers should verify where they made a mistake. If a team doesn’t know how to do something, they have to point this out to the customer during the time of estimating the task. He has to be aware that something is difficult and more labor-consuming as soon as possible.
Avoid increasing the technical debt or take care of it
All programmers taking your code over will appreciate it if the project is free from technical debt. However, sometimes programmers aren’t able to develop a perfect solution for all cases. It may occur because of time constraints, or clients’ decision to limit investment. In such cases, developers should document this part extremely carefully to let others understand the problem in detail.
In professional cases, a static code analysis tool should be used to measure technical debt in projects – it raises the awareness of debt, helps to fix/refactor/write code, and allows to reserve the proper amount of time for adjustments.
Experiments are needed and fun but… not always. When working on a mature project – consistency is a key to write code that is clean and clear for everyone. The new approach in such a project can introduce confusion and be misleading for both new developers and ones that are already familiar with the app. A single project should consist of a coherent body and not look like a sandbox.
Developers should try new approaches but in new projects. If a programmer wants to apply a new approach, has to be sure that it won’t break consequently applied conventions adopted at the beginning.
Create “small” merge requests
Countless developers fight with a “BIG-MERGE-REQUEST-PROBLEM”. Huge MRs are the biggest issue for reviewers – they are spending a lot of time omitting key elements (it’s very discouraging). Even if someone creates the rules of what a merge request should look like, there is a problem with the numbers. It’s hard to define how many lines/files/characters should be changed in a single MR. One can contain 100 lines of changes with 1000 changed characters when the other one has 1000 lines of changes and 500 changed characters. That’s why it’s hard to define numbers when it comes to limits in MRs. The only reasonable solution is for Merge Request creator to define, when is the right time to create the request that will be easy to review.
Be a reviewer
The review is an essential part of every task! During this step, several parts of coding can be checked. A reviewer can take a look at code quality, logic, approach, or architecture – depends on the circumstances. It’s a good practice to make reviews in pairs where less experienced developer review as the first one. More experienced reviewers can check and teach both creator and less experienced mate in such approach. It’s valuable feedback and should be treated as such. The well-done review contains not only complaints or comments but questions and praises also.
Keep project components in the appropriate order
It may seem that components arrangement in a project isn’t so crucial. It’s true. It isn’t but well-organised components may tell developers many things about the project. It can provide inside on architecture or external services, and provide better navigation. Overall, it’s better to work with a well-organized structure than with a meaningless structure.
PS. The entry threshold is lower in such a project also.
SOLID is a mnemonic acronym for five design principles:
- S – Single-responsibility Principle
- O – Open-closed Principle
- L – Liskov Substitution Principle
- I – Interface Segregation Principle
- D – Dependency Inversion Principle
We won’t be going further with the explanation in this article. Uncle Bob (Robert Cecil Martin) did it perfectly. Our intent is to underline the importance of this excellent practice in everyday coding. The SOLID principles should be in every developer’s mind. Following them will ensure that the project is extendable and easy to change. What’s more, these rules make a code much clearer and easier to understand for new contributors. The beginners should read about it, look at the examples, open their old projects, try to find out a code that contradicts these rules, and refactor it – after doing this, they will be much better programmers in the future. Working on a particular example will help them learn the importance of this practice.
PS. These rules should be well known for all programmers using object-oriented programming!
Every team member participating in the project should take care of names and their meanings. Most words have synonyms which can sometimes lead to misunderstandings that may result in bugs. That’s why every project member should use appropriate vocabulary to avoid confusion (both managers and technical guys). It’s a great idea to create a project dictionary in the initial phase of the project. Accepted names should be used in the documentation, code, during the meetings, etc.
Take care of naming
Everyone knows that inventing names is almost the most difficult thing in the programming world. That’s why the names in the code have to be well thought out! Naming is not only important at a high level, but this also applies to class names, global variables, local variables, etc. Call things according to their meaning, for example:
- variable keeping car amount: “carCounter”,
- class configuring Google connector: “GoogleConnectorConfig”,
- method/function returning user: “getUser”,
- account repository-class: “AccountRepository”;
Developers should remember that code with well-chosen names is self-explanatory and doesn’t need additional comments or documentation.
Think of the readme file as a part of the process
Readme isn’t an additional, worthless file in the project. Software developers should maintain it from the beginning to the end of the process. It is documentation with great value, where all the most significant things about the whole project are kept. The readme content mainly consists of information about the license, copyrights, project configuration, use cases, bugs, changelogs, contact to developers, installation instructions, and so on – it depends on the kind of the project. Having this file updated, it’s a high probability that other developers won’t ask how to do the simplest things in this project or how to run it – so it saves time in the long run.
Test the code
If somebody thinks that testing is a waste of time, THEY ARE WRONG. The tests are a crucial part of the development process. Thanks to the tests, developers can find bugs, check logic correctness, be sure that future coding won’t cause bugs/break contracts with incompatible changes, or make them intentionally (developer changing code will have to change tests too, and the reviewer can point it out). Many companies/clients require high code test coverage, which is an excellent practice – the development process is longer, but delivered products are better. Additionally, well-written tests can explain a code, and extremely detailed documentation is no longer needed.
PS. Many well-known development strategies are using various testing approaches, e.g., TDD, BDD.
Comment your code
Difficult parts shouldn’t be left without comments. The comments aren’t for others only but for the authors also – they will understand comment importance, when will have to fix, change or refactor a piece of logic. Short explanations in code help understand what’s going on (instead of exploring the author’s intention).
Of course, it’s nonsense to explain the variable “carCounter” holding car amount. Still, if the software developer found, e.g., regex on the Internet, he should put a link in the comment for everybody to know where it’s coming from.
PS. For me, the most helpful comments are comments describing classes in external dependencies because a developer who potentially wants to use this class can read the description and decide if the class is useful in his particular case.
Avoid code nesting
Some say that nesting shouldn’t be deeper than 2 or 3 levels. Code nesting can be avoided by returning from method/function ASAP. Make the smallest method as possible – the smaller method, the less direct nesting.
If-else blocks are useless in many cases. If “return” is used in the “else” block, then revert “if check” and put “return” into the “if” block – the rest of the code DOESN’T need the next block of code. A great example can be found in Google Testing Blog.
Do not push commented code into Git
This is a common phenomenon that software developers (not all of them) who are not confident in changes – are constantly trying to push comments on old code into the Git. It’s strange because all version-control systems (or most of them) keep history. It means that the removed code pushed in the next code version can be reverted BECAUSE IT IS IN MENTIONED HISTORY.
NOTE: There is a way that code from previous versions can be unreachable:
- After commit with amend option.
- After commits squashing
PS. If you aren’t familiar with Git, please read Git Book.
Conclusion - coding is so much more than programming languages
Many good practices presented above refer to the beginners or new developers joining mature projects. How many times, have you seen someone new in your team, trying to write code and having troubles with understanding the whole concept? It’s a common event due to lack of documentation (including readme, comments, variables called “a” or “temp”, commented code, unstructured components). Sometimes, it’s because of the time shortage. All developers should respect some rules which aren’t difficult to use in daily work. In this case, simple steps are bringing indispensable value. The article mentions some of them – basics only. There are many more but relax. Most of them are used subconsciously and naturally.
Remember that self-discipline always pays off in the long run!