我最近花了很多时间阅读SOLID原则并决定了解我使用的代码库的比较方式。
在我们的一些代码中有一个存储库(存储库A)。当要从存储库A中删除记录时,我们还需要从存储库B中删除关联的记录。因此,原始编码器创建了对存储库B的具体实现的依赖性。存储库A中的方法在事务中并且从存储库A中删除记录,然后调用存储库B上的方法以删除关联的数据。
我对S原理的理解是每个对象应该只有一个改变的理由,但是对于我的存储库A有2个理由要改变?还是我离开了标记?
答案 0 :(得分:46)
存储库应该承担单一责任 - 坚持一种实体。例如。雇员。如果必须从其他存储库中删除一些关联的记录,它看起来像业务逻辑。例如。
当员工被解雇时,我们应该删除他的工作日志
业务逻辑的通常位置是域服务。这项服务将拥有两个存储库并完成所有工作:
staffService.Fire(employee)
实施将如下所示
public class StaffService
{
private IEmployeeRepository employeeRepository;
private IWorkLogRepository workLogRepository;
private IUnitOfWorkFactory uowFactory;
// inject dependencies
public void Fire(Employee employee)
{
using(var uow = uowFactory.SartNew())
{
workLogRepository.DeleteByEmployee(employee.Id);
employeeRepository.Delete(employee.Id);
uow.Commit();
}
}
}
所以,基本建议
如果您有员工并且它有一些存储在不同数据库表中的嵌套对象,您可能想知道该怎么办。如果您将该对象与员工分开使用,那么一切都如上所述 - 您应该有单独的存储库,以及一些操作这两个存储库的其他对象(服务)。但是,如果您不将该嵌套对象与员工分开使用,那么员工是一个聚合根,您应该只有员工存储库,它将查询内部的两个表。
答案 1 :(得分:-2)
在这种情况下,您应该使用event dispatcher模式。
在 RepoA 上执行删除操作后,您可以发送如下事件:
dispatch repositoryA.deleted(RecordA)
将保存已删除记录的信息。
然后,一个发泄池将订阅此类事件,并且将存储库B作为依赖关系将调用删除。
让我们使用B作为实体名称,监听器声明应该听起来像:
Listen RepositoryA.delete and invoke onDelete(Event)
通过这种方法,您已经意识到 repoA 和 repoB 之间存在松散耦合(强制执行开放/关闭原则 - 在收盘方面),因此 repoA < / strong>现在(再次)
问候。