参考数据或查找表是诸如 CustomerType、ProductType 等。它们很少更改,偶尔会添加新类型或淘汰旧类型。在代码中,它们经常被复制为枚举/常量,也用于填充组合框。添加新类型不应破坏现有应用程序,并且通常只需要这些新类型来支持新应用程序的功能,旧应用程序应该忽略它。
这种情况在大多数开发商店中都很熟悉,几年/几个月后它变得混乱、不受控制,如果数据库和代码不同步,就会发生坏事。
其他人如何处理这个问题?代码/数据库是什么样的,它是如何进行版本控制的?
参考数据或查找表是诸如 CustomerType、ProductType 等。它们很少更改,偶尔会添加新类型或淘汰旧类型。在代码中,它们经常被复制为枚举/常量,也用于填充组合框。添加新类型不应破坏现有应用程序,并且通常只需要这些新类型来支持新应用程序的功能,旧应用程序应该忽略它。
这种情况在大多数开发商店中都很熟悉,几年/几个月后它变得混乱、不受控制,如果数据库和代码不同步,就会发生坏事。
其他人如何处理这个问题?代码/数据库是什么样的,它是如何进行版本控制的?
您的意思是,ID 和标签在代码中是硬编码的,并且也出现在数据库的查找表中?
我们采用的方法是从数据库中读取“类型”ID 和标签,并使用它们来填充列表框。
(幸运的是)我不必支持需要从同一个查找表中读取不同值集的应用程序的不同版本。
我听说有人将最低版本 ID 分配给查找表值。应用程序传入其版本(可能是 1.5),并检索所有版本为 1.5 或更低版本的查找值。为更高版本的应用程序(例如 2.1)添加的查找值将被忽略。
这显然会引入一些重要的维护开销。
我们创建了一个自主开发的工具,它在构建期间运行在一个或多个文件中指定的查询,并生成枚举类型类,每个引用数据表一个。该工具至少只要求引用数据表具有两列:主键(具有唯一约束)和字符串。每个枚举实例都有一个从字符串生成的名称(通过算法将名称转换为大写,将空格和其他无效字符替换为下划线等)。
该工具足够灵活,可以在每个值上添加其他属性;例如,“显示名称”、“描述”、可能关联的数值和其他简单类型。我们还在枚举类上生成静态方法来获取值的各种子集;总是至少有一个返回所有值,但我们可以根据 SQL 查询生成其他值。例如,对于颜色枚举,我们可能有一个“primaryColors()”静态方法。生成额外的静态方法以根据其键查找值;例如,
public static Color valueOf(int key);
枚举使在代码中使用众所周知的参考值变得更容易和更易读;例如,
if (selectedColor == Colors.RED) {
.
.
.
}
这确实有一个需要额外构建步骤的缺点,但在我们的案例中,这远远超过了优点:更简洁的代码、确保 UI、业务逻辑和数据库有效值同步等。
我们经常谈论将上述静态机制与添加更多动态行为相结合,但实际上我们从未真正感觉到它足以增加复杂性。