导言

想来从事服务器端开发也有将近一年的时间,服务端开发不能忽略的一个架构就是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. Java判断数字的奇偶

    package anli; import java.util.Scanner; public class jiou { public static void main(String[] args){ ...

  2. [整理]docker内部时区修改的两种方法

    方法一 终端执行 date命令,查看宿主服务器的时区是否正确 如果正确: 执行 docker cp /etc/localtime 容器ID:/etc/localtime 将本地时间拷贝到docker内 ...

  3. Camera2与TextureView使用

    package com.intsig.bcrsdk.demo.Activity; import android.annotation.TargetApi; import android.app.Act ...

  4. 在C/C++程序中打印当前函数调用栈

    前几天帮同事跟踪的一个程序莫名退出,没有core dump(当然ulimit是打开的)的问题.我们知道,正常情况下,如果程序因为某种异常条件退出的话,应该会产生core dump,而如果程序正常退出的 ...

  5. storm-kafka版本不匹配的问题

    storm集群是1.0.0版本,kafka的集群版本是0.10.0,所以想当然的使用了kafka_2.10-0.10.0.1.jar作为storm-kafka-1.0.0.jar的依赖使用, 没想到导 ...

  6. Spring Data JPA 简单查询

    一.常用规则速查 1  And 并且2  Or  或3  Is,Equals 等于4  Between  两者之间5  LessThan 小于6  LessThanEqual   小于等于7  Gre ...

  7. 关于socket的疑问

    一直感觉一端发送数据,另一端接受数据很不可思议的事情,如果不能即时地读走会导致什么后果呢? 其实socket读出来的数据,你自己看着办,里面的数据是什么格式你自己去解析,用户可以基于TCP去实现你自己 ...

  8. iOS-数据持久化之Sqllite

    iOS中的数据存储方式 Plist(NSArray\NSDictionary) Preference(偏好设置\NSUserDefaults) NSCoding(NSKeyedArchiver\NSk ...

  9. 习题:就是干(DP)

    洛谷2301 题目描述 眼看着老师大军浩浩荡荡的向机房前进.LOI 的同学们决定动用自己的力量来保卫他们的好朋友loidc.现在每个人都要挑选自己的武器——两根木棍.一根用做远距离投掷,另一根用做近距 ...

  10. ListView获取网络数据并展示优化练习

    权限: <uses-permission android:name="android.permission.INTERNET"></uses-permission ...