写点什么

如何提高代码质量

  • 2020-09-14
  • 本文字数:4315 字

    阅读完需:约 14 分钟

如何提高代码质量

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

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

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

为何需要提高代码质量?

以下是我认为的几点:


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

  • 促进交流,促进知识共享,做好 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,我还觉得有理,我也会更新进来。


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


本文转载自公众号淘系技术(ID:AlibabaMTT)。


原文链接


如何提高代码质量


2020-09-14 14:067074

评论 3 条评论

发布
用户头像
“打印日志时,禁止直接用 JSON 工具将对象转换成 String” 请问下,这个是基于什么考虑呢?
2020-09-22 10:12
回复
1年半的文章,不知道你是否已经知道了答案,我从自己的角度简单回答下哈。
我们知道JSON转化是要消耗性能的,在高并发的场景下,这会是一个巨大的瓶颈。在日志调用传递参数时,一般这样写logger.debug("error info = {}", JSON.toJsonString(XXX))。此时没有判断相关日志的级别是否开启(比如logger.isDebugEnabled()),那么每次调用该语句都会先执行JSON转化,然后才进入日志处理。而线上是不开启debug日志的,也就是说JSON转化没有意义。如果该语句在大量调用的路径上,你会发现CPU在没有该语句和有该语句的情况下存在巨大差异(请求量足够大时)。
2022-04-24 11:21
回复
用户头像
”第二种途径:从糟糕的代码开始—> 不断去重构,向优秀的设计方案和代码风格不断逼近—> 再延续下去“, 大多数情况是第二种途径
2020-09-15 10:28
回复
没有更多了
发现更多内容

ZBC通证月内已翻倍,Nautilus Chain 上线前夕的“开门红”

股市老人

ZBC通证月内已翻倍,Nautilus Chain 上线前夕的“开门红”

鳄鱼视界

数据库审计有什么用?过等保三级需要吗?

行云管家

数据库 等保 等级保护 数据库审计

云数据库 TiDB 入门级别的体验

TiDB 社区干货传送门

6.x 实践

龙蜥开发者说:为爱发电!当一个龙蜥社区打包 Contributor 是怎样的体验?| 第16期

OpenAnolis小助手

Linux 开源 rpm 龙蜥社区 贡献

TiDB x Aliyun 免费试用,竟还有这般福利?

TiDB 社区干货传送门

社区活动 版本测评 6.x 实践

在流媒体时代,如何看待音乐版权?

HIFIVE音加加

知识产权 音乐 版权

Python基础知识入门(一)

漫步桔田

即时通讯技即时通讯技术文集(第8期):移动端弱网优化系列 [共14篇]

JackJiang

测试角色在项目各阶段的项目管理tips

京东科技开发者

项目管理 测试 测试 单元测试 企业号 2 月 PK 榜

LeetCode题解:2357. 使数组中所有元素都等于零,排序,详细注释

Lee Chen

JavaScript 算法 LeetCode

最佳实践|用腾讯云智能文字识别实现网约车信息管理

牵着蜗牛去散步

人工智能 腾讯云 腾讯 最佳实践 文字识别

爆肝!《Java权威面试指南(阿里版)》,冲击“金三银四”有望了

程序知音

Java java面试 java架构 后端技术 Java面试八股文

云数据库TiDB-试用

TiDB 社区干货传送门

管理与运维 版本测评 安装 & 部署

DevEco Studio 3.1 Beta1版本发布——新增六大关键特性,开发更高效

HarmonyOS开发者

HarmonyOS

英方软件加入龙蜥社区,联手夯实数字基础设施坚实底座

OpenAnolis小助手

开源 数据复制 英方软件 龙蜥社区 CLA

颜色的认识与使用(大屏颜色/仪表板报告设计)

Data 探险实验室

大屏配色 颜色 可视化颜色 配色搭配

云数据库 TiDB 初使用

TiDB 社区干货传送门

版本测评 安装 & 部署 性能测评 扩/缩容 6.x 实践

Fine BI、Smart BI怎么办,瓴羊Quick BI已经可以提供移动端自助分析整体解决方案!

对不起该用户已成仙‖

不要 ChatGPT,我们要你!2023 涛思招聘季重磅来袭~

TDengine

数据库 tdengine 时序数据库

ChatGPT“狂飙”出圈,快来分享你眼中的ChatGPT吧!

InfoQ写作社区官方

热门活动 ChatGPT

EasyNLP集成K-Global Pointer算法,支持中文信息抽取

阿里云大数据AI技术

人工智能 深度学习 信息抽取 算法模型 企业号 2 月 PK 榜

互联网企业如何进行数字化转型?业务需求迭代频繁的应对之策!

优秀

数字化转型 互联网行业

前端监控之性能与异常

京东科技开发者

监控 服务端 页面 企业号 2 月 PK 榜 js代码

在字节跳动,造赛博古籍

字节跳动技术范儿

后端 nlp 搜索 OCR 多模态

中冶赛迪:基于鲲鹏DevKit开发智慧城市基础设施管理平台,性能提升47%

Geek_2d6073

打造江西数智产业高地,百度飞桨人工智能产业赋能中心落户南昌青山湖

飞桨PaddlePaddle

飞桨 PaddlePaddle

行云管家属于高新企业吗?安全吗?

行云管家

云计算 网络安全 高新企业 云管理 高新技术

云小课|MRS基础原理之Hue组件介绍

华为云开发者联盟

大数据 华为云 企业号 2 月 PK 榜 华为云开发者联盟

云数据库TiDB免费试用初体验

TiDB 社区干货传送门

社区活动 6.x 实践

如何提高代码质量_安全_朱天富(海培)_InfoQ精选文章