问题
The Service layer is supposed to be on top of the Model layer. As such, models are not supposed to call services.
However, I'm facing a situation where I need to, for example:
interface Component {
getResult();
}
class Number implements Component {
private value;
public getResult() {
return value;
}
}
class Addition implements Component {
private component1;
private component2;
public getResult() {
return component1->getResult() + component2->getResult();
}
}
class ConstantFromExternalSource implements Component {
private identifier;
public getResult() {
// call a service for fetching constant identified by identifier
}
}
(pseudo-code)
Here, my model needs to access an external data source through a Service (webservice or not).
How am I supposed to do in this situation? Is it OK to call a service in the model?
If you suggest to move away the "getResult" method from the model and put it into the "ComponentService", I would disagree because I would then loose all the advantages of OOP (and here my model makes a tree that needs to be recursively resolved, so OOP is the best solution).
回答1:
You can achieve this in several ways. First of all you can extract your model's dependency in separate interface like:
interface CustomService {
getResult();
}
class ExternalService implments CustomService
{
getResult() { // access web service }
}
And then inject that dependency into the model:
class ConstantFromExternalSource implements Component {
private identifier;
private CustomService service;
ConstantFromExternalSource(CustomService service)
{
this.service = service;
}
public getResult() {
// call a service for fetching constant identified by identifier
return service.getResult();
}
}
Another way to achieve this is to use Observer Design Pattern and notify higher level abstractions that you need something from them.
In both ways you can decouple you model from concrete implementation of the service layer.
回答2:
I would have the external source return directly the constant as a Component. I wouldn't couple the ConstantFromExtenralSource class to a service, not even as the interface, because the class (at least in this form) does nothing but call the service.
However if the external source returns some data that needs to be wrapped up in the ConstrantFromExternalSource class, I'd just push the data into the object via the constructor.
In a nutshell, if the model is just an abastraction to get data from an external source, just use a Repository to actulally get the data and to return a model if the external source won't return directly the object you need.
回答3:
Is it OK to call a service in the model?
Depends on what kind of service. As far as DDD goes,
The domain should definitely not know about the underlying application layer services that consume the domain.
Domain layer services are not much of a problem since they are part of the same layer.
In contrast, Infrastructure layer services have to be injected into your domain objects and their interfaces must be declared in the domain layer if you want loose coupling between domain and infrastructure (same as with repository interfaces/implementations). Sergey has a good implementation of this.
来源:https://stackoverflow.com/questions/13527621/model-service-decoupling-what-if-my-model-needs-a-service