规范模式对象应该在哪一层“新建”?
因此,我在这里查看了一些有关规范模式的帖子,但尚未找到此问题的答案。
我的问题是,在 n 层架构中,我的规范到底应该在哪里“更新”?
我可以将它们放在我的服务层(又名,应用程序层,有时被称为......基本上,.aspx 代码隐藏会与之对话的东西)中,但我觉得这样做,我让业务规则泄漏出域。如果以其他方式访问域对象(除了服务层),则域对象无法强制执行自己的业务规则。
我可以通过构造函数注入将规范注入到我的模型类中。但同样,这感觉是“错误的”。我觉得唯一应该注入到模型类中的是“服务”,例如缓存、日志记录、脏标志跟踪等......如果可以避免它,请使用方面而不是乱扔模型的构造函数具有大量服务接口的类。
我可以通过方法注入(有时称为“双重调度”???)来注入规范,并明确让该方法封装注入的规范以强制执行其业务规则。
创建一个“域服务”类,它将通过构造函数注入获取规范,然后让服务层使用域服务来协调域对象。这对我来说似乎没问题,因为规范强制执行的规则仍然在“域”中,并且域服务类的命名方式非常类似于它所协调的域对象。这里的事情是,我觉得我正在编写很多类和代码,只是为了“正确”实现规范模式。
除此之外,所讨论的规范需要一个存储库来确定它是否“满意”。
这可能会导致性能问题,尤其是。如果我使用构造函数注入,b/c 消耗代码可以调用一个可能包装规范的属性,而该属性又调用数据库。
那么有什么想法/想法/文章链接吗?
更新和使用规格的最佳地点在哪里?
So, I've looked at some posts about the Specification Pattern here, and haven't found an answer to this one yet.
My question is, in an n-layered architecture, where exactly should me Specifications get "newed" up?
I could put them in my Service Layer (aka, Application layer it's sometimes called... basically, something an .aspx code-behind would talk to), but I feel like by doing that, I'm letting business rules leak out of the Domain. If the Domain objects are accessed some other way (besides the Service Layer), the Domain objects cannot enforce their own business rules.
I could inject the Specification into my Model class via constructor injection. But again, this feels "wrong". I feel like the only thing that should be injected into Model classes are "services", like Caching, Logging, dirty-flag tracking, etc... And if you can avoid it, to use Aspects instead of littering the constructors of the Model classes with tons of service interfaces.
I could inject the Specification via method injection (sometimes referred to as "Double Dispatch"???), and explicitly have that method encapsulate the injected Specification to enforce its business rule.
Create a "Domain Services" class, which would take a Specification(s) via constructor injection, and then let the Service Layer use the Domain Service to coordinate the Domain object. This seems OK to me, as the rule enforced by the Specification is still in the "Domain", and the Domain Service class can be named very much like the Domain object it's coordinating. The thing here is I feel like I'm writing a LOT of classes and code, just to "properly" implement the Specification pattern.
Add to this, that the Specification in question requires a Repository in order to determine whether it's "satisfied" or not.
This could potentially cause performance problems, esp. if I use constructor injection b/c consuming code could call a property that perhaps wraps the Specification, and that, in turn is calling the database.
So any ideas/thoughts/links to articles?
Where is the best place to new up and use Specifications?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
简短回答:
您主要在服务层中使用规范,所以就在那里。
长答案:
首先,这里有两个问题:
您的规格应该放在哪里,以及它们应该在哪里更新?
就像您的存储库接口一样,您的规范应该存在于域层中,因为它们毕竟是特定于域的。有一个关于SO的问题在存储库接口上讨论了这个问题。
但他们应该在哪里更新呢?好吧,我在我的存储库上使用 LinqSpecs 并且在我的存储库上几乎有三种方法:
我的其余查询是在我的服务层中构建的。这可以防止存储库因 GetUserByEmail、GetUserById、GetUserByStatus 等方法而变得臃肿。
在我的服务中,我更新了我的规范并将它们传递给我的存储库的 FindAll 或 FindOne 方法。例如:
这是规范:
因此,为了回答您的问题,服务层中的规范是新的(在我的书中)。
,您不应该向域实体中注入任何内容。
这是代码异味。我会在那里审查你的代码。规范绝对不需要存储库。
Short answer:
You use Specifications mainly in your Service Layer, so there.
Long answer:
First of all, there's two questions here:
Where should your specs live, and where should they be new'd up?
Just like your repository interfaces, your specs should live in the domain layer, as they are, after all, domain specific. There's a question on SO that discusses this on repository interfaces.
Where should they be new'd up though? Well, I use LinqSpecs on my repositories and mostly ever have three methods on my repository:
The rest of my queries are constructed in my service layer. That keeps the repositories from getting bloated with methods like GetUserByEmail, GetUserById, GetUserByStatus etc.
In my service, I new-up my specs and pass them to the FindAll or FindOne methods of my repository. For example:
and here is the Specification:
So to answer your question, specs are new'd up in the service layer (in my book).
IMO you should not be injecting anything into domain entities.
That's a code smell. I would review your code there. A Specification should definitely not require a repository.
规范是业务规则的实施检查。它必须存在于领域层句号中。
很难详细说明如何做到这一点,因为每个代码库都是不同的,但我认为任何业务逻辑都需要位于域层而不是其他地方。该业务逻辑需要完全可测试,并且与 UI、数据库、外部服务和其他非域依赖项松散耦合。所以我肯定会排除上面的1、2、3。
4 是一个选项,至少该规范将存在于您的域层中。然而,规范的更新实际上又取决于实施。我们通常使用依赖注入,因此几乎所有对象的更新都是通过 IOC 容器和相应的引导代码执行的(即我们通常流畅地连接应用程序)。然而,我们绝不会直接将业务逻辑直接链接到 UI 模型类等。我们通常在 UI 和域等事物之间有轮廓/边界。我们通常定义域服务契约,然后可以由 UI 等外部层使用。
最后,我的答案是假设您正在使用的系统至少在某种程度上是复杂的。如果它是一个非常简单的系统,那么领域驱动设计作为一个概念可能就太过分了。然而,在我看来,无论代码库如何,都应该尊重一些概念,例如可测试性、可读性、SoC 等。
A specification is an implementation check of a business rule. It has to exist in the domain layer full stop.
Its hard to give specifics on how you do this as every codebase is different, but any business logic in my opinion needs to be in the domain layer and nowhere else. This business logic needs to be completely testable and coupled loosely from UI, database, external services and other non-domain dependencies. So I would definitely rule out 1, 2, and 3 above.
4 is an option, at least the specification will live in your domain layer. However the newing up of specifications depends really again on the implementation. We usually use depencency injection, hence the newing up of pretty much all of our objects is performed via an IOC container and corresponding bootstrapping code (i.e. we usually wire the application fluently). However we would never directly link business logic directly to e.g. UI model classes and the like. We usually have contours/boundaries between things such as UI and domain. We usually define domain service contracts, which can then be used by outside layers such as the UI etc.
Lastly, my answer is assuming that the system you are working on is at least some way complex. If it is a very simple system, domain driven design as a concept is probably too over the top. However some concepts such as testability, readibility, SoC etc should be respected regardless of the codebase in my opinion.