【问题标题】:How to implement clean architecture component boundaries in c++?如何在 C++ 中实现干净的架构组件边界?
【发布时间】:2020-04-26 21:57:27
【问题描述】:

我正在阅读 Robert C. Martin 的 Clean Architecture,我想将书中的知识应用到我的 C++ 程序中。然而,我不明白的一件事是接口边界应该如何工作。

“内层”(业务规则)不应该知道外层的任何事情。这意味着红线上方的东西不应该知道下图中红线下方的东西。

但是如果业务规则使用 C++ 接口(纯抽象类)与数据库(下图中的数据库接口)对话,他们是否必须在“数据库访问”中包含对实现头的引用/Database”模块,因为无法实例化抽象基类?那岂不是违反了业务规则不应该知道外层的任何事情的原则?

在 c++ 中正确的方法是什么?

图片:来自 Clean Architecture 的图 17.2

【问题讨论】:

  • 你确定这本书建议“红线以上的事情不应该知道以下事情的任何事情”吗?也许作者的意思是“红线上面的东西不应该知道下面的东西是如何实现的”
  • 从书上看不是很清楚...,至少那一章不是。作者说“请注意离开 DatabaseAccess 类的两个箭头。这两个箭头指向远离 DatabaseAccess 类的方向。这意味着这些类都不知道 DatabaseAccess 类存在。”这对于这两个相邻的类当然是正确的。然而,并没有说业务规则应该知道的确切内容。在另一个例子中,他说“我们在业务规则和数据库之间画了一条边界线。这条线阻止了业务规则对数据库的任何了解,”
  • 你注意到离开的两个箭头是不同类型的吗?它们有不同的含义,一个是继承,一个是使用(聚合)。
  • 是的,我知道它们是不同的,谢谢

标签: c++ architecture software-design clean-architecture


【解决方案1】:

C++ 中的纯虚拟接口大致类似于 C# 或 Java 等托管语言中的接口:

struct DatabaseInterface {
    virtual ~DatabaseInterface();
    virtual std::string get(std::string key) = 0;
    virtual void put(const std::string& key, const std::string& value) = 0;
};

依赖于数据库的类可以依赖于指向抽象基类的拥有指针。它不需要知道任何关于实现的信息:

struct BusinessRules {
    std::unique_ptr<DatabaseInterface> db; // reference
    BusinessRules(std::unique_ptr<DatabaseInterface>);
    /* stuff using the database interface */
};

虽然你不能直接实例化它,但你可以让另一个类继承接口,你可以将具体类的实例传递给需要指向抽象类接口的指针的消费者:

struct SpecificDatabaseAccess: public DatabaseInterface {
    SpecificDatabaseAccess(const std::string& connectionString);
    std::string get(std::string key) override;
    void put(const std::string& key, const std::string& value) override;
};

/* ... */

// dependency injection through the constructor
auto db = std::make_unique<SpecificDatabaseAccess>("...");
auto rules = BusinessRules(std::move(db));

标准库对istream 做了类似的事情。 istream 有一堆方法作用于较低级别的 streambuf 成员之上。 streambuf 是一个抽象接口,其实现执行 I/O 访问(对标准输入、filesstrings 等)。

虽然这些都直接与 Clean Architecture 相关,但您可以通过这种方式使组件的实现独立于它们的依赖项。

【讨论】:

    猜你喜欢
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 2019-03-28
    • 1970-01-01
    相关资源
    最近更新 更多