/Java-cleancode-practises

Code samples and notes on best practices from book Effective Java-3rd edition

Primary LanguageJava

This project is an attempt to put together various coding practises recommended in various programming books, online blogs,
online programming tutorials etc.

Design hints from unit tests:
    Don't pass unnecessary data to a method.
    Avoid primitive obsession. Prefer to wrap primitives in object when they are to be passed around.
    Don't mutate input objects in a method, as it makes mocking such methods in unit tests too complex as we now need
    to mock the mutation behaviour too. Also now we need to validate for number of invocations of such impure methods.
    Try to have immutability as much as possible
    Prefer pure functions:
        No side effect + always return same result for same input
        Follow command-query-segregation
        Follow CQS(Command-Query-Segregation): Organize codebase into commands(methods changing state of the application)
        and queries(methods for querying data,pure functions which have no side effects and always returns same result for same input)
        A method must be either a command or a query, but not both
        Code smell hint in unit test: if for testing a code we are stubbing its dependency method as well as validating for its number of invocations,
        it means dependency method is breaking CQS. Refactor the dependency method into COMMAND and QUERY
        COMMAND needs validation for number of invocations, QUERY needs to be stubbed
        Try to put complex logic in pure functions so that corresponding tests need minimum or no mocks
        Follow Functional-Core-Imperative-Shell segregation pattern
        Make external calls in imperative parts, and then invoke functional parts(containing complex biz logic) passing fetched data

Guiding principles of clean code:
    Modular
    Separation of concern
    Abstraction/information hiding
    Loosely coupled
    Cohesive

Ways to achieve above/ best refactoring practices:
    DRY
    SOLID
    Prefer clarity over brevity
    Boy scout rule: Always leave the code base healthier than when you found it
    Split Loop
    Replace temporary variable with Query(calling a method having meaningful name)
    Split Temporary Variable: Don't use same variable for different contexts/purposes
    Put things together that change together

Code smells:
    Monster methods
    Global variables
    Usage of code types -> replace by strategy/polymorphism
    Don't have methods using boolean in signature, it means method violates SRP
    God class
    Too many parameters
    Lambdas more than 2-3 lines
    Primitive obsession -> use microtypes instead(java record, scala case class simplifies making microtypes)
    feature envy : when we are doing too much about state of an object from another object -> follow 'Law of demeter',meaning
    an object should interact with its immediate dependencies only; objects must follow 'Tell, don't ask' pattern.
    Move all the code modifying an object's state into that object and make object expose an API for clients. This helps
    in hiding implementation details, and hence reduces coupling, as any changes are localized to class only.
    Divergent change: When we have to change a module in different ways for different reasons. It means module is not following SRP
    and needs to be split.
    Data clumps -> put such data pieces together in a class, and then look for feature envy on this class to move behaviour to it
    Repeated switch/if-else statements -> replace with polymorphism
    loops -> replace with first class functions like filter,map etc
    lazy elements -> code elements like class, functions etc which over the time loose their importance. Needs to be deleted.
    Message chains/middle man
    Refused request: when a subclass methods don't really need the behaviour and code it inherits from parent class ->
    Replace inheritance with delegation

    refactoring...page 100