重构访问遗留系统中存储库的域逻辑

我正在使用具有贫血域模型的遗留系统。

域具有以下实体类: CarCarTypeCarComponentCarComponentType

对于其中的每一个,都有一个单独的存储库。 还有许多服务可以访问这些存储库,并且基本上包含所有逻辑。

我需要实现一个方法来确定供应商CarComponentType可以停止CarComponentType 。 逻辑如下:只有当前没有现有汽车的组件才能停止组件。

最初,我在服务类中实现了它。

 public boolean canBeDiscontinued(CarComponentType carComponentType) { List cars = carRepository.getCarsWithComponent(carComponentType); return cars.isEmpty(); } 

这有效 – 但是这个逻辑在代码中的其他几个地方使用。 它可能会增长,它看起来像是可以放在 CarComponentType类中的东西:

 public boolean canBeDiscontinued() { List cars = carRepository.getCarsWithComponent(this); return cars.isEmpty(); } 

但是,我不能把它放在那里,因为它需要访问存储库(据我所知,它是一个非常严重的反模式,实体要知道数据访问层)。 加载组件类型时,我无法加载该类型的所有汽车,因为这可能是数千个对象。 我们没有使用任何ORM,因此制作延迟加载的集合不仅体积大,而且非常容易出错。

像我第一次在服务类中实际使用此方法更合适吗? 这不重要吗? 还有另一种选择吗? 我应该从另一个起点开始重构吗?

这里有一个类似的问题。 但是我的问题与Java有关,所以我不认为这个解决方案适用于我的情况。 此外,抱歉使用汽车和组件作为我的域模型。 🙂

Frederik Gheysels的回答很好,虽然可能有点短。 详细说明:在您的情况下,您可以通过为您的规范定义一个接口(请原谅我的C#语法):

 public interface ICarSpecification { bool IsSatisfiedBy(CarComponentType carComponentType); } 

然后,您可以创建使用您的存储库的ICarSpecification的implmenetation。 像这样的东西:

 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本身:

 public class CarComponentType { private readonly ICarSpecification discontinueSpec; public CarComponentType(ICarSpecification discontinueSpec) { this.discontinueSpec = discontinueSpec; } public bool CanBeDiscontinued() { return this.discontinueSpec.IsSatisfiedBy(this); } } 

或者,如果您不喜欢在类的每个实例中随身携带规范,则可以使用Method Injection而不是Constructor Injection:

 public bool CanBeDiscontinued(ICarSpecification spec) { return spec.IsSatisfiedBy(this); } 

这种方法在实现方面并没有真正增加任何价值,但更容易被发现。

这听起来像是规范模式的一个很好的候选者

我不认为“这可以停止”属于任何一类。 谁负责确定零件是否可以停产? 不是汽车或汽车组件。 我认为您在服务中实施初始方法时走在正确的轨道上。 也许您需要一个CarInventoryManagementService,它负责回答有关汽车库存项目的问题,例如:

 carsUsingComponent( CarComponent comp ) canComponentBeDiscontinued( CarComponent comp ) etc 

如果您在代码中有多个位置需要询问与库存相关的问题,例如您的“canBeDiscontinued”,那么创建一个具有该职责的服务可能是有意义的。

我认为我不像下一个男人那样厌恶贫血领域模型,这并不是轻描淡写的。

然而,鉴于你正在研究的系统已经建立了贫血领域模型/服务(反)模式,我认为引入额外的模式可能是在孤立的情况下完成系统的威慑,因为我相信你在这里。 这样的决定应该由团队做出,并且应该有明显的好处。

另外,恕我直言,我认为你的原始代码片段比其他答案中提出的解决方案更简单(没有冒犯Mark和Frederik,只是观察:-)而且更复杂的解决方案并没有带来任何好处 – 我的意思是,function在两种情况下都相同,但后者使用更多移动部件

就如何进行而言,仅举一个例子就很难说。 介绍一个ORM(你提到的目前没有使用)可能是一种方法,因为它应该减少你的服务类中的代码,并有明显的好处,所以我很想从那里开始,然后一旦到位审查情况。