如何围绕对象状态设计系统以不重复代码和后端中的机制?

Posted

技术标签:

【中文标题】如何围绕对象状态设计系统以不重复代码和后端中的机制?【英文标题】:How to design system around state of object to not duplicate mechanisms in code and back-end? 【发布时间】:2014-11-24 12:50:37 【问题描述】:

我使用 ATM 的系统是 C# 和 oracle,但是我遇到的问题与系统无关(可能发生在带有 java 和 mysql 或任何其他前端和后端组合的系统上):

我有 TransactionDetail 可以有 9 个状态的对象

Open, 
Complete, 
Cancelled,
No Quote, 
Quoted, 
Instructed, 
Declined, 
Refunded, 
Removed

根据我的经验,当一个人必须处理前端代码中的状态时,他应该尽其所能避免对象状态具有设置器。这是因为状态是内在的品质,必须在需要的时候确定——换句话说,状态应该始终由方法确定,或者只获取属性而不是设置。

因此,正在使用这样的机制检索状态(这只是一段代码,但应该告诉您它是如何工作的)

public TransactionStatus TransactionStatus()

    if (db.DeclinedTransactions.Any(o => o.TransactionId == this.TransactionId))
        return TransactionStatus.Declined;

MI 在 SQL 视图中询问这些事务状态,该视图还包含与事务相关的所有数据。

如果对象状态只能从对象本身的数据中确定,则创建计算列可以解决数据库中的这个问题。但是像TransactionDetail 这样跨越多个表的对象呢?没有计算列机制允许“窥视”其他表。

我能想到的唯一解决方案是添加确定状态的 SQL 函数,然后创建一个包含函数 + 表中数据的 SQL 视图。我不喜欢这种方法的是它需要在代码和数据库中复制逻辑。

应该如何围绕要确定的对象的状态设计系统,需要来自多个表的信息,而不需要在代码和后端复制机制? p>

【问题讨论】:

【参考方案1】:

如果这是我正在进行的一个项目,我不会希望创建一个视图来计算这些数据。

我会查看我的应用程序业务逻辑。

虽然完全规范化的数据库对 DBA 来说非常有意义,但在某些情况下,应用程序的性能和可扩展性可以从一点反规范化中大大受益。

如果您有一个可靠的业务逻辑框架(即定义良好的业务对象、良好的封装、可靠的单元测试),那么我个人希望将其添加到业务对象中。

这允许您在代码中定义您的状态行为并更新显式状态。例如,如果对业务对象进行了更改,将其放入不同的TransactionStatus,那么您可以显式地更改业务对象的该状态并将整个更改保存到您的数据库中。

对这种设计建议的通常反应是,您必须确保您有责任保持两件事同步(显式状态与对象的状态) - 答案是确保只有一个逻辑来执行这些更改,并且您的业务逻辑如前所述是无懈可击的。

一个例子:

发票包含一个或多个 InvoiceItem InvoiceItem 有一个值。 发票在显示时需要发票总金额

执行此操作的通常方法是使用SUM() 在数据库中“即时”计算发票总额,以填充 Invoice.Total 值。

但是,如果我的业务逻辑定义明确——也许我在代码中将 InvoiceItem 添加到 Invoice 对象,并且 Add 逻辑也从 InvoiceItem 中获取值并将其添加到 Invoice.Total 值中——那么当我提交更改,我也可以提交该 Invoice.Total 值。

当我想显示总数时,我只有一个值,而不必在数据库中聚合。

【讨论】:

以上是关于如何围绕对象状态设计系统以不重复代码和后端中的机制?的主要内容,如果未能解决你的问题,请参考以下文章

无法使用“terraform init -reconfigure”将 S3 后端中的 Terraform 远程状态转换为本地状态

Spring实战笔记:后端中的Spring

使用推送通知订阅对象的“p256dh”或“endpoint”键值作为后端中的标识符是不是安全?

什么是前端和后端

如何使用 type-graphql 解析器函数获取 graphql 后端中的选定字段?

如何使用 Apollo Express 仅为 Graphql 后端中的特定解析器设置中间件?