Reputation: 531
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
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:
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.
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
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
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