你会如何为这个应用程序建模?

时间:2010-02-04 13:21:50

标签: php design-patterns oop architecture

我有一个用Zend Framework编写的MVC应用程序,它从Oracle 10g数据库中提取数据并在表和列表中显示这些数据,并通过颜色和图表直观地丰富这些数据。没有ORM,也没有涉及创建,更新或删除,只是纯粹的阅读。数据从另一个应用程序插入。数据库中的数据是根据它们所代表的概念建模的,并由DB视图访问,这些概念从各种其他表(遗留的,不能改变的)聚合这些数据,例如。

| Event ID | Start               | End                 | Status | Created_By |
-----------------------------------------------------------------------------
| 12345678 | 2009-10-01 12:00:00 | 2009-10-01 12:15:00 | booked | John Doe   |
| 12345679 | 2009-11-01 13:00:00 | 2009-12-01 12:00:00 | booked | John Doe   |
| 12345680 | 2009-11-01 13:00:00 | 2009-12-01 12:00:00 | tba    | Jane Doe   |

用户可以从View中影响列显示,排序和排序。客户端可以拒绝/允许访问列并将列内容限制为特定值。用户无法覆盖客户端设置。用户是演员,而客户端基本上只是一个过滤器,它为属于客户端的用户创建可用数据的子集。用户和客户端设置保持不变。

我目前的做法大致如下:

Request --> Controller
            | <--> sanitizes and returns Request params
            | ---> Facade (capsules steps to fetch View Data)
            |      | <--> Table Data Gateway builds Query for requested View
            |      | <--> Query Decorator¹ applies User/Client settings
            |      | <--> DB Adapter fetches RecordSet from decorated Query
            | <----returns Recordset
            | <--> applies RecordSet to View
            | <--> Data-Aware ViewHelper render RecordSet (and View)
Response <--returns rendered View

¹ Query Decorator可以读取持久化的用户/客户端设置,并将其添加到TDG即时返回的基本Query对象中。

然而,最近我一直怀疑这种方法,并希望改进它。我想我可以完全删除TDG并使视图构建从UI完全通用;仅基于DB结构。用户肯定会喜欢这个。问题是,View必须对数据有很多了解。 ViewHelpers必须知道列名以丰富数据,并且通常它们是关于Recordsets中的多个列的。它们不能是通用的,有些东西告诉我这无论如何都是麻烦。感觉就像混蛋。我无法确定原因。

非常感谢任何模式,想法和意见。我知道这个问题有些模糊,但就像我说的那样,我无法确定是什么让我怀疑这种方法。所以我想我正在寻找以可维护的方式构建用户和客户端可定制数据库中心应用程序的任何良好实践方法。我当然不需要解决方案,只需要一些想法和一些链接来了解其他人如何解决这个问题,所以我可以在下次重构时将其考虑在内。

注意
在接受答案之前,我会将问题保持开放状态。任何意见都表示赞赏。

3 个答案:

答案 0 :(得分:13)

在重新阅读你的问题几次并稍微反思之后,我相信我会这样总结一下情况:

“MVC”中缺少“M”。

此时,您手工制作了一个关系数据库模式,使其与您的域模型具有1:1的映射关系。这很好,它使映射非常容易,但记录集仍然不是域类。

MVC上下文中的术语 Model 是指域模型,而不是关系模型。如果您有支持此应用程序的关系数据库,那么您需要某种映射。这并不是说你需要一个像Doctrine这样的完整ORM框架 - 尽管我发现这些工具让我的生活变得更加轻松,即使对于小型项目 - 但你需要某些东西。实际上,Zend Framework甚至详细介绍了在Quick Start中映射域模型的详细信息。

我认为您不需要删除TDG。抽象很好。为了让你的应用程序更加精简,我可以比较一下,进入办公楼并撕掉电话系统,理由是员工可以使用他们的手机。他们可以,但你不想他们,就像你不希望你的视图直接在数据库中抛出SQL查询一样。它效率低,通常难以管理。

我的架构版本如下所示:

Request --> Controller
            | <--> sanitizes and returns Request params
            | ---> Facade (encapsulates steps to fetch View Data)
            |      | <--> Table Data Gateway builds Query for requested View
            |      | <--> Query Decorator applies User/Client settings
            |      | <--> DB Adapter fetches RecordSet from decorated Query
***         |      | <--> Mapping layer converts RecordSet to Domain Model
***         | <----returns Model
***         | <--> applies Model to View
***         | <--> Data-Aware ViewHelper render Model (and View)
Response <--returns rendered View

我已使用***标记了更改行。实际上,我唯一改变的是,它不是从外观中拾取记录集,而是拾取模型(可能是一个域类数组),并将 应用于View。

而不是像[帮助]中的$row['Status']这样的字词,您将拥有$event->status,这样可以更长久地维护更安全,更简单。那里没有列名,只是一个属性。

现在你在问题的最上面明确提到你没有任何ORM,所以我想你可能已经意识到这一点,也许只需要推动。那些令人唠叨的疑惑可能与你的想法有关:如果它不总是只读的话怎么办?如果数据模型变得更复杂怎么办?如果人们开始要求更复杂的报告怎么办?

所有这些都是您拥有域模型的原因,为什么它实际上是MVC的基本构建块:最终,您的用户的心理模型不同步数据模型,由于一些我不会在这里讨论的原因。关键是,它几乎总是发生。

我确定这是必要的吗?我是肯定的,这不仅仅是矫枉过正,一堆仪式咒语对于这么小的项目没有意义吗?

不,我不是。只有你可以决定。我可以告诉你的是,如果没有合适的域模型,作为特定架构的MVC范例对你没有多大帮助。它有点好,但 比在每个页面中只有内联查询或façade调用要好得多。没有模型,MVC只不过是一种奇特的URL重写方案。

也许你需要这种抽象水平,也许你不需要;但我猜你可能怀疑你可能,否则你不会问这个问题。考虑一下,分析当前的需求和范围,问问自己可能会发生什么样的变化,如果当前的体系结构看起来太脆弱而不适应,那么下一个逻辑步骤就是域模型 - 即使今天< / em>它只是关系模型的精确镜像。明天可能不会。

希望这是您正在寻找的那种答案!

答案 1 :(得分:0)

数据库架构设计具有不同的要求(查询/写入性能,可伸缩性)作为一个很好的用户界面(良好的页面流,支持人们的工作方式或流程的工作方式)。因此,UI和DB方法很难直接映射。

作为一个不好的例子,我记得使用“Oracle Forms”的应用程序,它直接呈现了数据库结构的通用视图。对于非技术人员来说,使用它通常非常违反直觉。

我认为,在您的情况下,如果View可以直接映射到数据库模式,那么一定要摆脱不必要的抽象层,代码并简化系统。尽可能简单地实施要求。

答案 2 :(得分:0)

为了根据用户输入从表中动态获取数据,您可以使用Zend_Dojo组件数据网格。您可以创建一个TDG对象,该对象将根据用户输入重新映射到新表。

http://zendguru.wordpress.com/2009/01/08/dojo-grid-in-zend-framework-creating-nice-and-cool-grid-in-php-using-zend-framework-and-dojo/