与任何设计模式一样,规范模式是一个很棒的概念,但容易被急切的架构师/开发人员过度使用。
我即将开始开发一个新的应用程序(.NET 和 C#),并且非常喜欢规范模式的概念,并渴望充分利用它。然而,在我全力以赴之前,我真的很想知道是否有人可以分享在开发应用程序时使用规范模式时遇到的痛点。
理想情况下,我想看看其他人是否有问题
- 根据规范模式编写单元测试
- 确定规范应位于哪一层(存储库、服务、域等)
- 当一个简单的
if
语句可以完成工作时,在任何地方都使用它 - ETC?
提前致谢
与任何设计模式一样,规范模式是一个很棒的概念,但容易被急切的架构师/开发人员过度使用。
我即将开始开发一个新的应用程序(.NET 和 C#),并且非常喜欢规范模式的概念,并渴望充分利用它。然而,在我全力以赴之前,我真的很想知道是否有人可以分享在开发应用程序时使用规范模式时遇到的痛点。
理想情况下,我想看看其他人是否有问题
if
语句可以完成工作时,在任何地方都使用它提前致谢
我不相信 LINQ 是规范模式的替代品。请记住,规范最好用于封装业务逻辑。因此,如果我的业务需求之一是让我获得所有重要客户的多项功能,我的 Linq 语句可能如下所示:
var valuedCustomers = Customers.Where(c => c.Orders.Count > 15 && c.Active).ToList();
我可以在整个应用程序中输入此声明,但如果我想附加客户必须在某个日期之前加入的规则怎么办?好吧,现在我必须检查我的应用程序并更改 Linq。或者如果我的对象图发生了变化(尽管这不应该是使用该模式的唯一原因)。相反,我可以做这样的事情
var valuedCustomers = Customers.Where(new ValuedCustomerRule.IsSatisfied()).ToList();
我同意该模式已被过度使用,但它对于出现在整个系统中的业务规则非常有帮助,因此当这些规则发生变化时您不会被咬。对我来说,这类似于在您的应用程序代码中留下 SQL 查询。
正如 David 在他的评论中指出的那样,现在可以使用 LINQ 等更简洁地实现规范的许多有用之处。
您可以即时创建任意规范,而不是新的规范类型:
GetCustomers().Where(customer => customer.IsActive && customer.City == "Oakland");
然而,这并不是规范的完全替代品,原因如下:
当然没有必要在任何地方都使用它,而且很可能你根本不需要它;我不知道您的域或您在做什么。
我认为最好的建议是不要使用它。当您开始编写一个看起来像您链接到的文章中的第一个示例的类时,您会看到它何时是必要的。
只需将它保存在您的心理模式存储库中,以便您在需要时得到它;如果你从不使用它,那只意味着你不需要它,那很好。
层的选择取决于规格和用途的性质。在许多情况下,它们是支持服务层的助手,但在某些情况下,它们封装了域逻辑。
至于单元测试,请记住您的规范是单位或包含单位。不要测试接受具有所有可能的规范组合的规范的方法;测试规范本身以确保它们的行为符合预期,然后您可以在许多方法和类中自信地重用相同的规范。
希望这有点帮助。
更新答案:我同意 Wix,LINQ 不能替代规范模式。我没有足够的声誉来为 Wix 答案添加评论,我只是作为答案进行回复。
根据本文,规范主要用于将域对象与语句进行匹配。尽管规范在与域对象匹配时返回真/假,但这并不意味着规范建议在您的代码中封装任何布尔条件。
我将进一步继续 Wix 的回答。如果您定义了 ValuedCustomer 规范,那么您有不同的使用规则的可能性:
var valuedCustomer = new ValuedCustomerSpecification();
//1. You can use this statement to check if a customer is valued or not in your domain
Customer customer = ....
if(valuedCustomer.IsSatisfiedBy(customer))
//2. You can use it to get just valued customers from repository,
var valuedCustomers = repository.Get(valuedCustomer);
//3. You can combine it with other specifications to create composite specifications. Following syntax can vary with implementation
var seniorValuedCustomer = valuedCustomer.And(seniorCustomer)
我从论文中的理解是,只要有需要并且您的应用程序 UI 允许,用户可以与规范交互以实现他们的目标。
上面提到的论文还提到了何时不使用规范模式。