原神剑欢欢:“你看,我的代码用的是策略模式和状态模式,如果以后客户有这样的需求,可以无缝扩展,多健壮啊!”清阳仪满脸狐疑,数次在心里说:“哼,设计过头了!”,只见她欲言又止,数次话到唇边又被自己咽了回去。近一周来,袁帅已经不是第一次听到这种关于设计的讨论了。就在昨天,他看到了青阳和正仪之间的口角。最近,清扬仕途不顺,好几次被搭档说得哑口无言。袁帅本想为死党青阳“讨回公道”,却没有直接出面帮青阳找回。设计标准在哪里?周五下午,公司内部敏捷工程实践指南中三个引人注目的价值观中的“简单”让袁帅陷入了沉思:简单:我们重视恰到好处的设计。只为当下设计,不为未来可能出现的需求设计。但是,我们做出的决定应该允许软件快速变化,并能够快速响应不断变化的需求。“简约”似乎明白它在说什么,但什么是恰到好处的设计呢?这句话让他想起了他在面向对象训练营上课后对学生说的一句话:“设计就像西红柿炒鸡蛋,盐分一定要恰到好处”。这句话是那么正确,却又是那么空洞。设计的好坏没有标准答案。这么多年,袁帅一直在跟软件界的大神们学习设计原理,但始终处于一种模糊的理解状态。他也知道,每个人心中都有一杆秤。什么是好的设计?变成了公说公有理,婆婆说婆婆有理,谁都很难说服谁。这次他不想再提那些空洞的东西了。为了让杨清能够快速抓住重点,敏捷团队程序员下发用户故事卡时,他尽量将范围缩小到编码设计上,避开了架构设计。从变量、常量、方法、类、类之间的关系和对象交互开始。旧文重温:简约设计周六,袁帅早早去书房,点亮背景音乐《稻香》,打开博客首页,发现了一篇多年前写的文章《简单设计》,仔细看完,感慨那还不错,可以作为介绍,发给清扬看,下周一一早去公司讨论。他花了将近一个小时的时间打磨文字,并根据自己最近的设计经验调整了部分内容,保留了文章的整体脉络。用特定的词汇表达设计抽象设计问题,大大提高了初学者的学习门槛。想太多可能会被说成设计过度,满脑子都是自找麻烦。我想得少,怕别人觉得我能力不足,没脑子写代码。怎么做,如何做出好的设计?SOLID的原理、GoF的23种设计模式、STUPID、GRASP,学完就够了吗?不,忘掉这些抽象和没有根据的设计原则吧。开始时,尽量不要让自己难堪。极限编程领域的编程大师KentBeck很早以前就提出了4个比较通俗易懂的参考原则:原则1:通过测试(信念)这个理解没有问题,但是需要两个前提应满足:测试覆盖率达到100%,所有测试均有效。如果这两点在你的项目中都达不到,当然99%的项目是不可能的(传说中还有1%)。这时候你需要换个角度去理解通过测试。你为什么要写测试?测试测量的是什么?不就是为了增强你对系统功能是否满足业务需求的信心吗?所以,“通过测试”广义上理解为满足业务需求,无论是自动化测试还是手工测试,你要做的就是满足业务需求,但我们提倡尽可能写足够多的自动化回归测试。原则二:消除重复(职责)重复是万恶之源——KentBeck并没有说重复意味着低内聚高耦合,导致修改困难(shotgunmodification),势必会降低系统对变化的响应能力。响应能力的降低必然导致维护工作量的增加。我简单设计价值观中的惰性会驱使我竭尽全力消除这些重复,从而减少修改的工作量,提高软件的响应能力。原则3:UnveilingtheDiagram(初衷)UnveilingDiagram听起来是一个难以描述的概念,如何表达UnveilingDiagram?对于这一点,我们很难有一个标准的、完美的答案。它不完美,但不妨碍我们努力做到完美。你可以在编码过程中不断问自己:代码容易理解吗?是否偏离了初衷(业务需求)?那么,进一步探究这背后暴露出的行为信号——《解释》:新人在了解业务需求后,能否第一时间从代码中清晰地找到对应的代码?新手需要额外解释代码的含义吗?如果是这样,你会在多大程度上解释它?这几个问题会让你不断反思自己的代码是否能体现业务的初衷?变量、方法、类等的命名,你时刻保持警惕:给它取一个更能准确表达业务的名字,一个不需要额外解释的名字。这使读者可以在深入了解细节之前快速地从较高层次理解代码的意图。原则4:最少元素(本质)既然我们在谈论代码,那么任何填充您的代码库的东西都可以理解为一个元素。当然,我们仍然关注代码相关的元素,比如变量、常量、注释、注解、关键字、包。“最少元素”的核心思想是:在不需要的时候,尽量减少代码元素,以降低代码复杂度,保持简单,贯彻少即是多的思想。它表达了简单设计的本质。原则5:前四个优先级依次递减(灵魂)简单设计前四个原则为设计决策提供指导。在实际应用过程中,遇到矛盾时,我们该如何选择呢?KentBeck还提出了一个优先级:通过测试>消除重复>=公开图表>最小元素。以上四个优先级依次递减,有点类似于敏捷宣言中的最后一句话:即虽然右项有其价值,但我们更关注左项的价值。通过测试,排除重复,揭示原理图的最少元素。以上四个优先级依次降低。优先级有助于揭开迷雾。周末很快就过去了。青扬看完袁帅发给他的,又看了很多遍。他脑子里所有的问题都等着我想和袁帅商量。她比平时早了一个小时到办公室,就看到袁帅已经在他的工位上了,一副等着她上门打架的样子。青扬还没开口,袁帅就递给她四张红色卡片,那是他亲笔写的字条。青扬一看,字迹工整,工整。似乎从来没有见过袁帅写得这么认真。她很惊讶也很感动,特别仔细地读了一遍。“青阳,我给你来个脑筋急转弯——在工作中,你领导的领导的领导的领导的领导的领导(4个人),当他们给你的指令相互矛盾时,你该听谁的?”。“当然是听从上级领导的吩咐!”程扬条件反射的快速回答。袁帅见状,会心一笑,青扬似乎听懂了袁帅的意思似的挠了挠头。“可是,我还是……”青漾话没说完,袁帅示意她凑近一点,看看他之前准备好的密码。Talkischeap例一:袁帅灵机一动:“这段代码是干什么的?如何用简单的设计框架来解读?”。青阳迅速回应:“抽取公共方法,违反‘最小要素’以‘去重’。”例2:“常量替换魔数,违反‘最小要素’以‘揭图’”袁帅还没来得及发问,清扬先回答了,当然赢得了袁帅的竖起大拇指。一转眼就到了08点55分,袁帅看到Jeany正朝他走来,提着一身正要穿的西装。“开会。”她起身准备去会议室跟她商量一下晚上OOBootcamp最后一节课的安排。表,看看能不能回答你的问题。袁帅转头冲青扬得意一笑,带着珍妮进了会议室。清扬拿起卡片开始阅读:袁帅这么懂她,清扬很意外。他确实是一个优秀的Buddy。很早就开始了良好的工作节奏。看完卡片,她又继续看了袁帅留给她的几个代码示例。15分钟后,她对简单的设计有了一点了解,拿起一张绿卡,认真地写下:通过测试(信念,不摇)消除重复(责任,认真)揭示原理图(初衷,不忘初心)意向)极简元素(精、精、简)以上四个优先级依次降低(灵魂、赋予生命)简约设计遐想与Jeany见面后,袁帅回到工作岗位,看到卡片很是欣慰程扬留下的。他知道清扬已经开始了,以后不会再让CodeReview哑口无言了,他帮清扬“讨回公道”,我的小愿望很快就会实现。此刻,他坐下来喝了一口水,表达了自己的感慨——KentBeck提出的简单设计原则更注重代码设计,简单的设计思想其实可以应用到架构设计、沟通和协作中。架构设计:首先要考虑的是满足业务的系统架构(通过测试:性能、稳定性等)。使用DDD合理划分微服务(爆料图:明确界定的上下文)。提取公共服务组件以分离关注点(去除重复:API网关、BFF等)。最后,我们在满足前三点的前提下,尽可能简化系统架构中的组件(最少元素)。沟通协作:在与客户的正式沟通中,始终要明确沟通的主题,确定目标(通过测试)。通过加强结构化思维,提高表达的结构性和清晰度,达到简洁(消除重复,显示图表)。最后,做到前三点后,我们尽量不说多余的废话(最小元素)。简单不仅仅是那么简单。设计五原则中,必须保证测试通过(满足要求),杜绝重复,不需要的元素不存在。这几个看起来比较具体,看得一清二楚。但是,每个人持有不同的标准是一个概念,这代表了代码的可理解性。可理解性的参考应该回到业务的源头,是否准确表达了业务概念。最后,不能忽视优先级原则,否则框架将失去灵魂和生命力。袁帅做过多年的软件开发和培训,他很清楚,完美的答案可能并不存在。软件开发是一种知识性工作,设计不同于旁观者。简单设计的五个原则可以在一定程度上帮助程序员少走弯路。除了这些,小组社交活动中的讨论也是一种非常有效的方式。这就是为什么他如此重视将社交互动引入他的工作室的原因。代码好不好读,除了自省,还需要多动脑筋,比如:CodeReview,结对编程。
