首页 » 小蓝 » 编写 DAO / 数据模型 时,切勿做这些犯傻的封装

编写 DAO / 数据模型 时,切勿做这些犯傻的封装


以下是最近看一些项目中 ,对DAO层面、数据模型的类的编写中,挖掘出来的一些不合理的部分。
大致原因来源于 面向对象 方面的基本功薄弱,设计模式知识的缺乏,对 数据 这个抽象概念的理解错误。
总结下来雨以下干货:

get* 类型函数,读取数据里某一个属性(字段)的,坚决不要


这个case,比如我封装了一个 Article 的类,就给它写一个 getTitle ,getCreateTime 这样的一系列函数,
表面上是在读取这些属性时非常方便,实际上是没什么意义的,应该统一为 getAttribute ,从参数里决定读取个别字短或读取全部。
set* 函数同理

is* 类型函数,请不要出现在DAO模型里

很多朋友喜欢这样做,比如用户表里有个 role 字短,就写一个 isAdmin 函数来判断 role是否等于 admin,
从而判断是不是管理员。 
你可能会觉得,这很好啊,很直观啊。
但是请记住一点,模型里,这个类只关心数据本身,而不应该包含对数据的判断,不然,就被业务层污染了。
要做这样的判断,请放在上一层(service)里,既灵活,又合理。

请不要在一个模型里操作与之不相干的模型

这一条很难描述,需要借助一个例子。
还是 Article 类, 有错误的做法,给它写了一个 flushCache() 的方法,以便操作memcache、redis等以刷新缓存,
逻辑上说得通,但是缓存这一层,是超出于这个模型本身的(自己琢磨)。
正确的做法是,封装一个 Cache类,实现一个接收 articleId作参数的flush函数。

函数逻辑里不需要实例化对象的,请弄成static

就是说,如果操作不是针对指定某个实例,理应写成静态。举个例子:
$a = new Article($articleId);
$count = $a->count();
这里的count实现就是不对的,虽然你可以让结果看起来是正确的,但是这样的代码,显然不能让人幸福。

模型别包含常量

请使用其他途径管理你的常量,模型应该是个绝对抽象的概念,原则上是只得到数据,也能表达出全部意义,
不能让数据跟模型捆绑在一起。
举个例子,你的Article模型里有一个 type 属性,是个数字,而这个type对应的 字符串,你用一个map写在
模型里,这样就不对了,尽管很多人还是这样做,应该用配置文件活着另一个常量模型来管理这些数据。

不要专门为一个业务功能实现一个方法

这种也十分常见,比如我要得到 一周内发表的技术文章 ,往往就造成一个  getTechArticleThisWeek 这样的函数,
时间一长,这类型方法就充斥在模型类里,我见过一个模型超过了 一万 行代码。
这又是典型的业务污染现象,你应该时刻明白一个原则,让你的模型迁移到别的项目也能全部发挥作用,只要数据没有变化。

只实现最小功能单元,别做无谓的附加操作

弄清楚当前的功能,不要合并功能。举个例子,
把 读取article详情 这个功能,和 让访问记录加一 这个功能,写在一个函数里,这就是附加操作,你应该把两个功能分开,
该如何组合,交给业务层决定。(比如,管理后台不需要访问记录加一)

不要有不为人知的反馈

这个case主要说的是,在你封装的函数里,不要秘密地改动 [全局变量]、[类的静态属性]等,
如果必须改,请以 引用参数 传进去,让掉用的人知道发生了什么。
比如这样的代码:
function doLogin(){
    /* do sth */
    $_SESSION['user'] = something ;
    return true;
 }
这段代码,调用方根本不知道操作了session,不看源码还不让人安心写业务了。
而下面的就好多了,清楚的告诉我,会操作一下session,并且改变它()
function doLogin(& $session){
    /* do sth */
    $session['user'] = something ;
    return true;
 }

未完待续