PureMVC(AS3)剖析:吐槽

PureMVCAS3)剖析:吐槽

写在前面

世上没有银弹——不存在适用于所有情况的框架,只有适合的框架。再者任何一个好的东西(语言、框架等)最终还取决于用的人,语言和框架本身并不能保证用户的代码清晰、解耦等,当然它只是尽可能地做到这点。所以记住我写这篇不是为了否定PureMVC,相反是为了更好的了解它、使用它

1.  吐槽一:过于强调解耦

PureMVC引入了多种设计模式、消息机制(使用观察者模式,发布/订阅模式)来解耦各个模块,它确实做到了这点,但是彻底解耦是需要代价的!

1.1.          Notification消息命名及管理复杂

PureMVC为了做到跨平台,使用Notification来实现模块间通信,而非Flash原生的EventDispatcher/Event机制。然而Notification使用字符串来定义消息,存在以下“问题”。

注:Notification并不是Event的替代物。一般情况下,Mediator给其视图组件添加Event侦听器,按常用方式处理,然后给目标Command/Mediator广播Notification

n  消息ID为字符串,虽然字符串可以做到编译时解耦,但无法做到消息强类型,这样错误将推迟到运行时才能发现。

n  消息命名,在一个大型项目中,需要一套详细的规则。相信我,否则你会吃苦头的。特别是多人参与项目中,如果没有按照一定规则命名,命名冲突可是会让你调试一阵。但不管你如何定义命名规则,【记住】为了模块间解耦,Notification发布者应该不关心谁对这个消息感兴趣(谁来处理),感兴趣者自行注册(Mediator通过listNotificationInterests注册、Command通过facade.registerCommand()注册)。例如当Proxy中用户信息改变时,不应该sendNotification通过“UpdateUserInfoVIew”“UpdateFriendListView”2个通过来分别更新用户信息、好友列表中对应用户的信息,而只是发送一个通知,如“UpdateUserInfo”,用户信息栏、好友列表都注册这个消息,然后分别处理。

n  无法知道Notification的源头。然而这点可以通过在消息体body中,增加字段标识,如:

sendNotification(ApplicationConstants.UPDATE_LEVEL_DATA, { "noticeSource": this, "levelData": m_levelData } );

noticeSource标识消息来源,如果您还想要知道消息传递层次,可以用数组表示,顺序插入传递者。

1.2.          强松耦合加重通信次数

PureMVC中模块间通信推荐使用Notification机制,但是全部使用Notification这种强松耦合模式:①强松耦合加重通信次数;②带反馈数据的通信加重通信负担。

PureMVC(AS3)剖析:吐槽

图:UI使用Notification修改Proxy中的数据通信过程

PureMVCUI修改Proxy的数据并返回后刷新过程:Mediator收到UI提交事件后,发送Notification消息给CommandCommand进行业务逻辑处理,调用Proxy接口修改数据(这里还可能涉及到与服务器通信),然后发消息给Mediator刷新,Mediator收到消息调用UI接口刷新。

因为都是消息机制,整个流程很长,而且Proxy中对数据进行操作后,发送Notification时,可能需要携带修改后的数据(可能是来自服务器的数据)。这个过程不仅通过次数多,而且带反馈数据的消息增加通信负担。另一方面要调试这个过程,我们只能在编译的时候找出一步一步的通信流程,才能跟踪调试。

2.  吐槽二:解耦增加了代码量,不方便调试

解耦的同时将使项目修改的复杂程度提高,某些解耦的办法还会增加代码量、降低执行效率。PureMVC是一个强解耦的框架,其效率本身不是很高,函数调用层次较深,而有时根本不清楚消息发到了哪里。

PureMVC为了实现解耦增加了代码量,不方便调试,但哪个MVC框架不是呢!这不是PureMVC的问题,已经有前辈编写了PureMVC模版,如FlashDevelop的模板(下载),使用模板可以减少手动编写代码量,但不能减少类的数量。

有篇文章详细介绍了PureMVC的耦合与解耦:耦合与脱耦——深入分析为什么使用pureMVC、接口或抽象基类(入口http://bbs.9ria.com/thread-161667-1-1.html

3.  吐槽三:过度使用单例模式

单例模式过于万能,属于高耦合写法。PureMVC中有4个单例ModelViewControllerFaçade我们可以通过ModelViewControllergetInstance()方法获取实例,并对他们进行操作。然而Façade是用于管理ModelViewController并对外提供接口。如果ModelViewController对外不可见,为什么要设定为单例,而不是Façade的成员变量呢?

4.  总结

上面说了一些PureMVC的缺点,不过总体来说PureMVC还算一个优秀的框架,解耦彻底、灵活性高。

上一篇:Chrome开发者工具的小技巧


下一篇:学习源码的第八个月,我成了Spring的开源贡献者 ----《我和开源的故事》