|
|
51CTO旗下网站
|
|
移步端
  • 快哭了!我把同事写的编码坑惨了

    写出整洁的编码,是每个程序员的追求。《clean code》指出,要想写出好的编码,第一得明白什么是肮脏代码、什么是一尘不染代码;下一场通过大量之刻意练习,才能真正写出整洁的编码。

    笔者:xybaby 来源:51CTO艺术栈| 2020-03-20 08:00

    写出整洁的编码,是每个程序员的追求。《clean code》指出,要想写出好的编码,第一得明白什么是肮脏代码、什么是一尘不染代码;下一场通过大量之刻意练习,才能真正写出整洁的编码。

    图表来自 Pexels

    WTF/min 是衡量代码质量的专门标准,Uncle Bob 在书中称糟糕的编码为沼泽(wading),这只突出了俺们是糟糕代码的受害者。

    境内有一度更适于的词汇:便山,虽然不是很大方但是更加合理,程序员既是受害者也是加害者。

    对于什么是一尘不染的编码,书中给出了大师们的总结:

  • Bjarne Stroustrup:优雅且高效;干脆;调减依赖;只做好一件事
  • Grady booch:大概直接
  • Dave thomas:可读,可保护,单元测试
  • Ron Jeffries:无需重复、单纯职责,表达力(Expressiveness)
  • 其中,我最喜欢的是表达力(Expressiveness)其一描述,其一词似乎道出了好代码的真谛:用简单直接的措施描绘出代码的效应,不多也不少。

    命名的技术

    坦白的说,命名是一件困难之作业,要想出一个恰到好处的命名需要一个功夫,尤其我们的母语还不是编程语言所通用的英语。

    不过这一切都是值得了,好的命名让你的编码更直观,更有表达力。好的命名应该有下面的性状:

    ①名副其实

    好的总分名告诉你:是什么东西,为什么存在,该怎么使用,如果需要通过注释来诠释变量,这就是说就先得不那么名副其实了。

    下是书中的一个示例代码,展示了命名对代码质量的升级:

          
    1. # bad code 
    2. def getItem(theList): 
    3.    ret = [] 
    4.    for x in theList: 
    5.       if x[0] == 4: 
    6.          ret.append(x) 
    7.    return ret 
    8.  
    9. # good code 
    10. def getFlaggedCell(gameBoard): 
    11.    '''扫雷游戏,flagged: 扭动''' 
    12.    flaggedCells = [] 
    13.    for cell in gameBoard: 
    14.       if cell.IsFlagged(): 
    15.          flaggedCells.append(cell) 
    16.    return flaggedCells 

    ②避免误导

    无需挂羊头卖狗肉,无需覆盖惯用缩略语!

    此地不得不吐槽前两角才看到的一份代码,居然使用了 l 表现变量名;而且,user 居然是一番 list(另一方面复数都没学好!!)

    ③有含义之区别

    代码是写给机器执行,也是送人阅览的,故此概念一定要有区分度:

          
    1. # bad 
    2. def copy(a_list, b_list): 
    3. pass 
    4. # good 
    5. def copy(source, destination): 
    6. pass 

    ④采用读的出来的单词

    如果名称读不出去,这就是说讨论的时节就会像个傻鸟。

    ⑤采用方便搜索的命名

    名字长短应与他作用域大小相对应!

    ⑥避免思维映射

    比如在代码中写一个 temp,这就是说读者就得每次看到这个单词的时节翻译成其真正的含义。

    诠释

    有表达力的编码是无须注释的:

          
    1. The proper use of comments is to compensate for our failure to express ourself in code. 

    诠释的适龄作用在于弥补我们用代码表达意图时遇到的挫折,这听起来让人丧气,但实际确实如此。

    The truth is in the code,诠释只是二手信息,两岸的不同步或者不等价是注释的最大问题。

    书中给出了一番奇异形象的例证来展示,用代码来阐述,而非注释:

          
    1. bad 
    2. // check to see if the employee is eligible for full benefit 
    3. if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) 
    4. good 
    5. if (employee.isEligibleForFullBenefits()) 

    故此,顶想要补注释的时节,可以考虑是否可以通过修改命名,或者修改函数(代码)的泛层级来展示代码的企图。

    当然,也未能因噎废食,书中指出了以下一些状态属于好的诠释:

  • 财务信息
  • 对意图的诠释,为什么要这么做
  • 警告
  • TODO 诠释
  • 推广看似不合理之物的重大
  • 其中个人最赞同的是第 2 点和程序 5 点,做什么很容易通过命名表达,但为什么要这么做则并不直观,特别涉及到标准知识、书法的时节。

    此外,局部第一感觉“不那么优雅”的编码,也许有他独特愿意,这就是说这样的编码就应当加上注释,表明为什么要这样,比如为了提升关键路径的性质,可能会牺牲局部代码的读报。

    最坏的诠释就是过时或者错误的诠释,这对于代码的跟随者(也许就是几个月后的和谐)是伟大的伤害,心疼除了 code review,并没有简单的主意来保证代码与注释的同步。

    函数

    ①函数的纯粹职责

    一度函数应该只做一件事,这件事应该能通过函数名就能清楚的展示。认清方法很简单:探望函数是否还能再拆出一番函数。

    函数要么做什么 do_sth,要么查询什么 query_sth。最恶心的就是函数名表示只会 query_sth,但事实上却会 do_sth,这使得函数产生了负效应。

    比如书中的例子:

          
    1. public class UserValidator { 
    2. private Cryptographer cryptographer; 
    3. public boolean checkPassword(String userName, String password) {  
    4.         User user = UserGateway.findByName(userName); 
    5. if (user != User.NULL) { 
    6. String codedPhrase = user.getPhraseEncodedByPassword();  
    7. String phrase = cryptographer.decrypt(codedPhrase, password);  
    8. if ("Valid Password".equals(phrase)) { 
    9.                 Session.initialize(); 
    10. return true;  
    11.             } 
    12.         } 
    13. return false;  
    14.     } 

    ②函数的泛层级

    每个函数一个抽象层次,函数中的语句都要在同一个抽象层级,不同之泛层级不能放在一起。

    比如我们想把大象放进冰箱,有道是是其一样子的:

          
    1. def pushElephantIntoRefrige(): 
    2.     openRefrige() 
    3.     pushElephant() 
    4.     closeRefrige() 

    函数里面的三句代码在同一个层级(高度)叙述了要形成把大象放进冰箱这件事顺序相关的三个步骤。

    众目睽睽,pushElephant 其一步骤又可能包含很多子步骤,但是在 pushElephantIntoRefrige 其一层级,是无须知道太多细节的。

    顶我们想通过阅读代码的措施来了解一下新的项目时,普通都是利用广度优先的方针,自上而下的读书代码,先了解整体布局,下一场再深入感兴趣的细节。

    如果没有对实现细节进行良好的泛(并凝练出一番名副其实的函数),这就是说阅读者就不难迷失在细节的汪洋里。

    那种程度看来,其一跟金字塔原理也很像:

    每一个层级都是为了论证其上一层级的意见,同时也要求从一层级的支持;同一层级之间的多个论点又要求以某种逻辑关系排序。

    pushElephantIntoRefrige 就是基本论点,要求多个子步骤的支持,同时这些子步骤之间也有逻辑先后顺序。

    ③函数参数

    函数的底数越多,重组出的涌入情况就愈多,要求的统考用例也就越多,也就越容易出题目。

    进出口参数相比返回值难以理解,这点深有同感,进出口参数实在是很不直观。副函数调用者的力度,一眼就能收看返回值,而很难识别输出参数。进出口参数通常逼迫调用者去检查函数签名,其一实在不谐和。

    向函数传入Boolean(书中称之为 Flag Argument)普通不是好主意。尤其是传播True or False此后的所作所为并不是一件事情的彼此,而是两件不同之作业时。

    这很显然违背了函数的纯粹职责约束,消灭办法很简单,那就是用两个函数。Dont repear yourself。

    在函数这个层级,是最容易、最直观实现复用的,很多 IDE 也举步维艰帮助我们讲一段代码重构出一番函数。

    不过在实践中,也会出现这样一种情景:一段代码在多个办法中都有采用,但是又不完整一样,如果抽象成一个通用函数,这就是说就要求加参数、加 if else 分别。这样就有点尴尬,貌似可以重塑,但又不是很完美。

    造成上述问题的那种情况是因为,这段代码也违反了单一职责原则,做了不只一件事情,这才导致不好复用,消灭办法是进行方法的撤并,才能更好复用。

    也得以考虑 template method 来处理差异的一部分。

    高考

    异常惭愧的是,在我经历的品种中,高考(尤其是单元测试)一直都没有得到足够的青睐,也没有试行过 TDD。正因为缺失,才更感良好测试的宝贵。

    咱们常说,好的编码需要有可读性、可保护性、可扩展性,好的编码、架构需要不停的重塑、迭代,但无测试是保证这一切的根基,没有高回报率的、电气化的大片测试、回国测试,哪个都不敢去修改代码,只能任其腐烂。

    即使针对核心模块写了单元测试,普通也很随意,认为这只是测试代码,配不上生产代码的位置,认为只要能跑通就行了。

    这就导致测试代码的读报、可保护性非常差,下一场导致测试代码很难跟随生产代码一起更新、演变,说到底导致测试代码失效。故此说,脏测试等同于没测试。

    故此,高考代码的三要素:

  • 读报
  • 读报
  • 读报
  • 对于测试的规则、轨道如下:

  • 没有测试之前不要写任何功能代码
  • 只编写恰好能够体现一个失败情况之统考代码
  • 只编写恰好能通过测试的效应代码
  • 高考的 FIRST 轨道:

  • 很快(Fast)高考应该够快,尽量自动化。
  • 独立(Independent)高考应该应该独立。无需相互依赖
  • 可反复(Repeatable)高考应该在其他环境上都能重申通过。
  • 本人验证(Self-Validating)高考应该有 bool 进出口。不要通过查看日志这种低效率方式来判断测试是否通过。
  • 适时(Timely)高考应该及时编写,在伊对应的生产代码之前编写。
  • 【编纂推荐】

    1. iOS新代码显示苹果可能推出iPhone 9 Plus
    2. 程序员经典面试题,为什么必发娱乐登录索引多用B+树
    3. 前者开发效率提高的代码规范篇
    4. 一文搞定泛型,增长代码复用率及程序的运作性能
    5. Uber 开源 Piranha,可自动删除过时代码
    【义务编辑: 武晓燕 TEL:(010)68476606】

    点赞 0
  • 代码  程序员  追求
  • 分享:
    大家都在看
    猜你喜欢
  • 24H热文
    一周话题
    每月获赞
  • 副技术转型做管理,我总结了那些套路!假如计算机是中华人口发明的,那代码是不是该这样快哭了!我把同事写的编码坑惨了硬件开发者升职加薪的8项技术重新定义Wi-Fi效益,Wi-Fi 6为什么要分两步?刺探微服务失败的这11个原因,预防和及时止损!研究院全面总结 2019 年世界必发娱乐手机版发展:八大关键技术崛起,AI 渗透到更多领域云“战疫”:8远处扩容100万核,咱们是这样监控的
  • 20年军龄技术大牛的心地感言,字字珠玑!TIOBE 3月编程语言排行榜:Java大涨,Delphi亮亮的不再!百度工程师非法控制公司服务器“挖矿”:4个月赚10万,判坐牢3年副技术转型做管理,我总结了那些套路!运维,请收好网络工具中的瑞士军刀,今后故障诊断不用愁!干了10年软件工程师,我学到10个教训降薪、下岗、减员……互联网员工挣扎求生众生相副CNCF寒暑报告看云原生领域15个最值得关注的取向
  • 一度运维的生活感:微盟36小时事件,咱们该反思什么?区块链:最新冠状肺炎,对不起,我来晚了程序员必备学习编程软件,观看看你用过几个?该署MySQL图片化管理工具你都在用吗?一度艺术总监的忠告:贯通那么多艺术为何还是做不好一个项目?钉钉在线“求饶”,大声喊爸爸!2020 IT工钱大调查:公款较高的职务是什么?副技术转型做管理,我总结了那些套路!
  • 订阅专栏+更多

    秒杀高并发白话实战

    秒杀高并发白话实战

    主流高并发架构
    共15章 | 51CTO崔皓

    50人口订阅学习

    网络排障一点通

    网络排障一点通

    网络排障及优化调整案例
    共20章 | 捷哥CCIE

    403人口订阅学习

    VMware NSX 入夜到实战

    VMware NSX 入夜到实战

    网络虚拟化革命性技术
    共16章 | Cloud袁

    224人口订阅学习

    订阅51CTO邮刊

    点击这里查看样刊

    订阅51CTO邮刊

    51CTO劳务号

    51CTO官微

  • <p id="7f9e8304"></p>
    
       
       
       
       
  • <dd id="9deef150"></dd>


  •