Inversion of Control: Putting All Together

百度 梅赛德斯-迈巴赫S级Pullman采用2+2+2的座椅布局,其中第一排座椅(正副驾驶区域)与后排乘坐区域被一块具备可电动升降的隔音玻璃分隔开来,另外,这块玻璃透明度还可以根据用户需要进行调整。

We were talking a lot about Dependency Inversion Principle and the Main and Abstraction concept, however, we missed a pretty important point:

How all of this get together?

TRY IT YOURSELF: You can find this post source code here.

Dependency Inversion Series

The Boundaries of Main and Abstraction

Let’s talk about our first example, Service and Repository classes:

Service and Repository definitions

Now, let’s find the boundaries of Main and Abstraction:

Main and Abstraction boundaries

Okey, we know:

  • Abstraction: Service class and Repository interfaces belongs to this group. They have my business logic and rules.
  • Main: MySQLRepository belongs to this group. It is a detail, that I might change in the future.

NOTE: You might ask: why do I put the Repository interface in the abstraction zone instead of the main? well, that’s a good discussion for another moment.

Putting all together: the object creation challenge

Well, the Main and Abstraction concept talks about Main must be responsible of object creation, so, let’s add something to handle this:

A new Starter class

We have now the Starter class, this is our boot up. Let’s see how this class could look like in Java language:

public class Starter{

 public static void main(String[] args){

  Repository repository = new MySQLRepository();

  Service service = new Service(repository);

  //TODO: Use service object.........

 }

}

In Java, we must have somewhere a main method like these to start the whole program. We see now how our Starter creates objects and assign them as dependencies to other objects.

See how beautiful Dependency Inversion Principle is, Service class depends on Repository, not on a specific implementation, so, let’s move to different database.

public class Starter{

 public static void main(String[] args){

  //Repository repository = new MySQLRepository();
  Repository repository = new MongoDBRepository();

  Service service = new Service(repository);

  //TODO: Use service object.........

 }

}

As we see, we changed the whole database only refactoring one line of code in our Starter. Our business logic and rules are safe and they can be reused totally.

This is the power of Dependency Inversion Principle in its maximum expression

NOTE: You might ask, “good for Java, but in my language I cannot do this”, well, you might not know how your language really works, for instance, you have a similar Main class on .net, an index.js file on Node.js, an Activity class on Android, and so on. Moreover, if you really don’t find a explicit starter in your language, you should define one.

CAREFUL: You might think, changing a database in a software project is not as easy as I show here. Well, if it is not easy, it means your business logic and rules know too much about your database.

TRY IT YOURSELF: You can find this source code here.

Final Thought

We now can create complete decoupling systems using the Dependency Inversion Principle and the Main and Abstraction concepts, handling the object creation challenge.

However, our projects are pretty much complex than two clases, so, how do we handle complexity when we talk about decoupling? We use another common friend: Dependency Injection.

Moreover, complexity moves us to the zone where we need to make a trade off on how much we want our system to be decoupled.

If you liked this post and are interested in hearing more about my journey as a Software Engineer,?you can follow me on Twitter and travel together.

10 comments