我们编写的代码,除了用于机器执行产生我们预期的效果以外,更多的时候是给人读的,这个读代码的可能是后来的维护人员,更多时候是一段时间后的作者本人。
如何能够写出优雅整洁且不让人【哔——】的代码?
今天我们邀请了 4 名淘系技术工程师,结合他们自身在写码过程中的感受,给大家分享一些他们对于优雅代码的理解和具体写作方式,希望能够对你有帮助。
01
所谓优雅,相对应的是坑。只有见过足够多的坑,才会形成自己的编码理念。
工程开发,除了要满足业务需求和性能需求之外,还需要保证可维护。要随时面对人员流动对系统带来的风险,所以我对优雅代码的理解更偏向于易维护。下面是我的个人理解:
基础理念:易懂、简单、高效 三个都要是最好的,但是很多时候我们需要做相对取舍,作为工程师,我认为易懂也就代表后来者更容易维护。这里的易懂不是意味着加注释,如果一段代码开发者感觉需要加注释,那说明它本身就不易理解了,可以考虑优化 。
编码规范
作为java开发,不得不提孤尽大神的《阿里巴巴开发规约》,这里面关于编码规范的说明很详细。不过以我的经验很少有人或者团队能够完全做到。比较实际的角度我认为,首先,团队的技术leader有必要去总结一份贴近与自己现状的开发规范,统一团队的开发风格,编码规范,工程结构,保证一个团队产出代码风格一致。其次,规范落实,团队新人进入之后,除了帮助了解业务,对于现有开发风格,编码规范,工程结构的培训和监督必不可少。
设计模式
二十三种设计模式是每个开发者都会遇到的。但是新手往往执着于设计模式本身,而忽略了背后的六大原则。
首先,设计模式要了解它的适用场景,引入设计模式会增加一定的理解成本,自身开发很难察觉到理解成本。所以需要在代码 review 的时候,也评估使用场景。
其次,现实中,我们学习设计模式,只看到它优势的一面。但是在实际开发中使用,一定需要了解它的缺点,防止滥用。
重构
重构应该存在于每一次的开发过程中,完成功能需求,性能需求之后,还需要思考改动后的代码是否优雅,结构是否清晰。很多时候虽然只加了一行代码,但全局维度需要重新调整结构。
最后想说,所谓优雅,相对应的是坑。只有见过足够多的坑,才会形成自己的编码理念。总结自己遇到的坑,找到避免坑的方法,就能保证持续进步。
02
整洁的代码不一定是好代码,但好代码一定是整洁的。
任何一个傻瓜都能写出计算机可以理解的代码。唯有写出人类容易理解的代码,才是优秀的程序员。(Martin Fowler)
很难给好的代码下一个定义,相信很多人跟我一样不会认为整洁的代码就一定是好代码,但好代码一定是整洁的,整洁是好代码的必要条件。整洁的代码一定是高内聚低耦合的,也一定是可读性强、易维护的。
高内聚低耦合
高内聚低耦合几乎是每个程序员员都会挂在嘴边的,但这个词太过于宽泛,太过于正确,所以聪明的编程人员们提出了若干面向对象设计原则来衡量代码的优劣:
可读性
代码只要具有了高内聚和低耦合就足够好了吗?并不见得,我认为代码还必须是易读的。好的代码无论是风格、结构还是设计上都应该是可读性很强的。可以从以下几个方面考虑整洁代码,提高可读性。
大到项目名、包名、类名,小到方法名、变量名、参数名,甚至是一个临时变量的名称,其命名都是很严肃的事,好的名字需要斟酌。
名副其实
好的名称一定是名副其实的,不需要注释解释即可明白其含义的。
具体可见:[阿里工程师谈,什么是好的代码?]
后者比前者的命名要好很多,阅读者一下子就明白了变量的意思。
容易区分
我们很容易就会写下非常相近的方法名,仅从名称无法区分两者到底有啥区别(eg. getAccount()与getAccountInfo()),这样在调用时也很难抉择要用哪个,需要去看实现的代码才能确定。
可读的
名称一定是可读的,易读的,最好不要用自创的缩写,或者中英文混写。
足够短
名称当然不是越长越好,应该在足够表达其含义的情况下越短越好。
良好的代码格式也是提高可读性非常重要的一环,分为垂直格式和水平格式。
垂直格式
通常一行只写一个表达式或者子句。一组代码代表一个完整的思路,不同组的代码中间用空行间隔。
public class Demo {
@Resource
private List<Handler> handlerList;
private Map<TypeEnum, Handler> handlerMap = new ConcurrentHashMap<>();
@PostConstruct
private void init() {
if (!CollectionUtils.isEmpty(handlerList)) {
for (Handler handler : handlerList) {
handlerMap.put(handler.getType(), handler);
}
}
}
publicResult<Map<String, Object>> query(Long id, TypeEnum typeEnum) {
Handler handler = handlerMap.get(typeEnum);
if (null == handler) {
return Result.returnFailed(ErrorCode.CAN_NOT_HANDLE);
}
return handler.query(id);
}
}
如果去掉了空行,可读性大大降低。
public class Demo {
@Resource
private List<Handler> handlerList;
private Map<TypeEnum, Handler> handlerMap = new ConcurrentHashMap<>();
@PostConstruct
private void init() {
if (!CollectionUtils.isEmpty(handlerList)) {
for (Handler handler : handlerList) {
handlerMap.put(handler.getType(), handler); } } }
public Result<Map<String, Object>> query(Long id, TypeEnum typeEnum) {
Handler handler = handlerMap.get(typeEnum);
if (null == handler) {
return Result.returnFailed(ErrorCode.CAN_NOT_HANDLE);
}
return handler.query(id); }
}
类静态变量、实体变量应定义在类的顶部。类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter 方法。
水平格式
要有适当的缩进和空格。
团队统一
通常,同一个团队的风格尽量保持一致。集团对于 Java 开发进行了非常详细的规范。
类与函数
类和函数都不应该过长(集团要求函数长度最多不能超过 80 行),过长的函数可读性一定差,往往也包含了大量重复的代码。
同一个函数的每条执行语句应该是统一层次的抽象。例如,我们经常会写一个函数需要给某个 DTO 赋值,然后再调用接口,接着返回结果。那么这个函数应该包含三步:DTO 赋值,调用接口,处理结果。如果函数中还包含了 DTO 赋值的具体操作,那么说明此函数的执行语句并不是在同一层次的抽象。
参数越多的函数,调用时越麻烦。尽量保持参数数量足够少,最好是没有。
注释
注释不能美化糟糕的代码。当企图使用注释前,先考虑是否可以通过调整结构,命名等操作,消除写注释的必要,往往这样做之后注释就多余了。
我们经常遇到这样的情况:注释写的代码执行逻辑与实际代码的逻辑并不符合。大多数时候都是因为代码变化了,而注释并没有跟进变化。所以,注释最好提供一些代码没有的额外信息,展示自己的设计意图,而不是写具体如何实现。
git等版本控制已经帮我们记录了代码的变更历史,没必要继续留着过时的代码,注释的代码也会对阅读等造成干扰。
错误处理
错误处理应该集中在同一层处理,并且错误处理的函数最好不包含其他的业务逻辑代码,只需要处理错误信息即可。
异常抛出时最好将执行的类名,关键数据,环境信息等均抛出,此时自定义的异常类就派上用场了,通过统一的一层处理异常,可以方便快速地定位到问题。
大多数的异常都是来源于NPE,有时候这个可以通过 Null Object 来消除掉。
不返回 null 和不传 null 也是为了尽量降低 NPE 的可能性。
我认为仅仅编写出可运行的代码是远远不够的,还要时刻注意代码的整洁度,留下一些漂亮的代码,希望写的代码都能保留并运行 102 年!
03
命名的重要性要大于注释,注释不是万能的,好的函数命名比写一大段注释易读的多。
我认为,第一要紧的是没有 BUG,实现了该实现的功能,考虑了该考虑到的异常,否则即使命名再完善,注释再详细,都不能改变这段代码是一段没有价值的,甚至对系统有破坏性影响的代码。
其次,需要让其他维护者能够读懂、读明白。好的代码不应该是一本晦涩的古书,而是能够轻松阅读的白话文小说。
软件设计是基础。在写代码前,特别是实现一个复杂功能或大型系统前,要进行必要的软件设计。不同领域的软件设计需要考虑到的方向会有所不同。前端项目一般可包括项目描述、本次实现的范围、基本架构、详细设计、与外部系统的交互设计等。在进行设计时要考虑模块的可重用性和移植性,也就是所谓的“高内聚低耦合”。好的软件设计可以帮助我们厘清思路,避免方向性错误,也能在初期就能从相关方或团队内获得反馈以便及时修改。
对于逻辑复杂或关键核心函数,需要搭配有效且详细的单元测试。单元测试需要考虑通用场景,但也需要考虑边界条件。新手可以根据单元测试的 FIRST 原则逐步熟悉。另外随着代码的迭代,单元测试也需要随之迭代,增加必要的 case。
易读的代码有非常的特性,例如:必要的注释、好的命名等等。我个人认为通常情况下命名的重要性要大于注释,注释不是万能的,好的函数命名比写一大段注释易读的多。命名需要是能够阐明函数功能的、在保证可读性的情况下足够短。对于有硬编码或特殊业务逻辑的代码段来说,需要添加注释,为以后的维护者提供足够的信息。另外,在编码风格上需要遵守团队的编码规范,前端可以借助 eslint、prettier 等工具帮助我们规范编码风格。
04
我认为优雅的代码 必然包含以下一些特性:容易理解,便于阅读、测试及其维护,还能够具备良好的扩展 性,命名清晰,注 释完善等等。
想要写出好的代码并不是一件容易的事情,它需要我们不断地对现有的代码进行反思,那如何写代码才能让它变得更加优雅。我觉得可以从以下几个方面入手:
注重代码规范
一名合格的码农,都应该至少完整地阅读一遍官方的代码规范指南,我觉得阿里的开发规约做的比较全面,值得推荐。然后在平时的开发中尽量遵守这种规范,久而久之代码就会越来越好看,衡量代码质量的唯一标准是阅读该代码时说脏话的次数!!!
逻辑清晰
对代码的逻辑层次要做到了然于心,编写代码要时时刻刻对当前代码所代表的逻辑层次要有“感觉”,要能意识到这段代码和上一段代码是否在某种标准下,处在同一个层次。编写代码要善于归纳这些层次,才能建构一个优美的结构。
低耦合、高内聚
耦合会严重影响代码的复用性及可扩展性,让后人维护时不得不修改甚至重写这部分代码,不仅浪费时间还会导致代码库中又多出一块类似的代码,很容易让人迷惑。同时,修改耦合度高的代码时经常会牵一发而动全身,如果修改时没有理清这些耦合关系,那么带来的后果可能会是灾难性的。高内聚就是不要将没有任何联系的东西堆到一起。
以上就是对如何写出一段不被骂娘代码的一些浅见。
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/-Ygqxr31uxYSZLTFRCICOA
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。