Clean Code

Episode 20 – Clean Test

Clean Code

Episode 20

This episode talks about more in-depth on how to keep test clean.

  • Anatomy of a Test
    • Four Phases of test function. 4 As of Test: Arrange, Act, Assert, Annihilate
    • Arrange:Act:Assert, Build:Operate:Check, Given:When:Then
    • Arrange: Set the test to the environment to run the test. Create test fixture.
    • Act: Call the function we want to act upon.
    • Assert: Check the expectation.
    • Annihilate: Put the test environment back to the original state.
  • The Arrange
    • Drive the test to the state (test fixture) it needs for testing
    • Transient Fresh – create and destroy around every test
    • Persistent Fresh – allow to exist between test, initial around every test
    • Persistent Shared – allow to exist between test, allow some states to carry over to other test
  • Setup Struggle
    • What happen if setup grows?
  • Test Hierarchy
    • Test group into Hierarchy so setup only specified in those test needed
  • Clean Composition
    • Action is the thing that you are testing
    • It is a good idea to put two or more actions into an utility function so the test looks like testing one actions
  • The Assertion
    • Test is a boolean operation
    • Single Action follow by Single Assertion
    • More than one assertion, then composition it into one well name assertion.
  • Conclusion
  • References
    • xUnit Test Patterns, Gerard Meszaros

Episode 19 – Advanced TDD

Clean Code

Episode 19

This episode is a two parts serie on a deep dive into the test-drive development.

  • TDD Review of the Three Laws
    • Before production code, must write unit test to fail
    • Stop writing the test as soon as you got a failure
    • Don’t write more production code than you need to pass the test
    • Red Green Refactor
  • The Single Assert Rule
    • Every unit test should only have one assert
    • Arrange-Act-Assert
    • Every action should have one assert.
  • Incremental Algorithmic
    • As the test gets more specific, the code gets more generic.
  • Getting Stuck
    • Should create degenerate test case first. Approach from outside in.
  • Getting Unstuck
    • First, make most degenerate test case.
    • Solve the problem using test case with incremental complexity
    • For every failed test, we make it pass by generalize the production code
    • Don’t make specific with the code
  • Conclusion
    • Test can only prove the program wrong and never prove the program right
  • References

Episode 18 – Component Case Study

Clean Code

Episode 18

This episode reviews the component principles.

  • Overview
  • Payroll Review
    • Controller use Builder to request data structure that they pass to interactor that they acquire from Factory. The interactor manipulate entity and database which create response data structure. The response data structure pass into Presenter which create view model data structure, which driven into view.
  • Ad Hoc Packaging
  • Cohesion
    • High level abstraction should not depend on low level concrete details
  • Coupling
    • No cycle
    • Concrete components depends on abstract components
    • Unstable components depends on stable components
  • Families and Metrics
    • Separating use cases and component that doesn’t belong together
  • References
    • Agile Software Development, Robert Martin

Episode 17 – Component Coupling

Clean Code

Episode 17

This episode talks about how components should depend on each other.

  • Overview
    • Acyclic Dependencies Principle
    • Stable Dependencies Principle
    • Stable Abstractions Principle
  • The Acyclic Dependencies Principle
    • Cyclic module cause those module to force to release at the same time
    • Solution is either split the component out or use dependency inversion
  • The Stable Dependencies Principle
    • Stability is something that is hard to change.
    • A component should depend on something more stable
    • Stability correlates with number of incoming dependency and inversely correlates to number of outgoing dependency.
  • The I metrics
    • I metrics = Fan-out / ( Fan-in + Fan-out )
    • All dependency arrow point toward decreasing I.
  • The Stable Abstractions Principle
    • Use open-close principle for the module at the bottom of the dependency.
    • The more stable a component, the more abstract it should be.
    • Abstract number = number of abstract classes / number total classes
    • A + I = 1
  • Distance
    • D = | A + I | – 1
    • Zone of uselessness is where there many abstraction but nothing using it
    • Zone of pain is there are too many concrete classes depend on each other
    • Distance metric between zone of uselessness and zone of pain
  • References

Episode 16 – Component Cohesion

Clean Code

Episode 16

This episode talks about how components should work together.

  • Overview
    • Release Reuse Equivalency Principle
    • Common Closure Principle
    • Common Reuse Principle
  • Cohesion
    • What is inside a component? The pieces is functions and the force to bind them is cohesion
  • False Cohesion
    • A group class work together to achieve a common goal is not a good reason to bind them together as a component.
    • Base class and their derivative are often package into separate component, with class that use base class package with the base class.
    • When one class polymorphic uses another class, those classes should be separate into different components.
    • Goal is interdependent deployability
  • Release Reuse Equivalency Principle
    • The granulate of reuse is granulate of release, you can’t reuse a component unless the author is willing to manage it thru a release cycle
    • You want a few strategic components instead of managing hundreds of tiny components
  • Common Closure Principle
    • Component don’t cross boundary
    • When requirement change, best outcome is one component per layer changes.
    • Minimize the number of component change when requirement changes.
    • The classes we grouped together should be closed to the same kind of changes.
    • We gather the classes that change for the same reason and separate the classes that changes for different reason.
    • This is similar to interface Segregation Principle
    • Those class that group into a component should have same responsibility, serve the same actor.
  • Common Reuse Principle
    • Group together classes that are using together, separate classes that are not. In another word, when you use a component, you use all the classes within that component.
  • The Tension Diagrams
    • CRP & REP → component affected by many responsibility
    • CRP & CCP → component aren’t reusable
    • CCP & REP → component are needlessly affected
    • As project mature, it moves from CRP & CCP to REP.
    • Component partitioning changes with project maturity
  • References

Episode 15 – Solid Component

Clean Code

Episode 15

This episode gives an overview of the component principles.

  • What is a Component
  • Relocatable Module
    • The creation of linker to link the subroutine library and create executable binary
  • Explosion of Libraries
    • Application call subroutines
    • Framework call applications
    • Dependency inversion of Framework and Application
    • Framework → flow of control → Application
    • Application → source code dependency → Framework
  • Linker’s Demise
    • Component is an independent deployable library (dll, gem, or jar)
    • Independent deployable mean change in one doesn’t cause another to recompile or redeploy.
    • The key is Application depends on Subroutine and Framework but not the other way around.
  • Coffee Maker Requirements
    • void setBoiler(bool);
    • void setWarmer(bool);
    • void setValve(bool);
    • void setLight(bool);
    • bool getBoiler();
    • int getPlate():
    • bool getButton();
  • The Architect’s Solution
  • A Real Design
    • Apply Single Responsibility Principle first
    • Who is the actor?
    • Brewer, Hot Drinker, Now Drinker
  • High Level Modules
    • Three Actors means at least 3 modules. One Module per Actor
    • Describe abstract purpose of component because High level module should not depend on low level details.
  • Methods and Relationships
    • Examine the methods and relationships of the modules by moving up and down the abstractions.
    • First, the actor send a start message to UI module.
    • Then, if UI not brewing? and HotWaterSource & ContainmentVessel ready? then send start message to HotWaterSource
    • This shows there is a start method for UI and HotWaterSource and ready?method for HotWaterSource and ContainmentVessel.
  • Brewing Begins
    • When the pot is removed, ContainmentVessel send suspend message to HotWaterSource
    • When the pot is replaced, HotWaterSource send resume message to ContainmentVessel
    • The take away is that message being send between module on high level abstraction
  • Implementation
    • Use Open-Close Principle
    • Creating a derivative for each of the modules.
    • Main call the derivative.
  • Components
    • All the dependency crossing from main to the application is pointing inward to the application
    • Benefit from good component design: Interchangeability, Interdependent deployability, the physical separation from high level policy to low level details.
  • Conclusion
    • Component Cohesion
    • Component Coupling
  • References

Episode 14 – Solid Summary

Clean Code

Episode 14

This episode reiterates all five SOLID principles.

  • Requirement and Use Cases
    • Use Case List (action)
    • Entity List (subject)
    • Building the data dictionary to support the requirement
  • The Single Responsibility Principle
    • Looking at which module belong to which actors
  • Diagrams and YAGNI
    • Diagram is usually using by communicate thought process and become obsolete
    • YAGNI – You ain’t gonna need it.
    • Separate each module to only one actor.
  • The Open-Closed Principle
    • Controller should not depend on the details of the data structure
    • Using Builder, Factory, and Interface to decouple the controller from the data structure and use cases.
  • The Liskov Substitution Principle
    • Don’t put a method in an interface that does apply to all the derivatives.
    • Only ok when all the methods of a derivative do nothing, then you have an null object pattern.
  • The Interface Segregation Principle
    • Violation indicated by the growing fan in from the controllers to the use case and the builder.
    • Let the use case Factory makes the controller by passing the type of controller it will use. This is dynamically create the controller.
  • The Dependency Inversion Principle
    • High level policy should not depend on the low level details
    • The algorithms should be generic without the details
  • Conclusion
    • Use these principles but use engineering judgement.
  • References