Episode 13 – The Dependency Inversion Principle

Clean Code

Episode 13

This episode talks about the Dependency Inversion principle.

  • Dependency Inversion Begins
  • Independent Deployability
  • What is dependency
    • Run Time Dependency exist whenever two module interact at run time.
    • Compile Time (Source Code) Dependency exist when a name is define in one module but use in another module.
      • If Module A uses the name from Module B, then you can’t compile Class A only, you must also compile both A and B because Class A depends on Class B.
  • Structured Design
    • A top-down methodology by start with main and design what main should call and so on down the tree.
    • The source code dependency follows the same path as the run time dependency.
  • Dependency Inversion
    • The purpose is to have source code dependency going the opposite of the run time dependency path.
    • The solution is polymorphism.
    • Example,
      • A –> B [+f()], if A call f() in B, then A has both run-time and source-code dependency on B.
      • A–> Interface[+f()] <– B [+f()], insert an interface between A and B by having A uses the Interface while B implement it. Then A has run-time dependency on the Interface but not compile time dependency. And B has source-code dependency on the Interface.
  • Plugins
    • Dependency Inversion create a boundary for the software. We want all the dependency across the boundary are pointing to the same direction, the application.
    • This is by creating plugin that depend on the application.
  • Architectural Implications
    • High level policy should not depend on low level details
    • Low level details should depend on high level policy.
    • High level like use cases.
    • Low level like web pages and database.
    • Therefore, design the low level details as plugin to the application.
  • A Reusable Framework
    • Building the reusable framework should be done parallel between those application that uses it.
  • The Inversion
  • Independent Developability
    • Developers can work separately without interfere each other’s module.
  • Dependence Inversion Example
  • The Furnace Example
  • Plugins
  • References

Episode 12 – The Interface Segregation Principle

Clean Code

Episode 12

This episode talks about the Interface Segregation principle.

  • Interfaces
    • Example: A light switch
    • switch —>> Interface <|—- light
    • The interface is couple with the switch more than the light object. Should call switchable.
    • Interfaces have more to do with the class that use them then the class that implement them.
           /--- D1 <---\
B (v) <---|             |--- M
           \--- D2 <---/
  • The Interface Rant
    • Deadly diamond of death
    • M could either have one instance variable v or two coming from each D1 and D2.
  • Fat Classes
    • The main class multiple inheritance many interface classes. Isolate fat classes by isolated each client specific interfaces and deploy them separately and able to develop separately.
  • The ATM example
  • Physical Structure
    • Ensure you don’t depend on method that you don’t call, otherwise, unnecessary coupling.
  • Factory
  • Dynamics and Injection
    • Dependency Injection
    • Main should create the messenger instance, all of the interactors, and main should takes the interactors and pass them across the boundary to the application.
  • The Need to know
    • Don’t force the user to depend on thing that you need
  • References

Episode 11 – Liskov Substitution Principle

Clean Code

Episode 11

This episode talks about the principle govern inheritance, polymorphism and subtyping.

Part 1:

  • Type Theory
    • “This statement is false” is a paradox.
  • Types
    • Solution is typing to avoid paradox loop.
  • What is a Type?
    • A Type is a bag of operations and how the data is stored is not matter to us as long as the operation is done correctly.
    • Similar to a class, a class is nothing but its methods and the data is hidden as private.
  • Subtypes
    • A subtype relationship of described point as a subtype of point is when described point can be cast into point but not visa versa.
  • Liskov & subtypes
    • What is wanted here is something like the following substitution property: If for each object 01 of type of S there an object 02 of type T such that for all programs P defined in term of T, the behavior of P is unchanged when 01 is substituted for 02 then S is a subtype of T.
  • Duck typing
    • Invoking method vs Send Message (Static vs dynamic language)
  • Refused Bequest
    • Refused Bequest is when an object invoke a method or send a message that is not expected.
    • Exception and side effect by the subtype that the base type didn’t expect
  • The Representative Rule
    • Rectangle and subtype Square with setHeight and setWidth vs setSide
  • Refused Bequest!
    • When program setHeight on an object of square, there is an undefined behavior of how to handle a setHeight in a square.
  • Latent OCP Violation
    • Dependency will be created when fixing the problem by checking if a Rectangle is a Square in the program. This is a violation of Open Close Principle.
  • Solution
    • Treat square and rectangle completely different type.
  • The Representative Rule
    • Representative does not share the same relationship of the objects that they represent
  • Number
    • Integer is subtype of Real and Real is subtype of Complex
    • However, complex number has two parts of Real number, one for the real value, and the other for the imaginary.
    • In programming, this complex and real relationship will create a recursive definition similar to the paradox at the beginning of the episode.
    • This is an example where real world model does not work with a computer representation
  • Lists
    • If S is subtype of T, List of S is not a subtype of List of T
    • For example, a Circle is a subtype of Shape but List of Circle is not a subtype of List of Shape because a List of Shape could include Rectangle, Square and other Shapes.

Part 2:

  • Heuristics
    • If base class does something, the derived class must do it too in a way that does not violate the expectation of the caller. This is appearance when a derived class throw an unconditional exception for a method or override with an empty method that the base class implemented.
    • Another indicator is the usage of if instanceof is being used.
    • Only use instanceof when you know the type to help the complier.
  • Typecases
    • The use of if instanceof can lead to additional else if instanceof and should replace with polymorphic dispatch.
  • Statics vs Dynamics
    • Dynamics language use TDD to help with type checking
  • Design by Contract
    • invariant, precondition and postcondition.
  • The Modem Problem
  • Long Distance Rigidity
  • Adapter
    • Adapter is derive from the Modem and delegate to the Ded Modem in the example.
    • If you need an ugly hack, make sure to isolate it from the system by pointing all the dependency away from it.
  • Conclusion
  • References
    • The Annotated Turing by Charles Petzold
    • Advanced C++ Programming Style and Idiom by James Coplien
    • Refactoring: Improving the design of existing code by Martin Fowler
    • Object-oriented Software Construction by Bertrand Meyer

Problem 052

Project Euler

Permuted multiples

Problem 52

It can be seen that the number, 125874, and its double, 251748, contain exactly the same digits, but in a different order.

Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits.

Unbelievably, I was able to do this by hand in less than 30 minutes.

First, the number has to be at least 6 digits to be able to satisfy the criteria because each of the multiples are a permutation of the original number. Since we are looking for the smallest, I start with 6 digits and thinking that I will have to worry about 7 digits later. Turn out the answer is a 6 digits integer.

Next, the first digit must be 1 or it will become 7 digits at 5x if it is greater than 1.

 x: 1 _ _ _ _ _

Now, if we have only 6 digits, and the first digit is 1, the last digit must be 7 because 2,4,5,6,8 will give us a zero at some point for the unit digit which is impossible for a 6 digits integer to start with zero as one of the permutation, and the multiple of 3 or 9 will never produce 1 as the last digit in any of the multiples.

 x: 1 _ _ _ _ 7

In fact, since we know the last digit is 7, we also know that 1,2,4,5,7, and 8 are the digits we must work with because those are the unit digit produced by 7’s multiples. The order of those last digits from 1x to 6x are 7, 4, 1, 8, 5, and 2. We also know that the order of the first digits must be 1, 2, 4, 5, 7, 8 because the first digit must grow in sequence.

 x: 1 _ _ _ _ 7
2x: 2 _ _ _ _ 4
3x: 4 _ _ _ _ 1
4x: 5 _ _ _ _ 8
5x: 7 _ _ _ _ 5
6x: 8 _ _ _ _ 2

Now, working from 1x to 2x, we know that the 2nd digit must not carry because 1st digit must be 2 at 2x. Therefore, 2 or 4 must be the 2nd digit in the original number. We also know that 4 can not be in front of 5, 7, and 8 because 4×2+1 = 9, which is not one of the digit we are working with. In another word, 4 must be in front of 2. Therefore

 x: 1 4 2 _ _ 7
2x: 2 8 5 _ _ 4

Both combination of 5, 8 work from 1x to 2x. However, if the original 5th digit place is 8 and last digit is 7, then it will produce 3×8+2 = 6 at 3x, which is not one of the digit we are working with again. Therefore,

 x: 1 4 2 8 5 7

Continue to multiply x up to 6x will find that this number works and it is the smallest positive integer that works.

Episode 10 – Open-Closed Principle

Clean Code

Episode 10

Episode ten talks about the Open-Closed principle where it is possible for source code to be open for extension but closed for modification.

  • Open and Closed
    • Software module should be open for extension but closed for modification
    • Open for extension means it should be very easy to change the behavior of the module
    • Closed for modification means the source code should not be change
    • Use abstraction and inversion by inserting abstract interface between the high level module and the low level module so that both modules are depend on the abstract interface.
    • Whenever there is a module whose behind you like to extend without modifying it, you separate the extendable behavior behind an abstract interface, and turn the dependency around.
  • Point of Sale Example
  • Implications
    • If a module is open for extension but closed for modification, then each new feature will only need additional new code and not modifying the exiting code.
  • Is this possible?
    • It is hard to be able to completely adhere to open-closed principle
    • The difficulty of conforming to open-closed principle is due to size. Small function, classes and small component are easy to conform but not with larger component.
  • A Smelly Design
  • De-Oderizing the Design
  • The Lie
    • Only protect you from changes if you can predict what they are
  • Two Solutions
  • Big Design Up-Front (BDUF)
    • Think of all possible extension before hand and build the system assuming these extension may be happening.
    • Problem with BDUF is that a major part of the system is unnecessary.
    • Abstraction create indirection and make it hard to follow the call.
  • Agile Design
    • Get a simple design out and then let the customer tell you what need to change and change that. Thus, it is an iterative process with lots of feedback.
    • By understanding what type of change is likely base on the pass changes, we can use the knowledge to predict future changes.
  • Agile Design in Practice
    • In real life, establish basis shape of the system but not over think that implement unnecessary abstraction.
  • Example
  • Reprise
  • References
    • Bertand Meyer, Object-oriented software construction

Episode 09 – Single Responsibility Principle

Clean Code

Episode 09

The ninth episode talks about the Single Responsibility principle.

  • Responsibility
    • Function and module.
    • Best module has only one responsibility
  • It’s about user
    • Responsibility that classes and function has to the user, who will request changes.
    • Responsibility can be view as the sources of change.
    • e.g. Employee class with method calculatePay, save, empolyeeInfo.
      • user for calculatePay maybe from accountants.
      • user for save maybe from DBA if the data is save in the database.
      • user for employeeInfo maybe from people who request the report.
  • It’s about role
    • Avoid coupling software, separate the user of the software from the role they play.
    • When user play a certain role, they are call actor. Responsibility is tied to actor and not to individual.
  • Reprise
    • Responsibility is a family of function serve one particular actors.
  • The two values of software
    • Secondary value is its behavior (no bug, no crashes).  Achieve by meeting the user’s need.
    • Primary value is the ability to change.
  • Friction
  • CM Collision
    • When a software with multiple responsibility is being changed by multiple users, changes would collide.
  • Fan out
    • Multiple responsibility will force the class to use multiple API. Thus, a large fan out is sensitive to changes in large array of API and cause the software its stability.
  • Collocation is coupling
    • When a software with multiple responsibility, changes from one of the users may force all other users calling this module to have to recompile and re-deploy when the changes has nothing to do with them.
  • Encroaching Fragility
    • Changes come from one user in module with multiple responsibility can affect another user when the two users initially share the usage of the same function.
  • SRP
    • Gather things that changes for the same reason and separate things that are not change for the same reason.
  • Invert Dependency
    • Separate the employee class into implementation and interface but the actors are still coupling
  • Extract Class
    • Separate the employee into three classes for each actors. However, its hard to find the right function for an employee class since it is now three different classes.
  • Facade
    • All users are using the facade class which delegate the implementation to different classes (like previously). However, actors still coupled.
  • Interface Segregation
    • Create 3 interface classes but one implementation class (see Invert dependency). Each actor is entirely decouple from the other because each actor uses its own interface. But developer need to hunt for the interface they need (see Extract Class) and implement still coupled because they are in the same implementation class.
  • Welcome to Engineering
    • No one solution fit all, balance the tradeoff.
  • Faking it
    • The episode follows a waterfall development cycle but in fact, it was done using TDD.
  • References

Episode 08 – SOLID Principle

Clean Code

Episode 08

The eighth episode talks about the SOLID principle.

  • The source code is the design
    • The cost of design is expensive for software vs building a software
  •  Design smell
    • Rigidity, Fragility Immobility
  • Rigidity
    • System is hard to change.
    • Reduce build and test time
    • Long build time is a function of coupling
  • Fragility
    • Small change in one module affect another module
    • Manage the dependency in the module and isolate them from each other
  • Immobility
    • Internal component cannot be easily extracted and re-use in new environment
    • Immobility is due to coupling and dependency between the module of the system.
    • Decouple the central abstract in the application from database, UI and framework… etc.
  • Viscosity
    • Necessary operation like build and test, check-in, check-out, merge are difficult to perform and take a long time to execute
    • Exist due to irresponsible tolerance
    • Cause by tight coupling
    • decoupling module and manage remaining dependency
  • Needless Complexity
    • Coding additional needless complexity because anticipating change for the future that are not required
    • Use TDD so code changes in the future can be trusted with tests and no need for needless complexity now. Focus on current requirement.
    • Needless complexity related to tight coupling because we anticipate relationship of modules which currently are not related.
  • Code Rot
  • Dependency Inversion
    • Avoid having the dependency pointing to the same direction of the flow of control
    • Having dependency oppose the flow of control, prevent code rot by preventing application fan out from growing and coupling with low level.
    • Example, C++ v-table for virtual function, polymorphic dispatch mechanism in Java, C# and Ruby.
    • Inverse key dependency by using dynamic polymorphism.
  • What is OO?
    • Dependency inversion
    • Protecting high level policy from low level detail
  • Dependency Management
    • SOLID principle (Dependency related)
      • Single Responsibility Principle
      • Open Closed Principle
      • Liskov Substitution Principle
      • Interface Segregation Principle
      • Dependency Inversion Principle
    • Component Cohesion Principles
      • Release-Reuse Equivalency Principle
      • Common Closure Principle
      • Common Reuse Principle
    • Component Coupling Principle
      • Acyclic Dependencies Principle
      • Stable Dependencies Principle
      • Stable Abstraction Principle
  • References