导言

想来从事服务器端开发也有将近一年的时间,服务端开发不能忽略的一个架构就是MVC架构,但一开始作为小白的我对这些高大上的概念也是很迷惑,由于很长一段时间应对的业务也是十分简单,业务代码也是流水一样的代码,所以对架构方面的东西接触也不是很多。

而随着过去几个月应对的业务越来复杂,越来越觉得脚本一样的模式写起来非常吃力。

思考

此前用flask和nodejs写过一些接口,这些代码一直是这样的:

# flask

from flask import Flask

app = Flask(__name__)

@app.route('/api/path')
def get_path():
# do something
return jsonify({'code':'0'})
// NodeJS express框架

var express = require('express');

var app = new express();

function dosomething(){
// do something
}
app.route('/api/path').get(dosomething);

以NodeJS express框架搭建的项目为例,项目目录结构只有两层:

app/
|-- users/
|-- user.model.js
|-- user.controller.js
|-- user.routes.js
|-- products/
|-- product.model.js
|-- product.controller.js
|-- product.routes.js

其中*.model.js就是对应的是一个数据库的表,*.routes.js文件定义路由,*.controller.js定义了所有的业务逻辑。这种结构一开始工作良好,但随着需求增加,接口代码不断增加,上述每个*.controller.js的代码量急速增加,部分甚至达到一万多行,而且里面基本就是一个接口对应一个函数,每个函数里面就是各种通过对数据库的增删改查操作。

如果只是代码量增多那可以接受,问题是业务需求经常改动,经常牵一发而动全身,此外还要考虑版本的兼容性。有些接口功能、逻辑基本上一样,只有细微的差别,但就是这一点点差别不得不另外再写一个类似的函数,造成代码大量冗余。

几经寻找找到一个思路,就是"fat model,skinny controller",它的观点是将部分的业务逻辑放到数据模型中定义,作为数据模型类的方法。这对我来说是一种新的尝试,因为使用这种代码编排方法意味着很多类似的代码可以放到model中,从而分担controller的负担。而NodeJS项目中使用的mongoose本身就提供了许多现成的方法。

然而使用了一段时间之后我发现,一个业务操作往往涉及了多个模块的数据库操作,*.model.js因此引入了大量其他模块中的模型,这样的结果反而更加复杂,严重的时候甚至出现了循环引用的问题:一个功能逻辑上本应该属于模型A,然而由于这个功能需要引用模型B,而B模型在其它功能上又引用了模型A。结果就是很多模型相互缠绕在一起。

偶然看到一篇文章,里面指出,"fat model,skinny controller"的分工不是一个好主意,虽然它相比于"fat controller"有优势,但并好不了多少。因为随着功能的增加,开发者不得不将所有的代码放到少数的几个类中,最终造成所谓的"god object",也就是上帝对象,一个用数千行代码来定义的类实例。

最近在读《企业应用架构模式》这本书,书中总结的一些架构模式启发了我不少。

其中有一部分专门讲数据源架构模式,讲的是业务逻辑应当与数据源适当地隔开。复杂的业务逻辑往往需要隔离数据源层。这一定程度体现了"一个类只做一件事并把它做好"的原则,也就是关注点分离。"fat model,skinny-controller"的模式的问题在于,一个模型既扮演了数据读写的功能又承担了作为业务逻辑主体的角色。这不符合书中提出的分层原则。

前面的文章也指出,我们应当突破框架的局限,突破mvc这种设计模式的限制,使用更多的类取更好地组织你的代码。

重读这篇文章收获颇多,一方面是对fat model的反思,另一方面是对《企业应用架构模式》理解的深入。下一步的方向是将事务脚本的代码转变成为领域模型的形式,削弱业务逻辑对模型层的依赖,增加数据映射器的使用。

一点关于"fat model, skinny controller"的思考的更多相关文章

  1. MVC(Model View Controller)框架

    MVC框架 同义词 MVC一般指MVC框架 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一 ...

  2. MVC模式(Model View Controller)下实现数据库的连接,对数据的删,查操作

    MVC模式(Model View Controller): Model:DAO模型 View:JSP  在页面上填写java代码实现显示 Controller:Servlet 重定向和请求的转发: 若 ...

  3. 深入浅出Java MVC(Model View Controller) ---- (JSP + servlet + javabean实例)

    在DRP中终于接触到了MVC,感触是确实这样的架构系统灵活性不少,现在感触最深的就是使用tomcat作为服务器发布比IIS好多了,起码发布很简单,使用起来方便. 首先来简单的学习一下MVC的基础知识, ...

  4. Model View Controller (MVC) Overview

    By Rakesh Chavda on Jul 01, 2015 What is MVC?Model View Controller is a type of user interface archi ...

  5. Model View Controller(MVC) in PHP

    The model view controller pattern is the most used pattern for today’s world web applications. It ha ...

  6. What is the difference between Reactjs and Rxjs?--React is the V (View) in MVC (Model/View/Controller).

    This is really different, React is view library; and Rxjs is reactive programming library for javasc ...

  7. Go语言根据数据表自动生成model以及controller代码

    手写model的用法请参考: https://www.jianshu.com/p/f5784b8c00d0 这里仅说明自动生成model文件的过程 bee generate appcode -tabl ...

  8. AngularJS开发指南11:AngularJS的model,controller,view详解

    model model这个词在AngularJS中,既可以表示一个(比如,一个叫做phones的model,它的值是一个包含多个phone的数组)对象,也可以表示应用中的整个数据模型,这取决于我们所讨 ...

  9. 设计模式 --- 模型-视图-控制器(Model View Controller)

    模型-视图-控制器(Model-View-Controller,MVC)是Xerox PARC在20世纪80年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已广泛应用于用户交互应用程 ...

随机推荐

  1. LeetCode - 70. Climbing Stairs(0ms)

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  2. android问题笔记集

    开发工具:android studio2.2 调试:手机直连调试,版本(android6) 问题1: Error:Unable to start the daemon process. This pr ...

  3. 平面最近点对(HDU 1007)

    题解:点击 #include <stdio.h> #include <string.h> #include <algorithm> #include <ios ...

  4. MySql数据库插入或更新报错:Cannot add or update a child row: a foreign key constraint fails

    具体报错信息: Cannot add or update a child row: a foreign key constraint fails (`xxx`.`AAA`, CONSTRAINT `t ...

  5. RadioGroup和GroupBox有什么区别?

    我在RadioGroup中放RadioButton和GroupBox中一样,搞不明白. radiogroup有个item属性都是radio控件,不需要拖控件上去.groupbox需要自己拖控件 分组的 ...

  6. css引入特殊字体

    http://www.fontsquirrel.com/tools/webfont-generator        ttf格式的字体转换成其他格式的字体   css引入特殊字体建议只是用英文字体,中 ...

  7. C#判断字符串是否为数字字符串

    在进行C#编程时候,有的时候我们需要判断一个字符串是否是数字字符串,我们可以通过以下两种方法来实现.[方法一]:使用 try{} catch{} 语句.      我们可以在try语句块中试图将str ...

  8. SRM710 div1 MagicNim(博弈论)

    题目大意: 给出n+1堆石子,前n堆石子的数量是a[i],最后一堆只有1个石子,但是具有魔力 拿走该石子的一方可以选择接下来是进行普通的Nim游戏还是anti-nim游戏 问是先手必胜还是必败 首先拿 ...

  9. 十个迅速提升JQuery性能的技巧

    本文提供即刻提升你的脚本性能的十个步骤.不用担心,这并不是什么高深的技巧.人人皆可运用!这些技巧包括: 使用最新版本 合并.最小化脚本 用for替代each 用ID替代class选择器 给选择器指定前 ...

  10. 实际上ECMAScript中并没有对类的定义

    首先,我们用一个经典例子来简单阐述一下ECMAScript中的继承机制. 在几何学上,实质上几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边).圆是椭圆的一种,它只有一个焦点.三角形. ...