c++ - 如何在 C++ 中实现干净的架构组件边界?
问题描述
我正在阅读 Robert C. Martin 的 Clean Architecture,我想将书中的知识应用到我的 C++ 程序中。然而,我不明白的一件事是接口边界应该如何工作。
“内层”(业务规则)不应该知道外层的任何事情。这意味着红线上方的东西不应该知道下图中红线下方的东西。
但是,如果业务规则使用 C++ 接口(纯抽象类)与数据库(下图中的数据库接口)对话,他们是否必须在“数据库访问/数据库”中包含对实现标头的引用模块,因为无法实例化抽象基类?这不是违反业务规则不应该知道外层的任何原则吗?
在 c++ 中正确的方法是什么?
图片:来自 Clean Architecture 的图 17.2
解决方案
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 访问(对标准输入、文件、字符串等)。
虽然这些都与清洁架构没有直接关系,但这是您可以使组件的实现独立于它们的依赖项的方式。
推荐阅读
- excel - Excel 链接的 IF 语句在宏更新后丢失单元格范围
- laravel - 我的计划没有调用 everyMinute()
- c - 相同内存地址的两个不同值?
- ruby - 为什么集成测试失败并显示“测试错误无法断言“login_path”
- python-2.7 - 改善曲线拟合日志
- java - Debian 的 Docker 映像:拒绝访问文件或目录“/usr/local/openjdk-8/bin/java”
- python - 旨在使用 JSON、请求和 gtts 发送音频消息的 Python VK 聊天机器人不起作用
- ios - SwiftUI 文本对齐
- python - 具有双索引的 Pandas 查询
- apache - Azure VM 上的 appache2 服务器出现错误:“无法访问此站点 *.*.*.*”