在我之前的工作中,大部分程序处理依赖于存储在数据库中的持久数据。
所以DB数据模型主导了运行时程序的数据结构。因此,我们使用主键值作为对其他对象的引用非常方便。
例如 :
1 - 考虑到我们有一家公司通过互联网向客户销售书籍等商品。我们有三个类:Book、Order 和 Customer。
Book 类包含有关书籍的不同信息以及唯一标识符,例如 ISBN 号。
客户类包含公司需要知道的所有数据(通常还有更多),以便将书籍运送给他们的客户,例如电子邮件地址。客户对象还有一个唯一的持久 id 来识别它们。
因此 Order 类包含两个关系引用
int isbn;
(书籍 ID)和int customer_id;
在本示例中,订单类方法不需要访问客户数据或书籍数据,因此订单类不需要依赖它们。
2 - 如果我们现在考虑另一个用于编写和发送订单确认电子邮件的类:
class OrderMailer
{
// Customer index
std::map<int, Customer *> customers;
...
// we have a function that send email with low level parameters
void sendEmail(const std::string& mailAddress, const std::string& body);
// and we have another method that simply sends the email for a given order
void sendEmail(const Order& order);
};
sendEmail(const Order& order) 方法需要获取客户的电子邮件地址,因此需要从其标识符中获取对象。
这就是为什么我们有一个地图,然后地址将被这样访问
const std::string& target = customers[order.customer_id]->emailAddress; // not found test omitted for reading.
这就是想法。
问题部分:
我在几年中使用这种引用方式,没有问自己“这真的是个好主意吗”,因为:
对象/记录 ID 是在公司中识别对象的方式
这种无处不在的持久性 ID(代码、日志、与其他 IT 的讨论)
运行时数据结构总是反映 DB 数据模型(它可能不是一个可靠的论点,但在 DB 世界和运行时世界(c++、python、js)之间切换时非常有用)
我不再在这家公司工作,但在处理持久记录时我保持这种编程方式,我不确定我是否做对了。
我们做了什么?
我们使用了一种引用对象的逻辑方式,而不是使用语言提供的方式:指针或 C++ 引用。当我这样说的时候,这听起来真的很糟糕。
从我的角度来看,这是使用这种“方法”的利弊列表:
优点:
- 如果有底层的关系数据模型,运行时数据结构反映了数据模型,事情就更容易理解了
- 这避免了类的无用耦合(在示例中,Order 不依赖于 Customer 和 Book 类)
- 唯一标识符可以是易于阅读的字符串
缺点:
- 为什么不使用语言的基本特性,即指针和引用来做到这一点?这听起来是一个糟糕的方法。
- 每次我们想要访问逻辑引用对象的数据时,我们都需要使用字典/索引(映射)
如前所述,我不确定使用逻辑/关系引用是否是一件好事。是否有一些规则可以应用来决定是否使用这种方法?我很乐意听取您对此的意见。