“什么狗屁代码,老子看了几个小时也没明白!”
“这么烂的代码,到底是谁写的!”
Bob大叔说:“衡量代码质量的唯一标准是阅读该代码时说脏话的次数”, 真是很有趣的说法。
什么是好的代码? 这个问题可能是仁者见仁,智者见智。 我先说说我的看法,欢迎大家留言讨论。
我个人觉得好代码分为两个层面, 一个是道,一个术。
1好代码之“道”
“道”这里指的设计,是对问题本质的洞察,是良好的抽象。
对一个好的系统设计来说,我觉得有这么一个重要的特点: 系统由几个基本的概念组成,这几个概念体现了系统的本质,形成了系统的骨架,他们非常地稳定,生命周期很长。
系统的其他代码围绕着这几个基本概念生长,变化,扩展,不断地演进。
举个例子, Linus 把Git的数据结构设计得非常精良,据说在之后十年的开发中,feature 扩展了无数,基础数据结构却很少变动。
我相信Linus在开发第一版Git的时候,肯定对它要解决的问题--分布式源码配置管理--有着深刻的洞察,实际上Linux内核的开发就是一个典型的、分布式的架构和流程, Linus要做的就是创建一个匹配这个流程的工具,基于对问题的深刻理解,他设计出了Git的系统骨架。
正所谓“简约而不简单”。
但是“道”这个东西太虚无缥缈了,有没有一些可以真正指导我们做设计的准则?
在面向对象编程的领域,这个道就是面向对象的设计原则,Robert Mafrtin在《敏捷软件开发 原则、模式与实践》中总结了SOLID原则。
Single responsibility principle : 单一职责原则
Open/closed principle :开闭原则
Liskov substitution principle :Liskov替换原则
Interface segregation principle :接口隔离原则
Dependency inversion principle : 依赖反转原则
如果我们设计出的类能满足这些原则,就不会有僵化、脆弱、重复、晦涩等种种可以导致代码腐化的问题。代码就容易扩展,生命力就会长久。
但是这些核心的、优美的设计很有可能在进度的压力下出问题:做个简单粗暴的修改,就能省好几天功夫,不用晚上加班了, 很少人能经受这样的巨大诱惑。 所以要坚决守住这些核心的设计,防止腐化。
如果你做的是基础组件的开发,为别人提供服务和API,那必须在设计层面狠下功夫才行,因为API的每次变化都会极大地影响上层应用。
很多人使用Spring做业务软件开发,使用的无非就是Controller, Service, DAO这样已经划分好的结构,增删改查就搞定了,似乎感受不到设计带来的力量。 但我相信,系统中或多或少隐藏着几个核心的数据结构,你只是没有注意到而已。
如果业务很复杂,不要让他们分散在系统的各个地方,要对他们做抽象,形成一套可以独立的,不依赖框架的,生命力长久的业务模型。
2术:写代码的十八般武器
术就是编写代码时的具体技巧和最佳实践。
这些技巧和实践在很多书中都有描述,比如《Effective Java》中提到的很多:
使可变性最小化
接口优于抽象类
优先考虑泛型
通过接口引用对象
遵守普遍接受的命名惯例
......
再比如《编写可读代码的艺术》和《代码简洁之道中》总结的技巧:
避免if嵌套的层次过深,形成“金字塔”代码
局部变量申明尽可能靠近使用的地方
如有可能,尽可能用常量
减少控制流变量
拆分超长表达式
函数应该短小,只做一件事情
把过多的参数封装成类
......
把这些“术”应用到编程当中,会让代码更加的专业。
很明显,这些技巧和实践比较容易学习,程序员学会了一门语言以后,应该去掌握它们,让自己的代码变得简洁可读。
相对于“术”,“悟道”就难得多,洞察问题本质,做出良好抽象,遵循设计原则,这都是内功,都需要不断修炼。
但是这些“道”直接决定了系统的未来方向,设计得不好,再多的“术”也于事无补。
相关阅读:
(完)
你看到的只是冰山一角, 更多精彩文章,请移步《2016文章精华》或者《2017文章精华》
码农翻身
用故事讲述技术