代码的简单设计五原则

news2025/7/20 17:37:42

欢欢:“你看我的代码用了策略模式和状态模式,假如后面客户会有这样的需求,可以无缝扩展,多么健壮!” 清扬一脸狐疑,心中念叨了数遍 :“哼,过度设计!”,只见她欲言又止,好几次话到嘴边又被自己咽回去了。

这种关于设计的讨论,袁帅最近一周不是第一次听到了,就在昨天他还看到清扬和正义的一次口水仗。最近清扬有点仕途不顺,几次被结对的搭档怼得无言以对。袁帅想为他的Buddy清扬“讨回公道”,但不是直接出面帮清扬怼回去。

设计的标准在哪里?

周五下午,公司内部的敏捷工程实践指导手册上醒目的三条价值观的「简单性」让袁帅陷入了沉思:

简单性:我们重视刚刚够用的设计。只为当下设计,不为未来可能出现的需求做设计。但是,我们做出的决策应当允许软件快速变更,能够快速响应需求变化。

「简单性」,看起来也似乎明白在讲什么,可什么是刚刚够用的设计呢?这句话让他想起来当年他在一次面向对象训练营的课后跟某个学员说过的一句话:“设计犹如西红柿炒鸡蛋,盐要恰到好处。” 这句话是如此的正确却又无比空洞。

设计的好坏本身没有一个标准的答案,这么多年,袁帅也在跟着软件界各路神仙学习设计原则,仍然处在似懂非懂的状态。他也深知每个人心中都有一杆秤。**什么是好的设计?**便成了公说公有理,婆说婆有理的问题,谁也难以说服谁。

这一次他不太想提那些空空如也的东西,为了能够让清扬快速掌握要点,他尝试将范围缩小到敏捷团队程序员交付用户故事卡时的编码设计,避开架构设计。从变量、常量、方法、类、类与类之间的关系、对象的交互开始。

重温旧文:简单设计

周六,袁帅很早就钻到书房,点燃背景音乐《稻香》,打开博客主页,发现了一篇多年前写的文章《简单设计》,仔细通读一遍之后,他觉得还不错,可以作为入门,发给清扬阅读,约下周一大一早去公司讨论。

他花了近一个小时将文字润色,也基于最近对设计的体会调整了部分内容,保留了文章的整体脉络。

用具体的词汇表达设计

抽象的设计问题大大提升了初学者的学习门槛,想得太多怕被说过度设计,吃饱撑着没事找事。想少了,又怕被人认为能力不足,无脑编码。到底怎么办,怎么样才能做出好的设计?SOLID、GoF的23种设计模式、STUPID、GRASP这些原则学会了就可以了吗?No,统统忘掉这些抽象不接地气的设计原则。

起步,尽量别为难自己。极限编程领域的大师程序员Kent Beck很早前就提出了4条相对容易理解的参考原则:

4个考虑原则

原则一:通过测试(信仰)

「通过测试」 通常会被一概地理解为通过自己在项目中的各种测试(自动化 + 手工),这么理解,也没有什么问题,但是需要满足两个前提条件:

  1. 测试覆盖率达到100%
  2. 所有测试都是有效的

如果你的项目中没法满足这两点,当然,99%的项目是做不到的(还有1%存在传说中)。此时你需要换一个角度去理解 通过测试

你为什么写测试?测试在测什么?不就是为了增强你对系统功能是否满足了业务需求的信心吗?所以「**通过测试 **」广义理解为要满足业务需求,不论是自动化测试还是手工测试,你需要做的是满足业务需求,只不过我们提倡尽可能编写足够的自动化回归测试。

原则二:消除重复(职责)

重复乃万恶之源——Kent Beck 没有说过

重复意味着低内聚、高耦合,导致的后果是难以修改(霰弹式修改),必然降低系统对变化的响应力。响应力的降低势必会造成维护工作量的提升,我的简单设计价值观 一文中的* 懒惰* 将驱使我尽我所能消除这些重复,从而减少修改时的工作量,提升软件的响应力。

原则三:揭示意图(初衷)

揭示意图,听起来是一个不可言说的概念,怎样表示揭示意图了呢?对于这一条,我们很难有一个标准且完美的答案,做不到完美,但不妨碍我们努力尝试趋近完美。

你可以在编码过程中,不断问自己:代码容易理解吗?它有没有偏离它的初衷(业务需求)?紧接着,进一步探索这背后暴露的行为信号 – 「解释」:

  1. 新人了解了业务需求后,能够第一时间清晰地从代码中找到对应的代码吗?
  2. 你需要额外对一个新人解释代码的含义吗?如果要,你要解释到什么程度?

这几个问题会让你不断反思你的代码能够体现业务初衷吗?变量、方法以及类的命名等,你时刻都保持警惕的是:**赋予它一个更加准确表达业务的名字,一个不要额外解释的名字。**从而让读者能够在深入细节之前就能够在较高层次上快速理解代码的意图。

原则四:最少元素(精髓)

既然说的是代码,那么充斥在你的代码库中的任何东西都可以理解是元素。当然,我们还是焦点聚焦在与代码相关的元素,比如,变量、常量、注释、注解、关键字、包。

最少元素」 的核心思想是:在不必要的时候,尽可能减少代码元素来降低代码复杂度,保持简洁,贯彻less is more的思想,它道出了简单设计的精髓。

原则五:前四条优先级依次降低(灵魂)

简单设计前四条原则给设计决策提供了指导,在实际运用过程中,当面临冲突时,我们如何取舍,Kent Beck也提出一个优先级:通过测试 > 消除重复 >= 揭示意图 > 最少元素。

以上四条优先级依次降低,这就话有点类似敏捷宣言中的最后一句:也就是说,尽管右项有其价值,我们更重视左项的价值。

  1. 通过测试
  2. 消除重复
  3. 揭示意图
  4. 最少元素
  5. 以上四条优先级依次降低

优先级帮助揭开迷雾

周末过的飞快,清扬读完了袁帅发给他的《简单设计》,而且读了很多遍,一脑子的疑问等着要找袁帅探讨。她比往日提前了一个小时到了办公室,只见袁帅已经在工位,一副就等她来战的态势。

还没等清扬开口,袁帅递给她四张红色卡片,是他的手写笔记,清扬见字迹工整,貌似她从未见过袁帅如此认真写过字,颇感意外和感动,格外认真地阅读起来。

“清扬,考你一个脑筋急转弯 – 在工作中你的领导的领导的领导的领导(4个人),当他们给你的指令有冲突时,你该听谁的?”。“当然是听更高级领导的指令啊!”清扬条件反射式快速回答到。

袁帅见状会心一笑,清扬也挠挠头貌似明白袁帅的意思。“可是,我还是…” 还没等清扬说完,袁帅示意她靠近来看他早早准备好的代码。

Talk is cheap

示例一:

袁帅快速出招:“这段代码在做什么?用简单设计框架怎么解读?”。清扬敏捷地接招:“抽取公共方法,为了「消除重复」而违背「最少元素」。”

示例二:

“常量代替魔鬼数字,为了「揭示意图」而违背「最少元素」。”还没等袁帅发问,清扬抢先回答,当然也赢了袁帅的大拇指(向上的)。

一晃就08:55了,袁帅见Jeany朝他走来,搭载着一副即将要开会的眼神,便起身准备去会议室跟她商量晚上OOBootcamp最后一次课的安排。

“喂,我还有一个疑问…” “桌上还有一张蓝色卡片,你看能不能解答你的疑问。” 袁帅扭着头得意地给清扬一个微笑,就跟Jeany进入了会议室。

清扬拿起卡片开始阅读:

清扬很是惊讶袁帅竟然如此懂她,不愧是优秀的Buddy,一大早开启了美好的工作节奏。她读完卡片,继续阅读袁帅留给她的几个代码示例,15分钟过去了,她对简单设计算是有点体会了,拿起一张绿色的卡片认真写下了:

  1. 通过测试(信仰,不可动摇)
  2. 消除重复(职责,尽职尽责)
  3. 揭示意图(初衷,不忘初心)
  4. 最少元素(精髓,精炼简洁)
  5. 以上四条优先级依次降低(灵魂,赋予生命)

简单设计遐想

跟Jeany开完会,袁帅回到工位上,看到清扬留下的卡片,深感欣慰,他清楚清扬已经入门了,日后Code Review不再会被怼得无言以对,而他帮清扬“讨回公道”的小心愿很快就要实现。

此时,他坐下来喝了口水,发出了感慨 – Kent Beck 提出的简单设计原则更多关注的是代码设计,简单设计思想其实也能运用在架构设计、沟通协作上。

架构设计

  • 我们应该最先考虑的是满足业务的系统架构(通过测试:性能、稳定性等)。
  • 借助DDD来合理的划分微服务(揭示意图:明确限界上下文)。
  • 提取公共服务组件来分离关注点(消除重复:API Gateway、BFF等)。
  • 最后,我们在满足了前三点的前提下尽可能简化系统架构中的组件(最少元素)。

沟通协作

  • 在与客户正式场合的沟通中,我们始终应该明确沟通主题,确定目标(通过测试 )。
  • 通过加强结构思考力来提升表达的结构性和清晰度,从而达到言简意赅(消除重复,揭示意图 )。
  • 最后,我们达到了前面三点之后尽量不说多余的废话(最少元素)。

简单不仅如此

简单设计五原则中,测试要确保通过(满足需求)、重复应该被消除、元素没必要就不要存在,这几条看起来相对具体,而且能见字如意。但揭示意图这样一个每个人持有不一样标准的概念,它代表了代码的可理解性,可理解性的参考则要回到业务源头,是否准确表达了业务概念。最后,优先级原则是万万不可忽略的,否则这个框架就失去了灵魂和生命力。

袁帅做了多年的软件开发和培训,他心里很清楚,那个完美的答案可能不存在。软件开发是一种知识工作,设计又是仁者见仁智者见智,简单设计五原则能在一定程度上帮助程序员少走弯路。

除了这些,在团队社交活动发生探讨是一个非常有效的途径。这也是他如此重视在工作坊中引入社交活动的原因。代码是否易读懂,除了自我审视,还需要多几个大脑,比如:Code Review、结对编程。

推荐阅读

  • 如何编写简洁代码?(上)
  • 如何编写简洁代码?(下)

文/Thoughtworks 袁慎建
原文链接:https://insights.thoughtworks.cn/code-simple-design-five-principles/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

APISpace 带你一起走进西湖美景

俗话说:“上有天堂,下有苏杭”。 “欲把西湖比西子,浓妆艳抹总相宜” 今天我就带大家走进杭州的西湖美景。自古以来,文人歌者面对西湖美景留下千古绝句,还以西湖为背景书写了一段段动人的爱情传说。 天生自带浪漫色…

医学生考研考博太卷,一篇文章轻松助力上岸——生物信息学及R语言基础知识之向量的运算(二)

考研考博太卷了,卷不过,想没想过本科发一篇文章呢? 330分考研人淘汰390分考研人这个故事,大家应该都知道吧。 本专栏带你六个月内,搞定一篇文章,本科生发文章也很容易。 在卷考研的同时,再卷一篇SCI,你就是新一任卷王。 本专栏教你不用花钱发一篇生信文章,从三个方…

态库、静态库之间的相互嵌套

本文的目的是测试各种类型库的编译后的使用效果,包括库又链接其他库的编译方法,使用方法,依赖性等。 太长不看版:请跳至文章最后的总结对比表。 一、内容包含: ①静态库libbb.a依赖静态库libaa.a的测试; …

学会分享,学会生活,分享5款简单易用的软件。

分享是一种博爱的心境,学会分享,就学会了生活。 1.在线图片编辑工具——佐糖 佐糖是一款在线免费图片编辑工具,采用AI人工智能技术,自动识别图片,支持一键抠图,更换背景,移除水印等。另外还提…

【向每个应用View中增加子控件 Objective-C语言】

一、把刚才计算九宫格的思路再给大家过一遍 1.现在我们要计算九宫格坐标 1)先把每一个格子,每一个九宫格的大小,先确定了, 在这里先指定宽和高 CGFloat appW = 75; CGFloat appH = 90; 2)再去计算第一个格子的一些间距, 到上面的间距,marginTop = 30; 再计算出…

别再花钱买 Chatgpt 资源了,这里有免费的,2 分钟上手

最近无论是打开社交网站,还是朋友圈,就连中午吃个饭都能听到大家都在聊 ChatGPT,仿佛如果这一刻你不懂这是个啥玩意儿,你就会觉得自己完全搭不上他们的话... 那ChatGPT 是什么? 百度上是这样解释的: ChatG…

最全的免费录屏工具,这 19 款录屏软件绝对值得你收藏

屏幕录制软件可让您捕获屏幕以与他人共享,创建与产品相关的视频、教程、课程、演示、视频等。这些软件是您能够从网络摄像头和屏幕录制视频。以下是精选的顶级屏幕录像机列表。 适用于 PC 的19 款免费录屏屏幕录像机软件 1)奇客免费录屏 奇客免费录屏&am…

2023家用投影仪怎么选?极米H5值得推荐

如今不管是手机还是电视都在不断向大屏幕靠近,消费者也在追求越来越大的屏幕尺寸。同时作为提升生活幸福指数的重要家居用品,投影仪正逐渐取代电视,成为消费者的首选。随着国内智能投影行业的不断发展,市面上智能投影产品也越来越…

Allegro移动器件时附带的孔和线被同步更改的原因和解决办法

Allegro移动器件时附带的孔和线被同步更改的原因和解决办法 用Allegro做PCB设计的时候,移动器件的时候,会出现附带的孔和线也会被同步更改,有时并不是期望的效果,如下图 Allegro其实将这个功能关闭即可,具体操作如下 选择Edit点击Move命令

Vulnhub 渗透练习(二)—— BILLU: B0X

环境下载 下载链接 环境搭建 直接用 vmware 打开,设为 NAT 模式。 信息收集 nmap 扫描 主机扫描: nmap -sP 192.168.200.0/24端口扫描: nmap -sV 192.168.200.129 开了一个 80 端口 apache 服务,和 ssh 服务,后…

时间轮算法概念

概述 在一些中间件中我们经常见到时间轮控制并发和熔断。 那么这个时间轮具体是什么呢,又是怎么使用的呢。 简介 其实时间轮可以简单的理解成我们日常生活中的时钟。 时钟里的指针一直在不停的转动,利用这个我们可以实现定时任务,目前lin…

c入门数的编程 拆数,构造数,c语言字符找出数字拼接,水仙花数 将一个多位数各位拆分

学会构造数和拆分数 目录 学会构造数和拆分数 1:一个三位数,求其各位数字之和 补充:将一个多位数各位拆分求和,(不知道位数怎么求) 2:串中取数(字符转数字) 3&#…

大数据之-Nifi-Nifi的应用场景1_创建并配置getfile处理器---大数据之Nifi工作笔记0004

来说一下nifi的应用场景,首先添加一个GETFILE处理器 添加以后设置处理器名称 设置处理器属性 getfile处理器的属性解释 这个加黑的是必须要选择的,非加黑的可以先不进行选择 这里我们只是设置这个input directory就可以了

是面试官放水,还是公司实在是太缺人?这都没挂,华为原来这么容易进...

华为是大企业,是不是很难进去啊?” “在华为做软件测试,能得到很好的发展吗? 一进去就有9.5K,其实也没有想的那么难” 直到现在,心情都还是无比激动! 本人211非科班,之前在字节和腾…

PMP是不是要考第七版了?

现在确实已经到第七版了,但是第六版还是需要学习的,就是结合两个版本去备考,新考纲把很多内容都缩减了,增加了敏捷管理的内容,但是第六版有很多详细的解析,所以如果你想稳一点,那么两个版本都需…

win10本地连接Xftp7时,压缩文件命名乱码解决方案

win10本地连接Xftp7时,压缩文件命名乱码解决方案1.问题如下图所示:2.解决方案如下: (1)如上所展示的问题,是因为所默认选则的语言是中文,计算机直接编译返回。 (2)修改属性中的选项中的编码语言&#xff0c…

Spring的概述

Spring框架是为解决企业应用开发的复杂性而诞生,它简化了Java应用开发,提高了应用开发的可测试性和可重用性。 Spring的核心理念是控制反转(IoC),其通过依赖注入(DI)的方式来实现控制反转。 Ja…

XQuery 简介

XQuery 简介 解释 XQuery 最佳方式是这样讲:XQuery 相对于 XML 的关系,等同于 SQL 相对于数据库表的关系。 XQuery 被设计用来查询 XML 数据 - 不仅仅限于 XML 文件,还包括任何可以 XML 形态呈现的数据,包括数据库。 您应该具备的…

我用python疯狂爬取公司数据

我是半路从一个纯小白学过来的,学习途中也掉过许多坑,在这里建议新手要先把基础打扎实,然后再去学习自己需要的内容,不要想着全部学完再用,那样你是永远学不完的,用哪方面就学习哪方面的内容,不…

Vue常用的修饰符有哪些有什么应用场景

Vue常用的修饰符有哪些有什么应用场景Vue常用的修饰符有哪些有什么应用场景一、修饰符是什么二、修饰符的作用表单修饰符lazytrimnumber事件修饰符stoppreventselfoncecapturepassivenative鼠标按钮修饰符键盘修饰符v-bind修饰符asyncpropscamel三、应用场景参考文献Vue常用的修…