问题描述
我正在使用具有贫血域模型的遗留系统。
I am working with a legacy system that has an anemic domain model.
该域具有以下实体类: Car
, CarType
, CarComponent
, CarComponentType
。
The domain has the following entity classses: Car
, CarType
, CarComponent
, CarComponentType
.
对于每个这些,都有一个单独的存储库。还有一些服务访问这些存储库并且基本上包含所有的逻辑。
For each of these, there is a separate repository. There is also a number of services that access these repositories and contain basically all logic.
我需要实现一个方法来确定一个 CarComponentType
可以由供应商停止。逻辑如下:只有当现在没有该组件的现有汽车时,才能停止组件。
I need to implement a method that determines if a CarComponentType
can be discontinued by the vendor. The logic is as follows: a component can be discontinued only if there are no existing cars with that component today.
最初,我在服务类中实现了这一点。 p>
Initially, I implemented this in a service class.
public boolean canBeDiscontinued(CarComponentType carComponentType) {
List<Car> cars = carRepository.getCarsWithComponent(carComponentType);
return cars.isEmpty();
}
这个工作 - 但这个逻辑是从代码中的其他几个地方使用的。它可能会增长,而且它看起来像可以适合 CarComponentType
类的东西
This works - but this logic is used from several other places in the code. It might grow, and it looks like something that could fit inside the CarComponentType
class instead:
public boolean canBeDiscontinued() {
List<Car> cars = carRepository.getCarsWithComponent(this);
return cars.isEmpty();
}
然而,我不能把它放在那里,因为它需要访问存储库(据我所知,这是实体意识到数据访问层的非常严重的反模式)。加载组件类型时,我无法加载该类型的所有汽车,因为这可能是数千个对象。我们没有使用任何ORM,所以做一个懒惰的加载集合不仅体积庞大,而且也很容易出错。
However, I can't put it there, since it needs to access the repository (and as I understand it is a very serious antipattern for entities to be aware of the data access layer). When loading a component type I can't load all cars of that type since that could be thousands of objects. We are not using any ORM, so making a lazy loaded collection for not only be bulky but also very error-prone.
实际上这种方法更适合我第一次做的服务类?这不重要吗还有另外一种选择吗?我应该从另一个起点开始重构?
Is it more appropriate to actually have this method in a service class as I first did? Is it not important? Is there another alternative? Should I start refactoring from another starting point?
有一个类似的问题。但是我的问题涉及到Java,所以我不认为这个解决方案适用于我的情况。此外,提前使用汽车和组件作为我的域名模型抱歉。 :)
There is a similar question here. But my question relates to Java, so I don't think that solution is applicable in my case. Also, sorry in advance for using cars and components as my domain model. :)
推荐答案
Frederik Gheysels答案是好的,虽然也许有点短。详细说明:在你的情况下,你可以通过定义一个接口来解释你的规范(请问我的C#语法):
Frederik Gheysels answer is good, although perhaps a bit short. To elaborate: In your case, you could start out by defininig an interface for your specification (excuse my C# syntax):
public interface ICarSpecification
{
bool IsSatisfiedBy(CarComponentType carComponentType);
}
然后,您可以创建使用您的存储库的ICarSpecification的插入。这样的东西:
You can then create an implmenetation of ICarSpecification that uses your Repository. Something like this:
public class CanDiscontinueSpecification : ICarSpecification
{
private readonly CarRepository carRepository;
public CanDiscontinueSpecification(CarRepository carRepository)
{
this.carRepository = carRepository;
}
public bool IsSatisfiedBy(CarComponentType carComponentType)
{
return this.carRepository.GetCarsWithComponent(carComponentType).Any();
}
}
你可以停在那里,但我的东西特别是关于规格模式是不是很可以发现。一个可能的解决方案是将规范注入CarComponentType本身:
You could stop right there, but the thing I don't particularly like about the Specification pattern is that it is not very discoverable. One possible solution would be to inject the Specification into the CarComponentType itself:
public class CarComponentType
{
private readonly ICarSpecification discontinueSpec;
public CarComponentType(ICarSpecification discontinueSpec)
{
this.discontinueSpec = discontinueSpec;
}
public bool CanBeDiscontinued()
{
return this.discontinueSpec.IsSatisfiedBy(this);
}
}
或者,如果你不喜欢随身携带在该类的每个实例中,您可以使用方法注入而不是构造函数注入:
Alternatively, if you don't like to carry around the Specification in every instance of the class, you could use Method Injection instead of Constructor Injection:
public bool CanBeDiscontinued(ICarSpecification spec)
{
return spec.IsSatisfiedBy(this);
}
这种方法在实现方面并没有真正添加任何值,更可发现。
Such a method doesn't really add any value in terms of implementation, but is more discoverable.
这篇关于重构访问旧系统中存储库的域逻辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!