晚上回家的时候跟同事聊起来一些编程的工具。主要是三个东西「MVC」「Gitflow」和「unittest」。最近开发的一个程序正好这三个都在用,深感对于开发出一个可维护的程序来说这三者的重要。
MVC 是什么?
- MVC 是 model view controler 三者的缩写。
- Model 是数据模型,业务逻辑和业务规则,一般成品后不会改变,比如博客里的文章,注意发布、回收、评论等虽然也是对数据的操作,但也被归到 model 里面,一般表现为类的方法。
- View 是视图,对用户而言只有 view 是可见的,这是 MVC 种变化频繁的部分,也是经常要改来改去的部分。
- Controller 是 Model 和 View 的中间层,Model 不会输出任何用于表现的东西,如 HTML 代码等,view 也不会对 model 有任何操作,controller 决定使用哪些 model,对 model 执行什么操作,为视图准备哪些数据。
- MVC 并不是一种设计模式,而是观察者模式(Observer)(Pub/Sub), 策略模式(Strategy)和组合模式(Composite)的合体。
为什么要用 MVC?
- 因为将 MVC 区分开来,Model 就可以专注于数据处理而不必担心表现端的更新,View 也可以只管自己更新而不用担心对数据有什么副作用,Controller 其实更像是负责 Model 和 View 之间的胶水。这样功能分清之后开发起来能让后续的更新和维护的代价减少到最小。而且对于大项目来说,多人合作也只需要把接口做好就可以了。
- 为什么要轻 controller,重 model。因为比如我在 controller 里直接改某个 model 的数值,那么一个被频繁使用的数值很可能会在多处有修改的痕迹,而 model 本身对此一无所知。如果是 model 提供一个接口给 controller,加入这个值出了异常,我只需要在 model 里面写个log,就能知道 到底是哪个调用接口的程序引入的bug。
怎么用 MVC?
- Model 主要是保存事物信息,数据,行为,方法是 model 的主要内容,Model所提供的数据都是原始数据。也就是说,不带有任何表现层的代码。 注意与Controller区分开。Model是处理业务方面的逻辑,Controller只是简单的协调Model和View之间的关系, 只要是与业务有关的,就该放在Model里面。好的设计,应当是胖Model,瘦Controller。
- Model 的粒度要尽可能小,这样容易复用,也容易通过多对多的数据结构实现逻辑。
- View 的部分比较明确,就是负责显示。一切与显示界面无关的东西,都不应该出现在View里面。 因此,View 一般没有复杂的判断语句或运算过程,可以有简单的循环语句、格式化语句。
- Controller 主要是响应用户请求,决定使用什么视图,需要准备什么数据用来显示。用于处理用户请求。 因此,对于reqeust的访问代码应该放在Controller里面,比如
$_GET
$_POST
等。 但仅限于获取用户请求数据,不应该对数据有任何操作或预处理,这些工作应该交由Models来完成。当涉及到多个Model时,有关的逻辑应当交给Model来完成。 - Model 和 View 一定要区分,Controller 则不一定要。
Gitflow 是什么?
- 是一种规范化使用 git branch 来管理分支代码的流程。
- 有develop、master两个主分支,此外还有 feature 分支系,release 分支系、和 hot-fix 分支系。
- develop 负责开发时使用,master 负责生产时使用,两者并不 merge。
- feature 从 develop 分支牵出来用于开发新特性。
- release 从 develop 分支牵出来用于发布前调试、文档、单元测试等,完成后由 release 分支合并到 master 分支。
- hot-fix 从 master 分支牵出来用于发布后改 bug,改完后立刻合并回 master 和 develop。
-
一图胜千言。
为什么要用Gitflow?
- 各个feature之间的代码是隔离的,可以独立地开发、构建、测试;
- 当feature的开发周期长于release周期时,可以避免未完成的feature进入生产环境。
要怎么用Gitflow?
- feature 分支只开发 feature,只能处理自己写的代码,不能对公用的接口代码做修改,否则多个 feature 同时开发时合并回去会很头痛。
- 如果要修改公用接口,用 hotfix 分支。
- 如果要重构,完成或放弃还在做的 feature 分支。
unittest 是什么?
- 单元测试是一堆测试断言,用来测试程序的接口有没有问题。
为什么要用 unittest?
- 因为测试驱动的开发能让你没开发一个新功能之后,方便地知道有没有引入新的 bug。
要怎么用 unittest?
- 每个测试都必须是独立的,在一个测试里有自己的上下文,测试的通过与否不应该受到其他测试的影响。
- 每次开发新功能都必须通过单元测试。
- 单元测试应该来测试那些你觉得很可能出错的地方,不需要覆盖到所有API。
- 每一次 bugfix 都应该更新单元测试,保证同样的 bug 不会再次发生。