Skip to content
- KISS – Keep it simple and stupid.
- What You Produce, Others Will Consume
- Be Open to the Future
- Plan Ahead for Reuse
- Clean code minimize the risk of bugs being hidden
- Loose coupling
- High cohesion
- Design should allow local change. Impact of change should be minimal
- Remove complicated blocks
- Single responsibility.
- A class should be small (less than 100 lines of code)
- Interface segregation principle.
- Dependency inversion principle
- Substitution principle.
- Open close principle.
- No cycles in package dependency
- Depend in the direction of stability
- Stable packages should provide highest abstraction
- Code build in one step.
- Test execution in one step
- Do not ignore warnings.
- Prefer container managed objects.
- Keep configurable data at higher levels.
- Make de-coupled systems. Change in a system shall not impact the other.
- Avoid complexities.
- Adding micro layers in the top without addition at the right place.
- Over configuration. Avoid unnecessary configurations.
- Any class level variable not defining state of the object need to be pushed into methods as local variables.
- Have reason for the structure in place. If not, others will feel empowered to change them.
- Structure over convention.
- Prefer polymorphism over if-else or switch case statement.
- Multi threading – Do not mix it with rest of the code. Make them in a seperate class.
- Misplaced responsibility – Placing the functionality in the wrong place (Do not).
- Make logical dependencies physical
- A module should know/call only it’s direct dependencies
- In a class, if certain methods to be invoked in sequence, enforce it.
- Avoid artificial coupling. Things that are not meant to be coupled shouldn’t be coupled.
- A module should know only its direct dependencies.
- Use dependency injection and container managed object.
- Choose descriptive names for methods, variables, etc.
- Name interfaces after functionality
- Name classes after how they implement the interface functionality
- Name methods after what they do
- Naming becomes more important with the scope. Class level fields have higher scope and hence have higher importance to descriptive names
- Standard nomenclature whereever possible.
- Follow consistency across codebase wherever applicable.
- Prefer dedicated value objects than the primitive types.
- Prefer writing expressive code than writing something very effecient and obscure.
- A method should do just one thing
- Method should descend one level of abstraction
- Prefer few parameters in methods. If ther are many parameters in the method, prefer having a dedicated class
- If a method change the state of a class, have the state changed by calling a method on which the state is mutated.
- Avoid methods with boolean flag arguments. Instead overload the method and user more methods
- If a method is static, make sure that it is appopriate
- Declare local variables near where it’s been used.
- Declare private methods near where it’s been used.
- Prefer to determine packages based on features.
- Single point of reference. Any thing in the code need to be defined once and referred everhwhere else
- Prefer positive conditions in code as it improves readability
- If the conditions are very complex, move it into method.
- Use checked exception for recoverable errors. Unchecked for irrecoverable errors.
- Exceptions are costly. Never use it for programming control flow.
- Never swallow exception in catch block.
- Declare the specific checked exceptions your method throws. Do not use “throws Exception” but be specific.
- Do not catch exception class but catch its subclass
- Never catch throwable because java also throws Throwable
- While rethrowing, always wrap the exception to get the stack trace.
- Never log and throw the exception. It will confuse the person who troubleshoots it.
- Never throw an exception from finally block.
- Catch exception only if you can handle or provide additional context to it. Otherwise do not catch at all.
- Throw early catch late. This gives opportunity to handle the exception at the high level abstraction.
- Use finally to clean up after catching
- Use exceptions on errors but do not use error codes.
- Keep the try-catch statement small. Do not put 100 of lines in it.
- Do not have a try-catch inside a loop.
- Catch all exceptons before it reaches UI.
- Always override equals for Value Objects (VO)
- Constructor can throw exception if the required initialization cannot be done right.
- Remove all dead code.
- Remove clutters from the code.
- Remove all references like story #. Any info which can be stored in a better place.
- Swallowing exceptions. Swallow only if the excepiton is completely resolved leaving the system in stable state
- Do not use exceptions to handle control flow in the program.
- Use exceptions instead of return codes or null
- Exceptions need to be thrown as early as possible. This helps in getting the right stack.
- Catch only if you can react to the excepiton in a meaningful way.
- Be specific in excepitons – catch or throws – be specific
- Avoid code duplication
- Replace magic numbers with strings at field level. If a value is of high signification don’t bury it inside.
- Model interfaces for every role (aspect of the system). Do not model monolithic interfaces.
- Do not keep configurable item in source code. Move it to configuration file
- Always override hashcode while overriding equals
- Very careful while using Cloneable interface as it’s just a marker interface. Think if you can use copy constructor.
- YAGNI – You aren’t going to need it. Develop only what is required.
- Make the dependencies tied via fundamental data types if possible.
Related