聊聊代码规约

代码规约

——车同轨、书同文。

引用:《码出高效:Java开发手册》(杨冠宝 高海慧 著)第九章 代码规约

代码规约的意义

提出背景

    别人都说程序员是搬砖的码农,但我们知道自己是追求个性的艺术家。也许我们不会过多在意自己的外表和穿着,但在不羁的外表下,骨子里追求着代码的美、系统的美、设计的美,代码规约其实就是对程序美的一个定义。但是这种美离程序员的生活有些遥远,尽管代码规约的价值在业内有着广泛的共识,然而在现实中执行得并不是很好。程序员曾经最引以为豪的代码,因为代码规约的缺失严重制约了相互之间的高效协同,频繁的系统重构和心惊胆战的维护似乎成了工作的主旋律,如何走出这种怪圈呢?众所周知,互联网公司的效能是企业的核心竞争力,体现在开发领域上,其实就是沟通效率和研发效率。

沟通效率的重要性可以从程序员三大编程理念之争说起:

  • 缩进采用空格键,还是Tab键
  • if单语句需要大括号,还是不需要大括号。
  • 左大括号不换行,还是单独另起一行。

    其中,if单语句是否需要大括号是争论不休的话题。相对来说,写过格式缩进类编程语言(比如Python)的开发工程师,更加习惯于不加大括号。因为单语句的写法,继续添加其他语句时,容易引起视觉上的错误判断导致程序逻辑问题,所以我们提倡ifforwhile单语句必须加大括号。

    此外,不加大括号还可能会导致作用域问题

public class IfSingleStatementTest {

    public static void main(string[] args) {
        // 以下三句均编体报错: declaration not allowed here
        if(true) int x;

        for(; ; ) int y;

        while (true) int 21
    }
}

    有的程序员想当然地认为编译会通过,最多出现警告提示: variable is never used。实际上,编译报错为declaration not allowed here单语句在没有加大括号的情况下,声明的变量不可能再被使用,编译器认为没有任何意义,参考官方说明,Every declaration that introduces a name has a scope, in which they can be used

    这些理念之争的本质就是程序员多年代码习惯出了茧,不愿意对不一样的代码风格妥协。很多代码风格客观上没有对与错,但是一致性、可读性很重要,团队沟通效率很重要。帕金森琐碎定律是指团队成员往往会把过多的精力花费在一些项碎的争论上,而真正重要的决议反而可以轻松通过。在代码风格上,团队不需要进行过多的讨论、争论,而应该把更多的精力放在重要问题的沟通、协调上。个性化应尽量表现在系统架构、算法效率的提升上,而不是独特的代码风格上。

    原始社会的部落冲突讲究个人蛮力,现代化战争则需要海陆空多兵种联合作战,软件工程亦是如此。从软件小作坊发展到现在,凭一己之力编写大型软件系统已经成为过去。跨团队的联合开发越来越常见,需要定的规范来保障沟通的有效性。如果规范不一,就如鸡同鸭讲,言语不通,一脸懵逼。

    代码规约除代码风格之外,还应该包括异常日志规约数据库规约安全规约单元测试规约等相关领域,旨在提升开发工程师之间的沟通效率。就像大雁,它们飞期的队形可以有效地减少空气阻力,非常讲究团队配合,折射出团队沟通、协作的理念,顺利达到共同的目标。

避免对代码规约错误的认识
代码规约消灭创造力

    程序员对代码的创造力、业务理解、建模能力、架构设计等都有关系。有人认为,代码规约是把程序员变成流水线上的工人,消灭创造力。非要类比的话,代码规约只是墙上的安全生产规范,并非定义工作内容本身(这才是程序员真正发挥创造力的地方),代码规约让代码生产更加有序、更加高效。

代码本人理解就行

    代码是写给三个群体看的:编译器、编写者、维护者。编译器需要代码符合语法;编写者需要代码符合自己的编程风格;维护者需要代码可读性强。在软件生命周期内,编译器的时间单位是,编写者的时间单位是,维护者的时间单位是。编写者有可能成为维护者。此外,一个人对于团队的价值,取决于他的稀缺性。有些程序员认为自己写的代码只有自己能够看懂,比如ifelse嵌套5层,再来一个for循环,才能显示出个人的不可替代性。实际上,写代码的时候,应该多从团队利益、公司战略的角度考虑,道从统一的代码规约利人利己,在维护自己代码的时候,也会更加从容。

一成不变的代码不需要规范

    代码部署到服务器上稳定运行后,即使没有任何功能的增加或删除,也不是永远不需要修改的。代码具有时间维度机器维度框架维度等相关属性。时间维度,比如千年虫问题或2038问题等;机器维度,比如机器过保或机器换代等;框架维度,比如JDK升级或框架安全风险等。举个例子,JDK6升级到JDK7必须要及时修改代码,使Comparntor满足JDK7的新要求,否则Arrays.sort会抛异常。诚如哲学家所述人不能两次踏进同一条河流,代码的每一次部署, 也是不可能完全相同的。所以没有一成不变的代码。

代码规约必须符合所有人的习惯

    如果双鞋适合所有人的脚, 那绝对是一双废鞋。代码规约并不是寻找最优解,而是寻找认知中的最大公约数。如果一个餐馆日料、法餐、湘菜、杭帮菜都做的话,必然不是一个好餐馆。 舍得就是舍去小部分的意志,得到大格局上的成功。在制订代码规约的过程中,一些规则的约定有着自身的合理性。比如返回集合时,是否允许returm null值的问题,可归结为防御式编程理念与契约式编程理念不同的处理方式。积累多次教训后,我们提俱防御式编程理念,明确允许返回为null值。在共识的规约面前,我们应该放下成见,牺牲小我,成就大我。

代码规约的意义
  • 码出高效:标准统一,提升沟通效率和协作效率, 促使研发效能的提升;
  • 码出质量:防患未然,提升质量意识,降低故障率、维护成本,快速定位问题;
  • 码出情怀:追求卓越的工匠精神,打磨精品代码。

如何推动落地

    任何出发点多么美好的规章制度,如果没有被落地执行到位,也终将是一纸空文。如何落地?上令下达, 往往是很多标准类文件的痛点。在制订团队代码规约的时候,往往是一帆风顺的, 但是真正到实际执行层面的时候,规约落地的过程总会遇到各种推三阻四的情况。我们可以尝试从三个方面推动落地:

立法透明

    在规约制订的过程中,保持全程透明、公开,充分讨论,反复审稿,谨慎定稿。需要明确回答规约为什么这样制订,违反了会有什么后果。不论团队成员是否理解,是否赞同,要让所有人觉得规约的制订是一个共同参与、共同讨论的过程,规约是共同遵守的约定。但某些规则或左或右时,仅仅需要的是一个拍板。由于技术是不断向前发展的,没有一套代码规约可以流行数年而不更新,我们需要保持规约内容的与时俱进。

执法坚定

    对于规约的遵守符合典型的破窗理论,如果团队中某个成员完全不遵守共同的代码规约,久而久之,出于人性的弱点,其他成员必然一个接一 个地开始违反规约, 最后规约就是形同虚设。

判断是否违反规约

    首先由程序自动分析保证,能够降低规约的遵守成本。保障规约轻量化落地的技术包括自动化扫描、数据分析等配套工具,自动化扫描最好提供全量和增量的配置,尤其是后者可以减少因为历史代码而增加的规约遵守成本。规约扫描的相关数据分析是指形成数据报表,按时间、团队、应用各个维度进行聚合,立体地分析违反现约的成员和代码,有助于长效地提升规约的生命力。如阿里巴巴提供的静态代码扫描工具P3C扫描插件,甚至提供部分自动纠销功能,可以有效地提升开发效事。
    其次,在自动化分析的基础上,增加入工CodeReriew来保证规约的落地,进步判断无法通过自动扫描的规则是否被遵守。比如:即使是多个字段组合,只要业务特性唯一,就必须建成唯一索引,这样的规则很难通过自动化分析进行判断,需要Reiewer根据业务逻辑进行人工审查。

如何进行奖惩

    数据分析的结果可以作为考核机制的参考指标,督促团队成员更好地遵守代码规约。此外,对于优秀代码,可以通过代码秀或者代码墙分享出来,引导其他成员学习和主动遵守代码规范。

组织支持

    公司是否需要代码规约来提升整体开发效率,维护长效的开发秩序,它是个管理决定,决定之后的执行需要某个部门进行专项推进。通常来说,推进规约落地是一件成就感并不是特别强的脏活累活,并且经常会面对各种低触行为,这时就同要组织给予充分的支持。

组织支持包括三个方面:

  • 给子负责人相应的考核权限;
  • 需要进行各种广泛而有力的宣传和引导;
  • 建立良性、有序、分享的长效代码文化。

    推进的节奏同要循序渐进,过于生硬的一刀切很可能触发团队的抵触情绪,甚至有些程序员会不惜辞职来捍卫自己的编程习惯。

规约参考

    建议中小企业参考《阿里巴巴Java开发手册》,该手册主要包含开发紧密相关的知识点、编码相关的生态知识。

    约束等级:

  • 强制:是一种命令型的约束,表达的是协作痛点或故障隐惠。
  • 推荐:是一种语气比较强的提倡, 即使不这样做也不会产生产重的问题,但如果团队一致道守会使代码结构更清晰, 团队协作更高效。
  • 参考
    • 无法用规则量化的要求,比如避免出现重复的代码,即Don' t Repeat Youself
    • 向左向右均可以,仅提出种期望, 自由度由开发工程师自己把握,比如在服务层的方法命名中,获取单个对象的方法用get作为前级等。

    扩展信息能够使读者非常舒心地完成阅读,掩卷退思,亦有所得。知其然,知其不然, 深度地理解规则背后的思想。
    扩展信息:

  • 说明:对内容做了引申和解释,为求知其然;
  • 正例:展示什么样的编码、配置、实现方式是被倡导的;
  • 反例:标识需要提防的雷区,以及真实的错误案例,让人知其不然。

聊聊成长

    成长并没有直线式的捷径,不走弯路就是捷径。弯路是成长的必经之路,我们在成长的路上需要注意的是保证弯路的前进大方向与直线的行进方向基本致。南猿北辙消耗的是时间成本、 精力成本、机会成本,尤其机会成本往往是可遇不可求的。弯路上的泥泞、徘很、痛苦等都是成长的养分,味地想速成某种能力,反而适得其反。夯实基础,方能建万丈高楼。浮沙筑高台,那只是极少数天才的专利而已。

敢于实战

    代码能力的提升就是不断磨炼、不断尝试、不断纠错的成长过程。编程实战能力是开发工程师的核心能力,现在越来越多的企业会进行在线编程能力测试。优秀的代码能力应该体现在运行效率和架构设计上。运行效率取决于对语言的合理运用和算法设计的合理性上。

勇于展示

    学习和体会计算机技术,也要敢于到班门去弄斧。提倡把自己丑陋的代码在比自己更优秀的人面前晒出来。含蓄的结果就是以为自己是宇宙中心,别人写的代码都不如我,自己的风格总是正道。

深入反思

    孔子曰:学而不思则罔,思而不学则殆。如果只是把书架上的书的数量来街量自己的技术功底,那真错了,真正的书架应在心中,反复地学习、实践,再夯实理论。如果缺乏思考,就会因为不能深刻理解书本的意义而不能有效地在实际中运用好这些知识,甚至陷入更深的迷茫中。我们只有把学习和思考结合起来,才能把知识转为己用。

做一个有技术情怀的人。

  • 热爱是一 种源动力,卓越是一 种境界。兴趣是最好的老师,也是最好的动力。而热爱是一种信念,即使痛苦,也不会让你背离这份事业和内心的执着。对技术的热爱,让人勇于追根究底,勇于坐冷板凳,勇于回馈别人。
  • 技术情怀提倡我们追求极致式的卓越,把卓越再往前提升。不管一个人如何卓越与优秀,都要学会自我驱动,持续进步,追求个人内心的极致。因为卓越,所以经典,只有这样百尺单头,才能更进一步。仰望星空的同时,是脚助实地,这样才能不断地学习和打磨自己。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值