As an Agile Coach, Miško is responsible for teaching his co-workers to maintain the highest level of automated testing culture, allowing frequent releases of applications with high quality. He is very involved in Open Source community and an author of several open source projects. Recently his interest in Test Driven Developement turned into http://TestabilityExplorer.org with which he hopes will change the testing culture of the open source community. Misko is a DZone MVB and is not an employee of DZone and has posted 38 posts at DZone. You can read more from them at their website. View Full User Profile

Where Have All The "new" Operators Gone?

09.11.2008
| 3867 views |
  • submit to reddit

In My main() Method Is Better Than Yours we looked into what a main() method should look like. There we introduced a clear separation between (1) the responsibility of constructing the object graph and (2) the responsibility of running the application. The reason that this separation is important was outlined in How to Think About the “new” Operator. So let us look at where have all of the new operators gone…

Before we go further I want you to visualize your application in your mind. Think of the components of your application as physical boxes which need to be wired together to work. The wires are the references one component has to another. In an ideal application you can change the behavior of the application just by wiring the components differently. For example instead of instantiating LDAPAuthenticator you instantiate KerberosAuthenticator and you wire the KerberosAuthenticator to appropriate components which need to know about Authenticator. That is the basic idea. By removing the new operators from the application logic you have separated the responsibility of wiring the components from the application logic, and this is highly desirable. So now the problem becomes, where have all the new operators gone?

First lets look at a manual wiring process. In the main() method we asked the ServerFactory to build us a Server (in our case a Jetty Web Server) Now, server needs to be wired together with servlets. The servlets, in turn, need to be wired with their services and so on. Notice that the factory bellow is full of “new” operators. We are new-ing the components and we are passing the references of one component to another to create the wiring. This is the instantiation and wiring activity I asked you to visualize above. (Full source):

  public Server buildServer() {
    Server server = new Server();

    SocketConnector socketConnector
         = new SocketConnector();
    socketConnector.setPort(8080);
    server.addConnector(socketConnector);

    new ServletBuilder(server)
      .addServlet("/calc", new CalculatorServlet(
                           new Calculator()))
      .addServlet("/time", new TimeServlet(
                           new Provider() {
        public Date get() {
          return new Date();
        }
      }));

    return server;
  }

When I first suggest to people that application logic should not instantiate its own dependencies, I get two common objections which are myths:

  1. “So now each class needs a factory, therefore I have twice as many classes!” Heavens No! Notice how our ServerFactory acted as a factory for many different classes. Looking at it I counted 7 or so classes which we instantiated in order to wire up our application. So it is not true that we have one to one correspondence. In theory you only need one Factory per object lifetime. You need one factory for all long-lived objects (your singletons) and one for all request-lifetime objects and so on. Now in practice we further split those by related concepts. (But that is a discussion for a separate blog article.) The important thing to realize is that: yes, you will have few more classes, but it will be no where close to doubling your load.
  2. “If each object asks for its dependencies, than I will have to pass those dependencies through all of the callers. This will make it really hard to add new dependencies to the classes.” The myth here is that call-graph and instantiation-graph are one and the same. We looked into this myth in Where have all the Singletons Gone. Notice that the Jetty server calls the TimeServlet which calls the Date. If the constructor of Date or TimeServlet all of a sudden needed a new argument it would not effect any of the callers. The only code which would have to change is factory class above. This is because we have isolated the instantiation/wiring problem into this factory class. So in reality this makes it easier to add dependencies not harder.

Now there are few important things to remember. Factories should have no logic! Just instantiation/wiring (so you will probably not have any conditionals or loops). I should be able to call the factory to create a server in a unit test without any access to the file-system, threads or any other expensive CPU or I/O operations. Factory creates the server, but does not run it. The other thing you want to keep in mind is that the wiring process is often controlled by the command line arguments. This makes is so that your application can behave differently depending what you pass in on a command line. The difference in behavior is not conditionals sprinkled throughout your code-base but rather a different way of wiring your application up.

Finally, here are few thoughts on my love/hate of Singletons (mentioned here and here) First a little review of singletons. A singleton with a lower case ’s’ is a good singleton and simply means a single instance of some class. A Singleton with an upper case ‘S’ is a design pattern which is a singleton (one instance of some class) with a global “instance” variable which makes it accessible from anywhere. It is the global instance variable which makes it globally accessible , which turns a singleton into a Singleton. So singleton is acceptable, and sometimes very helpful for a design, but Singleton relies on mutable global state, which inhibits testability and makes a brittle, hard to test design. Now notice that our factory created a whole bunch of singletons as in a single instance of something . Also notice how those singletons got explicitly passed into the services that needed them. So if you need a singleton you simply create a single instance of it in the factory and than pass that instance into all of the components which need them. There is no need for the global variable.

For example a common use of Singleton is for a DB connection pool. In our example you would simply instantiate a new DBConnectionPool class in the top-most factory (above) which is responsible for creating the long-lived objects. Now lets say that both CalculatorServlet and TimeServlet would need a connection pool. In that case we would simply pass the same instance of the DBConnectionPool into each of the places where it is needed. Notice we have a singleton (DBConnectionPool) but we don’t have any global variables associated with that singleton.

  public Server buildServer() {
    Server server = new Server();

    SocketConnector socketConnector
         = new SocketConnector();
    socketConnector.setPort(8080);
    server.addConnector(socketConnector);

    DBConnectionPool pool = new DBConnectionPool();
    new ServletBuilder(server)
      .addServlet("/calc", new CalculatorServlet(
                           pool,
                           new Calculator()))
      .addServlet("/time", new TimeServlet(
                           pool,
                           new Provider() {
        public Date get() {
          return new Date();
        }
      }));

    return server;
  }

From http://misko.hevery.com

Published at DZone with permission of Misko Hevery, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Jay Ceron replied on Thu, 2008/09/11 - 8:28am

"Factories should have no logic!"

If permissions have to be checked to determine if something gets created or not, does that belong in the factory?  I kept going back and forth on that namely because the factory, and only the factory, knows how to create the target object and it could be agrued that it should also know when, as that is part of the creation process.  What are your thought on that? 

Guillaume Jeudy replied on Thu, 2008/09/11 - 9:12am

Interesting article but i'm curious though, how do you inject your ServerBuilder factory? I don't see it implementing an interface. Does it mean your objects using the factory have a hard-dependency on a concrete factory implementation? Can we then argue that your objects depend transitively on a specific set of implementations and cannot be changed easily as you would have to change code to use a different factory ?

 Let me know if you have a more complete example showing how you would use the factory.

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.