首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >领域驱动设计批评

领域驱动设计批评
EN

Stack Overflow用户
提问于 2011-03-31 15:37:28
回答 2查看 1.9K关注 0票数 1

我想要一些建议和批评与领域驱动的设计如下。我在下面包括了伪码。真正的代码会封装属性。

关注点

我唯一担心的是,它似乎是贫血。

步骤

  1. 使用值创建一个新请求
  2. 请求被批准了吗?
    1. 如果是,则显示值。
    2. 若否,请说明未获批准的理由。

代码语言:javascript
复制
enum UnitedStatesState {
  ALABAMA,
  //...
  CALIFORNIA,
  //...
  MAINE,
  //...
  WASHINGTON
}

class License {
  int id;
  String name;

  //enum of state that the license is applicable in
  UnitedStatesState state; 
}

class LicenseRequest {
  //the name of the person making the request
  String name; 

  //enum of state to which the user is requesting a license in
  UnitedStatesState state; 

  LicenseResponse submit()
  {
     //TODO: move creation of the rules out of this class
     RuleGroup<LicenseRequest> ruleGroup = new RuleGroup<>();
     ruleGroup.add(new StateExclusionLicenseRequestRule(UnitedStatesState.MAINE));

     boolean approved = ruleGroup.execute(this);
     if(approved) {
       License license = createLiscense(request);
       return new ApprovedLicenseResponse(license);
     } else {
       DeniedLicenseResponse response = new DeniedLicenseResponse();
       response.rules = newArrayList(ruleGroup);
       return response;
     }
  }

  //TODO: move create license out of Request. maybe a factory class?
  private License createLicense()
  {
     License license = LicenseIdGenerator.generate(this.state);
     license.name = this.name;
     license.state = this.state;
     save(license);
     return license;
  }
}

//visitor for the rule
interface Rule<T> {
  public boolean execute(T o);
  public List<String> getMessages();
}

//rule that auto denies when the request is made in an excluded state
class StateExclusionLicenseRequestRule : Rule<LicenseRequest> {
  public List<String> getMessages();
  UnitedStatesState excludedState;
  public boolean execute(LicenseRequest request) {
     if(request.state == excludedState)
     {
       messages.add("No license for " + request.state + " is available at this time.");
       return false;
     }
     return true;
  }
}

//rule that groups all other rules
class RuleGroup<T> : Rule<T> {
  public void addRule(Rule<T> rule);
  public List<Rule<T>> getFailedRules();

  public List<String> getMessages() {
     List<String> messages = new ArrayList<>();
     for(Rule<T> rule : rules) {
       messages.addAll(rule.getMessages());
     }
     return messages;
  }

  public boolean execute(T o) {
     List<Rule<T>> failedRules = new ArrayList<>(rules.size());
     for(Rule<T> rule : rules) {
       boolean approve = rule.execute(o);
       if(!approve) {
         failedRules.add(rule);
       }
     }
     return !failedRules.isEmpty();
  }
}

interface LicenseResponse {
  boolean approved;
}

class ApprovedLicenseResponse : LicenseResponse {
  License license;
}
class DeniedLicenseResponse : LicenseResponse {
  private List<Rule<LicenseRequest>> rules;

  public List<String> getMessages()
  {
     List<String> messages = new ArrayList<>();
     for(Rule<LicenseRequest> rule : rules) {
       messages.addAll(rule.getMessages());
     }
     return messages;
  }
}

样本码

代码语言:javascript
复制
request = new Request(name: 'Test', state: UnitedStatesState.CALIFORNIA)
response = request.submit()
if(response.approved)
{
  out('Your request is approved');
  out('license id = ' + reponse.id);
}
else
{
  out('Your request was denied');
  for(String message : response.messages)
  {
    out(message);
  }
}

更新1:背景

这只是对我想要实现的东西的嘲弄。这是一个简单的系统,用户在表单中输入有关他们自己的信息,并批准或拒绝他们的许可。经批准后,证书可供打印。

例如,唯一的规则是拒绝缅因州的许可证请求。

更新2:重构规则和删除处理程序

我对上面的例子做了一些修改。移除处理程序并将所有代码移动到LicenseRequest。我还将批准/拒绝类的规则移到了实现vistor模式的类上。

EN

回答 2

Stack Overflow用户

发布于 2011-03-31 20:32:57

不幸的是,有些更相关的代码没有显示出来,但我想看看哪些代码可以被推入LicenseRequest。特别是,LicenseRequest可以创建License而不是处理程序(可能通过给它ID)。如果LicenseRequest的属性仅用于创建已批准的许可证,则尤其如此。这样就不必向getter公开这些信息了。

我还会让determineApproval (可能使用另一个名称)直接创建响应,而不是传递可写消息列表(仅用于失败)。

你应该找的气味是特征Envy。特别是,应该检查使用来自LicenseLicenseRequest的数据的任何计算,看看是否应该在这些类中进行计算。

数据对象(特别是不可变的数据对象)有其用途,但您应该关注。

票数 2
EN

Stack Overflow用户

发布于 2015-06-23 20:11:35

就可扩展性而言,状态应该是ValueObjects。例如,当您需要将一个州的缩写与其名称等同时,会发生什么?

看起来你的设计也没有真正的聚合根源。如果没有许可证,LicenseRequest是否毫无意义?在这种情况下,它应该通过许可证(或许可服务)来处理,而不是直接由调用代码(可以是web服务器、控制台应用等)来处理。

所以对于伪代码来说

代码语言:javascript
复制
var license = licenseFactory.NewLicense();
response = license.Request(name, state)

更有意义吗?如果你有多种类型的驾照,比如商业驾驶执照,会发生什么?

另外,对于规则,而不是命令模式(执行),您可以通过将规则作为规范- 模式来获得更清晰的解决方案。

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

https://stackoverflow.com/questions/5502464

复制
相关文章

相似问题

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