【发布时间】:2010-12-06 11:55:29
【问题描述】:
最近有很多关于模型-视图-控制器、模型-视图-视图模型、模型-视图-演示者等的讨论。
您认为与 delphi 和非数据感知组件一起使用的最佳模式是什么?
你通常如何实现它?
【问题讨论】:
标签: delphi design-patterns model view
最近有很多关于模型-视图-控制器、模型-视图-视图模型、模型-视图-演示者等的讨论。
您认为与 delphi 和非数据感知组件一起使用的最佳模式是什么?
你通常如何实现它?
【问题讨论】:
标签: delphi design-patterns model view
您可以在他的被动视图变体中使用模型视图演示者模式。 前段时间我写了一篇关于它的帖子。 http://www.danieleteti.it/?cat=18
你也可以使用 Model Gui Mediator (http://www.andypatterns.com/index.php/design_patterns/model_gui_mediator_pattern)
【讨论】:
MVC 的目的是解耦。解耦系统显然更容易维护,并且可以说更容易开发。你能在不影响你的 GUI 代码的情况下彻底改变你的数据库设计吗?您的 GUI 能否完全改变而不会对您的数据库设计产生太大影响?数据库中数据的一致性是否独立于 GUI 或基于表单的事件发生的顺序?这些才是真正重要的问题,而 MVC 是一种正面回答这些问题的方法。
我不是专家,但过去我被这几件事烧伤了:
尝试将所有对 DB 访问和 DB 访问组件的显式引用放入数据模块中。如果你在过多的数据模块方面犯了错误也没关系,但要注意不要在同一个数据模块中放置太多不相关的 DB 访问项(组合代码比分离代码容易得多)。
虽然在设计时将所有 DB 组件连接到主连接/会话组件非常方便(这样做是 Delphi 的优势之一),但能够显式设置在运行时动态的连接字符串、会话或连接引用,特别是当想要在不同项目中使用数据模块时,无需添加原始项目的数据库连接单元(如果存在)。
尽最大努力将尽可能少的业务逻辑放入组件事件中。这是不使用数据感知组件的自然延伸。很难坚持这一点,因为始终如一地进行似乎就像是在做额外的工作,尤其是在一个新项目中,并且您告诉自己稍后再重构;当然,你知道那是个谎言,因为以后永远不会来。
第 (3) 点可能需要一个示例。以下两个 sn-ps 在清晰度和可维护性方面存在巨大差异,但如果单独查看它们可能并不明显,如下所示:
// "LoadEntries" is (loosely) analogous to the "C" in MVC.
// What happens /inside/ LoadEntries is the Model,
// and button interaction is part of View functionality.
// MyList may also be viewable on screen as part of
// the View.
procedure TForm.Button1Click(Sender: TObject);
begin
MyDataModule.LoadEntriesIntoMyList(MyList); // LoadEntries is the "C" in MVC
end;
而不是
// The "controller" is missing. That omission of the essential
// decoupling mechanism between the model and the view will
// cost you or your company lots of money!
procedure TForm.Button1Click(Sender: TObject);
begin
MyList.Clear;
MyDataModule.qMyData.Open;
while not MyDataModule.qMyData.Eof do
begin
NewItem := MyList.AddNewItem();
NewItem.Blah := MyDataModule.qMyData.Fields['Field1'].Value;
...
MyDataModule.qMyData.Next;
end;
end;
我目前正在阅读 django 的书,他们的 MVC 设计确实令人印象深刻。特定于实现的模型、视图或控制器的任何部分都可以被不同的系统替换,而不会(显着)影响其他两个。毫无疑问,其他框架也有类似的方法,但我无法对此发表评论。
【讨论】:
恕我直言,模型-视图-控制器模式中的控制器部分通常是 delphi 应用程序的一种开销,因为此类应用程序基于事件的性质。模型和视图的分离就像在任何其他编程语言中一样。
【讨论】:
我切换到 C# 和 MVVM 模型 (WPF)。
先看看 Embarcadero 的 Object-Oriented Design 论坛吧。
您可以查看tiOpf,因为我看到他们有一些用于构建 GUI 的组件。 还有InstantObjects,不过不知道是不是还在开发中。
VCL 组件的主要问题是它不支持绑定到对象/列表。因此解决方案是使用像EzSepcials 这样的虚拟数据集和数据感知组件,或者使用非数据感知组件并为各个组件编写中介。我应该提到Virtual TreeView。
【讨论】:
我认为典型的 MVC 不适合 delphi 应用程序。我见过添加了太多样板代码的实现,这很可怕。与他们试图解决的问题相比,他们与自己的工作更多。
我已经为 delphi 编写了一个 MVC 框架,但目前我只在我自己的项目中使用它。我还没有找到它的生产材料。它基于Model和Viewer,控制器只是两者之间的连接组织。
模型包含或处理业务逻辑,查看器仅用于查看(GUI)。所以流程是这样的:
我已经自动化了这个,所以当从视图中调用命令时,模型中相应的命令处理程序方法会被自动调用。当模型完成更改时,视图会更新。如果视图中存在与命令名称对应的方法,则调用该方法,否则调用通用的“UpdateView”方法。仅传递更改的数据,并且仅更新视图的相关部分。如果一个模型有多个视图,则全部更新。目前来回传递数据的媒介是 XML,因为它很灵活,因此传递任何类型的数据都没有问题。是的,在极端情况下性能可能会受到影响,但总体而言,这种方法似乎有效。我只需要清理它,这样就可以尽可能少地减少样板和开销。
如果有兴趣,我可以在博客中介绍解决方案并对其进行清理以提高生产质量。
【讨论】:
我没有专门使用 MVC 或其他模式,但我今天所做的(当我使用 DB 感知控件进行数据同步时)就是以这种方式做某事:
每个 entity 表单('entity' 以一种非常松散的方式,我指的是当用户点击菜单项或按钮时首先出现的表单)都有自己的数据模块及其数据组件。
DM.SearchCustomers(<conditions>) 或DM.SaveData() 之类的操作。表单不执行 SQL,句号。我有一个标准的表单(和数据模块)层次结构,所以大多数时候简单的注册(如支付方式)表单都是用很少或没有代码的。
Delphi 缺少(如上所述)对象的数据绑定,并且大多数控件要么是数据件,要么完全忽略它。
【讨论】:
我发现这方面有一些新举措。
Stefan Glienke 在 2011 年 12 月写了一篇关于 MVVM 的 blog post 和一个名为 DSharp 的 delphi 库。
现在看来它们是trying to implement 类似于 Delphi 的 Calibrun.Micro,这听起来很有趣。
【讨论】: