这两个选项中的哪一个最适合在域中实现端口
Which one of these two options is the best for implementing a port in the domain
我有一个 Document
class 需要在保存到数据库之前进行外部授权。
是否可以创建一个 authorize
方法,例如...
class Document:
authorize(IExternalAuthorizator authorizator):
authorization_result = authorizator.authorize(this)
// update internal state with result...
然后在用例或服务中使用它...
class UseCase:
execute(IDocumentRepository repo, IExternalAuthorizator authorizator):
doc = new Document()
doc.authorize(authorizator)
repo.save(doc)
或者我应该像这样 Document
class ...
class Document:
authorize(AuthorizationResult result):
// update internal state with result...
然后是像...
这样的用例
class UseCase:
execute(IDocumentRepository repo, IExternalAuthorizator authorizator):
doc = new Document()
result = authorizator.authorize(doc)
doc.authorize(result)
repo.save(doc)
或none,但还有第三种选择?
有什么帮助吗?
根据我自己的文献研究
- 第二种形式更好
- 两者差别很小
你的领域模型本质上是一个状态机:它有一些自己的信息,新信息到达,模型决定如何将新信息与它已知的信息相结合。
当我们需要一些额外的信息来让模型继续进行时,通常会引入额外的端口,而这些信息在其他地方。
其他地方的信息的问题是信息可能在我们需要它的时候不可用(可能是授权停止服务升级)。
所以一个合乎逻辑的问题是:这些接口中的哪个更适合异步信息交换?
当然,如果我们付出大量努力将领域模型与持久性解决方案隔离开来避免代码混乱,那么出于同样的原因,我们也应该将领域模型与异步消息检索隔离开来。该代码是管道世界的一部分,与我们编写域计算时完全无关。
实际上,让应用程序担心与授权协商意味着,当授权不可用时,应用程序可以继续处理其他工作,并在授权数据可用时返回到此特定文档。域模型本身没有(也不应该)有执行此操作的上下文。
换句话说,领域模型的“单一职责”是簿记,而不是信息检索。
另请注意,这两种方法不一定差别太大:
class Document:
authorize(IExternalAuthorizator authorizator):
authorization_result = authorizator.authorize(this)
this.authorize(authorization_result)
authorize(AuthorizationResult result):
// update internal state with result...
或
class UseCase:
execute(IDocumentRepository repo, IExternalAuthorizator authorizator):
doc = new Document()
authorize(doc, authorizator)
repo.save(doc)
authorize(Document doc, IExternalAuthorizator authorizator):
authorization_result = authorizator.authorize(doc)
doc.authorize(authorization_result)
简而言之:这两种情况都一样 除了 小数据检索部分。当数据检索微不足道时,这不会有什么不同,但随着越来越多的管道问题被引入,它会有所不同。
我有一个 Document
class 需要在保存到数据库之前进行外部授权。
是否可以创建一个 authorize
方法,例如...
class Document:
authorize(IExternalAuthorizator authorizator):
authorization_result = authorizator.authorize(this)
// update internal state with result...
然后在用例或服务中使用它...
class UseCase:
execute(IDocumentRepository repo, IExternalAuthorizator authorizator):
doc = new Document()
doc.authorize(authorizator)
repo.save(doc)
或者我应该像这样 Document
class ...
class Document:
authorize(AuthorizationResult result):
// update internal state with result...
然后是像...
这样的用例class UseCase:
execute(IDocumentRepository repo, IExternalAuthorizator authorizator):
doc = new Document()
result = authorizator.authorize(doc)
doc.authorize(result)
repo.save(doc)
或none,但还有第三种选择?
有什么帮助吗?
根据我自己的文献研究
- 第二种形式更好
- 两者差别很小
你的领域模型本质上是一个状态机:它有一些自己的信息,新信息到达,模型决定如何将新信息与它已知的信息相结合。
当我们需要一些额外的信息来让模型继续进行时,通常会引入额外的端口,而这些信息在其他地方。
其他地方的信息的问题是信息可能在我们需要它的时候不可用(可能是授权停止服务升级)。
所以一个合乎逻辑的问题是:这些接口中的哪个更适合异步信息交换?
当然,如果我们付出大量努力将领域模型与持久性解决方案隔离开来避免代码混乱,那么出于同样的原因,我们也应该将领域模型与异步消息检索隔离开来。该代码是管道世界的一部分,与我们编写域计算时完全无关。
实际上,让应用程序担心与授权协商意味着,当授权不可用时,应用程序可以继续处理其他工作,并在授权数据可用时返回到此特定文档。域模型本身没有(也不应该)有执行此操作的上下文。
换句话说,领域模型的“单一职责”是簿记,而不是信息检索。
另请注意,这两种方法不一定差别太大:
class Document:
authorize(IExternalAuthorizator authorizator):
authorization_result = authorizator.authorize(this)
this.authorize(authorization_result)
authorize(AuthorizationResult result):
// update internal state with result...
或
class UseCase:
execute(IDocumentRepository repo, IExternalAuthorizator authorizator):
doc = new Document()
authorize(doc, authorizator)
repo.save(doc)
authorize(Document doc, IExternalAuthorizator authorizator):
authorization_result = authorizator.authorize(doc)
doc.authorize(authorization_result)
简而言之:这两种情况都一样 除了 小数据检索部分。当数据检索微不足道时,这不会有什么不同,但随着越来越多的管道问题被引入,它会有所不同。