24

如何提高代码质量

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ%3D%3D&%3Bmid=2650410563&%3Bidx=1&%3Bsn=3e15490f0655c74846d117727456c7be
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

MVb2ai6.gif!mobile

说起代码质量,脑子里会冒出很多词,命名规范、格式规范、日志规范、单元测试覆盖率.. .

但我觉得,代码质量总结起来就两个: 好看和好用。

好看是指代码可读性好,容易理解、容易维护,别人接手了不骂你; 好用则指代码健壮,不容易出错,机器跑着不骂你。 即使出错,也容易定位,容易止损和恢复。

为何需要提高代码质量?

以下是我认为的几点:

  • 提升代码的可维护性,降低新人接手的成本

  • 进交流,促进知识共享,做好backup

  • 促进风格一致,降低团队间应用流转的难度

  • 建设写好代码、做好设计的团队氛围

但有一点需要说明,我认为写代码本身是一个创造过程,能让人享受其中,如果有太多的条条框框约束,写代码就失去了创造的乐趣,所以,这里为代码质量建设立一个原则:

  • 只提供建议,不强制遵循

  • 鼓励创造性的编码

  • 鼓励艺术性的编码

如何才能拥有高质量的代码

有两种途径:

  • 第一种途径:先有好的设计--->然后用优秀的编码去实现--->再把优秀的编码风格延续下去

  • 第二种途径:从糟糕的代码开始--->不断去重构,向优秀的设计方案和代码风格不断逼近--->再延续下去

代码质量建设怎么开始呢?

首先得知道什么是好的代码, 这就要有标准,那就是我们常常看到的各种各样的规范,但我觉得要有几个简单的原则,太多了,记不住,有几条原则简单的原则,可以时不时拿来判断,当前做得对不对。

然后就是去实践规范,这里需要一些技巧、一些工具,来帮助我们更好地遵循规范。

接着是度量, 看我们对规范实践的效果,这就是我们常说也常做的Code Review,但Code Review也需要遵循一定的规范,应用一定的技巧。

度量之后是改进, CR结果要及时跟进,这是最重要一环,否则CR就没有实际意义。

总结不可少,复盘是一种很有用的工具,CR也需要复盘,总结CR流程、过程等方面好的和不好的地方,更新规范和checklist。

接下来我们分别聊一聊各个步骤。

  ▐   规范: 先知道什么是好代码

从上边高质量代码的诞生途径我们可以看出,设计也是很重要的一环,所以我们的规范包括设计规范和编码规范,结合我们的生产实际,这里加上安全生产的规范,所以规范有3部分:设计、编码、安全生产。

设计: 先有优秀的方案

设计推荐多用图表达,图比文字有更直观的传达能力:

首先是业务流程图, 它能快速构建起我们对业务的认知,带着对业务的理解再来看代码,事半功倍。

然后是用例图, 清晰地表达出我们系统的职责、边界、服务对象,结合业务流程图,能快速构建起我们对系统职责的认知。

接着是架构图, 从我们日常的设计需求来看,架构图是需要的。好的架构图能快速给人搭建起理解的框架,再来看系统的细节部分,就很好理解。架构图推荐  C4  规范,它是我目前接触的表达最清晰的架构图规范。

接着再用时序图、状态图、ER图 等把关键和复杂部分的设计表达出来。

但日常我们的需求有大有小,方案也不需要都遵循统一的范本,为了设计而设计,就徒增加工作量了。以按需为第一原则,能把要做啥,怎么做的表达清楚即可。这里按场景推荐各个图的使用场景:

新建应用/对原有应用进行重大修改/复杂项目

  • 业务流程图(交代业务背景)

  • C4的系统上下文、容器、组件这3张图

  • 用例图:有多个外部参与者

  • 类图:关键模型超过5个

  • 状态图:对象状态超过3个

  • 时序图:关键流程或复杂链路的参与对象超过3个

  • ER图:涉及数据库变更(包含数据表结构文档)

一般项目/重大日常

  • 业务流程图

  • 时序图(复杂功能、关键流程)

日常

  • 按需

编码: 优秀的方案需要优秀的编码

编码最重要的是可读,控制复杂度,做到自解释,能让人像读自然语言一样读自己的代码,这是最高境界,也是神仙境界。然后是可维护性和可变更性,能快速、安全地修改代码是目标。最后是对优雅实现的要求,卓越的代码会让人拍着大腿叫好,这个不稀奇,我们乱糟糟的代码里也偶尔会有闪光的片段。

编码最高原则:

可读性

  • 控制复杂度

  • self-document

可维护性

优雅

✎ 分层规范

合理的代码分层,能控制各层的复杂度,以分层的思路去设计,也能提高代码的复用性。对于分层,我认为熟悉的就是好的,能满足工作中的大部分情况就好,这里不谈六边形架构、清晰架构、DODAF等概念,自己驾驭不了,还不能拿出来吹。我推荐DDD最基础的4层分层架构,如下:

用户界面/接口层

应用层

领域层

基础设施层

这里举个我实际项目中用到的例子:

-- bootstrap
-- BeanConfig
-- application
-- pv
-- ChannelPvApplicationService
-- sns
-- domain
-- abtest
-- AbtestService
-- address
-- coupon
-- entity
-- Coupon
-- CouponStatus
-- CategoryCouponTemplate
-- category
-- user
-- UserRepository
-- service
-- OneIdService
-- UserService
-- item
-- ItemRepostory
-- live
-- LiveStatus
-- infrastructure
-- concurrent
-- ThreadPoolExecutorFactory
-- MonitorableCallerRunsPolicy
-- dal
-- IGraphDal
-- TuringDal
-- DefaultUserRepository
-- dao
-- MybatisItemDao
-- util
-- DateUtil
-- MoneyUtil
-- UriUtil
-- monitor
-- Event
-- Timing
-- TimingAspect
-- TimingEvent
-- Monitors
-- view
-- atomicwidget
-- BannerWidget
-- CrazySubsidyWidget
-- FeedItemsWidget
-- NavigateBarWidget
-- LiveWidget
-- page
-- HomeScreenPage
-- CategoryFeedsPage
-- SearchCardPage
-- widget
-- Widget
-- DispatchableWidget
-- Debuggable
-- AbstractWidget
-- AbstractDispatchableWidget
-- WidgetDispatcher
-- WidgetResult
-- WidgetContextIncompatibleException

上述项目结构中,因为是导购项目,view相当于用户界面层,application是应用层,domain是领域层,infrastructure是基础设施层。

再对包的划分说明一下:

  • 领域对象、值对象、DTO、Service等定义都放在子域的包下,不要有大而全的entity、service、impl等包(这里的子域是一个内聚的逻辑概念,对应的是领域设计里的子域,如上例中的item在我们的导购里就是商品这个子域)

  • 常量定义尽量跟着相关的类走,作为类的静态字段,不要有大而全的Constant类(Switch相关的除外,但也要按职责尽量拆分开关类)

✎  代码规范

代码规范就推荐阿里经济体开发规约,很全面,也是阿里同学的基本要求。代码规范就推荐「阿里经济体开发规约」,很全面,也是阿里同学的基本要求,开源版本: 阿里巴巴java 开发手册 https://github.com/alibaba/p3c

结合自己的经验,重点说几点:


命名

  • 命名不用泛称(反例:processData)

  • 尽量用完整的单词描述清楚作用和意图,不要怕字多

  • 对象后 领域对象不带后 DTO: RPC接口提供的对象以作为 VO: 跟前端交互的对象 PO: 跟数据库直接交互的对象

日志

  • 所有后台都要有操作日志、数据变更日志

  • 日志要配置异步写盘

  • 线上仅保留WARN和ERROR级别日志

  • 所有日志都要有traceId

  • 异常日志要有堆栈、入参、能说清楚是什么错误的信息(可以出统一组件)

  • 打印日志时,禁止直接用JSON工具将对象转换成String

异常

  • 怎么抛:尽量使用非受检异常,提高代码可读性

  • 怎么处理: 统一异常用切面处理,或依赖SpringMvc的ControllerAdvice统一处理

  • 异常catch范围尽量小,分清稳定代码和非稳定代码

  • 禁止直接吞掉异常

  • 时刻警惕NPE,多用Optional处理

注释

  • 注释只为了说明为什么这么做,不用来说明是在做什么

面向对象

  • 遵循原则:SRP/OCP/LSP/ISP/DIP

  • 尽量只暴露行为,不暴露数据

  • 慎用继承,优先使用组合方式

其它规范

  • 方法行数保持在一屏之内(30行以内)

  • 代码提交 commit message一定要讲清楚做了啥 控制每次提交的代码量(一个功能一提交)

  • 参数 尽量用不可变对象(不对入参做修改,保持明确的入参和出参) 尽量不用隐式入参(ThreadLocal)

  • 数据结构 无随机读取时,用LinkedList替代ArrayList

  • 风格 做好分层,同层用统一的风格(设计/编码)

安全生产

安全生产还没有系统总结过,结合自己做稳定性的工作经验提几点,后边跟负责安全生产的同学多学习学习,再来更新:

防资损

  • 要有资损评估/监控

易恢复

  • 任何新功能上线都要有灰度能力

监控/报警

  • 兜底设计/监控

  • 性能监控

  • 异常监控

  • 低容忍错误要报警

  • 键指标要监控(业务/技术)

  • 减少不必要的报警

降级/限流

  • 识别出弱依赖,保证弱依赖可降级

  • 识别出可限流的依赖方,做好监控和限流配置

  ▐   实践: 如何去实践规范

给一些原则和技巧建议,帮忙落地规范。

设计

  • 图都不是必须的,只要能讲明白是怎么做的,为什么这么做

编码

  • 使用Aone-Idea,它已经集成了PMD/FindBugs/CheckStyle功能,给开发的同学点个暂,超牛逼。开源版本: Alibaba Java Coding Guidelines alibaba   https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines

  • 使用lombok,保持代码的简洁性

  • 不断重构,且遵循以下原则: DRY/YAGNI/Rule Of Three/KISS/POLA 每次需求都是重构契机 反问自己,能不能在[可读性/易维护性]做得更好

  • 使代码读起来像自然语言

  • 功能性代码和非功能性代码分离

安全生产

这得跟着公司和部门规范来,学习学习再来补充。

  ▐   度量: 如何去验证实践效果-CodeReview

Review时机

  • 项目提测后第一时间: 不要在项目上线的前夜review,来不及改,review结果容易搁置,浪费参与人的青春

Review方式

  • 小模块: 随时/Aone代码评审/@backup同学

  • 项目代码: 面对面投屏/Aone代码评审 + IDE show/项目组+重点关注同学

Review内容

  • 关注代码的设计是如何落地需求的

  • 总体流程

  • 关键设计

  • 重点功能

Review前提

  • 代码是编译通过的

  • 开启Aone-Idea的实时检测

Checklist

  • 规范性

    可读性

    可维护性(高内聚低耦合、面向对象原则、实现复杂性等)

    可变更性(扩展性等)

  • 全性/健壮性 输入检查 异常处理 边界检查

  • 性能 依赖合理性

   改进: 跟踪CodeReview结果的执行

  • 有运行时风险的问题必须上线前完成改动

  • 其它问题尽量上线前完成修改,如未修改则要加todo,指定人和时间来修改

  • 工具来统计和提示CR结果改进情况

总结优化

  • 定期回顾和总结(周会环节)

  • 更新checklist和代码规范

  • 发现好的代码和设计,定期展示,给与奖励

后话

以上是摘取的各家之言,加上自己的一些思考。学习是个渐进过程,代码质量的学习我还在进行中,如果有收获,会来更新。如果被人diss,我还觉得有理,我也会更新进来。

写的这些也是我自己的学习和实践方向,所以,如果发现我的代码没做到这些,吐槽我,然后给我建议,让我做得更好。

淘系技术部- 全域营销团队

招聘后端技术、数据技术,P6-P8。我们是阿里最重要的营销场之一,深入最核心的电商业务,接受最大的挑战,获得你期待的成长。了解详情,点击下方 “阅读原文”

简历投递,邮箱:postbox:: [email protected]

文献参考:

有很多书都在告诉我们怎样写好代码,这里推荐一些我读过且有收获的:

  • 《编写可读代码的艺术》

  • 重构》

  • 重构与模式》

  • 《代码精进之路》

  • Google Engineering Practices Documentation https://github.com/google/eng-practices?spm=ata.13261165.0.0.707e40eaLLQkp6 

  • 用于软件架构的 C4 模型 https://www.infoq.cn/article/C4-architecture-model?spm=ata.13261165.0.0.707e40eaLLQkp6 

✿  拓展阅读

QjUnIvU.png!mobile6jaUnyb.png!mobile

jUBjme.png!mobile

作者| 朱天富(海培)

编辑| 橙子君

出品| 阿里巴巴新零售淘系技术

veE3IrM.jpg!mobile

uyQNNnZ.png!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK