代码简洁之四 统一抽象层次

我是一个phper,但是也写java,ruby,python,go等代码。最近一直focus on coding in clean,觉得抛开语言的门第之见,从思想上总结如何写更优雅代码的方式和方法,也希望阅读了本文的朋友留言讨论。当然我还是用php做代码演示,不过灵感是来自于《代码简洁之道》的java代码。

首先我要提出一个概念:写代码和写文章是完全一样的事情。

文章可以写得短小精悍,也可写得冗余拖沓。可以写得言简意干、调理清晰,也可被写成云里雾里的天书。

同样的现象也会发生在我们写得代码上。一千个coder可能写出超过一千种style的代码。那些丑陋的代码不仅讳莫如深,而且会腐烂到让整个程序都崩坍。

写好一手好代码, 我觉得涉及的点太多,我下面只谈一个概念:封装的抽象层次。

其实代码无论是面向过程,还是面向对象方式或者AOP方式去编写,只是代码的组织方式不同罢了。具体到每一行的书写,我希望是做到一行一个调用,每个封装的函数是同一个抽象层次,每个函数里面的封装调用也是同一个抽象层次。如果不在同一个抽象层次,那么就会让可读性变差,让人不知道总的步骤逻辑的脉络 ,每当这个时候就需要move methods和extract method。

做一个更好的攻城狮,需要有好的鼻子,能够smell到坏代码中的bad 味道。

最近在写一个API项目,还是用的restful+mongo方式,然后在model层里面我对验证的钩子程序作了验证调用的封装,大致如下:

    public function validation()
    {
        $this->checkRequire();
        $this->checkPhone();
        $this->checkNumeric();
        $this->checkRegion();

        return $this->validationHasFailed() != true;
    }

每一行调用都是检查某类型字段的有效性,看起来也没什么错。但实际上最后一行的checkRegion和checkPhone的抽象程度比其他几个要低,他们已经不是某类型的字段的检查,而是具体到phone字段的有效性和行政区域的有效性的检查。我们可以根据实际的业务做一些调整,我的调整如下:

 public function validation()
    {
        $this->checkRequire();
        $this->checkRegex();
        $this->checkNumeric();
        $this->checkArray();

        return $this->validationHasFailed() != true;
    }

    /**
     * 检查所有涉及需要正则匹配有效性的字段
     */
    public function checkRegex()
    {
        $this->checkPhone();
        $this->checkId();
        $this->checkWeiXinID();
    }

    /**
     * 检查所有至少必须是数组类型字段
     */
    public function checkArray()
    {
        $this->checkRegion();
        $this->checkTags();
        $this->checkServices();
    }

这样改了之后,感觉代码层次更分明了,也更容易阅读。其实很可能有很多人会反对我的调整方法。他们会吐槽:把这些调用层次弄那么深入,感觉会加到代码运行成本,也让查阅代码需要不断地跳转调用的地方,还让代码变多了(因为有新的一层封装,当然代码行数会增加)。其实写代码就是在找平衡,我还是非常支持在《代码简洁之道》里面说的成本维度顺序:
代码简洁性。
功能完整。
执行效率(速度)。
编程所用时间。
健壮性。
灵活性

编程本就是折中的结果。时间成本和质量之间做平衡。

放在第一条的就是简洁,而简洁最重要的一点是可读性。调用层次深在语言层次上的消耗可以忽略不计,随着php7的稳定版发布,它的性能已经double了,何况还有zend做一层代码缓存的方法。再者查询代码可以使用高效的ide(或者你像我一样是vimer死忠,早就把vim弄得插件化了)去查阅,完全不会增加阅读难度,反而由于抽象层次一致,更理解代码上的实现和业务逻辑的梳理。

时间: 2024-10-25 15:28:13

代码简洁之四 统一抽象层次的相关文章

代码简洁之二:函数只做一件事儿

函数应该做一件事.做好这件事.只做这一件事. 所以我们简化代码的一个简单方式就是不断拆分函数(Extract Method),一直拆分,拆分到不能再分出一个函数为止. 拆函数的过程就是一个概括目的.步骤,提取抽象层次动名词的过程.不要做只是解释代码的简单概括,要让函数中的语句处于一个相同抽象层次,如果是更细节的事儿,请再进一步拆分出一个函数出来.让代码拥有自顶向下的阅读顺序. 以我之前写的一个列表显示的action(MVC框架里面的某个控制器里面的一个方法),最开始代码是这样的: // 接收查询

Jsoup代码解读之四-parser

Jsoup代码解读之四-parser 作为Java世界最好的HTML 解析库,Jsoup的parser实现非常具有代表性.这部分也是Jsoup最复杂的部分,需要一些数据结构.状态机乃至编译器的知识.好在HTML语法不复杂,解析只是到DOM树为止,所以作为编译器入门倒是挺合适的.这一块不要指望囫囵吞枣,我们还是泡一杯咖啡,细细品味其中的奥妙吧. 基础知识 编译器 将计算机语言转化为另一种计算机语言(通常是更底层的语言,例如机器码.汇编.或者JVM字节码)的过程就叫做编译(compile).编译器(

代码简洁之道——类

(1)类的组织:一般排列顺序公共静态变量.私有静态变量.私有实体变量.公共函数.公共函数调用的私有工具(函数) (2)类应该短小: 单一权责原则:类或模块只有一条加以修改的理由: 内聚:方法操作的变量也多,内聚性就越高: 保持内聚性就会得到许多短小的类 (3)为了修改而组织:对类加以组织,减低修改的风险 隔离修改:借住接口和抽象类来隔离修改细节带来的影响 DIP 依赖导致原则,类应当依赖于抽象而不是依赖于具体细节 代码简洁之道--类

代码简洁之道:C++ 11 之auto+ for_each + lamda表达式

摘要:在很多中情况下,我们需要这样的运算:给vector中每个元素进行相似的处理(每个元素+1,或者其他).一般情况下,我们会选用for循环,然后然后对每个元素进行处理.实际上,C++ 11提供了了lamda表达式,结合for_each,可以写出更加简洁和高效的代码. 1.for_each.简介 for_each是C++中的模板,具体用法可以参考这里:http://www.cplusplus.com/reference/algorithm/for_each/ 2.lamda表达式 lamda表达

知晓设计模式,框架,去提高开发效率,使代码简洁

转自:http://kb.cnblogs.com/page/516088/ http://kb.cnblogs.com/page/516088/ 知晓各种设计模式,框架,技术技巧只是事情的一方面,而知道何时该.何时不该应用他们才是更重要的问题.在不知道一种技巧方式如何能对系统的开发有帮助的情况下,这种模式方法极有可能成为一种开发的阻碍,而不是一种有益的帮助. 好代码是廉价的代码. 但是 … 设计模式毕竟是个好东西 … 不是吗? 当然,但它们好在哪里?它们能提供什么好处? 容易维护 产品更健壮 容

代码简洁之道(1)-年份

1.说明 本文是在阅读一些好的框架的源码时看到的,在此做个记录. 2.具体内容 2.1判断年份是否是闰年 2.1.1前言 为什么会有闰年? 若以陽曆為例,「年」的計算基礎是回歸年,而一個回歸年大約等於365.24220日.因為在平年西曆只計算365日,結果四年後便會累積0.24220×4=0.9688日,大約等於一日,所以便逢四年增加一日閏日以抵銷這0.9688日. 然而,累積4年後多的0.96876天,與真正的1日尚差0.03124天,故如果不間斷地按照4年1閏的方式修正,百年後將累積成365

Delphi中使代码简洁的 5 条忠告(转)

写代码是一种艺术.使用Delphi,任何人都可以轻而易举地开发出某种软件.完成某些任务.而完美的代码则只有真正的高手才能写出.除了正确的缩进.大小写.命名规则之外,请时刻牢记爱因斯坦的名言--简单就是美.下面将谈及的五个代码问题,可能是初学者.甚至一些老鸟都会犯的错误. 忠告一 布尔型变量的赋值操作应该是直接的.例如,在一个if/then/else语句中,if子句将布尔型变量赋值为True,而else子句将其赋为False.下面这段代码的写法是不好的: if If_Love_Delphi the

堆排序讲解(代码简洁)

//本文适用于对堆排序部分理解的同学,主要体现的是代码的简洁. /*算法思想(以大顶堆为例):      1.将长度为n的待排序的数组进行堆有序化构造成一个大顶堆      2.将根节点与尾节点交换并输出此时的尾节点      3.将剩余的n -1个节点重新进行堆有序化      4.重复步骤2,步骤3直至构造成一个有序序列*/ //堆排序public class HeapSort {    public static void heapSort(int arr[]){        int s

C#代码简洁规范

1.巧用select where orderby 等方式. 将复杂的for循环和foreach循环提炼在 List<Math_Deptinfo> list = bLL_Deptinfo.Search(start, length, out total, where); List<UI_Math_Deptinfo> listUIRoleModel = new List<UI_Math_Deptinfo>(); foreach (Math_Deptinfo item in l