Good code and Why should we care?
This is a post about the importance of writing good code with not just quality, but aesthetics, readability and predictability.
As a developer, writing code is an activity that we do day-in, day-out. However, unlike a sculptor who carves his work, most of the time, we go about grabbing code snippets and stitching up a patched dress instead of crafting an Armani or a Ralph Lauren.
We never care about finesse as we don’t value the code that we produce on the same lines of an artist with his fine brush strokes. Recently i came across a [blog post](http://blog.d3in.org/post/130288777151/10-principles-for-good-code) which attempts to list reasons to consider your code a canvas for your artwork rather than a boring task to get over with.
Some of the characteristics that we definitely need to ensure that our code act as:
1. Simplest as possible
2. Aesthetic and consistent
3. Help understand the Product function
4. Commented for reason
One of the sayings that we have in our team is
The best bug-free code is the one which is never written.
Before writing any piece of code, check if the same is already available, as part of your code base or external libraries. The simplest reason being it would have been tested, does not need additional unit testing in our code base and definitely has lot less bugs that the code that we would write to perform the same function. Quite a few times, there might be minor discrepancies in terms of parameters or types. In that case, as a seasoned developer, try to weigh in the options — If it is really necessary to recreate or if your code should actually be using the parameter structure of the established library.
My personal preference is
Even if its not directly usable, attempt to verify if the re-usable code can be best aligned by minor changes in your code base.
Establish a set of shared coding standards: Programmers can understand a piece of code faster if they don’t encounter unexpected surprises while reading it.
keep in mind that the code should be readable by the next person debugging the code, even ourself after six months.
There are so many style guides, such as from Google or Oracle itself. It does not really matter which one is being used, as long as the team agrees and adheres to it. One of the easiest ways to ensure consistency is to use Eclipse Formatter or Intellj IDEA preferences or similar common formatters for the IDE of your teams’ choice.
Why is this important?
Assume the team is working on a code base consisting of thousands of files and someone is attempting to identify a bug in the middle of the night.
It would be better to have a line width of 200 rather than a line width of 80 and half the screen white and needing the developer to scroll multiple times to view a single function.
Irrespective of the formatter rules, there are few common and mostly sensible practices that we follow.
1. Never have a function span more than 10–15 lines of code.
2. Ensure each function performs only one action.
3. Name the function appropriately.
4. Remember the types of parameters or parameter names are not necessary in the function name. For example, it is better to name a function add(int i, int j) rather than addIntegers(int i, int j)
5. One other quirk is to not have the return parameter type or name as part of the function name. For Example: public JSONObject convertStringToJSONObject(String s) is better named as public JSONObject convert(String s).
6. Ensure that your class encapsulates the function of one object.
7. Ideally any class should have at a maximum of 6 or 7 functions. If there are more check if refactoring to more atomic classes are needed.
Any product created should have its purpose served best by its utility. From a simple spoon to a complex rocket ship can be appreciated of its beauty only if its usefulness is completely achieved. Aesthetic structure is not just for web or native applications, but also for API designs, code written, even for comments.
Maintaining symmetry and consistency is appreciated if it serves its usefulness, similar to:
1. Code style Consistency
3. Absence of unstructured notes (TODO, FIXME, etc.)
5. Naming conventions
“When you have the opportunity, try deodorizing the smelly code. Don’t rush. Just take small steps. — Michael Hunger
Utilizing Conventions and Configurations
In recent years convention over configuration has been an emerging software design paradigm. By taking advantage of it, developers only need specify the non-common part of their application, because the tools that follow this approach provide meaningful behavior for all the aspects covered by the tool itself. These default behaviors often fit the most typical needs. The defaults can be replaced by custom implementations where something more specific is needed. ”
However, many times developers get themselves too knotted in the conventions and configurations that they sacrifice readability and maintainability for Magic. There are numerous frameworks with auto-magic conventions and injections that cannot be identified unless someone painstakingly unravels the Trick. Always falter on the side of being more verbose than automatic configurations to save many sleepless nights.
Code development is a marathon. Don’t lose focus of the end goal.
Cyclomatic complexity is a numeric value that represents the number of execution paths through a method. A high value makes its highly expensive for maintenance, testing and extensions and a high risk of bugs and errors.
There are numerous tools to measure the Cyclomatic complexity. Use this judiciously to identify components of the code base which has a higher complexity value and break them into more modular and independent components. This improves the testing capabilities and reduces the risk of errors as well.
Vinci quote on simple
Testing is a first class citizen
Treat all types of testing, may it be unit testing, integration or function testing, as first class citizens and not as an afterthought post code development. Identity means to inject dependencies, mocking capabilities as part of the development activity. Take special care in choosing parameters and data types to ensure consistency and ease of testability.
A good practice that we follow is to decouple the experience part of the code to be as thin as possible. This enables easier and more robust testing of the codebase and allows us to leverage UX testing for primarily rendering, optimizations, accessibility and browser compatibility.
A good start to any good code development strategy, especially for an Object oriented programming language, is to follow the SOLID principles.
- S — Single Responsibility Principle (SRP)
- O — Open Closed principle
- L — Liskov Substitution Principle (LSP)
- I — Interface Segregation principle (ISP)
- D — Dependency Injection or Inversion principle
In computer programming, the term SOLID is a mnemonic acronym for five design principles intended to make software…en.wikipedia.org
Code structure — Classes
Creating classes during code development should always encapsulate a granular entity and Interfaces should capture behavior. Classes should extend Interfaces to express the intent and responsibilities of the class.
Following the principle of single responsibility diligently is crucial for methods and functions. A rule of thumb that we follow is that each method should be viewable in the code window with no need for scrolling. Lesser the number of lines, better.
It also means that the methods should be named appropriately with the naming giving a good idea about its purpose and function.
Write code with the Throw-Away principle. Any code written today will be obsolete and thrown away in a year or two.
Steve Jobs toiled over the internals of the Mac to make them polished and pleasing, even though most of the consumers would never see it. Writing comments is one of the most overlooked parts of the code base.
Comments should provide answers to the “Why?” and not the “How?”
Every comment should be written with the maintenance of the code base as its goal. Remember that each line of code need to be readable by the next person debugging the code, even ourself after six months and comments should ensure easy readability.
Comments should not be the sole source of truth rather adhoc the code with more clarity. Its imperative to write the code in a clear and concise manner and use comment sparingly but to good effect. Its also important to remove irrelevant and long winded comments.
Comments need to be supplementary, simple and with readability in mind. Always explain the Why? as the How? is already clear in the code.