我目前正在为我正在设计的服务实现命令处理程序模式,其中命令本质上是处理程序.Handle()
方法的 DTO。当我开始实现各种具体的类时,我意识到为了满足开放/封闭原则和单一职责原则,我最终可能会得到数千个 Command 和 Handler 类,这将严重违反 Don't Repeat Yourself 原则。
例如,我封装的部分过程需要ProjectId
从 60 个奇数表中删除所有数据以重置它们。如果我将每个类都实现为原子具体的 Command 对象和具体的 CommandHandler 对象,那么我将有 120 个类仅用于第一步。 他们都将完全遵循 SRP 和 OCP,但是 DRY 受到严重打击......
public class DeleteProjectLogCommand : CommandBase
{
public long? ProjectId { get; set; }
}
public class DeleteProjectLogCommandHandler : ICommandHandler<DeleteProjectLogCommand>
{
public async Task<Feedback<DeleteProjectLogCommand>> Handle(DeleteProjectLogCommand command, CancellationToken token)
{
// ...
}
}
或者,我可以实现一个单一的、多用途的命令和处理程序类,并且ProjectTables
可以使用枚举来代替所有离散类。
public class DeleteTableByProjectIdCommand : CommandBase
{
public DeleteTableByProjectIdCommand(ProjectTables table, long? projectId) {}
public long? ProjectId { get; set; }
public ProjectTables Table { get; set; }
}
public class DeleteTableByProjectIdCommandHandler : ICommandHandler<DeleteTableByProjectIdCommand>
{
public async Task<Feedback<DeleteTableByProjectIdCommand>> Handle(DeleteTableByProjectIdCommand command, CancellationToken token)
{
switch(command.Table)
{
case ProjectTables.ProjectLog:
// x60 tables
break;
}
}
}
然而,这将违反开放/封闭原则,因为如果添加新表,则枚举和使用它的每个地方都必须更新。更不用说你从 60 例 switch 语句中得到的气味了。
苏……谁赢了?DRY 还是 SRP 和 OCP?