代码诊所续

几年前,我有机会负责一个项目的咨询。团队很小,目标是对旧有系统的后端用Java改写,而团队的开发人员全为C程序员。我的工作职责是负责项目设计、开发,以及担任项目开发过程敏捷化的教练,并培养Java开发人员。

我在团队工作室的墙角落,开了一个小小的诊所,广而告之——“每日一贴,包治百病”。这是当时我在项目上的第二次诊断。

代码诊所

第一条:变量的声明(定义)应尽量与使用放在一起

本规则与代码的可读性有关,倘若方法还没有保持短小,这个问题就更要命。或许这是C语言开发者容易犯的毛病。当然也有许多Java程序员从前辈程序员处继承了这一陋习。我曾经在一个遗留项目中看到过一个长达几千行的Java方法,在方法头部堆砌了数十个变量定义,让人目不暇给!

除了影响代码的可读性之外,还可能导致隐藏的缺陷。很多程序员之所以习惯在一开始就声明变量,就是将这种局部变量当做了存储中间状态的容器,在方法内部反复使用该变量,这种中间结果的变迁未必符合开发者意图,又或者后来的代码维护者没有理清这种变化,从而做出变量值的误判。

第二条:对常量和枚举的使用

本规则本不足道,写在这里,为了进一步惊醒一下团队成员。在咨询过程中,我看到有这段代码:

Integer.parseInt(freeFlash, 16);

这个16,究竟是什么鬼?Magic Number,很多时候会让人感到困惑。

在JDK没有提供枚举之前,很多Java程序员喜欢使用接口类型来包装一大堆常量。如果常量存在内聚的分类意义,还是使用枚举为佳。

第三条:进行合理封装,避免方法调用顺序错误

封装是非常有必要的。有时候,暴露太多的细节会让调用者感到无可适从。

对于TelnetService类,我们需要依序调用connect()、login()、enterUShell(),然后在执行命令后,必须依序执行exitUShell(),disconnect()。这让我想起事务处理,FTP访问等与资源有关的逻辑,都需要在执行逻辑前后包裹一些基础设施的处理逻辑。为了避免在执行命令前后忘记连接或断开telnet,最好能将此过程封装。

这是从调用安全性来考虑。

如果从调用的简洁性考虑,封装亦有必要。当我们需要通过TelnetService发送telnet命令时,为何还需要了解内部的执行逻辑呢?

那么,该如何封装才能两全其美,既满足对执行逻辑顺序的重用,又满足对命令逻辑的扩展?通常做法是将真正的执行逻辑提取为接口,如Java中Runnable的方式。这其实可以看作Command模式的运用。当然,我更愿意看做是对函数的封装,例如Guva中的tranform()、filter()之类的方法,接受更具有函数气质的Function或者Predicate接口(当时,Java 8还未问世呢)。

因此,我的做法如下:

public class TelnetService {
    public T withCommand(ExecutionCommand<T> command) {
        connect();
        login();
        enterUShell();
        T result = command.send();
        exitUShell();
        disconnect();
        return result;
    }
}

可以这样调用:

String result = telnetService.withCommand(new ExecutionCommand<String>() {
        @Override
        public String send() {
            return telnetService.transfer();
        }
    }
);

第四条:遵循异常处理的架构规则

团队成员对异常极为陌生,面对java的受控异常、非受控异常,不知如何选择;也不知道该何时捕获异常,何时抛出异常。因而我针对该项目确定了异常处理的架构原则,其目的是为了让整个架构变得更简单,让异常处理更加一致。

我的目的是减轻开发人员的负担,但同时又不降低代码质量,并利于未来对代码的维护。规则如下:

  • 同层之间的调用不做try-catch,上层调用下层的对象,必须try-catch。即使对象抛出了异常,只要不是checked exception(我们尽量避免使用checked exception,以避免它对接口的污染),就无需考虑去捕获这个异常。这样的设计并不会导致异常泄露,因为我们要求在上一层捕获。至于最顶端的Application Layer,则只做捕获异常的事儿,不干抛异常的活儿。
  • 为各层(即领域层和基础设施层)定义各自的异常超类。其中,领域层定义的异常要求提供Error Code。Error Code并非我所愿,但对于本系统的上游系统,却需要该值,不得不为。
  • 领域层。若是结合实际情况由自己抛出异常,则只需考虑异常消息和错误码;若是捕获了异常再抛出,则在捕获时记录日志,再度抛出的异常需要包裹原始异常对象。

在代码诊所中诊断出来的疾病,可以作为代码评审的一个标准,同时这些处方则可以当做团队内部分享与交流的知识库。长期累积下来,非常有利于团队成员编码能力的成长。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,069评论 4 358
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,212评论 1 287
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 105,912评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,424评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,741评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,194评论 1 206
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,553评论 2 307
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,289评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,923评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,251评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,775评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,144评论 2 249
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,698评论 3 228
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,936评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,658评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,214评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,159评论 2 258

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,534评论 25 707
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,292评论 18 399
  • 前言 抛开工作,以电子爱好者的身份,单片机玩多了都会想着在单片机的外围设备玩出一些花样来。这其中首先想到的就是“升...
    淡定的H羊阅读 61,996评论 16 55
  • 重返20岁 subtitle 东野圭吾<秘密>的童话版本,对称的幸福生活下去 Who : main actiors...
    CqrxFZ阅读 700评论 0 1
  • 今天早上奶奶叫我起床穿衣服,刷牙,洗脸,我就穿好衣服去刷牙,洗完脸就下去吃饭了, 我吃饭的时候看见了我的胡萝卜长根...
    贤惠的煎蛋饼阅读 138评论 0 0