首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >DDD --如何使用基本示例编写优秀、健壮的代码

DDD --如何使用基本示例编写优秀、健壮的代码
EN

Stack Overflow用户
提问于 2014-11-11 09:58:40
回答 3查看 482关注 0票数 0

对于一个新的应用程序,我使用的是层:

RestRessource -> ApplicationService ->域

我有一个基本的用例,用户可以在其中创建一个“bduget”。如果本年度没有其他预算,则状态为“初始”。AFter表示可以创建新的预算,其状态将与另一个属性“索引”相结合: CORRECTIVE#1,CORRECTIVE#2,.

现在是一些编码。ApplicationService有一个名为"createBudget“的方法。

代码语言:javascript
运行
复制
@Autowired
private BudgetRepository budgetRepo;

@Autowired
private BudgetService budgetService;

public Budget createBudget(int year) {
    Budget newBudget;
    if (budgetService.existsBudgetInitialFor(year)) {
        newBudget = new Budget(year, "INITIAL");
    } else {
        newBudget = new Budget(year, "CORRECTIVE", budgetService.nextIndex());
    }
    budgetRepo.insert(newBudget);
    return newBudget;
}

BudgetService正在使用BudgetRepository来计算数据库。existsBudgetInitialFor返回一个布尔值,如果计数>0 :)

现在问题是:

  1. 对于这个例子,我发现budgetServcie毫无用处。在existsBudgetInitialFor中移动BudgetRepository更好吗?
  2. 你觉得“如果.否则.”语句位于一个好位置:它是AppService层的责任还是对您来说是一条域规则,要强制执行,您是否在BudgetService中移动这些代码?
  3. 为了封装budgetService.nextIndex调用,起诉工厂创建预算更好吗?(代替构造函数)。你认为现在是计算nextIndex的正确时机吗?
  4. 应用层是亚喷射到单元测试,还是可能只用于集成测试?你为什么要那样做?当我试图对这个方法进行单元测试时,我需要至少模拟一下BudgetService,BudgetRepository,我在想:这是代码嗅觉的标志吗?另一种简化单元测试的解决方案是将budgetService.existsBudgetInitialFor(year)提取为私有方法,模拟它以返回真/假,依此类推。
  5. 在编写这段代码时,我并不认为创建是实体的责任。我发现尴尬的地方是“如果.否则.”预算实体内部的逻辑。我说得对吗?(请告诉我至少有一次我是对的)
  6. 最后一个问题是我问自己:也许我从一开始就错了。如果UI发送一个createInitialBudget命令,然后发送一个createCorrectiveBudget命令,会更好吗?在这种情况下,我们需要检查命令的有效性(以避免多个初始创建:唯一性验证)。

这只是一个非常简单的代码(我把权限管理、验证等放在一边)。所以我试着在编写更复杂的应用程序之前,先做好这类代码。其主要目的是验证这些层,向我的同事解释,显示这段代码可以测试,等等。

非常感谢!

弗朗索瓦

EN

回答 3

Stack Overflow用户

发布于 2014-11-11 16:55:05

  1. 您的应用程序服务似乎具有业务逻辑。如果是这样的话,它属于域服务。然后,应用程序服务将被称为domainBudgetService.CreateBudget(int ),就像您现在使用的那样。如果需要,可以将existsBudgetInitialFor移动到存储库。
  2. 见#1
  3. 是的,最好是工厂。
  4. 如果您将预算服务方法移到存储库,那么我认为这不是一个问题。我通常只对域服务和实体进行单元测试。
  5. 工厂应该消除这种尴尬。
  6. 我只需要一个createBudget命令,并将逻辑保持在内部,就像您拥有它一样。否则,UI现在需要有业务逻辑来确定发送什么样的命令。

希望这能有所帮助。

票数 0
EN

Stack Overflow用户

发布于 2014-11-11 21:12:32

这是一项属于财政预算案本身的执行关注事项,亦是财政预算案对如何指明某一地位的知识:

a)域服务:

代码语言:javascript
运行
复制
numberOfBudgets = budgetRepository.numberOfBudgetsIn(anYear);
budget = Budget.newFrom(anYear, numberOfBudgets + 1);
budgetRepository.add(budget);

( b)财政预算案类别内的公营工厂方法:

代码语言:javascript
运行
复制
Budget.newFrom(anYear, budgetNumber) {
  status = 'INITIAL';
  if (numberOfBudgets > 0) {
    status = 'CORRECTIVE' + budgetNumber
  }
  return new Budget(anYear, status);
}

这样,您只在a点中提到了一个域服务。

干杯,塞巴斯蒂安。

票数 0
EN

Stack Overflow用户

发布于 2014-11-12 02:03:03

对于这个例子,我发现budgetServcie毫无用处。在existsBudgetInitialFor中移动BudgetRepository更好吗?

好主意我说,我个人不喜欢xxxService(xxx是实体名称),名称本身并没有多大的意义。

你觉得“如果.否则.”语句位于一个好位置:它是AppService层的责任还是对您来说是一条域规则,要强制执行,您是否在BudgetService中移动这些代码?

在这个用例中,我认为将语句留在应用程序服务中是可以接受的。由于单元测试仍然很简单,有两个备选路径(初始和预算存在)。如果用例变得更加复杂,或者其他一些用例涉及预算创建,那么您可能需要一个BudgetFactory来保存该语句。

为了封装budgetService.nextIndex调用,起诉工厂创建预算更好吗?(代替构造函数)。你认为现在是计算nextIndex的正确时机吗?

是的,我想是时候了。如果不在这里计算,它很可能是在持久性层中计算的,因为它们通常需要更多的精力来编写和维护,并且更加脆弱,因此测试起来更加困难。

应用层是亚喷射到单元测试,还是可能只用于集成测试?你为什么要那样做?当我试图对这个方法进行单元测试时,我需要至少模拟一下BudgetService,BudgetRepository,我在想:这是代码嗅觉的标志吗?另一种简化单元测试的解决方案是提取budgetService.existsBudgetInitialFor(年份)作为私有方法,模拟它以返回真/假,等等。

考虑到这个用例的简单性,如果您将if-else语句留在应用层中,那么就进行单元测试。如果您引入一个BudgetFactory来封装if-else和nextIndex,那么应用层就会变得很薄。如果采用tdd,仍然可以编写单元测试,如果没有,也可以将其保留在功能测试中。

在编写这段代码时,我并不认为创建是实体的责任。我发现尴尬的地方是“如果.否则.”预算实体内部的逻辑。我说得对吗?(请告诉我至少一次我是对的)我同意。单一预算无法判断是否存在其他预算。 最后一个问题是我问自己:也许我从一开始就错了。如果UI发送一个createInitialBudget命令,然后发送一个createCorrectiveBudget命令,会更好吗?在这种情况下,我们需要检查命令的有效性(以避免多个初始创建:唯一性验证)。

当UI显示带有createCorrectiveBudget和createInitialBudget的两个按钮,让用户选择他/她应该单击的按钮时,我不认为这是个好主意。后端的验证是好的,但知识泄露,迫使人们做出不必要的选择。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26862117

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档