Sunday, July 12, 2015

The Dependency Inversion Principle - SOLID



https://miafish.wordpress.com/2015/02/09/dependency-injection-pattern/
Dependency injection is basically providing the objects that an object needs (its dependencies) instead of having it construct them itself.

Advantages and Disadvantages of Dependency Injection
advantages are:
easily testable : easy for unit test in isolation using mock or stubs that simulate other objects not under test.
loose coupling : allows a client to remove all knowledge of a concrete implementation that it needs to use.
centralized configuration : externalize a system’s configuration details into configuration files allowing the system to be reconfigured without recompilation.
Disadvantages are:
code difficult to trace since it separates behavior from construction.
diminish encapsulation by requiring users of a system to know how it works and not merely what it does.
increasing the coupling between a class and its consumer(the consumer needs more info to create it) and dependency and its consumer(the consumer needs to know the dependency to use)
https://miafish.wordpress.com/2015/01/10/the-dependency-inversion-principle/
what is the dependency inversion principle?

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions.
Traditional Layers Pattern:
Traditional Layers Pattern.png
Ownership Inversion:
DIPLayersPattern.png
high level module depends directly on low level module. so if we have to write eBook reader for other type of book, such as mobile books. then we have to change the eBook reader. so the correct way to implement it would be using interface.
http://code.tutsplus.com/tutorials/solid-part-4-the-dependency-inversion-principle--net-36872
Robert C. Martin -- Agile Software Development, Principles, Patterns, and Practices


A. High level modules should not depend upon low level modules. Both should depend upon abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions. (http://www.objectmentor.com/resources/articles/dip.pdf)
Forces
We wish to avoid designs which are:
  • Rigid (Hard to change due to dependencies. Especially since dependencies are transitive.)
  • Fragile (Changes cause unexpected bugs.)
  • Immobile (Difficult to reuse due to implicit dependence on current application code.)
The ObserverPattern can be considered a two-layered architecture, where the model is the lower-level module and the higher level module is the observer.
http://www.codeproject.com/Articles/615139/An-Absolute-Beginners-Tutorial-on-Dependency-Inver
This design violates the dependency inversion principle. i.e. the high level module AppPoolWatcher depends on EventLogWriter which is a concrete class and not an abstraction. 

Dependency inversion was a software design principle, it just states that how two modules should depend on each other. 

Inversion of control is the actual mechanism using which we can make the higher level modules to depend on abstractions rather than concrete implementation of lower level modules.

Now our high level modules are dependent only on abstractions and not the lower level concrete implementations, which is exactly what dependency inversion principle states.

Dependency Injection
 Dependency Injection is mainly for injecting the concrete implementation into a class that is using abstraction i.e. interface inside. The main idea of dependency injection is to reduce the coupling between classes and move the binding of abstraction and concrete implementation out of the dependent class.
Dependency injection can be done in three ways.
  1. Constructor injection
  2. Method injection
  3. Property injection
IoC containers will help us to map the dependencies easily when we have chained or nested dependencies.

Difficult to write unit tests should give us hints like:
  • Our class is trying to do too much
  • Our class has lots of different dependencies
  • Our class requires a lot of setup to do work
  • Our class is just like this other class that does the same thing only for a different input
https://lostechies.com/gabrielschenker/2009/01/30/the-dependency-inversion-principle/
public class EncryptionService
{
    public void Encrypt(IReader reader, IWriter writer)
    {
        // Read content
        byte[] content = reader.ReadAll();
 
        // encrypt
        byte[] encryptedContent = DoEncryption(content);
 
        // write encrypted content
        writer.Write(encryptedContent);
    }
 }
http://javarevisited.blogspot.com/2012/12/inversion-of-control-dependency-injection-design-pattern-spring-example-tutorial.html
public class AuditServiceImpl implements AuditService{
    private AuditDAO auditDao = new AuditDAO();
  
}
1) Every AuditServiceImpl has its own copy of AuditDAO which is an expensive object as it wraps a database connection with in.
2) AuditServiceImpl is closely coupled with AuditDAO as its creating instance of AuditDAO using new() operator. If you change the constructor of AuditDAO this code will be broken. Because of this coupling its difficult to replace AuditDAO with better implementation.
3) There is no easy way to test audit() method which is dependent on auditDAO.
public class AuditServiceImpl implements AuditService{
    private AuditDAO auditDao;
    public void setAuditDao(AuditDAO AuditDao) {
        this.AuditDao = AuditDao;
    }
}

1. Since AuditDAO is injected here its possible to share single AuditDAO (an expensive object) between multiple AuditService.
2. Since AuditServiceImpl is not creating instance of AuditDAO its no more coupled with AuditDAO and work with any implementation of AuditDAO.
3. Because AuditDAO is injected by DI at runtime its easy to test audit() method by providing a mock AuditDAO class


PTOM – Brownfield development – Making your dependencies explicit
Poor Man’s Dependency Injection
Since this is a brownfield project we cannot provide the perfect solution but we can provide a decent one. We just new up instances of the required dependencies in the forward call
   1: public OrderService() : this(
   2:     new OrderRepository(),
   3:     new EmailSender(ConfigurationManager.AppSettings["SMTPServer"])
   4:     )
   5: { }
http://martinfowler.com/articles/dipInTheWild.html
http://www.objectmentor.com/resources/articles/dip.pdf

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts