Java Spring design: all in one component?
up vote
1
down vote
favorite
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:
- Unnecessary (boilerplate) code for autowiring most of the same components
- Sometimes Spring context loading error may occur due to circular references between components
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 bussiness 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?
java spring design-patterns
add a comment |
up vote
1
down vote
favorite
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:
- Unnecessary (boilerplate) code for autowiring most of the same components
- Sometimes Spring context loading error may occur due to circular references between components
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 bussiness 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?
java spring design-patterns
1
Both of these are clear examples of consumer services that are performing far too much functionality. You should refactor your services so that each performs a single responsibility.
– chrylis
Nov 11 at 5:37
Good point, every time you have more than one service (maybe 2, depending on the use case), you should consider refactoring, your class is breaking the single responsibility principle of the 5 SOLID principles. Look into it a bit more
– Urosh T.
Nov 11 at 5:43
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
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:
- Unnecessary (boilerplate) code for autowiring most of the same components
- Sometimes Spring context loading error may occur due to circular references between components
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 bussiness 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?
java spring design-patterns
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:
- Unnecessary (boilerplate) code for autowiring most of the same components
- Sometimes Spring context loading error may occur due to circular references between components
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 bussiness 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?
java spring design-patterns
java spring design-patterns
edited Nov 11 at 6:42
asked Nov 11 at 5:03
serg kunz
1297
1297
1
Both of these are clear examples of consumer services that are performing far too much functionality. You should refactor your services so that each performs a single responsibility.
– chrylis
Nov 11 at 5:37
Good point, every time you have more than one service (maybe 2, depending on the use case), you should consider refactoring, your class is breaking the single responsibility principle of the 5 SOLID principles. Look into it a bit more
– Urosh T.
Nov 11 at 5:43
add a comment |
1
Both of these are clear examples of consumer services that are performing far too much functionality. You should refactor your services so that each performs a single responsibility.
– chrylis
Nov 11 at 5:37
Good point, every time you have more than one service (maybe 2, depending on the use case), you should consider refactoring, your class is breaking the single responsibility principle of the 5 SOLID principles. Look into it a bit more
– Urosh T.
Nov 11 at 5:43
1
1
Both of these are clear examples of consumer services that are performing far too much functionality. You should refactor your services so that each performs a single responsibility.
– chrylis
Nov 11 at 5:37
Both of these are clear examples of consumer services that are performing far too much functionality. You should refactor your services so that each performs a single responsibility.
– chrylis
Nov 11 at 5:37
Good point, every time you have more than one service (maybe 2, depending on the use case), you should consider refactoring, your class is breaking the single responsibility principle of the 5 SOLID principles. Look into it a bit more
– Urosh T.
Nov 11 at 5:43
Good point, every time you have more than one service (maybe 2, depending on the use case), you should consider refactoring, your class is breaking the single responsibility principle of the 5 SOLID principles. Look into it a bit more
– Urosh T.
Nov 11 at 5:43
add a comment |
2 Answers
2
active
oldest
votes
up vote
3
down vote
accepted
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.
add a comment |
up vote
2
down vote
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
I don’t think that is so very difficult to find dependencies for a Spring component using the second approach. Besides Spring components should be independent enough to make no big regression to others.
– serg kunz
Nov 11 at 5:52
@sergkunz in second approach you can have circular dependencies, just with more clutter
– user7294900
Nov 11 at 5:58
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
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.
add a comment |
up vote
3
down vote
accepted
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.
add a comment |
up vote
3
down vote
accepted
up vote
3
down vote
accepted
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.
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.
edited Nov 11 at 6:50
answered Nov 11 at 5:49
Mark Bramnik
11.2k32445
11.2k32445
add a comment |
add a comment |
up vote
2
down vote
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
I don’t think that is so very difficult to find dependencies for a Spring component using the second approach. Besides Spring components should be independent enough to make no big regression to others.
– serg kunz
Nov 11 at 5:52
@sergkunz in second approach you can have circular dependencies, just with more clutter
– user7294900
Nov 11 at 5:58
add a comment |
up vote
2
down vote
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
I don’t think that is so very difficult to find dependencies for a Spring component using the second approach. Besides Spring components should be independent enough to make no big regression to others.
– serg kunz
Nov 11 at 5:52
@sergkunz in second approach you can have circular dependencies, just with more clutter
– user7294900
Nov 11 at 5:58
add a comment |
up vote
2
down vote
up vote
2
down vote
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
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
answered Nov 11 at 5:30
user7294900
18.7k93056
18.7k93056
I don’t think that is so very difficult to find dependencies for a Spring component using the second approach. Besides Spring components should be independent enough to make no big regression to others.
– serg kunz
Nov 11 at 5:52
@sergkunz in second approach you can have circular dependencies, just with more clutter
– user7294900
Nov 11 at 5:58
add a comment |
I don’t think that is so very difficult to find dependencies for a Spring component using the second approach. Besides Spring components should be independent enough to make no big regression to others.
– serg kunz
Nov 11 at 5:52
@sergkunz in second approach you can have circular dependencies, just with more clutter
– user7294900
Nov 11 at 5:58
I don’t think that is so very difficult to find dependencies for a Spring component using the second approach. Besides Spring components should be independent enough to make no big regression to others.
– serg kunz
Nov 11 at 5:52
I don’t think that is so very difficult to find dependencies for a Spring component using the second approach. Besides Spring components should be independent enough to make no big regression to others.
– serg kunz
Nov 11 at 5:52
@sergkunz in second approach you can have circular dependencies, just with more clutter
– user7294900
Nov 11 at 5:58
@sergkunz in second approach you can have circular dependencies, just with more clutter
– user7294900
Nov 11 at 5:58
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53245990%2fjava-spring-design-all-in-one-component%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Both of these are clear examples of consumer services that are performing far too much functionality. You should refactor your services so that each performs a single responsibility.
– chrylis
Nov 11 at 5:37
Good point, every time you have more than one service (maybe 2, depending on the use case), you should consider refactoring, your class is breaking the single responsibility principle of the 5 SOLID principles. Look into it a bit more
– Urosh T.
Nov 11 at 5:43