- Use intention-revealing namings
- Capture business knowledge
- Avoid encoding and technical details
- Use pronounceable names
- Use searchable names
- Avoid noise and redundant words
- Use strong words
- Don't use abbreviations
- Be consistent with concepts and use the same vocabulary
- Use is/has/should/can prefix for booleans
- Avoid negative names for booleans
- Use naming conventions within your project
- Boolean name should be an adjective
- Class names should be noun or noun-phrases
- Function names should be verb or verb-phrase
- Keep a function small and concise
- Avoid too many function arguments
- Max number of lines of a function should be 8-10
- Avoid passing boolean as a function parameter
- Strive for no side effects.
- Use enums as flags
- Use empty lines to separate logic
- If it takes more than 3 seconds to figure out what a function does, then refactor it
- Should have only one main responsibility
- Avoid large classes (~100 lines of code can be a smell)
- Strive for one public function per class
- Create small private functions to do single tasks
- Order your functions based on execution
- Avoid comments as much as possible
- Don't state the obvious
- Don't use them extensively because nobody will read them
- Replace them with good namings of your software elements
- Use comments only for explaining the why
- Use comments for revealing implicit behavior
- Use comments for API doc generation
- Use descriptive tests names describing the test scenario
- Use GivenWhenThen or ShouldWhen naming templates
- Use Arrange/Act/Assert pattern to structure tests
- Avoid logic (if, for, and while loops) in test code
- Couple a test with one behavior
- Use meaningful test data
- Hide irrelevant test data
- Use clean assertions, describing the domain behaviors
- Create deterministic tests
- Remove duplication with parameterized tests
- Prefer fakes for mocking out 3rd party code
- should be fast
- should be independent of other tests
- should be repeatable
- should be self-validating
- should be thorough cover covering all happy paths, edge cases, negative cases, security, and illegal issues
- Commit early & push often
- Make your commit messages meaningful, explaining the reason for the change.
- Use the imperative mood in the commit message
- Use present tense in the commit message
- Add link reference to the actual user story, task or bug
- Avoid magic numbers
- Avoid magic strings
- Avoid long conditions
- Avoid global variables
- Avoid long parameter list
- Don't be obsessed with primitives. Model your domain with complex types.
- Avoid deeply nested logic
- Reduce cyclomatic complexity
- Hard-to-test logic is a code smell to fix
- Set up team standards
- Use automated code formatters
- Set max width for horizontal formatting
- Don’t use horizontal alignment.
- Don't break indentation
- Variables should be declared close to their usage
- Don't repeat yourself (DRY): remove knowledge duplication
- Keep it simple (KISS): simple code beats both complex and clever code
- You ain't gonna need it (YAGNI): don't produce code that is not needed in your current context
- Tell, don't ask: bundle data and functions together
- Single Responsibility Principle (SRP): organize logic into modules with one reason to change
- Liskov Substitution Principle (LSP): a subtype should be able to replace its base type without altering the program
- Interface Segregation Principle (ISP): split large interfaces into small and more specific ones
- Dependency Inversion Principle (DIP): high-level modules should not depend on low-level modules. Both should depend on abstractions.
- Favor composition over inheritance: inheritance leads to tight coupling, composition gives more flexibility
- Divide and Conquer: break down a problem into smaller sizes to manage complexity
- High cohesion: group related code together. It helps you to find logic easier and makes your code easy to maintain
- Low coupling: your modules should independent of other modules. By doing so, you can easier make changes to internals without breaking other modules
- Use a solid IDE with refactoring functionalities
- Master your IDE hot keys
- Use feature based folder structure
- Work with pair programming, it makes writing clean code easier
- Delete non used code - code is a liability, not an asset
- Write code humans to read, and not just for machines to execute
- Readability > cleverness
- Favor readability over efficiency
- Always leave the code a better place behind
- Test early, test often
- Refactor early, refactor often
- Do code reviews in real-time instead of PR reviews
- Use the rule of three to remove duplications
- Avoid using
NULL
, it is a code smell - Working code != clean code
- You can't have clean code without tests
- Write code that reads like a well-written prose