Application Wiring on Auto-Pilot

September 24th, 2008 · 11 Comments ·

by Miško Hevery

We talked about how it is important to separate the new operators from the application logic. This separation forces your code to have factories which are responsible for wiring your application together. By separating this responsibility the tests can always wire together a subset of an application with key components replaced for friendlies making testing easier and more focused. 

But lets look at a sample factory

class CarFactory {
  Car create() {
    return new Car(
          new EngineCompartment(
                new Engine(),
                new ManualTransmission(),
                new PowerSteering(),
                new Battery()
             ),
          new Cabin(
                new Door(new PowerWindow()),
                new Door(new PowerWindow()),
                new PowerSeat(), new PowerSeat()
            ),
         Arrays.asList(
              new Wheel(new Tire(), new Rim()),
              new Wheel(new Tire(), new Rim()),
              new Wheel(new Tire(), new Rim()),
              new Wheel(new Tire(), new Rim())
            )
       );
  }
}

This factory builds a car. The first thing to notice is that all of the new-operators are here (If you were to look inside each of the classes it would be devoid of “new”s). The second, is a complete lack of logic (no loops or conditions). And finally the third, your application behavior is controlled by the way the classes are wired together. If I wanted a automatic-transmission car, all we have to do is to wire the classes differently. The wiring responsibility is in the factory class not with the application logic.

However, why do we need to tell the JVM how to wire these Classes together? Is it not self obvious?  After all look at the constructors of these classes:

Car(EngineCompartment ec, Cabin c, List<Wheel> ws);
EngineCompartment(Engine e, Transmission t, 
              Steering s, Battery b);
Cabin(Door driverDoor, Door pasangerDoor, 
              Seat driverSear, Seat passangerSear);
Engine(float dissplacement, int pistonCount);
Battery(float voltage);
Door(Window window);
PowerWindow() implements Window;
PowerSeat() implements Seat;
Wheel(Tire tire, Rim rim);
...

Imagine you could just ask for things. Lets start simple and look at the Wheel. The constructor of Wheel needs a Tire and Rim. So when we ask for a Wheel it should be self obvious that we want new Wheel(new Tire(), new Rim()). Why do we need to make this explicit in our factory? Lets build a framework from which we can ask for a class and it returns an instance of that class. So in our case if we ask for getInstance(Wheel.class) it returns instance of new Wheel(new Tire(), new Rim()). Now a framework like this is easy to build since all we need to do is look at the constructor and recursively try to instantiate the objects until all recursive constructors are satisfied.

But things are a bit more complicated than that. What if we ask for Cabing as in getInstance(Cabin.class). Well Cabin needs two Doors and two Seats, but Seat is an interface and so we have to make a decision. What subclass of Seat should we instantiate. To help our framework make that decision we will add a bind method such as bind(Seat.class, PowerSeat.class). Great now we call get(Seat.class) the framework returns new PowerSeat(). Similarly, we will have to call bind(Window.class, PowerWindow.class). Now we can call get(Cabin.class) and the framework will return new Cabin(new Door(new PowerWindow()), new Door(new PowerWindow()), new PowerSeat(), new PowerSeat()).

Notice that a closer to the root a class, the class you ask for is, the more work will the framework do for us. So ideally we just want to ask for the root object. In our case Car. Calling get(Car.class) will cause the framework to do all of the work originally in our factory.

As you can see a framework which will call the new operators on your behalf is very useful. This is because you only have to ask for the root object (in our case the Car) and the framework will build the whole object graph on your behalf. This kinds of frameworks are called Automatic Dependency Injection frameworks and there are few of them our there. Namely GUICE, PicoContainer, and Spring

Since I know most about GUICE, The above example can be rewritten in GUICE like this:

class CarModule extends AbstractModule() {
  public void bind() {
    bind(Seat.class, PowerSeat.class);
    bind(Seat.class, PowerSeat.class);
    bind(Transmission.class, ManualTransmission.class);
    bind(new TypeLitteral<List<Wheel>>(){})
      .toProvider(new Provider<List<Wheel>>(){
        @Inject Provider<Wheel> wp;
        List<Wheel> get() {
          return Array.asList(wp.get(), wp.get(), 
                              wp.get(), wp.get());
        }
      });
  }
}
Injector injector;
injector = GUICE.createInjector(new CarModule());
Car car = injector.getInstance(Car.class);

As you can see Automatic Dependency Injection frameworks can do a lot of things for you. Namely, that you don’t have to worry about writing the factories. You simply write your application logic and ask for your dependencies in the constructor and let the framework resolve all of them for you. You move the responsibility of calling the new operator to the framework. Or to put it differently DI-framework is your new “new”. Now DI-frameworks can do lot of other things, which are beyond the scope of this article, such as manage object lifetimes, enforce singletons (in a good way, see: Root Cause of Singletons and Singletons are Pathological Liars) and manage different configurations of your application such as production vs development server.

For a more real life example of a GUICE Module see: CalculatorServerModule.java

Tags: Uncategorized

11 responses so far ↓

  • RichB // Sep 26, 2008 at 4:11 am

    When you code like this, do you never see constructor overloads?

  • misko // Sep 26, 2008 at 7:31 am

    @RichB

    Yes, it is very rare to have multiple overloaded constructors for object since each constructor just does simple field assignment.

  • Arvind // Sep 29, 2008 at 11:05 pm

    I have been following your articles for sometime now. Your articles sure get me thinking on how to write applications that could be tested and maintained easily. However, I am not clear how much of this is applicable to applications written in C++. Since that is the language that I exclusively program in. Please clarify.

  • misko // Sep 30, 2008 at 10:12 am

    @Arvind,

    I am not a C++ expert but I have forwarded your question to someone who is. My understanding is that most of these things apply in any language. There are differences, for example C++ does not have automatic dependency injection, and you have to worry about object ownership for reclaiming memory, but the high level concepts should hold.

    – Misko

  • Dave Astels // Sep 30, 2008 at 11:20 am

    I agree with Misko. The design and testability concepts he’s been talking about here are fundamental OO ideas… nothing language dependent. The implementation of those ideas will definitely be language dependent. Java has several dependancy injection frameworks to choose from. I’m not familiar with any for other languages. AFAIK C++ doesn’t have the reflective capability, and dynamic languages like Ruby don’t have the type information on constructor arguments. You would have to add some form of meta-linguistic information to state your dependancies for a DI framework to use.

    So.. the ideas are valid outside of Java, and have the same value (i.e. high). You just have to do more of the work yourself.

    Dave

  • To “new” or not to “new”… | Miško Hevery // Sep 30, 2008 at 9:04 pm

    [...] for wiring your application together. However, better than writing factories,  we want to use automatic dependency injection such as GUICE to do the wiring for us. But can DI really save us from all of the new [...]

  • sx2008 // Aug 23, 2009 at 10:11 am

    In a programming language without garbage collection (eg. Delphi or C++):
    Who is responsible to free the injected objects like “Wheel”?
    The test class asks the factory for building a new Car; so when the tests are finished it frees the car object (inside teardown).
    Should the car class free all injected objects?

  • misko // Aug 23, 2009 at 10:19 pm

    @sx20082

    that is an excellent question, but unfortunately, I don’t have any experience with those languages, so I am not sure what the right answer is.

  • Freeman // Oct 1, 2009 at 3:03 pm

    sx2008,
    In delphi language you can inherit your objects from TInterfacedObject and implement an interface that you use to reference your object.
    TInterfacedObject implements reference counting and frees the object when there is no reference to it.

  • Manny Fleurmond // Sep 9, 2012 at 8:54 pm

    Trying to wrap my head around this in an example I’m working on:

    Suppose you get a response from a server that is an XML file with a set of records and you want to insert each record in a class instance of getters for each attribute in that record. Are you placing this code in your logic or your factory?

  • Ivan Milosavljević // Oct 30, 2012 at 10:21 am

    Manny, I was asking myself the same question. Factories shouldn’t contain logic, but that file must be parsed somehow. If you make separate class which will be responsible for parsing file and creating objects/records from it, you can say that class itself is factory with logic. Maybe Miško can offer his opinion on this?

Leave a Comment