Program code is executed by the machine, that is a fact. Machines do not care how your code looks, they will just run it. But it is important to remember that actual code is written by people and, most importantantly, for people. That's why high-level programming languages have human-understandable syntax and commands.
Everything Should Be Made as Simple as Possible, But Not Simpler
– Albert Einstein
Modern software projects are developed by groups of programmers, sometimes separated not only by office space, but also by continents and oceans. Fortunately, the level of technology development allows using the skills of the best developers, regardless of the location of their employers or other team members. This approach to development makes serious demands on the quality of the code, in particular, its readability and comprehensibility.
Acronyms OOP, DRY, SOLID, KISS, YAGNI and SOC should become the true companions of every competent developer in ourdays. These techniques and principles definitely deserve respect and reflect the universal rules of good code – simple, clear, readable, testable and maintainable. In addition to them, there are a few extremely simple rules that solve a number of problems with having a good code.
Style guide
A coding style agreement is a set of rules or guidelines for each aspect of a program written in that language. Some programming languages have official style references, others have variations naturally formed during software development. Adherence to the agreement on coding style is not a random whim of the team, and evidence of serious approach.
This is the first thing that a new project developer should be introduced before writing a single line of code.
These conventions usually cover comments, naming conventions, architectural best practices, declarations, white space, programming rules of thumb, programming principles, programming practices, file organization, etc.
In some development environments, you can initially set code formatting rules by loading settings with a separate file. Thus, all programmers of the project automatically get the same code, which greatly improves the perception. It is known that it is difficult enough to retrain after years of practice and get used to new rules. However, in any company code style is a law that must be followed strictly.
Magic Numbers
Simple rule of how you do not need to write code. Most often, the magic number as an anti-pattern is a constant used in the code, the meaning of which is unclear without comment or context. Such numbers not only complicate the understanding of the code and worsen its readability, but also cause problems during refactoring.
For example, there is a line in the code:
DrawContainer(35, 90, 850, 240)
Obviously, it will not cause errors in the code, but its meaning is not clear to everyone. It is much better not to be lazy and immediately write this way:
left = 35
top = 90
width = 850
height = 240
DrawContainer(left, top, width, height)
Sometimes magic numbers arise when using conventional constants, for example, when writing the number π. Let's say the project was added:
CircleArea = 3.14 * radius * radius
What's wrong with that? What if you need to make calculations with high accuracy during, then you will have to look for all occurrences of a constant in the code. This is a waste of a work resource. Therefore, it is better to write this:
pi = 3.14;
CircleArea = pi * radius * radius
By the way, sometimes fellow programmers may not remember the value of the constant used by you – then they just do not recognize it in the code. Therefore, it is better to avoid writing numbers without declaring them in variables, or even better, utilize constant values. By the way, these constants are almost always in the built-in libraries, so the problem is solved by itself.
Descriptive names
Code obfuscation – deliberate obfuscation of the program code with the help of the obfuscator application. The purpose is to hide the implementation and to turn the code into an inarticulate set of characters. This process renames variables, changes the names of methods, functions, and so on … Unfortunately, it happens that the code looks confusing even without obfuscation – due to the meaningless names of variables and functions: kGreenVar, myBestClass, NewMethodFinal, etc. This not only hinders the developers who contribute to the project, but also leads to an infinite number of comments. Meanwhile, renaming the function, you can get rid of the comments – the name will itself talk about what it does.
The result is a so-called self-documented code – a case in which variables and functions are named in such a way that when you look at the code it is clear how it works. The idea of self-documenting code has many supporters and opponents, whose arguments are worth listening to. I personally recommend to observe the balance and use reasonably and comments, and "talking" variable names, and the possibilities of self-documenting code where it is justified.
For example, take a code like this:
// find the sheet, write it to r
if x != null
while x.a != null
x = x.a
r = x.n
else
r = ""
From the comment it should be clear what exactly the code does. But it is completely unclear what x.a and x.n are. Let's try to make changes this way:
// find the sheet, write the name to leafName
if node != null
while node.next != null
node = node.next
leafName = node.name
else
leafName = ""
In that case we actually can question the appropriateness and necessity of using comment now. When there are a lot of comments, they lead to low code readability. Almost always there is an opportunity to make such changes to the code so that the need for comments disappears. In large projects, comments are justified in the case of using the API, the designation of connecting third-party code, the designation of points of contention or moments that require further processing.
CASAS – Call a spade a spade, new acronym?
Divide and rule
Almost any code you can look at closely and see the pieces, the algorithms that take a separate, completely independent solution. It takes time and experience to learn to see, highlight and, not less important, give them a meaningful name.
Let's take a look at these examples of adding subscription:
function subscribe(category)
return false if archivedAt != null || !viewPermissions.include(category) || currentSubscriptions.include(category)
subscriptions.add(category)
function subscribe(category)
return false if archived || accessRestrictedTo(category) || subscribedTo(category)
subscriptions.add(category)function archived
archivedAt != nullfunction accessRestrictedTo(category)
!viewPermissions.include(category)function subscribedTo(category)
currentSubscriptions.include(category)
This code is already similar to normal English speech. It's cognitive load is very low. By reading the "archived" method, you see what decision it makes and focus your attention only on a high level. By reading "accessRestrictedTo" and "subscribedTo" methods, you understand how they make their decision and your focus is on specific data. This code no longer requires analysis – it's enough to just read it. At the same time, we don't have to worry how permissions and subscriptions are implemented, we don't care if they change later. And notice that this code does not need any comments.
If you can't write it down in English, you can't code it.
Peter Halpern
Most programmers confuse good and perfect code. Perfect code just does not exist. There is no sense to engage in infinite improvement in the pursuit of the ideal one. Good code is readable, understandable, solves the problem, is correctly structured, and does not contain errors. Most of the rules listed above are basic and definitely deserve the Captain Obvious award, however are routinely ignored by most developers. Although compliance with these simple foundations, without deepening into the jungle of perfectionism, can make their code better at times, in all respects.
Writing good code is not just our goal, it's our responsibility.