哪些设计模式应该用于存储在数据库中、管理和显示动态类型数据?

huangapple go评论77阅读模式
英文:

Which design patterns should I use for storing in BD, managing and displaying dynamic typed data?

问题

我经常需要存储/显示/管理数据,其类型未确定并可能由用户、外部数据提供者或运行时的其他因素更改。

例如:我正在收集一些关于已完成的工作的数据(假设这是客户想要在线查看的报告)。不同类型的工作有其自己的数据字段集,其中一些可以存储在一个共同字段中(比如完成日期、成本、负责人等),其中一些不能(比如运输服务的距离或可能在此工作期间使用的某些材料的类型,这些并不适用于所有类型的工作,只适用于特定类型的工作)。

那么,我尝试过的方法有:

  1. 最糟糕的方法(依我之见)是仅使用一个表,并为每种数据类型创建专用字段。这是最快实现的方法,但会大幅增加列数(特别是如果我在通过API导入新数据时动态创建新字段)。只有在我们确保项目永远不会增长的情况下才能使用。

  2. 可接受的方法是将最常用的数据存储在主表中(如成本、日期等),并创建一个类似于(主记录ID、字段类型、字段值)的表,其中存储所有其他字段。

但现在的问题是如何在PHP中更好地管理它。

  • 我经常用于小型应用程序的方法是只是有一些常量集或枚举来定义类型,并有一堆类似case的逻辑来根据特定类型验证、存储、显示和以其他方式使用该值。在项目规模较小时,创建速度快,读起来相当清晰。

  • 我尝试过的方法也是定义一个契约,然后为每种数据类型创建一个单独的类,该类封装了与此类型相关的所有逻辑(验证、存储,有时甚至是显示)。起初可能有点复杂,但它有效,并且(我希望)应该能帮助我避免在将来使我的应用程序过于复杂时出现问题... 但是!它似乎违反了单一责任原则,让我更担心的是,我感觉它可能会受到脆弱的抽象问题的影响,而开始时的微小错误可能会在将来造成严重问题。

因此,我的问题是:在这种情况下,你会使用什么方法?在项目增长超出预期时,哪种模式在实践中被证明是可靠的?
我应该考虑学习哪些模式,以更好地看到可能的选择方式?

英文:

I often have to store/display/manage data which type isn't determined and can be changed by user, by external data providers or by whatever at runtime.

For example: I'm gathering some data about work that is completed (say it's sort of report which customer wants to see online). Different kinds of job have their own set of data fields, some of them can be stored in one common field (like a date when it was done, cost, person who is responsible for it, and so on), some of them can't (like distance for transporting service, or maybe type of some materials used during this work, which doesnt suit all kinds of jobs, just one particular one).

So, what approaches I tried:

  1. the worst one (imho) is to use only one table and to create dedicated field for each type of data. The fastest one to implement, but increases amount of columns drastically (especially if I create new ones dynamically while importing new data via API). Can be used only if we are 200% sure that the project will never ever grow.

  2. acceptable one is to store the most commonly used data in main table (like cost, date and so on) and to make table like (main_record_id, field_type, field_value) which stores all other fields.

but the question now is how to manage it better in PHP.

  • approach I often use for small applications - is just to have some const-set or enum to define type, and a bunch of case-like logic that validates, stores, displays and elseway-uses the value according to particular type. it is fast to create and quite clear to read while project is quite small.

  • approach I tried to use as well is to define a contract and then create a separate class for each data type that incapsulates all the logic (validation, storing, even displaying sometimes) connected to this type. seems a bit more complicated at startup, but it works, and should (I hope) help me to avoid over-complicating my app in future... BUT! It seems to break the single-responsibility rule, and, which makes me worry way more, I feel that it can be affected by fragile-abstract problem, and a tiny error at the beginning may cause huge problems in future.

So, my question is: what approach would you use in such circumstances? which pattern is practically proved to be reliable when your project grows more than it was expected?
What patterns sould I consider to learn to better see possible ways to be able to make a better choice?

答案1

得分: 1

总的来说,这似乎就像是在沙漠中寻求瀑布一样 - 要使数据有用,必须了解其属性(如数据类型)。我建议围绕手头的问题定义数据模型,并管理与客户的期望。

假设您确实需要随时处理任何数据,那么需要考虑很多因素,但听起来您可能正在寻找一个修改过的“EAV模型”(实体-属性-值)。

哪些设计模式应该用于存储在数据库中、管理和显示动态类型数据?

通过添加supported_data_types表,您可以扩展对其他数据类型的支持。一般来说,数据类型应该只包括数据存储支持的原始类型(字符串、整数、二进制、日期等)。数据结构应该由带有属性的实体表示。

所有数据结构都可以存在于EAV模型中。这可能会变得非常复杂,特别是在嵌套结构方面(例如,“Job”实体包含“Job_Result”实体等)。

通过添加针对手头任务的新表,可以稍微减轻复杂性:在EAV中表示“Job”实体,而“Job_Result”则是一个新表。

使用多个EAV模型也可能有所帮助,假设嵌套结构也是无结构的。

注意:使用EAV越多,设计和实现就会变得越复杂。尽量避免这样做

另一种选择是使用JSON或NoSQL数据库。这会增加查询和索引的难度,而且您仍然面临有一个数据垃圾场的问题。

其他考虑事项:

  • 在设计系统时请记住所有的SOLID原则,并了解支持它们的相关设计模式。例如,看起来您可能在“开闭原则”周围遇到了问题(Robert C. Martin有更多信息)。

  • 确定一组核心用例,可用于设计一个可以处理当前和未来需求的系统。围绕着不稳定性进行设计(Juval Lowy有更多信息)。

  • 考虑将具体的用例提取为应用程序可以使用的插件。以IDE为例思考:核心用例是在一个或多个代码文件上执行操作。插件可以增加对代码文件类型的支持,编辑体验以及可以在文件上执行的操作。

英文:

Overall, this seems like asking for a waterfall in the desert - for data to be useful, its properties need to be known (such as data type). I recommend defining data models around the problem at hand and manage expectations with your customer.

Assuming you do really need to handle any data any time, there's a lot to consider but sounds like you may be looking for a modified EAV model (Entity-Attribute-Value).

哪些设计模式应该用于存储在数据库中、管理和显示动态类型数据?

With the addition of the supported_data_types table, you can extend support for other data types. Generally, the data types should be primitive only as supported by the data store (string, integer, binary, date, etc). Data structures should be represented by entities with attributes.

All data structures could live within the EAV model. This can be enormously complicated especially with nested structures (e.g. a Job entity contains a Job_Result entity, etc).

The complexity can be slightly mitigated by adding new tables specific to the task at hand: a Job entity is represented in the EAV while the Job_Result is a new table.

Using multiple EAV models could help as well assuming the nested structures are also unstructured.

Caution: The more EAV is used, the more complex the design and implementation. Avoid needing to do this at all cost

An alternative is to use JSON or a NoSQL database. This increases the difficulty of querying and indexing, and you still have the problem of having a single junkyard of data.

Other considerations:

  • Remember all of the SOLID principles when designing a system and understand related design patterns that support them. For example, it seems like you may be running into a problem around the Open-Closed Principle. (Robert C. Martin has more info).

  • Determine a core set of use cases that can be used to design a system that can handle current and future requirements. Design around volatility. (Juval Lowy has more info).

  • Consider extracting concrete use cases as plugins that the application can use. Thinking of an IDE for example: A core use case is performing operations on one or more code files. Plugins can add support for code file types, the editing experience, and what operations can be performed with the files.

huangapple
  • 本文由 发表于 2023年6月26日 00:19:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76551371.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定