命令/查询分隔是否适用于创建对象并返回其ID的方法?


12

假设我们有一个调用业务流程的服务。此过程将在数据层上调用以在数据库中创建类型为A的对象。

之后,我们需要再次调用数据层的另一个类以在数据库中创建类型B的实例。我们需要传递有关外键A的一些信息。

在第一种方法中,我们创建一个对象(修改状态)并在单个方法中返回其ID(查询)。

在第二种方法中,我们有两种方法,一种是保存的(createA),另一种是查询的(getId)。

    public void FirstMethod(Info info)
    {
        var id = firstRepository.createA(info);           
        secondRepository.createB(id);
    }

    public void SecondMethod(Info info)
    {
        firstRepository.createA(info);
        var key = firstRepository.getID(info);
        secondRepository.createB(key);
    }

据我了解,第二种方法更完全遵循命令查询分离。但是我发现查询数据库来获取我们刚刚创建的对象既浪费又违反直觉。

您如何在这种情况下调和CQS?

是否仅第二种方法遵循CQS,如果可以,在这种情况下是否更可取?


2
如果A和B以任意频率创建,那么我可能会立即创建一个存储过程,然后如果存在问题,则可以消除先创建B或创建不包含B的A的可能性。
Ryathal 2011年

在游戏后期介入,提供使用out参数的选项。从技术上讲,这不是返回值!;)

Answers:


13

CQS是一个准则,而不是绝对规则。有关严格CQS不可能进行的活动的示例,请参见Wiki文章

但是,在这种情况下,如果您确实想维护CQS,则可以在客户端(例如GUID)上创建ID,或者客户端可以在创建任何对象之前向系统请求ID,这样对您来说更干净我比创建对象然后查询它(但比仅使用标识列更难)。

就我个人而言,我只是返回ID,并将其称为CQS不合适的情况之一。

另一个带有示例的好文章:Martin Fowler


3

如果您遵循一种方法论,并且似乎使您陷入困境,则应重新评估它。

我看到一个新创建的对象的标识符作为返回参数是一件很有效的事情-不仅方便,而且还是“好”的-正如您看到的那样,代码会更好。

在任何情况下,我都不熟悉“命令查询分离”,但是我非常怀疑它不允许命令返回有关命令执行的信息,如果确实如此,则仅将其丢弃-成功/失败始终存在,而我确实不要认为“您的对象创建成功,其ID为xxx”与“您的对象创建成功”有很大不同。


-1

仅第二种方法遵循CQS。

我认为CQS是鼓励良好编码实践的指南。在开发过程中利用良好的编码实践,如果以后发现此方法包含对资源至关重要的代码,则仍可以对其进行优化。

过早的优化是万恶之源:)


第二种方法有什么特别好的呢?
CheatEx

我没有说第二种方法是“好的”。我说过它遵循了CQS范例。如果您不遵循CQS,我想第二种方法对您不利。如果您想知道为什么有些人尝试遵循CQS,请参阅http://en.wikipedia.org/wiki/Command-query_separation
cheesus说停止发射mods

您说CQS鼓励良好的编码实践,如果确实如此,那么我们应该在第二种方法中观察到某种“良好”。它在哪里?
CheatEx

显然您没有阅读我提供的链接。CQS流行语:提出问题不应改变答案。在第一种方法中,您有一个提供“答案”的方法(“ createA”),但是每次您问时都会更改答案。在第二种方法中,您不需要这样做,这就是其中的“优点”。需要明确的是:我不是CQS纯粹主义者,我不会每次都遵循它。
cheesus说停止发射mods
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.