如何围绕对象状态设计系统,以免在代码和后端重复机制
本文关键字:代码 后端 机制 状态 对象 何围绕 系统 | 更新日期: 2023-09-27 18:31:47
我正在使用ATM的系统是C#和oracle,但是我遇到的问题是与系统无关的(可能发生在带有java和mysql或任何其他前端和后端组合的系统上):
我有TransactionDetail
对象可以有 9 种状态
Open,
Complete,
Cancelled,
No Quote,
Quoted,
Instructed,
Declined,
Refunded,
Removed
根据我的经验,当一个人必须处理前端代码中的状态时,他应该尽一切努力避免对象状态有一个 setter。这是因为状态是内在的品质,必须在需要的时候确定——换句话说,地位应该始终由一种方法确定,或者只获得属性而不是设置。
因此,使用这样的机制检索状态(这只是代码片段,但应该为您提供指示它的工作原理)
public TransactionStatus TransactionStatus()
{
if (db.DeclinedTransactions.Any(o => o.TransactionId == this.TransactionId))
return TransactionStatus.Declined;
}
MI 在 SQL 视图中请求这些事务状态,该视图还将包含与事务相关的所有数据。
如果对象状态只能从对象本身的数据中确定,则创建计算列可以解决数据库中的此问题。但是像TransactionDetail
这样的对象跨越多个表呢 - 没有计算的列机制可以"窥视"其他表。
我能想到的唯一解决方案是添加确定状态的 SQL 函数,然后创建一个包含函数 + 表中数据的 SQL 视图。我不喜欢这种方法的是它需要在代码和数据库中复制逻辑。
应该如何围绕要确定的对象的状态设计系统,需要来自多个表的信息,以一种不需要在代码和后端复制机制的方式?
如果这是我正在从事的项目,我就不会希望创建一个视图来计算这些数据。
我将查看我的应用程序业务逻辑。
虽然完全规范化的数据库对 DBA 来说非常有意义,但在某些情况下,应用程序性能和可伸缩性可以从一点点非规范化中受益匪浅。
如果你有一个可靠的业务逻辑框架(即定义良好的业务对象,良好的封装,可靠的单元测试),那么我个人希望将其添加到业务对象中。
然后,这允许您在代码中定义状态行为并更新显式状态。 例如,如果对业务对象进行了更改,并将其放入不同的TransactionStatus
则可以显式更改业务对象上的该状态,并将整个更改保存到数据库中。
对这种设计建议的通常反应是,您必须确保承担保持两件事同步(显式状态与对象状态)的负担 - 答案是确保只有一个逻辑来执行这些更改,并且您的业务逻辑如前所述是无懈可击的。
举个例子:
- 发票包含一个或多个发票项
- 发票项具有值。
- 显示发票时需要发票总值
执行此操作的常用方法是使用SUM()
在数据库中"动态"计算发票总计,以填充 Invoice.Total 值。
但是,如果我的业务逻辑定义良好 - 也许我在代码中将 InvoiceItem 添加到 Invoice 对象,并且Add
逻辑也从 InvoiceItem 中获取值并将其添加到Invoice.Total
值 - 那么当我提交更改时,我也可以提交该 Invoice.Total value。
当我想显示总计时,我只有一个值,而不必在数据库中聚合。