<<

OO Design principles Dagger

CSC301 WINTER 2020 SOLID PRINCIPLES. ENTERPRISE . DEPENDENCY INJECTION.

Ilir Dema

University of Toronto

Feb 23-24, 2021 OO Design principles Adapter Pattern Dependency Injection Dagger

OVERVIEW

1 OODESIGNPRINCIPLES

2 ADAPTER PATTERN

3 DEPENDENCY INJECTION

4 DAGGER OO Design principles Adapter Pattern Dependency Injection Dagger

SOLID

S Single responsibility principle O Open/closed principle L Liskov substitution principle I segregation principle D Dependency inversion principle OO Design principles Adapter Pattern Dependency Injection Dagger

A CLASS SHOULD HAVE ONLY ONE REASON TO CHANGE OO Design principles Adapter Pattern Dependency Injection Dagger

S:SINGLE RESPONSIBILITY PRINCIPLE

Definition: A class should have a single responsibility, where a responsibility is nothing but a reason to change. • every class should have a single responsibility • responsibility should be entirely encapsulated by the class • all class services should be aligned with that responsibility Why? • makes the class more robust • makes the class more reusable OO Design principles Adapter Pattern Dependency Injection Dagger

SRPEXAMPLE -IDENTIFYTHEPROBLEM

public class Employee{ private String employeeId; private String name; private string address; private Date dateOfJoining; public boolean isPromotionDueThisYear(){ //promotion logic implementation } public Double calcIncomeTaxForCurrentYear(){ //income tax logic implementation } //Getters & Setters for all the private attributes } OO Design principles Adapter Pattern Dependency Injection Dagger

SRPEXAMPLE -ISSUES

• The promotion logic is responsibility of HR. • When promotion policies change, Employee class need not change. • Similarly, tax computation is the finance department’s responsibility. • If Employee class owns the income tax calculation responsibility then whenever tax structure/calculations change Employee class will need to be changed. • Lastly, Employee class should have the single responsibility of maintaining core attributes of an employee. OO Design principles Adapter Pattern Dependency Injection Dagger

REFACTOR THE EMPLOYEE CLASSTOMAKEITOWNA SINGLERESPONSIBILITY.

Lets move the promotion determination logic from Employee class to the HRPromotions class:

public class HRPromotions{ public boolean isPromotionDueThisYear(Employee emp){ // promotion logic implementation // using the employee information passed } } OO Design principles Adapter Pattern Dependency Injection Dagger

REFACTOR THE EMPLOYEE CLASSTOMAKEITOWNA SINGLERESPONSIBILITY.

Similarly, lets move the income tax calculation logic from Employee class to FinITCalculations class:

public class FinITCalculations{ public Double calcIncomeTaxForCurrentYear(Employee emp){ //income tax logic implementation //using the employee information passed } } OO Design principles Adapter Pattern Dependency Injection Dagger

EMPLOYEE.JAVA ADHERINGTO SINGLE RESPONSIBILITY PRINCIPLE.

Our Employee class now remains with a single responsibility of maintaining core employee attributes:

public class Employee{ private String employeeId; private String name; private string address; private Date dateOfJoining; //Getters & Setters for all the private attributes } OO Design principles Adapter Pattern Dependency Injection Dagger

A CLASSSHOULDBEOPENFOREXTENSIBILITY, BUT CLOSED FOR MODIFICATION. OO Design principles Adapter Pattern Dependency Injection Dagger

O:OPEN/CLOSED PRINCIPLE

• Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. • add new features not by modifying the original class, but rather by extending it and adding new behaviours • the derived class may or may not have the same interface as the original class • originally defined by Bertrand Meyer in his book Object Oriented Software Construction. OO Design principles Adapter Pattern Dependency Injection Dagger

O:OPEN/CLOSED PRINCIPLE - 3 STATEMENTS

1 A module will be said to be open if it is still available for extension. For example, it should be possible to new fields or new methods. • What it means: If attributes or behavior can be added to a class it can be said to be “open”. 2 A module will be said to be closed if it is available for use by other modules. This assumes that the module has been given a well-defined, stable description. • What it means: If a class is re-usable or specifically available for extending as a base class then it is closed. 3 A class adheres to the Open/Closed Principle when: • It is closed, since it may be compiled, stored in a library, baselined, and used by client classes • But it is also open, since any new class may use it as parent, adding new features. • What it means: A class can be open and closed at the same time. OO Design principles Adapter Pattern Dependency Injection Dagger

EXAMPLEOF OPEN/CLOSED PRINCIPLEIN JAVA.

Lets say we need to calculate areas of various shapes. Say our first shape is Rectangle:

public class Rectangle{ public double length; public double width; }

Next we create a class to calculate area of this Rectangle which has a method calculateRectangleArea() :

public class AreaCalculator{ public double calculateRectangleArea(Rectangle rectangle){ return rectangle.length *rectangle.width; } } OO Design principles Adapter Pattern Dependency Injection Dagger

EXAMPLEOF OPEN/CLOSED PRINCIPLEIN JAVA.

Let’s create a new class Circle with a single attribute radius:

public class Circle{ public double radius; } Then we modify AreaCalculator class:

public class AreaCalculator{ public double calculateRectangleArea(Rectangle rectangle){ return rectangle.length *rectangle.width; } public double calculateCircleArea(Circle circle){ return Math.PI*circle.radius*circle.radius; } } OO Design principles Adapter Pattern Dependency Injection Dagger

O:OPEN/CLOSED PRINCIPLE -IDENTIFY THE FLAWS

• Lets say we have a new shape pentagon next. In that case we will again end up modifying AreaCalculator class. • As the types of shapes grows this becomes messier as AreaCalculator keeps on changing and any consumers of this class will have to keep on updating their libraries which contain AreaCalculator • As a result, AreaCalculator class will not be baselined(finalized) with surety as every time a new shape comes it will be modified. • So, this design is not closed for modification. OO Design principles Adapter Pattern Dependency Injection Dagger

O:OPEN/CLOSED PRINCIPLE -IDENTIFY THE FLAWS

• Also, note that this design is not extensible: • As we add more shapes, AreaCalculator will need to keep on adding their computation logic in newer methods. • We are not really expanding the scope of shapes; rather we are simply doing piece-meal(bit-by-bit) solution for every shape that is added. OO Design principles Adapter Pattern Dependency Injection Dagger

MAKETHEDESIGNEXTENSIBLE.

For this we need to first define a base type Shape

public interface Shape{ public double calculateArea(); } OO Design principles Adapter Pattern Dependency Injection Dagger

MAKETHEDESIGNEXTENSIBLE.

Next, have Circle & Rectangle implement Shape interface

public class Rectangle implements Shape{ double length; double width; public double calculateArea(){ return length * width; } }

public class Circle implements Shape{ public double radius; public double calculateArea(){ return Math.PI*radius*radius; } } OO Design principles Adapter Pattern Dependency Injection Dagger

MAKETHEDESIGNCLOSED.

In our case consumer will be the AreaCalculator class which would now look like this

public class AreaCalculator{ public double calculateShapeArea(Shape shape){ return shape.calculateArea(); } }

This AreaCalculator class now fully removes our design flaws noted above and gives a clean solution which adheres to the Open-Closed Principle. OO Design principles Adapter Pattern Dependency Injection Dagger

LISKOVSUBSTITUTIONPRINCIPLE OO Design principles Adapter Pattern Dependency Injection Dagger

L:LISKOVSUBSTITUTIONPRINCIPLE

• If S is a subtype of T, then objects of type S may be substituted for objects of type T, without altering any of the desired properties of the program. • “S is a subtype of T”? In Java, S is a child class of T, or S implements interface T. • For example, if C is a child class of P, then we should be able to substitute C for P in our code without breaking it. OO Design principles Adapter Pattern Dependency Injection Dagger

LISKOVSUBSTITUTIONPRINCIPLE OO Design principles Adapter Pattern Dependency Injection Dagger

EXERCISE

• Write (paper and pencil is fine) an implementation of Rectangle. • Extend the Rectangle class to a Square class. • Declare a List and stuff in a number of Rectangle and Square objects. • After all, each Square is a Rectangle, so we should have no problem doing that. • Pass the list to a cutting machine that cuts wood shapes. • An emergency requirement comes in: due to new packaging rules, no shape can have height greater than a preset MAX_HEIGHT. OO Design principles Adapter Pattern Dependency Injection Dagger

EXERCISE (CONTINUED)

class CuttingMachine { // ... some code ... protected void fixHeight(List rectangleList, double maxHeight) { for rectangle in rectangleList rectangle.setHeight(maxHeight); } }

1 Explain what might happen. 2 Solve the problem. OO Design principles Adapter Pattern Dependency Injection Dagger

L:LISKOVSUBSTITUTIONPRINCIPLE

• In OO programming and design, unlike in math, it is not the case that a Square is a Rectangle! • This is because a Rectangle has more behaviours than a Square, not less. • The LSP is related to the Open/Close principle: the sub classes should only extend (add behaviours), not modify or remove them. OO Design principles Adapter Pattern Dependency Injection Dagger

CLIENTSSHOULDNOTBEFORCEDTODEPENDON METHODSTHEYDONOTUSE OO Design principles Adapter Pattern Dependency Injection Dagger

I:INTERFACE SEGREGATION PRINCIPLE

• No client should be forced to depend on methods it doesn’t use. • Better to have lots of small, specific interfaces than fewer larger ones. • Easier to extend and modify the design. OO Design principles Adapter Pattern Dependency Injection Dagger

EXAMPLE:THE RESTAURANT INTERFACE

public interface RestaurantInterface { public void acceptOnlineOrder(); public void takeTelephoneOrder(); public void payOnline(); public void walkInCustomerOrder(); public void payInPerson(); } OO Design principles Adapter Pattern Dependency Injection Dagger OO Design principles Adapter Pattern Dependency Injection Dagger

IDENTIFYINGPROBLEMS ...

• Since OnlineClientImpl.java is for online orders, the other methods throw UnsupportedOperationException. • Since the 5 methods are part of the RestaurantInterface, the implementation classes have to implement all 5 of them. • Implementing all methods is inefficient. • Any change in any of the methods of the RestaurantInterface will be propagated to all implementation classes. Maintenance of code then starts becoming really cumbersome and regression effects of changes will keep increasing. • RestaurantInterface.java breaks Single Responsibility Principle because the logic for payments as well as that for order placement is grouped together in a single interface. OO Design principles Adapter Pattern Dependency Injection Dagger

APPLYING INTERFACE SEGREGATION PRINCIPLE

• Separate out payment and order placement functionalities into two separate lean interfaces. Let’s name them PaymentInterface.java and OrderInterface.java. • Each of the clients use one implementation each of PaymentInterface and OrderInterface. For example - OnlineClient.java uses OnlinePaymentImpl and OnlineOrderImpl and so on. • Change in any one of the order or payment interfaces does not affect the other. They are independent now. • There will be no need to do any dummy implementation or throw an UnsupportedOperationException as each interface has only methods it will always use. OO Design principles Adapter Pattern Dependency Injection Dagger

D:DEPENDENCYINVERSIONPRINCIPLE

• When building a complex system, we may be tempted to define the “low-level” classes first and then build the “higher-level” classes that use the low-level classes directly. • (for simplicity, “low-level” - components, “high-level” - classes that use those components) • But this approach is not flexible! What if we need to replace a low-level class? The logic in the high-level class will need to be replaced. • To avoid such problems, we can introduce an abstraction layer between low-level classes and high -level classes. OO Design principles Adapter Pattern Dependency Injection Dagger

DEPENDENCYINVERSIONPRINCIPLE OO Design principles Adapter Pattern Dependency Injection Dagger

DEPENDENCY INVERSION PRINCIPLE

• Depending on which source one refers to, Dependency Inversion Principle, as defined by Robert C. Martin, can be defined in any of the following ways: • Depend upon Abstractions. Do not depend upon concretions. • Abstractions should not depend upon details. Details should depend upon abstractions. • High-level modules should not depend on low-level modules. Both should depend on abstractions. OO Design principles Adapter Pattern Dependency Injection Dagger

DEPENDENCY INVERSION EXAMPLE

// Identify and fix the problem public class DoBackEnd {// Low level module public void writeJava() {...} } public class DoFrontEnd {// Low level module public void writeJavascript() {...} } public class Project { // high level module private DoBackEnd backEnd= new DoBackEnd(); private DoFrontEnd frontEnd = new DoFrontEnd(); public void implement() { backEnd.writeJava(); frontEnd.writeJavascript(); } } OO Design principles Adapter Pattern Dependency Injection Dagger

DEPENDENCY INVERSION SOLUTION

public interface Developer {void develop();} public class DoBackEnd implements Developer { @Override public void develop() {writeJava();} private void writeJava() {...} } public class DoFrontEnd {// Similar } public class Project { // high level module private List developers; public Project(List developers) { this.developers = developers; } public void implement() { developers.forEach(d->d.develop()); } } OO Design principles Adapter Pattern Dependency Injection Dagger

DEPENDENCY INVERSION PRINCIPLE

To understand the Dependency Inversion Principle better, let us first take a look at how the traditional procedural systems have their dependencies organised. In procedural systems, higher level modules depend on lower level modules to fulfil their responsibilities. The diagram below shows the procedural dependency structure OO Design principles Adapter Pattern Dependency Injection Dagger

DEPENDENCY INVERSION PRINCIPLE

The Dependency Inversion Principle, however, advocates that the dependency structure should rather be inverted when designing object-oriented systems.. Have a look at the diagram below showing dependency structure for object-oriented systems OO Design principles Adapter Pattern Dependency Injection Dagger

WHATISWRONGWITHTRADITIONALPROCEDURAL SYSTEMS?

• If you take a re-look at the diagram above showing modular dependencies in a procedural system, then one can clearly see the tight coupling that each module layer has with its sub-layer. • Thus, any change in the sub-layer will have a ripple effect in the next higher layer and may propagate even further upwards. • This tight coupling makes it extremely difficult and costly to maintain and extend the functionality of the layers. OO Design principles Adapter Pattern Dependency Injection Dagger

ADVANTAGE OF USING DEPENDENCY INVERSION PRINCIPLE

• The Dependency Inversion Principle, does away with this tight-coupling between layers by introducing a layer of abstraction between them. • So, the higher-level layers, rather than depending directly on the lower-level layers, instead depend on a common abstraction. • The lower-level layer can then vary(be modified or extended) without the fear of disturbing higher-level layers depending on it, as long as it obeys the contract of the abstract interface. If, as shown in the object-oriented design diagram above, the lower layers literally extend the abstraction layer interfaces, then they will follow the contract. OO Design principles Adapter Pattern Dependency Injection Dagger

SOLVING DEPENDENCY INVERSION

There may arise scenarios where the lower-level layers cannot directly extend the abstraction interfaces. In such cases an Adapter Design Pattern implementation is used. OO Design principles Adapter Pattern Dependency Injection Dagger

SOLIDPRINCIPLESINACTION.

If we have an existing system which need to work with a vendor class library, with interfaces designed differently from last vendor’s, we would write a class that adapts the new vendor interface into the one we are expecting: OO Design principles Adapter Pattern Dependency Injection Dagger

ADAPTER PATTERN

DEFINITION The Adapter Pattern converts the interface of a class into another interface the clients expects. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces. OO Design principles Adapter Pattern Dependency Injection Dagger

WHYDOWENEEDADAPTERS?

ADAPTER PATTERN • Adapter pattern allows allows us to use a client with an incompatible interface by creating an Adapter that does the conversation. • Adapter decouples the client from the implemented interface, and if we expect the interface to change over time, the adapter encapsulates that change so that the client doesn’t have to be modified each time it needs to operate against a different interface. OO Design principles Adapter Pattern Dependency Injection Dagger

ADAPTER PATTERN - OO Design principles Adapter Pattern Dependency Injection Dagger

GOOD DESIGN PRINCIPLESIN ADAPTER PATTERN

• Uses to wrap the adaptee with an altered interface. • Also the pattern binds the client to an interface, not to an implementation; we could use several adapters, each covering a backend set of classes. OO Design principles Adapter Pattern Dependency Injection Dagger

APPLICATION:ENUMERATORS AND ITERATORS

• Early colection types in Java (Vector, Stack, Hashtable, and a few others) implement a method elements() which returns an Enumeration. • The Enumeration interface allows you to step through the elements of a collection without knowing the specifics of how they are managed in the collection. OO Design principles Adapter Pattern Dependency Injection Dagger

APPLICATION:ENUMERATORS AND ITERATORS

• When Sun released their more recent Collection classes they began using an iterator interface that, like Enumeration, allows you to iterate through a set of items in a collection, but also adds the ability to remove items. OO Design principles Adapter Pattern Dependency Injection Dagger

ADAPTINGAND ENUMERATION TO AN ITERATOR

• First need to see how methods map from one to the other. That is what to call on the adaptee when the client invokes a method on the target. OO Design principles Adapter Pattern Dependency Injection Dagger

DESIGNINGTHE ADAPTER

• Adapter needs to implement Target interface, and that is composed with an adaptee. hasNext(), next() map straightforward from target to adaptee. OO Design principles Adapter Pattern Dependency Injection Dagger

FULL IMPLEMENTATION OO Design principles Adapter Pattern Dependency Injection Dagger

EXERCISE

While Java has gone the direction of the iterator, there is neverthless a lot of legacy code that depends on Enumeration interface, so an Adapter that converts an Iterator to an Enumerator is quite useful. Write an Adapter that adapts an Iterator to an Enumerator. You can test your code by adapting an ArrayList. The ArrayList supports Iterator but does not support Enumerate. OO Design principles Adapter Pattern Dependency Injection Dagger

WHAT IS DEPENDENCY INJECTION?

DEFINITION The definition of dependency injection was first given by Martin Fowler in the blog post Containers and the Dependency Injection pattern. The dependency injection is an Enterprise Design Pattern, which aim is to separate the responsibility of resolving object dependency from its behaviour.

NOTE: An Enterprise Design Pattern is a Design Pattern used in enterprise applications. OO Design principles Adapter Pattern Dependency Injection Dagger

FOWLER’SEXAMPLE OO Design principles Adapter Pattern Dependency Injection Dagger

EXERCISE

• Try to write (on paper) a constructor for MovieLister. • Identify the broken design principles ... OO Design principles Adapter Pattern Dependency Injection Dagger

THE MOVIELISTER CONSTRUCTOR

public class MovieLister { private MovieFinder finder; public MovieLister() { // This statement tightly coupled (1) // the two classes because the class has a // direct reference to a particular // implementation of MovieFinder interface (2) this.finder = new MovieFinderImpl(); } // ... OO Design principles Adapter Pattern Dependency Injection Dagger

HOWDIDWEGETINTROUBLE?

• Clearly, in the previous slide we used a long venerated design principle: • Favor composition over inheritance • However letting a class to explicitly create an instance of another class tightly coupled the two implementations, increasing the dependency between them.

FRED BROOKS:NO SILVER BULLET There is no single development, in either technology or management technique, which by itself promises even one order-of-magnitude improvement within a decade in productivity, in reliability, in simplicity. OO Design principles Adapter Pattern Dependency Injection Dagger

LET’SLOOKFORHELP!

• Well we know a design pattern used to make objects. • The factory pattern! • Its intent is: • creates objects without exposing the instantiation logic to the client. • refers to the newly created object through a common interface OO Design principles Adapter Pattern Dependency Injection Dagger

UML FOR THE FACTORY PATTERN OO Design principles Adapter Pattern Dependency Injection Dagger

LET’S APPLY IT...

Notice the dependency graph is directed acyclic (DAG). OO Design principles Adapter Pattern Dependency Injection Dagger

HOUSTON, WE HAVE A PROBLEM!

• Now MovieLister has a dependency with the implementation of MovieFinderFactory. • Notice factory is implemented as a Singleton ... • Moreover, we certainly have more than a single dependency in a class, which leads to a plethora of factories rising. • And dependencies can have dependencies, and so on. • We get a chain of growing dependencies. • There are two possibilities: • The chain blows up in finite time. • The chain stabilizes (i.e. the nightmare comes to a limit). OO Design principles Adapter Pattern Dependency Injection Dagger

MARTIN FOWLER’SSOLUTION

Take the factory idea to the limit and we create a module that is responsible to resolve dependency among classes. OO Design principles Adapter Pattern Dependency Injection Dagger

DEPENDENCY INJECTOR

• The Injector module is called dependency injector and it is to all effects a container. • Applying the Inversion of Control pattern, the injector owns the life cycle of all objects defined under its scope. • The only things we still miss are the following: • A way to signal to the injector that a class has a certain dependency • A way to instruct (or configure) the injector to resolve dependencies OO Design principles Adapter Pattern Dependency Injection Dagger

INTERLUDE:JAVA BEANS

• Since the definition of the Java , the aim of the Sun Microsystem was standardization. • The Java Bean Specification stated that a java bean must have: • a default constructor • a couple of getter and setter methods for each attribute it owns. • Having defined a standard way of creating objects, the Sun built a plethora of standards and interfaces on it, that are the basis of the JEE specification. OO Design principles Adapter Pattern Dependency Injection Dagger

CONSTRUCTORINJECTIONVERSUS SETTERINJECTION

• Since dependencies are nothing more then objects attributes (more or less), the injector has to be instructed to know how to fulfill these attributes. • In Java there are three ways to set attributes of an object, which are: • Using the proper constructor • Using setters after the object was build using the default constructor • Using Reflection mechanisms • Once you have selected your preferred way, you will annotate the corresponding statement with the @Inject annotation. • The annotation and its behaviour are defined inside a JSR. Dependency injection is so important in the Java ecosystem that there are two dedicated Java Specification Requests (JSRs), i.e. JSR-330 and JSR-299. OO Design principles Adapter Pattern Dependency Injection Dagger

CONSTRUCTORDEPENDENCYINJECTION

• If you want the injector to use the constructor to inject the dependency of a class, annotate the constructor with @Inject. • Every time you will ask the injector an instance of a MovieLister, it will know that it has to use the constructor annotated with the @Inject annotation to build the object. • So, the dependency are identified as the annotated constructor parameters.

public class MovieLister { private MovieFinder finder;

@Inject public MovieLister(MovieFinder finder) { this.finder = finder; } } OO Design principles Adapter Pattern Dependency Injection Dagger

SETTERDEPENDENCYINJECTION

• To instruct the injector to use setter methods to create an object, annotate the setter methods with the @Inject annotation.

public class MovieLister { private MovieFinder finder;

// The injector first uses the default // constructor to build an empty object public MovieLister() {} // Then, the injector uses annotated setter // methods to resolve dependencies @Inject public void setFinder(MovieFinder finder) { this.finder = finder; } } OO Design principles Adapter Pattern Dependency Injection Dagger

THEINJECTOR

• There are many implementations in the Java ecosystem of dependency injectors. Each implementation differs from each others essentially for these features: • How the injector is configured to find the beans it has to manage • How it resolves the dependencies DAG • How it maintains the instances of managed beans. OO Design principles Adapter Pattern Dependency Injection Dagger

THEINJECTOR

• Some injectors used in practice are the following: • : Guice is a lightweight dependency injection framework that uses Java configuration, implements both types of injection (constructor and setter injection) and maintains managed instances with a Map, Object> • Spring Injector: It is not quite lightweight as Guice, but it is fully integrated with the whole Spring ecosystem. It implements all types of injection; it provides an XML style of configuration and a Java style. Differently from Guice, the container is a Map, that associates each managed instance with a label. It also support auto discovery of beans through classpath scanning. OO Design principles Adapter Pattern Dependency Injection Dagger

WHAT IS DAGGER-2?

• Dagger-2 is a fast and lightweight dependency injection framework. • It is implemented through an external component which provides instances of objects (or dependencies) needed by other objects. • In particular, the injection happens at run-time or at compile-time. • Run-time DI is usually based on reflection which is simpler to use but slower at run-time. An example of a run-time DI framework is Spring. • Compile-time DI, on the other hand, is based on code generation. This means that all the heavy-weight operations are performed during compilation. Compile-time DI adds complexity but generally performs faster. • Dagger 2 falls into this category. OO Design principles Adapter Pattern Dependency Injection Dagger

EXAMPLE

In order to use Dagger in a project, we’ll need to add the dagger dependency to our pom.:

MAVEN CONFIGURATION com.google.dagger dagger 2.16

Note: Eclipse needs be configured as follows: • Install m2e-apt • Window -> Preferences -> Maven -> Annotation Processing: Select "Automatically configure JDT APT" OO Design principles Adapter Pattern Dependency Injection Dagger

EXAMPLE

Also need to include the Dagger compiler used to convert our annotated classes into the code used for the injections:

MAVEN CONFIGURATION org.apache.maven.plugins maven-compiler-plugin 3.6.1 com.google.dagger dagger-compiler 2.16 OO Design principles Adapter Pattern Dependency Injection Dagger

THE CAREXAMPLE

• Dagger uses the standard JSR-330 annotations in many places, one being @Inject. • Since Dagger doesn’t support injection on private fields, we’ll go for constructor injection.

BUILDACARBYINJECTINGITSCOMPONENTS public class Car { private Engine engine; private Brand brand;

@Inject public Car(Engine engine, Brand brand) { this.engine = engine; this.brand = brand; } // getters and setters } OO Design principles Adapter Pattern Dependency Injection Dagger

CODE NEEDED TO PERFORMTHE INJECTION

• Next, we’ll implement the code to perform the injection. More specifically, we’ll create: • a module, which is a class that provides or builds the objects’ dependencies, and • a component, which is an interface used to generate the injector • Complex projects may contain multiple modules and components but since we’re dealing with a very basic program, one of each is enough. OO Design principles Adapter Pattern Dependency Injection Dagger

CREATING A MODULE

A Module class is annotaed with the @Module annotation, indicating that it can make dependencies available to the container. Then, we need to add the @Provides annotation on methods that construct our dependencies:

AMODULEEXAMPLE @Module public class VehiclesModule { @Provides public Engine provideEngine() { return new Engine(); } @Provides @Singleton public Brand provideBrand() { return new Brand("CSCC01"); } } OO Design principles Adapter Pattern Dependency Injection Dagger

COMPONENTS

• Components are essentially the glue that holds everything together. • They are a way of telling Dagger what dependencies should be bundled together and made available to a given instance so they can be used. • They provide a way for a class to request dependencies being injected through their @Inject annotation. OO Design principles Adapter Pattern Dependency Injection Dagger

COMPONENTEXAMPLE

Moving on, we’re going to create our component interface. This is the class that will generate Car instances, injecting dependencies provided by VehiclesModule. Simply put, we need a method signature that returns a Car and we need to mark the class with the @Component annotation. Notice how we pas our module class as an argument to the @Component annotation. If we didn’t do that, Dagger wouldn’t know how to build the car’s dependencies.

A COMPONENTEXAMPLE @Singleton @Component(modules = VehiclesModule.class) public interface VehiclesComponent { Car buildCar(); }