问题标签 [ddd-service]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
1462 浏览

spring-boot - 如何使用 DDD 定义带有翻译的实体

我有一个使用领域驱动设计的小型应用程序,现在我想要一个带有翻译的实体。

我在互联网上读到域驱动设计的最佳实践是将翻译与模型分开,但我不知道该怎么做。

这是我所拥有的一个例子:

然后我的问题是:

想象一下,我正在接收产品 DTO 中的翻译,我想知道如何去做。

感谢并感谢您的帮助。

0 投票
3 回答
841 浏览

entity-framework - 实体框架和 DDD - 在将实体传递到业务层之前加载所需的相关数据

假设您有一个域对象:

你有 ASP.NET Web API 控制器来处理它:

它接收实体标识符,通过 id 加载实体并使用域服务在其上执行一些业务逻辑。

问题: 这里的问题是相关数据。ArgumentEntity具有AnotherEntities集合,仅当您通过 Include/Load 方法明确要求这样做时,EF 才会加载该集合。 DomainService是业务层的一部分,应该对持久性、相关数据和其他 EF 概念一无所知。

DoDomething服务方法期望接收带有加载的 AnotherEntities集合的ArgumentEntity实例。您会说 - 这很简单,只需在Repository.GetById中包含所需的数据并使用相关集合加载整个对象。

现在让我们从简化示例回到大型应用程序的现实:

  1. ArgumentEntity要复杂得多。它包含多个相关集合,并且相关实体也有其相关数据。

  2. 您有多种DomainService方法。每种方法都需要加载相关数据的不同组合。

我可以想象可能的解决方案,但它们都远非理想:

  1. 总是加载整个实体 -> 但它效率低下而且通常是不可能的。

  2. 添加几个存储库方法:GetByIdOnlyHeader、GetByIdWithAnotherEntities、GetByIdFullData以在控制器中加载特定的数据子集 -> 但控制器会知道要加载哪些数据并将其传递给每个服务方法。

  3. 添加几个存储库方法:GetByIdOnlyHeader、GetByIdWithAnotherEntities、GetByIdFullData以在每个服务方法中加载特定的数据子集 -> 效率低下,每个服务方法调用的 sql 查询。如果您为一个控制器操作调用 10 个服务方法怎么办?

  4. 每个域方法调用存储库方法来加载额外的所需数据(例如:EnsureAnotherEntitiesLoaded)-> 这很难看,因为我的业务逻辑意识到相关数据的 EF 概念。

问题: 在将实体传递到业务层之前,您将如何解决加载实体所需的相关数据的问题?

0 投票
1 回答
962 浏览

domain-driven-design - 从 ddd 聚合查询远程休息服务

我已经阅读了双调度模式,它可以将服务接口传递给聚合方法:https ://lostechies.com/jimmybogard/2010/03/30/strengthening-your-domain-the-double-dispatch-pattern/ , http://blog.jonathanoliver.com/dddd-double-dispatch/

在我的域中,我有一个BitbucketIntegration聚合,它是远程 bitbucket 帐户的本地副本,其中 包含一些额外的域特定数据。现在,我必须从云同步存储库和团队等,以便能够在它们上进行业务操作。在我的第一个实现中,我使用服务访问 Bitbucket Cloud,然后设置聚合的存储库、团队、帐户。通过这种方式,我将DDDAnemic Domain Model混合在一起,因为一半的聚合状态是使用服务中的类似 setter 的方法设置的。使用Double Dispatch,我可以通过例如BitbucketService接口到方法参数。这样,聚合可以更多地保护它的不变量,因为某些数据只能通过连接到其余服务来验证(例如,如果聚合的accessToken,bitbucketAccountrepositories同步),这是服务的责任。还有一件事是accessToken我的聚合中有一个字段,这只是一个技术问题。

是否有任何推荐的模式将远程资源的副本保存在 ddd 聚合中?另外,如何避免技术方面的影响?还是第一种使用域服务的方法足够好?

现在代码看起来像:

作为旁注,我只查询Bitbucket。

编辑: Martin Fowler 写了关于访问外部系统的文章,包括定义反腐败层,它将远程资源表示转换为域类型。

0 投票
3 回答
4293 浏览

c# - DDD设计理解

我已经开始学习 DDD 并且我有几个问题,以便我可以提高对它的理解。

所以典型的 DDD 架构是这样的

领域层 => 该层应该与技术无关,并且应该包含以下内容

Domain.Entities(与持久层实体不同,应该只包含验证规则?任何其他域业务应该去这里吗?)

Domain.ValueObjects(不需要在域中唯一的对象,应该只包含验证规则)

Domain.Services(该层应包含业务逻辑,尽管与聚合相关,但不适合聚合本身。需要多个 Domain.Entities 和/或 Domain.ValueObjects 协作的操作的编排器)

Domain.Factories(这个层不知何故还没有完全理解,我的意思是它的责任是创建聚合或什么?)它纯粹是工厂设计模式还是与它不同?

Domain.Repositories(这一层也是模棱两可的,除了我知道这一层负责与外部服务通信,它应该处理什么类型的业务逻辑?)

反腐败层(这一层应该作为域层和应用层之间的网关,它应该负责将响应和请求从一层转换到另一层)

应用层 => 只能用于以客户端易于理解的格式公开数据。过滤在这一层完成(Linq-To-SQL)/(Linq-To-Entity)

客户端(最后一层)=> 应该没有任何逻辑,只公开应用层服务提供的模型。

我看到的其他图层

Shared.Kernel(跨多个限界上下文共享的Domain.ValueObjects / Domain.Entites(不是AggregateRoots))

Infrastructure.Domain.Common(在整个域中共享,例如 AggregateRoot、BaseEntity、BaseValueObject 等)

Infrastructure.DataAccess.Provider(例如 EntityFramework / nHibernate/ MongoDriver ,该层应该与谁通信?应用层?

0 投票
4 回答
3008 浏览

domain-driven-design - DDD:测试实体存在的逻辑应该去哪里?

我正在重构应用程序,并试图找出某些逻辑应该适合的位置。例如,在注册过程中,我必须根据用户的电子邮件地址检查用户是否存在。由于这需要测试用户是否存在于数据库中,因此该逻辑似乎不应与模型绑定,因为它的存在取决于它是否存在于数据库中。

但是,我将在存储库中有一个方法负责通过电子邮件等方式获取用户。这将处理有关检索用户(如果存在)的部分。从用例的角度来看,注册似乎是一个用例场景,因此似乎应该有一个带有 register 方法的 UserService(应用程序服务),该方法将调用存储库方法并执行 if then 逻辑以确定返回的用户实体是否为是否为空。

就 DDD 而言,我是否走在正确的轨道上?我是否以错误的方式看待这种情况,如果是这样,我应该如何修改我的想法?

此链接是作为一种可能的解决方案提供的,在哪里检查用户电子邮件尚未退出?. 它确实有帮助,但似乎并没有结束这个问题的循环。我似乎从本文中遗漏的事情是,谁将负责调用 CreateUserService、应用程序服务或聚合根上的方法,其中 CreateUserService 对象将与任何其他相关参数一起注入到方法中?

如果答案是应用程序服务,您似乎通过将域服务从域层中取出而失去了一些封装。另一方面,采用另一种方式意味着必须将存储库注入到域服务中。这两个选项中的哪一个更可取并且更符合 DDD?

0 投票
2 回答
923 浏览

python - 领域驱动设计 (DDD):领域或基础架构问题

我沉浸在 DDD 中,并且有一个关于什么属于该域以及什么是基础架构问题的问题。

描述域的简化示例:

该应用程序中的上下文之一是关于允许用户检查网页以获取某些信息的便利功能。IE。

“用户想要检查网页并确定短语“lorem ipsum”是否出现以及出现在什么位置。

我们将使用 Selenium 作为匹配短语的底层技术。

在深入研究 DDD 之前,我会创建一个如下所示的类(下面是 Python,但语言无关紧要):

该实体现在依赖于 selenium,不再是纯对象(PO​​CO、POJO 等)。在 DDD 中,这对我来说并不正确。

我的理解是,selenium 表达式也不属于应用程序服务层,因为这会使类/方法膨胀,理想情况下服务层应该很薄。

那么这是否属于基础设施层?很像一个带有持久性代码的存储库。就像是:

这听起来像正确的方向吗?如果是这样?:

这意味着 Page 实体开始趋向于贫血模型,并且正在成为一个简单的 DTO。如果是这样,这个实体是否还有必要?

应用服务层是否可以直接调用基础设施层并执行一些操作(以执行用例)而不涉及任何实体(以及域)?即使采用更多的事务脚本方法,我的理解是 Selenium 功能仍然不应该存在于域中?

或者(而且我是 DDD 的新手)我完全脱离了基础,在这种情况下,非常欢迎任何建议或建议。

谢谢

0 投票
2 回答
126 浏览

validation - 向用户返回错误描述的最佳方式

假设我需要在我的系统中注册用户。

商业规则是:

  • 电子邮件应该是唯一的(一种身份);
  • 名称不应为空。

看起来我需要服务。

大概是这样的:

在我必须向用户返回失败原因之前,这很好。如何处理?

我可以看到几个选项(但我不喜欢其中任何一个):

  1. 实现一种结果对象:

    public interface RegistrationService { RegistrationResult Register(String email, String name); } 公共接口 RegistrationService { bool Succes(); 错误[] 错误();用户新用户();}

很好,甚至可能对 REST api 有用。但是是不是太麻烦了(特别是考虑到可能应该在工厂检查空白名称)?

  1. 抛出异常

    公共接口 RegistrationService { void Register(String email, String name) throws RegistrationError; }

它看起来更准确一些。但例外是昂贵的。像这样使用它们看起来是个坏主意。

  1. 使用数据库约束。但它看起来比(2)更混乱。
0 投票
3 回答
667 浏览

php - PHP DDD如何命名入口点方法?

在遵循 DDD 设计原则时,在 php 中命名服务中的入口点方法的最佳做法应该是什么。

与类相同:

命令模式:

适配器模式:

0 投票
1 回答
439 浏览

architecture - 在六边形架构中动态加载适配器的最佳方式?

我想将六边形架构应用于我的userManagement boundedContext. 所以我想定义 2 个端口(一个用于UI,另一个用于serviceBus集成,用于侦听来自另一个服务的事件)。

问题是我是否想使用不同的技术WCFOwinadapters来实现UI port(我不确定是否应该调用它UI port,基本上这是操作所在的接口) 。如何将它们添加到我的控制台应用程序?CreateNewUser, BlockUser, CheckIfUserExists

假设我想Soap adapter使用WCF实现并使用Owin休息。在许多示例中,我看到人们为每个驱动适配器创建单独的控制台应用程序,即:MyDDD.UserManagement.Api.Rest.HostMyDDD.UserManagement.Api.Soap.Host. 我想要实现的是一个主机应用程序以及以某种方式将适配器连接到它的能力。请分享你的想法!

0 投票
2 回答
737 浏览

user-interface - 用例到命令/应用层映射:实现

我读过的一些关于 DDD 的文章表明,应用层中的应用服务或命令 (CQRS) 密切反映了特定的用例。

对于简单的用例,这种映射是有意义的,但在需要多个用户交互的更复杂的实例中,我试图了解如何映射 API 的课程粒度级别,而不将应用程序逻辑推送到 UI 中。

示例: - 想象一个应用程序服务:

  • 从系统/用户界面的角度来看,在导入产品数据时,我们要检查是否有任何产品已经存在,如果存在,则在继续之前提示用户是否要继续。

我常用的方法:扩展 API 以包括:

如果返回 true,则提示用户是否要继续,然后调用。

我的问题是这是否会将大部分应用程序逻辑转移到 UI 层?(即UI现在控制是否可以覆盖产品,以及在导入产品数据之前是否应检查现有产品等)

如果是,我无法想象应用程序层和域层将如何处理这个问题?除了:

来电:

如果失败,检查失败的原因,如果由于产品已经存在,提示用户并再次调用:

这感觉就像做与上述相同的事情的不同方式。

这可能看起来有点迂腐,但我正在努力使表示层 (MVC) 尽可能轻薄。

关于任何更优雅的解决方案的想法?