Least Privilege Principle:
- Put as much restriction as possible.
- Single Responsibility Principle - There should be only one reason to change a class.
- Class should always be responsible for maintaining its valid state.
- Class shouldn’t expose its internal implementation.
- Tell, don’t ask - Get the information you need from others, and then do your own calculations and make your own decisions. Don’t give up control to others!
- Main should be just the entry point of program, it shouldn't contain any program logic.
- Class containing main shouldn't contain any other fields or methods.
- Constructor should do minimal amount of work to make the object in valid state.
- Use factory or builder pattern when you need parameter validation.
- No public variables.
- Variables should be exposed only by properties.
- Don't reuse variables.
- Always try to minimize the scope of variables.
- A method should do only one thing and does it well.
- Don't mutate parameters of a method; if you do, return that parameter and make it explicit.
- Comments that contradict the code are worse than no comments.
- Comments aren't replacement of documentation.
- Do not comment WHAT you are doing, but WHY you are doing it.
- Don't use static variables unless you have a compelling reason as static variables introduce global state.
- Think twice before introducing static methods. Does it belong to an object?
- Static methods shouldn't change any object's state.
- Regardless of state, static methods should give same output for same input set.
- Favor composition over inheritance.
- Don't use inheritance for adding extra functionality.
- Don't use inheritance for code reuse.
- Use inheritance only when there is an "IS A" relationship
- Always obey Liskov Substitution Principle.
- Code against interface as it reduces coupling, separates behavior from implementation
- Interface should be granular - an interface should only contain logically related set of behaviors.
- Don’t trust user input or external data. Always validate them.
- Exceptions are for exceptional scenarios, not for normal logical code flow.
- Don’t swallow exceptions without proper explanation
- Design by contract.
- If you assume anything make it explicit by using assert/contract.
- For external library adopt Defensive Coding.
- Use empty collection instead of null.
- Use list instead of array as list allows more flexibility unless there is a compelling reason.
- Premature optimization is root of all evil.
- Always optimize algorithm and data structures.
- Don’t micro-optimize as modern compilers are better in micro optimization. Micro optimization often leads to unreadable and buggy code.
- Optimize only when you need to.
- Don’t optimize without profiling your code or knowing the bottleneck.
- Code for humans, not for machine. As machine only understands 0 or 1.
- Avoid Deep Nesting.
- Whatever you do, be consistent.
- Limit line length. Shouldn’t be more than 120 characters.
- Refactor early, refactor quick. As more time elapses, refactoring becomes more hard and costly.
- Write the least amount of clearly understandable code as number of bugs increases with LOC.