serg kunz
serg kunz

Reputation: 531

Java Spring design: all in one component?

Sometimes Spring components may look like this:

@Service
public final class SomeService {
    @Autowired
    private SomeService2 someService2;
    @Autowired
    private SomeService3 someService3;
    @Autowired
    private SomeService4 someService4;
    // … and many other services
    @Autowired
    private SomeDao someDao;
    @Autowired
    private SomeDao2 someDao2;
    @Autowired
    private SomeDao3 someDao3;
    // … and many other DAOs

}

In other words Spring components have plenty services and DAOs that are mostly repeated in other Spring components. IMHO it has the following drawbacks:

What about to use all-in-one component that combine, say, all services or all DAOs. It will contain only links to Spring components with no any business logic inside:

@Service
public final class AllServices {
    @Autowired
    private SomeService2 someService2;
    @Autowired
    private SomeService3 someService3;
    @Autowired
    private SomeService4 someService4;
    // … and many other services

    // get methods to get some service
    public someService getSomeService(){};

and inject it into other components:

@Service
public final class SomeService {
    @Autowired
    private AllServices serv;
    @Autowired
    private AllDaos daos;
    @Autowired
    private Environment env;

// inside some code
…
serv.getSomeService().processData();

IMHO it will look more succinct without circular references issues…

What pros and cons of this approach?

Upvotes: 1

Views: 108

Answers (2)

Mark Bramnik
Mark Bramnik

Reputation: 42481

The second approach might look appealing, a well-known facade pattern comes to mind at first, so I can totally understand this.

However, I think the first pattern will work better in fact and here is why:

  1. You say that the "all-mighty" service can solve circular dependencies

    Well, circular dependencies usually point on a wrong / bad design and are code smell by there own, so hiding it behind a facade won't improve the system, resolving the circular dependencies will. In addition if from the actual services, called by "AllServices" you'll want to invoke additional service (again, bad design is preserved) then the code will probably pass through AllServices again, and hence the circular dependency is still there.

  2. Using the second design assumes that this "AllServices" class will be used by all the components of the system, but in this case it becomes a "one-central-point" and refactoring in this class can turn to a madness - all the components / their tests might be affected

  3. Initialization of this service can become a mess by itself, since you probably won't want to maintain a constructor that has 20-30 input parameters you'll resort to field injection (like in the example) which is bad by its own because if you want to initialize it somehow, probably from test, or something you want know what should be mocked and what not, in which order, and so forth.

Upvotes: 3

Ori Marko
Ori Marko

Reputation: 58772

Second approach may look cleaner, but it will be difficult to know which service is connected to service/DAO and therefore it will be hard to refactor or do/decide on which regression any change will cause. Meaning it effect software flexibility

This is the important difference which make the difference to choose first option IMHO

Upvotes: 2

Related Questions