高级程序员的代码质量应当达到什么水准

news/2024/11/14 3:41:05/文章来源:https://www.cnblogs.com/lovesqcc/p/18540998

不断思考总结提炼,持续迭代优化前进。

工作十余年,对代码质量有过一段孜孜不倦的追求,同时也在实战中有一些亲身体会,总结下对代码质量的观点和经验。

关于代码质量,基本都总结在我的博客上:代码修行。也写过一本小小的电子书,再分享一次,https://pan.baidu.com/s/1noGsrkJto_CoAPxjXEmMSA?pwd=yvu6 。一年有效期。

概述

那么,在我看来,高级程序员的代码质量应当达到什么要求呢?兼顾时间成本,我认为适中即可。达到如下代码质量要求是可以的:

  • 功能的深度正确实现
  • 清晰性和可维护性
  • 良好的健壮性
  • 必要的日志记录
  • 核心方法的充分单测
  • 大数据量,考虑性能
  • 大流量,考虑稳定性
  • 适度的通用性
  • 适度的可扩展性
  • 代码安全性

要达到代码质量要求,程序员需要掌握代码重构技能,需要熟悉各种代码错误并有效规避。踩过的雷和坑越多,越有意识地规避,才能避免重犯错误。可阅:代码问题及对策。

代码质量

功能的深度正确实现

代码质量的最起码要求是功能的正确实现。

要能完成程序功能的基本正确性,对于程序员来说是不难的。不过说到深度正确,何为深度正确呢?在我的工作经历里,有以下几种情况需要考虑:

  • 变更处理。比如你的表从其它APP冗余了几个字段(比如主机名、主机业务组等),当这些字段变更时,需要监听消息去更新它们;当主机卸载时,需要删除对应的记录;当租户变更时,需要插入新的初始化记录。
  • 关联处理。多个功能相互影响,比如告警加白、归并和响应。归并在加白流程之前,如果归并了,告警就不能加白,可能与用户预期不符(因为用户设置了白名单,归并却是用户并不感知的系统内置机制)。而告警归并会导致后面被归并的告警的元素无法响应;此外,多个告警会共享同一个元素,一个元素在一个告警里响应了,也会展示在其它告警里,导致其它告警展示响应信息,但是告警列表的告警却没有响应信息,可能导致客户困惑。
  • 大数据量处理。一个主机封禁一个IP好解决,十万台主机封禁上千个IP呢?
  • 并发处理。引入OpenAPI之后,元素响应接口调用频次就高了很多。对于元素响应接口来说,高频重复发送同一个元素的同一个操作(或者相近操作),操作可能落到不同机器上,你的程序能正确应对么?如果第一次成功,后续失败,会不会出现异常?
  • 错误处理。一个普通的主机响应操作,如果主机不在线怎么办?如果数据库操作失败怎么办?如果主机在线但是处于空跑状态无法响应任何请求怎么办?如果中间件异常怎么办?一个耗时操作分为同步和异步两部分,如果异步流程出错了,怎么办?

如果这些都不能考虑到,那就等着被测试同学提的BUG轰炸吧!我也是从各种BUG中提炼出这些场景的。

清晰性和可维护性

可维护性可以说是程序员耳熟能详的关于代码质量的词眼了。可维护性涉及多个方面,这里不一一赘述。可以去知乎上搜索下,或者阅读各种代码质量相关的书籍。比如《编程珠玑》、 《 Effective Java 》、《代码整洁之道》、 《Writing solid code》、《编写可读代码的艺术》、《重构》、《敏捷技能修炼》。

清晰性是一个很重要的目标,但是却不那么容易达到。我们都写过类似的特殊处理的代码,通常是为了绕过某些检测或者适配某种流程的条件。但这种代码是很不清晰的,很容易留坑。如果没有注释的话,即使当初写这段代码的人也很容易忘记为啥会有这段代码。

因此,要达到清晰性,要尽量避免这种原子性的判断。用有语义的函数替代,并辅以必要的注释。

// 反例
if shop_id != "" && shop_type == "plain" && other condition {head_shop_id = ""
}// 也不算好的正例
if isPlain(shop_id, shop_type) != "" {// 为了适配某种流程,需要设置总店ID为空head_shop_id = ""
}func isPlain(shop_id, shop_type) bool {return shop_id != "" && shop_type == "plain" && other condition
}

良好的健壮性

实现功能之后,健壮性是第一个必要的基本要求。要想线上不出各种奇奇怪怪的问题,健壮性一定要做好。实现健壮性的基本理念是防御式编程和契约式编程。

健壮性检查通常包括:

  • 参数校验:比如特定信息(IP,端口,邮件等)的格式。
  • NPE (nil point reference) 处理:对象为空。
  • 数值溢出。比如有些 IPv6 地址转成整数会超出 int64 能表示的最大数值。
  • 数组列表越界:数组列表越界,尤其是使用 split 方法之后提取字段的时候。
  • JSON 解析出错:json 格式不对、json 内容不全。
  • 错误处理:立即失败、重试、重续、根据条件判断、抛出并捕获异常。
  • 资源和锁管理:确保资源和锁及时被释放,不会释放错误的资源和锁。
  • 并发安全:确保多线程处理同一个共享可变对象加了同步措施。

以上所列,只是部分。更详细的可以问ChatGPT。对于一般功能,能达到功能实现正确、适度的健壮性,就已经足够了。易测、清晰、健壮,是我认为代码质量的基本要求。可阅:写代码的指导思想:如何写出易测、清晰、健壮的牢固代码。

必要的日志记录

线上运行之后,一定会出现一些问题,需要进行问题排查。问题排查的基本思路就是线索+逻辑推理。线索从哪里来,从日志记录和数据库里来。

记录关键变量、关键路径。由于日志量不宜过多(影响性能、磁盘存储空间),因此往往会倾向于把业务ID及业务ID 关联关系记录下来,然后根据业务ID去数据库里查询详情。对于流程,最好能有一个业务ID或唯一键,能够贯穿整个流程,这样,根据业务ID或唯一键就能看到整个流程,以及看到流程在哪里终止了。

对于并发问题,一定要留意时间线索。可阅:软件调试与问题排查的修炼之路与实战经验 。

必要的核心方法的单测

单测必不可少。程序员往往嫌单测麻烦而不愿写单测。实际上,单测是一个减少时间成本的保障措施。通过单测,确保核心逻辑没有问题,就可以怀疑是流程中的参数不合理或者是其它地方有问题,而不至于一遍遍调试,结果发现是核心方法的一个地方没有覆盖到或者没有处理好。短链路调试显然比长链路调试要省时。

关于单测编写,可阅: 深入探究单元测试编写,使用Groovy+Spock轻松写出更简洁的单测,使用Java函数接口及lambda表达式隔离和模拟外部依赖更容易滴单测,改善代码可测性的若干技巧 。

现在,代码和单测都可以通过 AI 生成了,进一步便利了程序员。所以,代码完成后,千万不要拉下单测啦!

性能和稳定性

有一定业务规模的互联网公司,往往对性能和稳定性也有要求。

处理大数据量或长流程时,接口往往会比较慢。解决性能的五件套:选择适合的数据结构和算法、索引、缓存、并发、异步非阻塞。此外还有精简流程。做方案时,养成评估数据量的好习惯。无论数据量多少,都做个评估。数据量,可能是瞬时大数据量,可能是基于较大日增量的累积大数据量。多数情况下要考虑累积数据量。可阅:应用层性能优化思路及方法。

稳定性通常涉及到对系统全局的理解和掌控。涉及大流量时,需要考虑对系统的冲击,即系统在大流量时不至于直接崩溃导致服务不可用。此时要考虑限流、降级,评估对核心 API 调用和对中间件访问的高频程度,避免对核心API和中间件造成冲击,尤其要避免雪崩。毕竟,核心API和中间件挂了,那就不只是一个服务出问题了。可阅:增强系统稳定性的基本方法 。

性能和稳定性考量,最考验一个高级程序员的综合技术素养。对互联网常用服务端技术有一个整体概览,对理解性能和解决问题也很有助益。正如修习内功也有助于修炼高阶武学。可阅:互联网应用服务端的常用技术思想与机制纲要 。

适度的复用性

复用性也是程序员非常看重的代码特性。写一次代码,多次复用,省时省力,何乐而不为?

代码复用性,涉及多个层面:代码级(函数、接口、类、对象)、模式级、API级、模块级、框架级、中间件级、服务级。初级程序员通常能做到代码级复用,高级程序员应该能做到针对一类需求或模式级或API级的可复用设计,一流程序员能够做到模块级、框架级、中间级、服务级。

泛型和函数式编程,是达成代码可复用目的的两大编程技巧。可阅:“写出可复用代码的基本思想与实践”, 函数式+泛型编程:编写简洁可复用的代码,再谈函数式编程:释放编程创造力。

复用性最考验程序员的抽象思维能力。抽象度越高,复用性越强。抽象能力强的人,通常是能写出一个好用框架的。

为什么说适度的复用性呢?因为代码的高复用性可能会导致代码清晰度下降或者有性能损耗,或者理解起来有一定成本,需要有所权衡。

适度的可扩展性

大多数公司对代码可扩展性并不作要求,更多是对系统架构设计有可扩展要求。不过,程序员为了省事省力,达到一定的代码可扩展性是有助益的。

达到代码可扩展性通常基于接口和插件编程,要求对设计模式有一定掌握。比如策略模式、组合模式、装饰模式、桥接模式、访问器模式、观察者模式等。可阅:实现可扩展代码的四步曲、由一次重构引发的对可扩展性的思考。

达成系统可扩展性,则需要具备更多技能和经验:【整理】系统可扩展性的设计与实现 。

为什么说适度的可扩展性呢?过度的可扩展性往往意味着过度设计,一开始考虑了很多,结果基本上用不上,反而导致系统实现复杂,维护成本增大,得不偿失。

代码安全性

代码安全性放在最后,但并非不重要。高级程序员往往也会忽视代码安全性。

  • 敏感信息泄露:比如密码、配置等打印在日志里(或者作为调试语句打印上线却忘了删除)。
  • 权限控制不当:低权限的人访问到其未授权的资源。
  • SQL注入:在数据库相关操作中,可以让用户填入过于灵活的查询条件却不加检查。
  • 远程代码执行:在可以让用户输入语句进行的应用里,没有对恶意代码进行检测或过滤。
  • 反序列化问题:fastjson 的事情大家都知道了。即使大厂程序员都不能避免,其它人更不谈了。
  • 文件路径漏洞:一般体现在文件上传上,不过在任何可以让用户输入路径的地方,都可能存在文件路径漏洞。

代码重构

代码重构,是提升代码质量技能的最有效的手段。

经过代码重构,代码能达到一种更精练更优雅的境界,阅读起来也是很有成就感的。可阅:精练代码:一次Java函数式编程的重构之旅 ,一次重复代码重构的思考及探索。

代码重构涉及程序员的综合技能素养:

  • 简单的代码删减和挪动,涉及对分层结构的深入理解;
  • 较复杂的代码结构改造,涉及对业务流程结构和设计模式的理解和应用;
  • 更复杂的系统级重构,涉及对系统设计理论和新技术栈的学习和应用。

只有第一种是相对安全的,后两种在完成之后,都要仔细检查是否对现有逻辑有改动,或者需要回归测试下。

进阶磨炼

迭代前进

不断思考总结提炼,持续迭代优化前进。

在熟练驾驭代码质量,且能够有效利用 AI 生成代码之后,就可以向更上层进阶了。

如何作出良好的设计方案,是下一步的目标。因为代码已经可以由AI 生成,你所需要做的是定好整体方案和规划,而不是沉迷于具体细节。可阅:如何做出一个好的设计方案 。

在方案之上,程序员还有更高的追求。那就是架构设计,全局视野。可阅:从系统整体观思考系统构建 。实际上,系统整体观,不仅仅应用于技术性系统,也可以应用于社会系统,机构组织等。这时候,你的视野不再局限于技术和代码,而是放眼于组织、社会、商业等。

思考力

程序员最核心的竞争力是什么?强大的抽象和逻辑思维,高质量的思考力。

强大的抽象和逻辑思维,清晰透彻缜密的思考力,像激光一样具有穿透力的思考力。这是从事软件开发磨炼出的特有的能力,这种能力可以轻易地理解现实社会的规则(尽管未必会屈从某些规则),理解很多比较复杂的关联关系。

小结

本文小结了代码质量相关的知识和技能。可以看到,代码质量看上去只是代码层面,实际上反映的是程序员的综合素养,包括程序员的逻辑和抽象思维、程序员的系统设计能力、程序员的编码和细节处理能力等。要写出高质量程序,可不那么容易。

每一次总结提炼,都是对自身的一次升华。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/832094.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT:报错误信息: Error: QDomNode file not found

QT:报错误信息: Error: QDomNode file not found ; Error: QDomDocument file not foundQT:报Error: QDomNode file not found QT:报错误信息: Error: QDomDocument file not found解决方法: 在项目文件 CH1302.pro 里添加 "XML" QT += core gui sql xml 优…

读数据质量管理:数据可靠性与数据质量问题解决之道01数据质量

数据质量1. 为什么数据质量值得关注 1.1. 数据是你的CEO的首要任务 1.2. 下游数据消费者(包括产品分析师、营销领导者和销售团队)则依赖于数据驱动的工具 1.3. 数据宕机1.3.1. 指数据丢失、不准确或出现错误的情况,它表现为过时的仪表板、不准确的报告,甚至是糟糕的决策1.3…

2024数据采集与融合技术实践-作业3

一、中国气象网单线程与多线程爬取图片码云仓库:作业3/task1 曹星才/2022级数据采集与融合技术 - 码云 - 开源中国(一)步骤 爬取网站:https://p.weather.com.cn/tqxc/index.shtml 1.1 单线程方式爬取 step1:设置为单线程方式爬取,settings.py中注设置最大并发请求数量CO…

Linux环境安装Splunk Enterprise服务端和Windows客户端Splunk Universal Forwarder

Ubuntu 22.04 安装Splunk Enterprise服务端这里采用安装Splunk Enterprise 8.2.5版本下载安装包 wget -O splunk-8.2.5-77015bc7a462-linux-2.6-amd64.deb https://download.splunk.com/products/splunk/releases/8.2.5/linux/splunk-8.2.5-77015bc7a462-linux-2.6-amd64.deb执…

数据采集第三次实践作业

第三次作业 作业①: 1.要求: 指定一个网站,爬取这个网站中的所有的所有图片,例如:中国气象网( http://www.weather.com.cn )。使用scrapy框架分别实现单线程和多线程的方式爬取。 –务必控制总页数(学号尾数2位)、总下载的图片数量(尾数后3位)等限制爬取的措施。输出…

WIN11 Chrome 双击打不开闪退及Chrome浏览器不能拖拽文件crx

WIN11 Chrome 双击打不开闪退及Chrome浏览器不能拖拽文件crx 1 WIN11 Chrome 双击打不开闪退 1.1 在 Windows 安全中心按照如下步骤操作1.2 右键对应的软件找到应用路径名称1.3 在程序设置按照如下图建立应用名称和后缀相同的命名,如 chrome.exe1.4 按照如下操作步骤打勾选项1…

LVM 使用与扩容总结

转载请注明出处:LVM(Logical Volume Manager,逻辑卷管理器)是一个用于Linux系统的磁盘管理工具。它提供了一种更加灵活的存储管理机制,可以方便地进行磁盘的扩容、缩减、快照以及迁移等操作。 基本概念物理卷(PV):物理磁盘或分区,如/dev/sda1。 卷组(VG):由一个或多…

针对搭建好的Self-Service-Password服务进行背景图片标题修改和去掉问答短信邮件功能选项的展示

官方链接https://ltb-project.org/documentation/index.html https://github.com/ltb-project/self-service-password关于安装我之前已经写了关于安装self-service-password相关的文章,具参考:https://www.cnblogs.com/autopwn/p/18208481修改背景先将要更改的背景图片上传上…

回归

回归时过境迁,上次发完博客后,之后的半年我努力学习,以106分的408分数极限通过了研究生考试初试,之后为了复试机试刷了ACWING,最终顺利通过了复试,被录取为硕士研究生。 进入新学校,技术上开始用java,springboot,mysql增删改查那一套;业务上一开始做开源仓的代码追溯…

开源 - Ideal库 -获取特殊时间扩展方法(四)

分享特殊时间获取的扩展方法,包括获取当前月第一个/最后一个指定星期几、上/下一个指定星期几、月份的第几周、年的第几周(ISO8601)、月份周数、是否周末、是否闰年、所在季度,提供详细代码和单元测试。书接上回,我们继续来分享一些关于特殊时间获取的常用扩展方法。01、获…

关于Windows外壳(Windows Shell)

在前面的文章中,我介绍过如何替换Windows Shell,将桌面替换为自己的程序。 但是这么做会有个问题,就是桌面环境未被初始化,即使创建了explorer.exe进程,桌面也不会出现。 这里搜集了一些关于WInlogon,LogonUI和Userinit的一些理论知识,有兴趣的小伙伴可以了解一下。Winlo…