"Why should I care about writing clean code?” you may still be asking yourself.
There are many reasons to get into the clean code mindset. Some of the most important reasons are:
Better Use of Your Time
The first beneficiary of clean code is the programmer themselves. If you are working on a project for months, it’s easy to forget things you did in the code, especially when your client comes back with changes. Clean lines of code make it easier to make changes.
Easier Onboarding for New Team Members
Using clean code principles helps to get a new programmer onboard. There is no need for documentation to understand the code; the new programmer can directly jump into it. This also saves time for both trainings the new programmer as well as the time it takes for the new programmer to adjust to the project.
Easier Debugging
Whether you write dirty or clean code, bugs are inevitable. But clean code will help you to debug faster, regardless of how much experience or expertise you have.
More Efficient Maintenance
As any project grows, it will need new features or changes to existing features.
You feel Good!
Universal Principles:
Follow standard rules: experiments always end in disaster.
- Avoid duplication in the code (DRY principle or Don’t Repeat Yourself ).
- We must apply The Boy Scouts rule to our profession: Leave the campground cleaner than you found it.
- Follow SOLID principles to write clean classes and well-organized APIs.
- Follow Code principles article for the detailed explanation.
Names Rules:
- Use searchable names.
- Make it easy to remember them.
- Use names according to the context.
- Choose descriptive and clear names.
- Use names that can be pronounced well.
- Use names that are consistent with each other.
- Use the same language in the names of variables, functions: English, French, etc.
- Avoid encodings and don’t append prefixes or type information.
Classes:
- Classes should be small.
- Use correctly package levels: public, protected, etc.
- Classes should have only one responsibility and only one reason to change (SRP).
- Keep utility methods and variables private. Exceptions are always there. for eg: for testing
Objects and Data Structures:
- Hide internal structure.
- If you can, call only your methods of your class, of objects you have created, and avoid call methods reachable through these objects (Law of Demeter).
- Improve the decoupling of objects.
- Variables should be private and manipulated by getters and setters, but remember, there is no necessity to add getters/setters to each variable to expose them as public.
- The base class should know nothing about their derivatives.
- Objects expose behavior and hide data. Conversely, data structures expose data and lacks of (significant) behavior.
Functions rules:
- They should be short and only do one thing. If your function is doing more than "one thing", it is a perfect moment to extract to another function.
- Keep the number of arguments as low as possible.
- Avoid side effects. Declare the arguments as final if you can.
- Functions should either answer something or do something, but not both.
- Prefer Exceptions to return error codes and extract error handling try catch into their function.
- Don’t return a null value. What is null? It does not provide any information. If you really want to then handle all exceptions which occur due to null values like Null Pointer Exception.
Design rules:
- You should declare local variables as close as you can to their usage.
- You should declare instance variables at the top of the class.
- Constants should be declared at the top of the class or in a Constants class by example.
- Follow the Law of Demeter: A class should know only its direct dependencies.
- Use dependency injection.
- Place methods in a top-down direction.
- If you use third-party libraries, wrap them, so if they change, only your wrapper implementation needs to change.
- It is a good idea to separate concepts vertically.
Exception handling:
- Throwing errors makes code cleaner than checking for status values throughout the code.
- Provide enough meaning to determine the cause and location of an error.
- Wrap third-party libraries APIs to remap their exceptions as required.
Concurrency:
- Concurrency, although it may improve the performance of the program, is difficult, so use it wisely and only when required.
- Keep concurrency control separate from other code.
- Know basic concepts and programming models like mutual exclusion, starvation, or deadlocks.
- Create locked sections small.
Tests:
- Fast: Unit tests should be fast and being executed in a short time.
- Independent: Tests should not depend on each other.
- Repeatable: Tests should be reproducible in any environment.
- One assert per test.
- TDD: Build your software using tests that guide your development.
- Cover all test cases. You can use jacoco to check if you have covered each test case of the class.
- Make a standard: to set coverage of Junits. for eg: 80% coverage you can set for running unit test cases.
Clean tests should follow F.I.R.S.T principles:
- Fast: ⏩ Tests should be fast. They should run quickly. When tests run slow, you won’t want to run them frequently
- Independent: 🆓 Tests should not depend on each other. One test should not set up the conditions for the next test. You should be able to run each test independently and run the tests in any order you like.
- Repeatable: 🔁 Tests should be repeatable in any environment. They should run in the production environment, the QA environment, and even on your laptop while riding home on the train without a network.
- Self-Validating: ✅ The tests should have a boolean output. Either they pass or fail. You should not have to read through a log file to tell whether the tests pass.
- Timely: ⏲The tests need to be written in a timely fashion.
- Comments are difficult to maintain and don’t tell the truth about the code, so try to avoid it.
- Use only as a clarification of code.
- The code is the best documentation.
- Don’t be redundant.
- Avoid unnecessary comments.
Formatting:
- Avoid too-long files.
- Good files have a heading, the critical stuff first, and details later.
- Avoid lines get too long (80 or 120 is perfect). You will get used to being more concise, and your code will be more readable.
- Be consistent with the rules of your team and better define rules before the start of the project. (in sprint 1 😉)