Refactor to modules


Let’s look quickly at typical application:

Although at first sight it looks many classes and packages this is very simplified, as you know from real projects. What we can see? Controllers, services, repositories, entities, dto’s, other classes. Every application has that building blocks. Can we see what are the relations, dependencies? No. Can we see functionalities? Not. That structure do not say anything!

If we represent the relations of the above application, it will look like this:

We can notice the groups of related classes:

Most of the relations are between building blocks of the same concept eg, Customer. Here we have a very simplified application, but it is much more complicated in real projects.

We achieved the first step – grouping, or rather, group identification.

Step1: Group identification

We can group things technically eg. architecturally or by layers (data access, services, presentation), but the biggest benefit brings functional grouping as you see above. Functional grouping collects things/classes that are heavily related – together they provide functionality or feature.

Step2: Separation

After identifying a group of related classes, we need to move them to a separate place. In Java, it could be a package, Java module, a maven build artifact, or a microservice:

It is quite a simple step, but after classes separation the compiler will detect missing/wrong relations. Run the tests, and check if everything is working fine. It could happen that some properties, resources, or configurations are missing – stay in other place.

Based on the identified group you could have a temptation to create groups like this:

No, if you identified close relations between Customer and Address it suggest that Address is used with Customer. The proper solution is:

Step3: Isolation

This is very important step.

The isolation means that we should to expose the API – public class or interface to the customer functionality:

public class CustomerService {
  public String getCustomerPaymentInfoForId (String customerId)
}
//or
public interface CustomerService {
  String getCustomerPaymentInfoForId (String customerId)
}

and other modules and rest of the applicaiton must only communicate with that public class. Other classes inside customer package should be invisible – package scope:

Payment functionality/module requires only some info about customer, so we expose (public) only, ONLY a CustomerService, nothing more is need. Please do not return the whole object CustomerDto ‘for future use’, because that future can never came. Also the controllers can be not public, it is not required by Spring,

We isolate customer functionality under API and hide the internal soltion. Great.

What we achieved?

Two modules.

That’s it? Yes, two modules that communicate through API. Most of the functionality is hidden, so we achieved also encapsulation. There are more benefits, but this article is not about it. Let’s see how final structure looks like in code:

What is a module?

Module is a group of related classes (things), separated and isolated from others.

Module is a cohesive unit that provide specific function, functionality or groups of related functionalities. We achive it by groupping related things, separation and isolation.

Summary

Modularization/modules brings a lot of benefits. In real projects you can follow above process, but to do it properly you need also analysis and design.

You should to refactor to functionalities like: payment/paying, client behavior analysis, route planning. They are like verbs. In our example we have a functional module payment. We have also a module called customer, so it looks like it is not functional, but rather a ‘noun’/concept. It could happen that in project you have a CRUD part of your application or functionality strictly based on some concepts. But, anyway you should to always think of functionalities and modularize functionalities. This way you achieve high cohesion and low coupling.

,

Leave a Reply

Your email address will not be published. Required fields are marked *