被人忽略的Model

长久以来我一直主张:好代码是廉价的代码。

MVC不是一种设计模式,而是一种指导原则,简单讲就是一个应用系统被划分为M(数据模型model)V和C(控制器controller)三个部分,每个部分都有比较清晰的职责划分。MVC指导原则下开发的系统代码逻辑清晰,容易扩展并且可复用。

当我跟做开发的同事说出这话时,他们的第一反应是一种惊愕,然后是将近一个星期的嘲笑,把它当作一个笑话来讲。当他们走近看我的表情、知道我是认真的时,才收敛一点。

在大多数时候,并没有一种代码级别的约束让你的程序看起来是MVC的思想,多数时候是靠程序员自己的“自觉”,维护一种看起来有序、可复用的模式。

当最初的惊愕消退后,他们会用一些这样的话来反驳:“好代码不廉价,好代码是采用经过数十年计算机科学研究和积累得出的最佳实践设计模式和方法论建立起来的精心制作的程序代码。”

最近我接触到一个系统,发现在controller里有大量的业务逻辑,这些业务逻辑包含了对表单数据的过滤,session的存取,当然还有大量的数据库的读写,甚至包含了数据库的事务,就像是一个“全栈工程师”,包揽了一个项目的大部分业务逻辑,view和model只能望洋兴叹,后来接手的程序员则更是痛苦,因为老板要求系统支持手机端的API,他如果是懒惰的人(也许不是懒惰,只是因为没时间),就会把当前的controller复制一遍,起个新的名字(极可能的名字是原有的action名称后面加上2,好点的加上_mobile),删除传递变量给模板的部分,最后返回一个json格式的字符串;勤奋的人(也许不是勤奋,只是因为重构的时间比较充足)会新建一个service层,把大部分的业务逻辑转移到service里,然后新建一个action,使得原来的action和手机端对应的action都调用service里的方法。当然也有自作聪明的人会修改原来的业务逻辑,在原有的action里加上了浏览器user-agent判断。

我只好继续解释为什么他们给出的好代码的定义有问题的原因是(这是很多开发人员都忽视了的一个原因):知晓各种设计模式,框架,技术技巧只是事情的
一方面,而知道何时该、何时不该应用他们才是更重要的问题。在不知道一种技巧方式如何能对系统的开发有帮助的情况下,这种模式方法极有可能成为一种开发的
阻碍,而不是一种有益的帮助。

重购前的代码就像是这样:

我还要解释说,我所说的“廉价的代码”是指这些代码只需要很少的人/天数就能开发出来,并不是说是由没有经验的开发人员、在很少的工资报酬下、用6个月封闭式、只有烤白薯和豆腐汤可吃的环境中开发出来的东西。

class UserController{ function login(){ $name = $this->request()->get; $password = $this->request()->get("passoword"); $user = new User(); $success = $user->where("name",$name)->where('password',$password)->find(); if{ return redirect; }else{ return redirect('login','login fail'); } }}

但是 … 设计模式毕竟是个好东西 … 不是吗?

澳门新葡亰8455下载app,当然,但它们好在哪里?它们能提供什么好处?

  • 容易维护

  • 产品更健壮

  • 容易理解

  • 易于日后的改进提高

  • 更好的可跟踪性

你会发现所有的这些最终都落到一点上:从长期的角度看,它们能让你更快的做事情。这事情有可能是系统迁移,或是增加一个新功能,不论是什么,通过运用这些方法模式,你会在时间效率上获得实实在在的好处。

这么说,我们观点一致吗?

怎么说呢,让我给你们说个例子,我们看看实现它的几种方式。

这样的代码似乎并没有什么问题,但是当业务逻辑比较复杂的时候,对于名字为login的action责任就太大了,而且我在新的接口里用到登录的逻辑时,就必须要复制代码:

系统

用PHP创建一个发邮件的表单,表单里有几个表单项,用邮件把这些数据发送给某个人。除此之外,表单里的内容还要存入MySQL数据库里。

现在,用什么方式实现它们最好?按照传统的说法,采用最好的实践设计模式,你可能会想到这些:

  • MVC

  • N-层设计,包括数据库抽象层

  • 对象关系映射(ORM)

  • 可能用到的框架

  • XML配置和相关模型

  • 等等.

我可以说,这简直是疯了,客户的这些需求完全可以用10几行代码、一个小时里(包括测试时间)完成,而且所有的那些方法模式所希望达到的效果(诸如
可读性,可移植性,稳定性)都有了。如果使用上面列出的那些,反而真正的会达不到这个目标,使代码复杂化,难于理解和维护修改。

那现在,假设客户又来了,要求做一些改动,比如要增加一个管理员的界面。这样的话,你就胜利了,你已经实现了很多很有用处的东西;然而这是因为你在
第一次开发这个系统时付出了很大的代价。我要向你声明的是,即使我现在把这些简单的代码进行重构,增加一些简单的业务层,也仍然比按你要求的那种过度技术
化的初始实现方案要简单的多。

再说了,如果客户要求的只是在表单里增加一个属性,那你的N-层设计方案会让你痛苦不堪,因为你需要改动各个层,包括那些CRUD代码。

class UserController{ function login(){ $name = $this->request()->get; $password = $this->request()->get("passoword"); $user = new User(); $success = $user->where("name",$name)->where('password',$password)->find(); if{ return redirect; }else{ return redirect('login','login fail'); } } function login_mobile(){ $name = $this->request()->get; $password = $this->request()->get("passoword"); $user = new User(); $success = $user->where("name",$name)->where('password',$password)->find(); return json_encode(array( 'success' => $success )); }}

SCRUM

我发现Scrum能吸引我的最大一个原因是它能迫使你敏捷开发;它能迫使你在每个Sprint结束的时候把东西都实现、发布。它不会让你做出目前用不到的多余的东西;它不会允许你在实现东西上有任何所谓“正确方式”的奢侈行为。

相反,在你需要的时候你才去重构。当然,这会有一定的风险,因为在实现某些功能上你会花去比当初已经做了一些基础工作的情况下要更长的时间。然而,
产品开发就像是一个沙漠中四处漂移的沙丘,你永远不可能准确的知道一个产品在将来会做如何的改动。所有的你花在实现这些很有吸引力的各种模式上的时间很可
能会成为一种完全的浪费。

所以现在我们作了以下的重构:

网站地图xml地图