漂亮整洁的代码不只给人清爽温馨的感受,也能有效提升程序员的工做效率,毫无疑问,在这个颜值担当的时代,代码也要看脸了,因此如何写得一手漂亮整洁的代码是程序员们特别须要get的技能。html
代码整洁的大前提git
代码大部分时候是用来维护的,而不是用来实现功能的程序员
这个原则适用于大部分的工程。咱们的代码,一方面是编译好让机器执行,完成功能需求;另外一方面,是写给身边的队友和本身看的,须要长期维护,并且大部分项目都不是朝生夕死的短命鬼。数据库
对清晰好看代码的追求精神,比全部的技巧都要重要。设计模式
优秀的代码大部分是能够自描述的,好于文档和注释微信
当你翻看不少开源代码时,会发现注释甚至比咱们本身写的项目都少,可是却能看的很舒服。当读完源码时,不少功能设计就都清晰明了了。经过仔细斟酌的方法命名、清晰的流程控制,代码自己就能够拿出来看成文档使用,并且它永远不会过时。框架
相反,注释不能让写的烂的代码变的更好。若是别人只能依靠注释读懂你的代码的时候,你必定要反思代码出现了什么问题(固然,这里不是说你们不要写注释了)。函数
说下比较适合写注释的两种场景:工具
设计模式只是手段,代码清晰才是目的测试
以前见过一些所谓“高手”的代码都比较抽象,各类工厂、各类继承。想找到一个实现老是要山路十八弯,一个工程里大部分的类是抽象类或者接口,找不到一两句实现的代码,整个读起代码来很不畅。我跟他聊起来的时候,他的主要立场是:保留合适的扩展点,克服掉全部的硬编码。
其实在我看来,也许他的代码被“过分设计”了。首先必需要认可的是,在同一个公司工做的同事,水平是良莠不齐的。不管你用了如何高大上的设计,若是大多数人都不能理解你的代码或者读起来很费劲的话,其实这是一个失败的设计。
当你的系统内大部分抽象只有一个实现的时候,要好好思考一下,是否是设计有点过分了,清晰永远是第一准则。
代码整洁的常见手段
code review
不少大公司会用git的pull request机制来作code review。咱们重点应该review什么?是代码的格式、业务逻辑仍是代码风格?我想说的是,凡是能经过机器检查出来的事情,无需经过人。好比换行、注释、方法长度、代码重复等。除了基本功能需求的逻辑合理没有bug外,咱们更应该关注代码的设计与风格。好比,一段功能是否是应该属于一个类、是否是有不少类似的功能能够抽取出来复用、代码太过冗长难懂等等。
我我的很是推崇集体code review,由于不少时候,组里相对高级的工程师可以一眼发现代码存在较大设计缺陷,提出改进意见或者重构方式。咱们能够在整个小组内造成一个好的文化传承和风格统一,而且很大程度上培养了你们对clean code的热情。
勤于重构
好的代码,通常都不是一撮而就的。即便一开始设计的代码很是优秀,随着业务的快速迭代,也可能被改的面目全非。
为了不重构带来的负面影响(delay需求或者带来bug),咱们须要作好如下的功课:
静态检查
如今市面上有不少代码静态检查的工具,也是发现bug和风格很差的比较容易的方式。能够与发布系统作集成,强制把主要问题修复掉才能够上线。目前美团点评技术团队内部的研发流程中已经广泛接入了Sonar质量管理平台。
代码整洁的常见技巧
单一职责
这是整洁代码的最重要也是最基本的原则了。简单来说,大到一个module、一个package,小到一个class、一个method乃至一个属性,都应该承载一个明确的职责。要定义的东西,若是不能用一句话描述清楚职责,就把它拆掉。
咱们平时写代码时,最容易犯的错误是:一个方法干了好几件事或者一个类承载了许多功能。
先来聊聊方法的问题。我的很是主张把方法拆细,这是复用的基础。若是方法干了两件事情,颇有可能其中一个功能的其余业务有差异就很差重用了。另外语义也是不明确的。常常看到一个get()方法里面居然修改了数据,这让使用你方法的人情何以堪?若是不点进去看看实现,可能就让程序陷入bug,让测试陷入麻烦。
再来聊聊类的问题。咱们常常会看到“又臭又长”的service/biz层的代码,里面有几十个方法,干什么的都有:既有增删改查,又有业务逻辑的聚合。每次找到一个方法都费劲。不属于一个领域或者一个层次的功能,就不要放到一块儿。
咱们 team 在code review中,最常被批评的问题,就是一个方法应该归属于哪一个类。
优先定义总体框架
我写代码的时候,比较喜欢先去定义总体的框架,就是写不少空实现,来把总体的业务流程穿起来。良好的方法签名,用入参和出参来控制流程。这样可以避免陷入业务细节没法自拔。在脑海中先定义清楚流程的几个阶段,并为每一个阶段找到合适的方法/类归属。
这样作的好处是,阅读你代码的人,不管读到什么深度,均可以清晰地了解每一层的职能,若是不care下一层的实现,彻底能够跳过不看,而且方法的粒度也会恰到好处。
简而言之,我比较推崇写代码的时候“广度优先”而不是“深度优先”,这和我读代码的方式是一致的。固然,这件事情跟我的的思惟习惯有必定的关系,可能对抽象思惟能力要求会更高一些。若是开始写代码的时候这些不够清晰,起码要经过不断地重构,使代码达到这样的成色。
清晰的命名
老生常谈的话题,这里不展开讲了,可是必需要mark一下。有的时候,我思考一个方法命名的时间,比写一段代码的时间还长。缘由仍是那个逻辑:每当你写出一个相似于”temp”、”a”、”b”这样变量的时候,后面每个维护代码的人,都须要用几倍的精力才能理顺。
而且这也是代码自描述最重要的基础。
避免过长参数
若是一个方法的参数长度超过4个,就须要警戒了。一方面,没有人可以记得清楚这些函数的语义;另外一方面,代码的可读性会不好;最后,若是参数很是多,意味着必定有不少参数,在不少场景下,是没有用的,咱们只能构造默认值的方式来传递。
解决这个问题的方法很简单,通常状况下咱们会构造paramObject。用一个struct或者一个class来承载数据,通常这种对象是value object,不可变对象。这样,能极大程度提升代码的可复用性和可读性。在必要的时候,提供合适的build方法,来简化上层代码的开发成本。
避免过长方法和类
一个类或者方法过长的时候,读者老是很崩溃的。简单地把方法、类和职责拆细,每每会有立竿见影的成效。以类为例,拆分的维度有不少,常见的是横向/纵向。
例如,若是一个service,处理的是跟一个库表对象相关的全部逻辑,横向拆分就是根据业务,把创建/更新/修改/通知等逻辑拆到不一样的类里去;而纵向拆分,指的是把数据库操做/MQ操做/Cache操做/对象校验等,拆到不一样的对象里去,让主流程尽可能简单可控,让同一个类,表达尽可能同一个维度的东西。
让相同长度的代码段表示相同粒度的逻辑
这里想表达的是,尽可能多地去抽取private方法,让代码具备自描述的能力。举个简单的例子
public void doSomeThing(Map params1,Map params2){ Do1 do1 = getDo1(params1); Do2 do2 = new Do2(); do2.setA(params2.get("a")); do2.setB(params2.get("b")); do2.setC(params2.get("c")); mergeDO(do1,do2); } private void getDo1(Map params1); private void mergeDo(do1,do2){...};
相似这种代码,在业务代码中随处可见。获取do1是一个方法,merge是一个方法,但获取do2的代码却在主流程里写了。这种代码,流程越长,读起来越累。不少人读代码的逻辑,是“广度优先”的。先读懂主流程,再去看细节。相似这种代码,若是可以把构造do2的代码,提取一个private 方法,就会舒服不少。
以上这些优化管理代码的方法可以有效使咱们的代码看起来更清爽更漂亮,仍是那句话,这毫不仅仅是颜值问题,这更是一个工做效率的问题,不想在冗杂的代码里挣扎就不妨尝试一下上面的方法吧,也许你会发现something amazing.
微信关注公众号:Aspose 知足一切文档需求