Architecture 鲍勃叔叔';s干净的代码用例定义 问题

Architecture 鲍勃叔叔';s干净的代码用例定义 问题,architecture,tdd,domain-driven-design,use-case,Architecture,Tdd,Domain Driven Design,Use Case,特定于“应用程序细节”的适配器、网关等是否属于用例交互器?或交互程序是否意味着从所有适配器抽象中清除,只与实体交互并返回POJO 我有一个问题,而且只有一个问题,上面的问题。其他一切都是我试图证明我的观点或支持我的问题 注意:Bob叔叔称之为“应用程序详细信息”的是网络、数据库、API调用和交付方法(通常) 所以,基本上 示例: 我看了又看。我在中找不到任何关于构成“用例”的确切内容的参考。当然,有很多关于它们如何编排事物、如何抽象和隐藏实现的信息。但是,我倾向于看到的关于“干净的代码用例函数”

特定于“应用程序细节”的适配器、网关等是否属于用例交互器?或交互程序是否意味着从所有适配器抽象中清除,只与实体交互并返回POJO

我有一个问题,而且只有一个问题,上面的问题。其他一切都是我试图证明我的观点或支持我的问题

注意:Bob叔叔称之为“应用程序详细信息”的是网络、数据库、API调用和交付方法(通常)

所以,基本上

示例: 我看了又看。我在中找不到任何关于构成“用例”的确切内容的参考。当然,有很多关于它们如何编排事物、如何抽象和隐藏实现的信息。但是,我倾向于看到的关于“干净的代码用例函数”的更常见的对话通常谈论的是那些留给我的问题多于答案的东西。通常,我阅读了关于用例是如何交互的,以及它们是如何单独与数据层交互的。根据Bob叔叔的定义和示例,当我阅读关于用例是什么(在高层)时,这些交互器中的“用例”基本上只是“用例”的UML概念。或者至少他所有的博客帖子和现场演讲似乎都在讨论抽象UML用例之类的用例,他从来没有接触过真正的代码或概念,就像一个黑匣子用户所知道的那样。这些用例描述了一组抽象的步骤,这些步骤非常抽象,人们无法真正使用它们来立即开始编码。你必须解释他的概念,我相信我可能没有这样做

我知道如何在用例函数本身中使用适配器或网关的依赖注入。这对用例隐藏了实现,而只是从接口调用函数名。但是,从技术上讲,interactor函数中的用例现在必须始终检查有问题的适配器,然后启动接口函数。所以用例有点“知道”关于“应用程序细节”。。。不是吗?它不知道实现,但它仍然需要问,“您在吗,适配器?如果在,请执行x”

我听说“Bob叔叔的用例”读起来像一个书面的句子(几乎),这是由于高度抽象。但是,如果必须在用例交互器方法中包含“应用程序细节”,我不知道如何做到这一点。我还没有看到有人提到“应用程序细节”特定代码在这些用例交互器方法中的级别或范围。我们是否在这里通过dep注入使用适配器,并进行从API调用函数返回的获取调用(作为POJO)?或者在interactor方法中调用“应用程序详细信息”特定功能是非常不合适的吗

我试图不说得太具体,因为所有语言都可以使用干净的代码,所以适配器是通过“构造函数”或“方法注入”注入的。但是,并非所有语言都包含接口/类。无论如何

我注意到Bob叔叔的UML用例总是包含诸如“更新购物车”或“完整事务”之类的内容。所以我的假设是,他正在将适配器注入到用例中,并简单地调用“completeTransaction”之类的函数。对此,我可以想象他会说

“我们不关心是否需要进行网络调用,我们只是询问参数列表中是否存在网络适配器,如果存在,则通过接口调用我们需要的函数。一个名为
completTransaction
”的函数

对于用例函数来说,
completTransaction
函数的实现是什么并不重要,它只是在适配器内部调用函数名,让适配器担心函数名的实现和需求

尽管如此。。。现在我需要“至少一个网络适配器”,这意味着我的用例函数“知道网络适配器”,但“不关心它在做什么”

鲍勃叔叔说:

“您将能够毫不延迟地运行测试。您将能够推迟有关UI的决策。您将能够在不存在UI的情况下测试业务规则。这种灵活性和解耦始终会加快您的速度。”

然而,如果我包括使用“应用程序详细信息”特定库和/或类的适配器或网关,那么我的测试将立即被阻止,因为需要开始模拟该服务。如果我从一个使用4种不同的“应用程序详细信息”特定服务(即网络呼叫、数据库、通知系统和状态更新)的用例开始,那么我会立即被4种模拟服务阻止

这如何加快我们的速度,让我们使用TDD当每个测试都以多种方式被阻止时,用测试驱动开发是相当困难的

我的假设 (我通过问这个问题来验证或纠正的,这不是我的问题…) 我不应该在用例中使用任何与任何“应用程序细节”(如网络调用、数据库等)相关的东西,无论函数看起来多么抽象。我的用例交互器中应该只有100%的业务逻辑,当我从用例函数返回POJO时,调用用例的控制器应该执行“应用程序细节”特定的功能。我认为Bob叔叔可能希望我们让域级用例功能只与下一层(数据)中的实体和业务对象交互,而不是与注入的适配器和控制器交互。如果您从用例中删除了所有与业务逻辑无关的概念,那么您就可以在不进行模拟的情况下进行测试,并在整个代码库或将来的其他代码库中更多地使用这些用例函数(使用si)
// This... ? (Includes a Network and a DB "Application Detail")
public function completeSale(saleDTO, networkAdapter, dbAdapter) {
    sale = transformSaleDTOToSaleEntity(saleDTO);
    transaction = null;

    // This is all based on there being "SOME KIND OF" implementation 
    // of a "network" and a "database" concept... meaning we're tightly coupled 
    // to a concept even though its implementation is hidden.
    if (netowrkAdapter && dbAdapter) {
        networkResults = networkAdapter.completeTransaction(sale);

        if (networkResults) {
            transaction = new Transaction(sale.id);

            transaction.timePurchased = sale.timeCreated;
            transaction.isCompleted = networkResults.completed;

            dbAdapter.save(transaction);
        }
    }

    return transformTransactionToTransactionDTO(transaction);
}

// Or this... ? (No adapters or "Application Details")
public function completeSale(saleDTO) {
    sale = transformSaleDTOToSaleEntity(saleDTO);
    transaction = new Transaction(sale.id);

    transaction.timePurchased = sale.timeCreated;
    transaction.isCompleted = true;

    return transformTransactionToTransactionDTO(transaction);
}