- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我对域驱动设计概念还很陌生,在使用带有域逻辑命令和命令处理程序的命令总线时,我遇到了在 API 中返回正确响应的问题。
假设我们正在使用领域驱动设计方法构建应用程序。我们有后端和前端部分。后端具有我们所有的域逻辑和公开的 API。前端使用 API 向应用程序发出请求。
我们正在使用映射到命令总线的命令和命令处理程序来构建我们的领域逻辑。在我们的域目录下,我们有一个用于创建名为 CreatePostCommand 的帖子资源的命令。它通过命令总线映射到其处理程序 CreatePostCommandHandler。
final class CreatePostCommand
{
private $title;
private $content;
public function __construct(string $title, string $content)
{
$this->title = $title;
$this->content= $content;
}
public function getTitle() : string
{
return $this->title;
}
public function getContent() : string
{
return $this->content;
}
}
final class CreatePostCommandHandler
{
private $postRepository;
public function __construct(PostRepository $postRepository)
{
$this->postRepository = $postRepository;
}
public function handle(Command $command)
{
$post = new Post($command->getTitle(), $command->getContent());
$this->postRepository->save($post);
}
}
在我们的 API 中,我们有一个用于创建帖子的端点。这是在我们的应用程序目录下的 PostController 中路由的 createPost 方法。
final class PostController
{
private $commandBus;
public function __construct(CommandBus $commandBus)
{
$this->commandBus = $commandBus;
}
public function createPost($req, $resp)
{
$command = new CreatePostCommand($command->getTitle(), $command->getContent());
$this->commandBus->handle($command);
// How do we get the data of our newly created post to the response here?
return $resp;
}
}
现在在我们的 createPost 方法中,我们希望在我们的响应对象中返回我们新创建的帖子的数据,以便我们的前端应用程序可以知道新创建的资源。 这很麻烦,因为我们知道根据定义,命令总线不应返回任何数据。所以现在我们陷入了一个令人困惑的境地,我们不知道如何将我们的新帖子添加到响应中对象。
我不确定如何从这里开始解决这个问题,我想到了几个问题:
最佳答案
首先,请注意,如果我们将 Controller 直接连接到命令处理程序,我们将面临类似的问题:
public function createPost($req, $resp)
{
$command = new CreatePostCommand($command->getTitle(), $command->getContent());
$this->createPostCommandHandler->handle($command);
// How do we get the data of our newly created post to the response here?
return $resp;
}
总线引入了一个间接层,允许您将 Controller 与事件处理程序分离,但您遇到的问题更为根本。
I'm not sure how to proceed with this problem from here
TL;DR - 告诉域使用什么标识符,而不是询问域使用了什么标识符。
public function createPost($req, $resp)
{
// TADA
$command = new CreatePostCommand($req->getPostId()
, $command->getTitle(), $command->getContent());
$this->createPostCommandHandler->handle($command);
// happy path: redirect the client to the correct url
$this->redirectTo($resp, $postId)
}
简而言之,客户端,而不是域模型或持久层,负责生成新实体的 id。应用程序组件可以读取命令本身中的标识符,并使用它来协调下一个状态转换。
在此实现中,应用程序只是将消息从 DTO 表示形式转换为域表示形式。
另一种实现使用命令标识符,并从该命令派生出将要使用的身份
$command = new CreatePostCommand(
$this->createPostId($req->getMessageId())
, $command->getTitle(), $command->getContent());
Named UUIDs在后一种情况下是常见的选择;它们是确定性的,并且碰撞概率很小。
现在,这个答案有点作弊——我们实际上只是证明了在这种情况下我们不需要来自命令处理程序的结果。
一般来说,我们更愿意拥有一个; Post/Redirect/Get 是用于更新域模型的好习惯用法,但是当客户端获取资源时,我们希望确保他们获得的版本包含他们刚刚所做的编辑。
如果您的读取和写入使用的是同一本记录簿,这不是问题——无论您读取什么,始终是可用的最新版本。
然而,cqrs是领域驱动设计中的一种常见架构模式,在这种情况下,写入模型(处理帖子)将重定向到读取模型——通常发布陈旧数据。因此,您可能希望在获取请求中包含最低版本,以便处理程序知道刷新其陈旧的缓存。
Is there an elegant way to return the post's data in the response?
您随问题提供的代码示例中有一个示例:
public function createPost($req, $resp)
想一想:$req 是 http 请求消息的表示,大致类似于您的命令,而 $resp 本质上是一个数据结构的句柄,您可以将结果写入其中。
换句话说,用您的命令传递回调或结果句柄,并让命令处理程序填写详细信息。
当然,这取决于你的总线是否支持回调;不保证。
另一种不需要更改命令处理程序签名的可能性是安排 Controller 订阅命令处理程序发布的事件。您协调 correlation id在命令和事件之间,并使用它来拉出您需要的结果事件。
细节并不重要——处理命令时生成的事件可以写入消息总线,或复制到邮箱,或....
关于php - 如何从命令总线取回数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37150637/
如何处理在 EditText 上键入时按返回键的事件?当显示虚拟键盘并且用户按回时,它会被隐藏。我想处理这个事件,但是在 EditText 中设置 OnKeyListener 并没有帮助。 最佳答案
我编写了 SMS 应用程序,并为其编写了 BroadcastReceiver。我想从 BroadcastReceiver 获取数据到我的 Activity 中,那么我该如何获取呢。 我的广播接收器代码
有一个场景,其中 httpentity 在 InputStream 中有图像的二进制数据,为了进一步处理,它被转换为库文件中的字符串 [String str = EntityUtils.toStrin
如何获取 uiwebview 的返回和转发 URL。我想要 URL,以便我可以相应地启用和禁用我的网络浏览器上的后退和前进按钮 谢谢 最佳答案 UIWebView 包含后退或前进的构建方法 只需使用执
CGRect rect = Temp_3_Artwork_Big_Image.frame; NSLog(@"Rect : %.2f,%.2f,%.2f,%.2f",rect.origin.x,rect
在返回旧项目并更新其依赖项后,我必须意识到,自版本 1.1.5 以来,logback 不再将 MDC 传播给子项:https://github.com/qos-ch/logback/commit/aa
holder.js 我想向我的页面动态添加占位符图像。 这样插入是行不通的: $('',{class:'file-item'}) .append($('',{'data-src':'holde
我在 C# 中使用 ExecuteOracleNonQuery 来使用存储过程将记录插入到我的 Oracle 数据库中,但似乎无法返回 ROWID。 在 C# 中 ... using (OracleC
我正在努力将一条记录插入到 postgresql 中: val res = DB.withConnection { implicit con => SQL(
我是新手,正在尝试使用 React 和 Redux 构建一个简单的书签应用程序。 我无法解决这个问题: 用户可以创建一个书签并将其添加到多个文件夹。所以我发送一个 addMark(bookmark)
我有一个像下面这样的网址 /pages/edit_product/11 在我的行动 edit_product我怎样才能得到 id 11 这样我就可以做@p = Product.find_by_id(1
我在php中有一个外部文件,输出为json格式 我希望数据以数组的形式发送回 jquery ....该怎么做? php: $options = "data 0 data 1 data 2 data 3
我有以下 C++ 代码: __declspec(dllimport) char* get_mac() { size_t byteToAlloc = 17; char *mac_addr
我正在编写一个 Azure 函数,该函数从 Microsoft 获取 OAuth token ,我已经成功获取了该 token 。我正在尝试使用该 token 访问 Microsoft Graph。我
我有一个 Python Google App Engine 应用程序,我想在 Emacs 中的开发服务器上进行调试。我创建了一个 pdb 可执行文件,以便在 Emacs 中进行调试: $ which
我正在开发一个 google chrome 扩展程序,需要在其中对 Twitch 上的用户进行身份验证。根据https://github.com/justintv/Twitch-API/blob/ma
我有一个简单的 Web API,它返回一个 Iobservable。我正在使用 HttpClient 获取 Observable,以便我可以订阅它。我的问题是订阅时返回的 Iobservable 发出
我正在使用 Ionic 2 构建 Web 应用程序的移动版本,该应用程序使用 SAML 进行 SSO,在我的客户端服务器上运行。现在我们有一个 api,当您未登录网站时会调用它,该网站会重定向到他们的
几个月前,我创建了一个使用 oauth2 与谷歌进行身份验证的 rails 应用程序 - 特别是 omniauth-google-oauth2 gem。我已经完成了创建身份验证和存储刷新 token
我正在尝试将一个值作为 JSON 从我的后端传递到我的应用程序的前端。我目前正在运行 express.js 并且所有发布方法的连接都是完美的。 在我的应用程序的前端单击按钮后,我想从我的服务器取回发票
我是一名优秀的程序员,十分优秀!