哪些设计模式适用于这种代码异味?

3

我有一个包含450个字段的PDF表单,我将使用我的数据库中的数据来填写它。PDF中的每个字段都有唯一的名称,我可以进行如下映射:

switch (fieldname)
{
    case "Name":
        value = GetData(Name);
        break;  // Etc...
    case "Date":
        value = Date();
        break;
    default:
        value = "";
        break;
}

现在看起来这个问题会变得非常复杂,因为有450个分支,如果添加其他文档,它可能会急剧增长。解决这种问题的潜在模式是什么?本质上,我想将PDF字段绑定到数据库字段。
*编辑* 所以,假设我有一个巨大的开关语句,约有450个分支,用于路由PDF字段名称,如“Name”、“Address”、“Phone”,到正确的数据库查询以执行。除了根据最终用户选择的文档而变化的字段名称之外,我还可以用什么其他方法解决这个问题?
*最终编辑* 我思考了一天,并感谢所有人的建议,想出了一个解决方案。我有一个名为GetElement()的函数。它将PDF字段名称作为参数,并执行返回数据库列和另一个过程名称的映射的存储过程。然后,使用一些动态SQL,我传递要查找的过程名称和列,并返回结果。在这里很难选择正确的答案,但我会把功劳归给推动我最接近的那个人。

循环语句?或者你只是没有在代码片段中包含它们? - Bojangles
你说的“填充它”是什么意思?为什么要将所有数据写入变量值中?此外,你是真的在寻找设计模式,还是更想要一种用于查询/处理数据库的工具或技术? - DaveFar
我正在使用数据库中的数据来填充PDF文档。因此,如果PDF文档中有一个名为“名称”的地方,我将从数据库返回相应的名称并将其写入文档。我目前使用的工具是Linq2Sql和iTextSharp,用于获取数据并将其写入PDF。所有的工作都正常运行,但我可以看到这个巨大的switch语句将数据从数据库路由到文档,这让我感到害怕 =\ - decompiled
正如jamWaffles所说,使用循环。foreach($fields as $field)$field ['value'] = GetData($field); - aziz punjani
@Interstellar_Coder,看起来你将路由问题传递给了 GetData(),这将需要类似数量的分支。 - decompiled
显示剩余2条评论
6个回答

4

从我对你的整体问题所知不多来看,似乎将字段名和值一起存储在数据库中会更容易。这样,它就是一个简单的名称-值对循环结构,而且你也不需要在代码中硬编码名称字符串。更通用?希望这能有所帮助。


我可以理解将字段名称存储在数据库中会很有帮助,但如果值根据用户输入而变化怎么办?另外,如果不使用基于存储在数据库中的内容的大型开关/ if else,如何从应用程序中检索它们? - decompiled
现在我们正在关注细节中的魔鬼。您的原始帖子中没有提到用户输入。 :) 您说:“...我将使用数据库中的数据填写它。” - joebalt
感谢Joe,我编辑了第一篇帖子。希望有所帮助。我提到的用户输入是他们可以选择的文档。根据文档,“字段”名称将不同。 - decompiled
我认为这个解决方案可以适用于根据文档不同而变化的字段名称...你只需要通过存储哪些字段名称在哪个文档中来将文档名称添加到等式中。 - Ahmed Khalaf

1

我认为你正在尝试实现一个对象-属性-值系统,这里的对象是一个文档,它具有各种属性...在不同的实例中具有不同的值。

这是一个非常常见的模型,但最好将其持久化存储在除传统关系型数据库之外的其他存储介质中,比如 XML 数据库。


或者使用像couchDB这样的noSQL数据库,或任何其他类型的基于文档的数据库。你甚至可以使用git和文件系统作为数据库。 - Raynos

1

除了设计模式,我会选择更简单的方法,如果我有错误的假设,请纠正我:

  • 您有不同类型的文档,每种文档都有不同的映射。
  • 在应用程序中,用户可以选择任何这些文档
  • 文档的映射可能会更改,并且可以添加新文档

一种选择是拥有一系列地图(具有键值对),它们保存文档的配置。

当应用程序从某些配置文件(某些属性或xml文件)启动并缓存地图时,地图将被初始化,因此您无需一直重新创建它们。

处理文档时,只需选择正确的地图对象并执行循环:foreach($field in $document): $field['value'] = getData(pdfMap.getValue($field));

如果需要更改或添加某些配置,请更改映射文件并重新启动应用程序(或更新映射,如果您不想重新启动)


0

你能不能使用SELECT语句从数据库中不返回所有450个数据项,然后使用fieldname进行索引?你在使用哪种编程语言?

例如

datarow dr = GetAllData();
foreach field in document {
  field.value = dr[field.Name];
};

0
作为一个结构化文档,我认为访问者将是您最好的选择。

0

你可以使用与pdf字段名称相同的名称创建数据库表。然后,您可以使用这种一对一映射来填充pdf文件中的值。我假设您在pdf中设置的所有内容都是字符串。

另一种方法: 如果数据类型是一个问题,您需要在某个地方(比如java中的ENUM)创建一个字段->数据类型映射。然后创建一个名为getValue(fieldName)的函数,该函数基于数据类型调用getString(fieldName)、getDate(fieldName)或getCurrency(fieldName)。

您的数据类型的switch case最多只有5-10个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接