- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
1) 当 Domain 层使用一个 Infrastructure Service IS 时,它的接口(interface)定义在 Domain 层,而它的实现定义在 Infrastructure 层。
我们不应该将和(例如存储库或电子邮件服务)直接注入(inject)域实体:
class Foo
{
IRepository repo;
...
public int DoSomething()
{
var info = repo.Get...;
...
}
}
class Foo
{
...
public int DoSomething(IRepository repo)
{
var info = repo.Get...;
...
}
}
class TransferService
{
IRepository repo;
...
public bool Transfer()
{
var info = repo.Get...;
...
}
}
class TransferService
{
public bool Transfer(IRepository repo)
{
var info = repo.Get...;
...
}
}
class Foo
{
...
public int DoSomething()
{
var info = TransferService.Transfer(...);
...
}
}
An IS can be injected into a domain service if it needs it for functionality - ie not passed to method. This is different than entities and it is because a domain service is stateless and so it can be configured with required dependencies once and used where needed, such as by other entities.
A domain service should be passed to entity as argument much like you would pass a repository interface as argument. The same principles apply.
That is one reason. Another is that is creates needless coupling. If a repository is needed for only a single behavior on the entity, why inject it into entity all the time? Also, now you have to consider how you will resolve those dependencies? Make entities part of dependency injection graph? This quickly overloads the responsibilities of the entity.
You can still pass an IS to a domain entity method and the problem here wouldn't be violation of PI since you're passing an interface, not an implementation. The problem would be violation of SRP if the domain method only used one method on the IS interface.
PI is maintained with the use of interfaces.
It is better however to be very explicit. So instead of passing a repository and implicitly understanding that it happens to provide a service to the entity, declare the provided functionality as its own interface and have the entity depend on that.
declare the provided functionality as its own interface
So if I understood you correctly - Injecting IS into Domain Service DS doesn't violate SRP, because DS is using it to execute its designated tasks ( ie its designated responsibility), while injecting IS into Domain Entity is a violation of SRP because primary responsibility of Domain Entity is focusing on its life cycle and identity, and ISmost of the times isn't an integral part in managing these two tasks ( ie focusing on life cycle and identity )?
是的,这是正确的,也是主要原因之一。
I - 从远处看,将 IS 注入(inject)域实体 DE 似乎完全合理,这个 DE 将违反 SRP,因为 “IS79104” IS79104不会有助于管理指定为 DE的两个任务。
但是当试图更详细地想象这个场景时会有点困难。也就是说,如果 DE的方法专注于管理两个指定的任务(即它的生命周期和身份),那么如果这些方法之一需要 是,这不是合理的吗?假设它需要 是来完成两个指定的任务而不是与 DE的生命周期和身份无关的其他任务?如果是,那么我们怎么能声称 DE违反了 SRP?
II - 我也很难想象管理 DE 的生命周期和身份究竟意味着什么。首先,一旦 DE被分配了一个身份,这个身份就不会改变。那么我们需要管理它的身份呢?
III - 管理 DE 的生命周期是什么意思?也许在 DE上定义不变量,以保持其数据一致或......?
IV - 那么现实世界实体执行的所有其他任务(即那些与 DE 的生命周期和身份无关的任务)都应该从 DE中提取出来并放入相关对象中?
d)
If IS implemented a role-based interface containing a single method, and instead we pass this role-based interface as an argument to domain method, would you still consider this as a violation of SRP? If not, why not?
这样做并不可怕,但它有可能违反 SRP 或作为
由 guillaume31 - ISP 更清楚地指定。
我不确定我们如何声称将 IS注入(inject) DE可能违反 ISP,因为据我所知只能违反“1094567”ISP79通过实现此接口(interface)的对象而不是注入(inject)此接口(interface)的实现的对象?
第四次更新:
我开始意识到 SRP 比我最初想象的要困惑得多
一种)
Behavior associated with the entity, which usually entails state changes, should also be placed into the entity. If such behavior requires use of a service, pass that service in, but generally try to place as much behavior into the entity as possible.
IV – 1 以下行为方法不包括状态更改,但我认为它们也应该属于Dog
实体:
class Dog
{
...
void DoBark();
void DoFetch();
void DoGuard();
Breed GetBreed();
Pedigree GetPedigree();
Snack FavSnack();
}
IV – b)GetBreed
、GetPedigree
和FavSnack
是行为方法吗?如果是,那么属性Breed
、Pedigree
和Snack
也应该被视为行为,因为它们本质上提供相同的功能(假设GetBreed
、GetPedigree
和FavSnack
不重计算,但只是返回对象):
class Dog
{
...
void DoBark();
void DoFetch();
void DoGuard();
Breed Breed { get{...} }
Pedigree Pedigree { get{...} }
Snack Snack { get{...} }
}
IV – c) 如果上述属性也有 setter,我们会说它们包含状态改变行为吗?
IV – d)
Behavior associated with the entity, which usually entails state changes, should also be placed into the entity.
但是如果域实体的主要职责是管理它的生命周期,那么包括与管理生命周期无关的行为是否违反了 SRP(在上面的例子中,诸如Dog.DoBark
之类的方法很可能没有太多需要与Dog
的生命周期有关)?!
d)
一世。
Passing IS to a DE behavioral method is better, however can violate SRP/ISP if IS interface has lots of things unrelated to the behavior at hand. This is the basic premise of ISP - dependencies should be made on specific interfaces as opposed to bloated interfaces that happen to contain the required functionality.
所以如果 是作为参数传递给DE的行为方法之一确实有一些与手头行为无关的操作,但DE的方法 M不使用任何 是的方法与行为 无关 M应该处理,我们仍然认为DE违反了SRP/ISP?
二、 – 我明白你在说什么,但我的困惑源于以下事实:根据 ISP 的以下定义,该术语只能用于指定对象 ServObj实现特定接口(interface)违反 ISP ,而注入(inject) ServObj的对象违反了SRP(由于接收到 ServObj):
The Interface Segregation Principle is similar to the Single Responsibility Principle in that both deal with the cohesion of responsibilities. In fact, the ISP can be understood as the application of the SRP to an object’s public interface.
To a certain extent, ISP can be considered a sub-set, or more specific form of the Single Responsibility Principle. The perspective shift of ISP, though, examines the public API for a given class or module.
谢谢
最佳答案
1a) 如果一个 IS 需要它的功能,它可以被注入(inject)到一个域服务中 - 即不传递给方法。这与实体不同,这是因为域服务是无状态的,因此可以使用所需的依赖项配置一次并在需要的地方使用,例如由其他实体使用。
1b) 域服务应该作为参数传递给实体,就像您将存储库接口(interface)作为参数传递一样。同样的原则也适用。此外,传递整个存储库接口(interface)会产生不必要的耦合,因此最好声明并传递特定于角色的接口(interface)。
更新
1a) 这是一个原因。另一个是造成不必要的耦合。如果实体上的单个行为只需要存储库,为什么一直将其注入(inject)实体?另外,现在您必须考虑如何解决这些依赖关系?让实体成为依赖注入(inject)图的一部分?这很快使实体的责任重载。
1b) 违反 PI 是违反单一责任原则的更一般概念的一个实例。您仍然可以将 IS 传递给域实体方法,这里的问题不会违反 PI,因为您传递的是接口(interface),而不是实现。如果域方法仅在 IS 接口(interface)上使用一种方法,则问题将违反 SRP。
1c) 见 1a)
1d) 否,因为 PI 是通过使用接口(interface)来维护的。
2)是的,这就是为什么我建议避免直接传递存储库接口(interface)。原理是相似的,因为您可以将存储库接口(interface)和域服务视为抽象服务,为域实体提供一些有趣的行为。然而,最好是非常明确的。因此,与其传递存储库并隐式地理解它恰好为实体提供服务,不如将提供的功能声明为其自己的接口(interface)并使实体依赖于它。
更新 2
1a) 是的,这是正确的,也是主要原因之一。
1b) 这样做并不可怕,但它有可能违反 SRP 或更明确地由 guillaume31 - ISP 指定。所以这比说注入(inject)实体实例要好,但可以通过声明一个特定的接口(interface)来改进。
不,如果您创建一个基于角色的界面,那么这在这种情况下就足够了。
1d) 如果实体使用存储库接口(interface)来持久化自己,那么这违反了 PI。然而,如果它使用存储库接口(interface)来执行一些查询以运行其业务逻辑,那么我们并不是真正在谈论持久性。要真正解耦存储库,请改用特定于角色的接口(interface)。
2a) 是的,出于同样的原因,将存储库注入(inject)实体是不合适的。
2b) 是的,但我只是建议在您将域服务传递给实体上的行为方法的情况下,而不是将其注入(inject)实体实例本身。
更新 3
1a) 这可能是一个我同意的争论点。但是,从实用的角度来看,最好将 DE 设计为消除它们对外部服务的依赖,或者使其变得非常明确和隔离。如果您的 DE 对 IS 具有实例依赖性,则意味着无论何时创建 DE 的实例,例如在重构期间或创建新实体时,都必须在那时提供 IS。这使依赖关系图变得复杂。此外,如果 DE 负责维护其自身状态的完整性,那么为什么会依赖于外部服务?可能需要服务来调用某些行为,但通常可以在没有外部服务的情况下完成保持完整性。事实上,以这种方式依赖外部服务通常是一种责任混淆的味道。
II, III) 这包括诸如保护不变量之类的事情。例如,实体可以通过引发异常来确保其值不会进入不一致的状态。这是 OOP 的一个基本前提——封装状态并公开行为。
IV) 与实体相关的行为,通常需要状态改变,也应该放入实体中。如果此类行为需要使用服务,请传入该服务,但通常会尝试将尽可能多的行为放入实体中。这并不总是完美的,但你可以为理想而努力。
d) 可以肯定的是,当我说注入(inject) IS 时,我的意思是从 DE 获得对 IS 的必需实例引用。由于上述原因,不鼓励这样做。将 IS 传递给 DE 行为方法会更好,但是如果 IS 接口(interface)有很多与手头行为无关的东西,则可能会违反 SRP/ISP。这是 ISP 的基本前提 - 应该依赖特定的接口(interface),而不是碰巧包含所需功能的臃肿接口(interface)。
关于domain-driven-design - 域服务应该如何调用基础设施服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14612673/
我是 DDD 的初学者。 我不知道谁负责 API 请求的流程。 我不知道谁负责间接依赖于基础设施层的功能。 如带有 Web API 请求的函数。 例如我正在创建在线购物系统,系统支持取消订单。 我想我
我有一个dispatcher-servlet.xml和一个applicationContext.xml。 我一直在做一些重构,并感动 从dispatcher-servlet.xml到applica
哪些工具可用于元建模? 特别是开发图表编辑器,目前正在试用Eclipse GMF 想知道还有哪些其他选择? 有什么可比性吗? 最佳答案 由于许多方面,您的问题对于单一答案来说太宽泛了。 首先,元建模不
我前段时间学习了决策树和决策表。我觉得决策表可以帮助处理条件 If-Then-Else 语句。特别是,我觉得决策表没有副作用,例如,如果您没有注意到您还需要一个“else if”语句。 但我不确定如何
我们的团队开始实现事件驱动设计。我们现在正在确定记录这些事件的模式的最佳工具和实践是什么。 用于此用例的常用工具有哪些? 任何链接或建议表示赞赏。 最佳答案 我将从常见的 CloudEvents sp
我听说过最小化代码和最大化数据的概念,并且想知道其他人在构建自己的系统时如何/为什么应该这样做的建议? 最佳答案 通常,数据驱动的代码更易于阅读和维护。我知道我已经看到数据驱动被极端化并且最终变得非常
我的工作任务是为物流应用程序编写详细的工程计划,我们正在编码该计划以向客户提出建议。有人告诉我这是一个数据驱动的应用程序。对于应用程序来说,“数据驱动”意味着什么?相反的是什么?尽管在网络搜索时我可以
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗?更新问题,使其仅关注一个问题 editing this post . 关闭 4 年前。 Improve this que
我是 DDD 的新手。现在我在看领域事件。我不确定我是否正确理解了这个领域事件,但我只是在想如果领域事件发布失败会发生什么? 我这里有一个案例。当买家从我的网站订购商品时,首先我们将创建一个对象,Or
当我在我的软件项目中实践 DDD 时,我一直面临这样的问题:“为什么我应该在实体中实现我的业务规则?它们不应该是纯数据模型吗?” 请注意,根据我对 DDD 的理解,域模型可以由持久模型和值对象组成。
我有一个名为 Campaigns 的聚合,每个聚合都有一个名为 campaign 的根实体,这个根实体有一个尝试列表(实体) public class Attempts: IEntity
我正在尝试使用分层架构实现 DDD 应用程序。我有: 基础架构层 - 实现应用程序特定技术部分的层。 领域层——包含领域模型的层。 应用层 - 包含与域模型交互的干扰的层。 和接口(interface
最近学习ddd,里面说两个相关的bounded context之间的关系是upstream和downstream。 但是有没有可能在一种情况下A是上游B是下游,而在另一种情况下B是上游又是下游? 但是
我有一个名为 Order 的实体,以及一个聚合根 OrderManager,它根据来自应用层的请求更新订单状态和一些其他信息(AppLayer 调用 OrderManager,OrderManager
让我们假设场景: 我们有系统的用户 每个 User 都有他们的 Clients(Client 总是分配给一个且只有一个 User)< Users 上传不同的 Documents 并且 Document
这是一个 ASP.NET MVC 网站。 在领域驱动设计之后,我们有一个服务层。我们的 Controller 要求应用程序服务类执行各种任务,然后将结果路由到 View 。 业务逻辑由服务类执行。 例
不,这不是重复问题。我有很多关于这个主题的资源,但我仍然觉得我没有完全理解它。 这是我目前掌握的关于什么是聚合和聚合根的信息(来自多个来源,无论是文章、视频等...): 聚合是多个值对象\实体引用和规
我正在重建一个会计软件。该软件可以处理多种类型的交易,例如销售、库存补货和费用。我没有会计背景,但我在网上学到了一些概念。我正在尝试根据这些原则对域进行建模: 一个日记账分录由几条记录组成,每条记录要
我正在从头开始学习 DDD 主题,在许多 DDD 示例中,我看到“存储库接口(interface)”位于域中。这个存储库的真正目的是什么/它到底做了什么或解决了什么问题?这与持久层实现是否对应或有某种
假设我们有以下内容: DDD聚合了A和B,A可以引用B。 管理 A 的微服务公开以下命令: 创建一个 删除 A 链接 A 到 B 取消 A 与 B 的链接 管理 B 的微服务公开以下命令: 创建 B
我是一名优秀的程序员,十分优秀!