美文网首页
简单就是美

简单就是美

作者: hxfirefox | 来源:发表于2018-12-02 21:39 被阅读8次

    我们日常的工作总会面临各种各样方案选择,究竟如何选,衡量的标准又是什么,其实每个软件研发人心中的答案是不一样。对我而言,简单设计是我在代码实现方案中的不二选择,也是我觉得到目前为止最为有效的衡量标准,而且它在业界也得到了充分的实践和验证,例如,阿里架构师就在《企业IT架构转型之道:阿里巴巴中台战略思想与架构实战》一书中提出:简单就是美,这是在总结了阿里各种实现数据库能力线性扩展的实践之后的经验之谈,即采取能够降低系统运维复杂度的方案,如果存在简单有效的方法则优先考虑。

    企业IT架构转型之道

    什么是简单设计,XP大师Kent Beck早就给出了清晰的答案:

    • 通过所有测试(Passes its tests)
    • 尽可能消除重复 (Minimizes duplication)
    • 尽可能清晰表达 (Maximizes clarity)
    • 更少代码元素 (Has fewer elements)

    以上四个条看似属于“有用的废话”,实在蕴藏了软件设计和实现过程中深刻的内涵。

    首要原则“通过所有测试”已经无需更多解读,从实际效果上讲测试是需求方意志的体现,所以无法通过测试,无论是功能的还是性能的,就是不正确的实现也毫无意义和价值。

    重复是万恶之源,重复会降低软件应对变化的能力,这个道理人人都懂可这种坑也是人人会挖,对简单设计最糟糕的理解就是简化实现,比如说复制粘贴大概是最最常用的简化(没有之一)。不过好在这一点通常容易纠正,稍大一些公司或是稍有追求的研发人员可以通过一些代码道场、OO训练营以及Code Review就能清除掉60-70%的“硬”重复。事实上真正难以觉察和意识的是那些结构性“隐”重复,比如下面这样:

    public AaNode query(DbService db, Long device, String a){
        return db.createQuery(A_TABLE, AaNode.class)
               .field(a).get();
    }
    
    public BbNode query(DbService db, Long device, String b, 
        String bb, String bbb){
        return db.createQuery(B_TABLE, BbNode.class)
               .field(b).field(bb).field(bbb)
               .get();
    }
    
    public CcNode query(DbService db, Long device, String c, 
        String cc){
        return db.createQuery(C_TABLE, CcNode.class)
               .field(c).field(cc)
               .get();
    }
    

    当把它们叠加在一起的时候,你一定会觉得这些代码确实看上去差不多;可当它们散落在各处时,你可能还会觉得这么写还挺不错的,因为这些方法并不完全一样至少参数有多有少。

    清晰表达是简单设计的要求,不过要把一件事说清楚可不简单,很多人对此的理解仅仅停留在声明式设计上,认为拥有一个易懂的命名就完成了一切,实际上具有清晰的命名只是迈出的第一步,更重要的是要为后面长久的维护留下可以依赖、好懂的线索。例如,VRF RD编码格式是RFC定义的,因此在实现时会完全参照RFC标准,如果仅仅把编码的方法定义为下面的形式(定义当时一定是很清晰的),那么经过一段时间维护人员再看到这段描述相对复杂的代码一定会纳闷当初为何要这样写。

    public long vrfRdEncode(short type, int admin, int sub) {
         // 此处省略复杂的编码实现   
    }
    

    其实给这个方法一些背景的描述就能够帮助维护人员弄清楚代码的由来,这样的注释虽然增加了工作量却产生了对维护更积极的影响。

    /*
    * this method refers to rfcxxxx
    * when type is asn, rd value is ....
    * when type is long asn, rd value is ...
    * when type is ip, rd value is ...
    */
    public long vrfRdEncode(short type, int admin, int sub) {
         // 此处省略复杂的编码实现   
    }
    

    变量、方法、类、包这些都是代码元素,设计越复杂代码元素的规模就会越大,虽说它们的规模不能完全代表设计的优劣,但却会影响我们的主观感受,通常过分大的包、类都会让我们在深入了解之前产生厌烦、恐惧、抓狂的感觉,那种感觉就和小时候遇到课后作业是全文背诵一样。

    背诵全文

    这种糟糕的体验通常出现在遗留代码的维护过程中,那些遗留代码本身就有不少是巨无霸(硕大的类、超长的方法、复杂的依赖),当有新需求时通常你会有几种选择:

    • 继续修改原来的方法
    • 增加新的方法实现
    • 考虑重构,尝试分解

    应该会有不少人选择1和2,这是很常规的想法,不过这样的选择就意味着“同流合污”,自己一边厌恶、吐槽原有代码的冗长复杂一边把自己变成自己厌恶的样子——让它们变得更冗长更复杂。

    现在在来看这四条原则就会发现没有哪一条是随随便便就能达成的,不深入理解并在项目中反复品味恐怕很容易就会遭遇上面各种各样的问题。运用得当便会成为我们判断软件设计、实现方案的有效供给,这是不少开发者在经历过风雨之后得到的宝贵智慧,在我刚从事软件研发时就听过身边的资深架构师讲过这样一句话:如果我们的实现非常复杂那么一定是我们的设计有问题。

    所以简单设计应当是我们在软件设计和实现过程中始终追求的目标,简单设计不是一句含糊的口号也不是虚幻飘渺的神迹,而是清晰有效的行动纲领,能够指导我们探寻到软件设计真正的美。

    相关文章

      网友评论

          本文标题:简单就是美

          本文链接:https://www.haomeiwen.com/subject/xsukcqtx.html