If someone ask me who is my Guru for Java, I would say 'Sun Microsystem' and 'Apache Foundation'.
I am from a generation, where most of the programming learning was by reading Java source code. Internet was not a big store of many rich blogs or forums, and hence reading through code was the best resource. Moreover, kind of components we built, were not possible without understanding the behavior of system we are extending. Hence reading through code was almost mandatory for building right extension, and the products.
One notable thing, I still remember and admire about Java and Apache kind of products source code is, clarity of code constructs and rich documentation, code which speaks its intention very clearly. That made the code reading experience enjoyable and easy like a story book. I remember reading tons of code of Swing, Concurrent library, Collections and Apache Axis etc like a novel. Much of the credit of reading such large codebase was to that effective coding and documentation style, which developers followed to write such code.
Fast forward today, we are in era where doing more by writing lesser code is sought after style. With availability of functional language, many abstract language constructs and lambada expression kind of support, it makes all the sense and makes code less bulky too.
Yesterday or today, then or now, basic principles of writing clean code are same and equally required. Ultimately it is all about art of writing readable code, clean code, a code which speaks of its intention clearly, where it is hard for bugs to hide, a code which can tell about any dysfunction loudly.
What is clean code:
Any fool can write code that a computer can understand. Good programmers write code that humans can understand - Martin Fowler
- A code which can be read easily by anyone and everyone other than its original author.
- A code which speaks of its intention clearly, either with write naming convention or with documentation as relevant
- A code where it is hard for bugs to hide
- A code which can tell about any dysfunction in system loudly itself
- Let us talk in brief about some of key enabler principles for clean code.
Meaningful Names - Names which reveals intention
If I need to choose one most important thing for clean code, I will pick this. That is its importance for code readability and maintainability.
Picking right name, which can reveal its intention of existence is very important. It takes time to pick right name, however, that effort and time are worth it as it could save hours of efforts later to understand the code or any issue.
Simple thumb rule > As soon as one read name of class or variable or function, it should tell loudly 'Why I exist'. This rule applies to names of Package, Class, Variable, Function, database tables, columns, property files, properties everything. Even name of iterator variable in for loop is equally important to keep code readable.
Few pointers:
- Use pronounceable names. Use full name, rather than acronym which needs a dictionary later. Ex: ctrlGpForPt > controlGroupforPatients.
- Don't be afraid of long descriptive names if it makes reading easy. Let VM, compiler, IDE handles lengths for us.
- Avoid confusing names for similar constructs, make clear distinction. Ex: accountActivation, accountToReactivate, accountActivated < has high potentional of confusion while reading the code.
- Use same pattern for similar operations. Ex: getRecords to get data from database, instead of using get, fetch, retrieve at different places
- Use domain names as much possible, as it helps reader later to make sense of code quickly as long as they understand the product domain. Ex: jobProcQueue > accountProcessorQueue
- Names should make reading code simple, rather than need to juggle the logic and multiple name <> construct relations in mind for readers.
Keep Length of Constructs in Check
It could be asked that what's in length if names are good, and code is clean. However, length of implementation for any construct defines the complexity for readers. Human mind can keep limited complexity and data in memory at a time. More we add to this, more it needs to juggle with memorizing and cross referencing.
Solution is to keep length in check for classes, and functions both. Easiest approach is, if there is some code doing related work, bundle it in separate function and call. Reading a function of 50 lines with 10 function calls of meaningful name is much easier than reading and understanding function of 500 lines.
Hence, break the implementation in multiple small functions with meaningful names.
Keep it smaller than small!
Principle of Single Responsibility
This is not only the architecture principle (Read more here), but equally applicable to low level design or function implementation and code readability also.
We started this article with principle that names should reveal the intention. How is that possible if a function or class is carrying multiple responsibilities.
If any class or function is serving more than one intent, break it further.
No Side Effect Code
It is an extension of previous point.
A code should do what it is supposed to do. Nothing more, nothing less.
Ex: Login function should check the authentication, may check and initialize the information for authorization. But, it should not initialize the JSON structure for UI Rendering. That will be like cutting the concerns, which defeat Principle of Single Responsibility and clear intentions both.
Have Same Code Format in a Product
How would you feel about reading a book which has 10 different fonts, indentation and color styles in 10 chapters. Not comfortable surely. Same is with code. Having same format across the classes, packages, modules make it easy to read the code.
Solution: Define formatting rules with team, and follow it everywhere. It is one of the easiest thing to implement by agreeing and defining a common code formatter config which is used by all developers in IDE.
Length of a Line
Does it really matter..... ?
Yes, it matters a lot. Length of line should be set according to normally used monitors width. It might be good to have 40 or 80 line length earlier with smaller screen, but now with wider screen monitors, it makes all sense to have it at least 120 as standard.
It makes code readable by keeping contents in same line, rather than reading multiple lines. Visualize reading a function name with 5 parameters in 3 lines, verses in one line.
Keep Related Code next to each other - Better Top Down
Although finding function is easy with IDE shortcuts. However, reading should be easy just by mouse scroll also in a class. Hence, it is advisable to keep related code next to each other, and better in top down format where reader can start from top and keep following next methods down similar to book reading.
One step closer to writing code which can be read like story book!
Assert if something is not as Expected
Assertions are not only to just check parameters. These are powerful tools to validate the behavior of system, when no one is looking at it.
Don't we expect our car to tell if engine oil or coolant is less. Or if there is some impurity in fuel. Why, because it makes our life easy by taking proactive action timely that also without spending hours to understand the reason before car breaks down.
Same is true for Software Systems too. A system should tell if something is not correct in it. Tastefully designed assertions (+ monitoring, alerting) can make developers life much easier by shouting erroneous conditions before these become big issue, like corruption of whole data in system.
Hence, spend quality time in designing assertions in your code. And before that, define a standard to log and report these assertions.
A self-validating system (code) is the best system!
There are few more important aspects of clean and maintainable code, which are Error Handling, Logging, Tests for Self validating Systems and Documentation. We shall talk more about these in next blog.
Till then, happy coding..
0 comments:
Post a Comment