What is Clean Code?
- Clean Code is a subjective concept so different programmers have different ideas about the exact meaning
- Clean Code methods used within a company should converge.
- There are well established techniques to implement clean code best practices
- It embraces S.O.L.I.D. object oriented design principles
- It comprises code optimization.
What is the purpose?
- If standards are followed throughout a company, it will be much easier to reuse code in the long run.
- Faster to ‘ramp up’ new projects as code written by other team members is much easier to understand.
- Teamwork happens faster and with less friction.
Here at ITEGRATION, we follow certain standards throughout the company to ensure we achieves the goal of clean code, re-use and more efficient projects, these are detailed below.
Clean Code Best Practices S.O.L.I.D. Design Pattern
S (S.R.P. – Single Responsibility Principle)
- In General: a class should have one and only one reason to change.
- A class should have only one job and should be changed only if the job itself changes.
- In this way a class contains less code, reducing the possibility of bugs and making debugging easier.
- A class contains less logic and makes testing easier.
O (O.C.P. – Open/Closed Principle)
- Classes should be open for extension but closed for modification.
- New features can be added to a class but only by extension and without modifying the code of the class itself.
L (L.S.P. Liskov Substitution Principle)
- Every subclass or derived class should be substitutable for their base or parent class without changing the behaviour of the code.
- Every subclass or derived class should be substitutable for their base or parent class, wherever the parent class is expected (e.g. as parameters or variables).
I (I.S.P. Interface Segregation Principle)
- A client programmer should never be forced to implement an interface he doesn’t use. Clients shouldn’t be forced to depend on methods they do not use.
- Many client-specific interfaces are better than one general-purpose interface — parts of the code should be loosely coupled.
D (D.I.P Dependency Inversion Principle)
- Higher level modules must not depend on low level modules but they both should depend on abstractions.
- Entities must depend on abstractions and not on concretions.
- Inversion of control (IoC) is a design principle in which custom-written portions of a computer program receive the flow of control from a generic framework.
- Dependency Injection is an Inversion of Control technique for supplying objects (‘dependencies’) to a class by way of the Dependency Injection Design Pattern. Typically passing dependencies via one of the following:
- A constructor – Magento 2
- A public property or field
- A public setter
- Service Locator / Registry: antipattern
- Either inject the container into your object or use a static reference to the DI container to create instances at runtime.
- The application is explicitly dependent on (thus tightly-coupled to ) the DI container.
- because DI container is injected/instantiated, it is not possible to see from class constructors what interfaces it is dependent on.
- Magento 2 object manager
- Dependency Injection Container (DIC)
- Reflection. Slower because of some extra processing but Magento 2 does a great job about this.
- Names should communicate their purpose and meaning without the need for browsing extra segments of cede.
- Don’t mislead fellow programmers via improper naming.
- Don’t use similar names.
- Match a word to a single concept and vice versa.
- Use abstract names for abstract classes.
- When changing the logic of a class or function, rename it so that it reflects the modified functionality.
- Defer from adding type based extensions as in a modern IDE we can get type hints just by hovering the mouse over a variable.
- Variables/Classes: nouns (Person, Car…)
- Methods: verbs (getPrice()…)
- Boolean methods: kifejezések (isEmpty(), hasTask()…)
- Scope rule
- It is advisable to use shorter variable names in smaller scopes and longer names in bigger scopes.
Functions and Methods
- Methods should contain minimal code.
- Even less than that!
- Robert C Martin: “4-5 row methods are OK but a 10 row method is not.”
- Bjarne Stroustrup
- “If a body of a function does not fit the screen it is simply too long. 1-5 functions can be considered normal.”
- The less embedded blocks and indents a function has, the easier it is to understand.
- Ideally this allows one row in the body of a “while” or “for” cycle.
- Simpler logic gives less chance for bugs.
- There is no need to scroll in the code, you can navigate using the IDE.
- Why do we love long methods?
- Most programmers are men. Men are proud of their orientational skills and a big method is like a complicated map.
- Minimize the number of parameters:
- The more we have, the more difficult is to figure out what they are for.
- Don’t pass boolean parameters:
- Create different methods for the true and false branches.
- Don’t use output parameters:
- Output parameters are not straightforward for the client programmer, let’s add more data to the return value instead.
Methods within a class:
- Use the Title – Summary – Main Topic pattern
- Name – Public methods – Private methods
- Rule of stairs: a method calls methods between them.
- A method should return the same value consistently it is called with the same parameters.
- Spit the logic if it does not work like that.
Segregation of Command and Initialization
- Methods that change the state of an object should not return a value.
- Methods that return some value should not change the state of the object.
- If the state of an object is queried and a command is sent to the same object based on the result of the query, we are probably doing something wrong. Objects should know their own states and should be able to act based on that.