我们有以下情况。我们有几个存储文档的存储库。我们编写了前端服务,用于处理不同存储库中的文档和文档数据。我们拥有允许您除其他外存储新文档和检索文档元数据的操作。
问题是,存储库中存在不同类型的文档,每个文档具有不同的元数据集。例如,一个存储库中的所有文档都具有文档名称,添加日期,大小,ID,文档类型和文档来源。开票凭证还包含开票帐号和客户名称。保单文件中有保单编号,被保险人姓名和代理商代码。一些特殊的政策文件也有生效日期和数据包类型。
在第二个存储库中,文档具有文档名称,添加日期,大小,类型和位置。发票(是另一个存储库中的开票凭证)具有帐号和客户名称,还具有发票日期。保单文件包含保单编号,被保险人姓名,代理机构代码,生效日期和保单类型。一些特殊政策文件有取消日期和到期金额。
现实更加复杂,但这代表了我遇到的基本问题。
我实际上无法控制现有的元数据字段。这些定义在其他地方,并且其中有些是遗留的。而且,这些都是SOAP Web服务,但最终将成为RESTful。但是现在,它们是由WSDL定义的。
那么,代表这些具有很多相似之处但又存在一些差异的事物的最佳方式是什么?
一些注意事项:
我想让客户端免受尽可能多的特定于存储库的信息的侵害。在理想环境中,尽管文档来自不同的领域,但客户可能不在乎该文档,尽管不同的领域可能使这成为梦pipe以求的事情。
我想要一个newDocument和getDocumentProperties调用来接受和返回每种类型的相关数据,而不是分别为每种不同的文档类型使用new和get调用。
我可以使用一个带有所有可能字段的大型胖对象和一个枚举来区分它们,但这意味着客户必须神奇地知道哪些字段适用,哪些不适用。
我可以为每个可能的文档字段集使用一个特定的对象,但是客户端必须知道文档是要去往还是来自某个特定的存储库,这比我希望他们知道的更多。
就目前而言,我已经做到了两全其美(或最坏?),同时提供了一些高级抽象(策略文档,账单文档),在可以进行转换的地方,并为该抽象保留了任何未知或未定义的数据。
但这意味着客户仍然必须知道,例如,对于某些开票文档,您将具有发票日期,而对于其他文档,则没有。或者,对于来自一个存储库的文档,您将具有一个ID,但是对于另一个存储库,您将具有位置。
无论如何,我正在寻找处理这些类似但不同的对象的最佳实践。
最佳答案
那么,代表这些具有很多相似之处但又存在一些差异的事物的最佳方式是什么?
我认为,如何表示/建模数据的方法取决于您的应用程序要求,并且我不了解全球公认的最佳实践,其中一些(全部?)选项是:
使用键值对映射文档字段
每个可能的领域都有一个肥胖的物体。
具有仅包含共享字段的类的苗条层次结构。
苗条的层次结构+动态元数据(例如BillingDocument仅包含共享字段,还包含包含此存储库唯一字段的映射)
具有子类的复杂层次结构,用于保存唯一字段(例如BaseBillingDocument,RepoOneBillingDocument,Repo2BillingDocument)
一些注意事项:
我想让客户端免受尽可能多的特定于存储库的信息的侵害。在理想环境中,尽管文档来自不同的领域,但客户可能不在乎该文档,尽管不同的领域可能使这成为梦pipe以求的事情。
这是一个业务问题,而不是技术问题,它是通过丢弃不必要的字段来规范化数据,将其声明为可选字段,并且有时应为空,如果它们是从其他常见属性派生的,则应计算缺失值,或者以事实您具有同一文档的不同子类型(BillingDocRepo1,BillingDocRepo2)
我想要一个newDocument和getDocumentProperties调用来接受和返回每种类型的相关数据,而不是分别为每种不同的文档类型使用new和get调用。
这几乎在所有表示形式中都是可行的,REST和SOAP Web服务都支持继承和多态性,如果您使用动态模式(实例或带有元数据的类的映射),也可以做到这一点。
关于java - 如何用不同的数据表示相似的对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49903542/