软件开发中的破窗效应
应该有很多人已经知道破窗效应【注1】这个社会学 (犯罪学)的词语,破窗效应最先由社会学家James Q. Wilson和George L. Kelling在一篇名为《Broken Windows》的文章中提出【注2】:
“一个房子如果窗户破了,没有人去修补,隔不久,其它的窗户也会莫名其妙地被人打破;一面墙,如果出现一些涂鸦没有被清洗掉,很快的,墙上就布满了乱七八糟、不堪入目的东西;一个很干净的地方,人们不好意思丢垃圾,但是一旦地上有垃圾出现之后,人就会毫不犹疑地抛,丝毫不觉羞愧。”
我们一直在喊敏捷开发,其实敏捷开发的一个很重要的目的就是消除浪费,防止破窗效应的发生。事情太难,就让它简单,更简单。流程太重,就让它轻点,更轻点。尽量扫清开发的障 碍,消灭破窗形成的环境。下面我会从软件构建的很多方面来描述如何防止“软件开发中的破窗”。
脏代码
如果代码不整洁,后来人就很难看懂,人们往往会对难以看懂的代码失去耐心,不愿意进一步了解。如果不能进一步了解一部分代码,也就难以改进它,这样 带来的一个后果可能有两点:1、这段代码被抛弃,然后重新编写。2、直接复制这段代码在别的地方使用。对于第一点,会带来软件开发中的浪费,而且再次编写 也不可能就能一部到位的编写正确,可能会引入新的bug。对于第二点,大家都知道重复代码是设计走向腐化的根源之一。
如果我们在编写代码时能不断的应用一些原则,确保我们的代码易懂,自描述。在开发新特性时还不断的使用重构手段,让我们的设计保持一个良好的状态。 我们就能防止窗户被继续打破。
测试
没有测试,或者混乱的测试代码都是破窗滋生的环境。
没有测试
没有测试时,当我们想对一块代码进行重构,我们就像没有带保险绳走钢丝,步履维艰,生怕一下子失去平衡,掉下悬崖。这样在我们的心中就产生了惧怕重 构的阴影,久而久之,我们就不去重构。最后带来的结果就跟上面一段说的一样,设计不断的腐化,然后就失去了控制。
如果有了单元测试,有了验收测试,当我们每做一下重构时,我们都可以从测试快速获得反馈,每当红条亮起时,我们知道我们破坏了一些已有的功能,我们 停下来去修复,当绿条亮起时,我们知道现在处于安全状态,可以安心的继续重构。一切都在我们的掌控之中,我们会喜欢上重构。
混乱的测试代码
有很多人觉得测试代码不是交付给用户的产品代码,可以区别对待,我们不需要花那么多时间琢磨变量命名,方法命名,我们也不需要关注重复的代码。但 是……
混乱的测试代码跟没有测试是一样的,甚至比没有测试更糟糕。我们以为我们有测试,但测试却给我们虚假的报告,当我们发现我们的重构破坏如此之深时, 已经为时已晚。即使测试能给出真实的报告,但如果测试代码混乱,那么添加新的测试就非常困难,我们就会越来越惧怕添加新的测试。而且随着产品代码的演进, 测试代码也需要伴随着演进,测试代码越混乱,我们就越难以修改测试,让它反应出现在产品代码的状态。终于到了一天,大家决定抛弃测试,如是我们又回到了没 有测试作保障的日子。
实际上,从某种程度上测试代码的整洁程度比产品代码的整洁程度更重要,因为有了好的测试我们可以无忧无虑的重构我们的代码,即使现在我们的产品代码 很糟糕也不怕,因为有了测试的保证,我们知道我们可以重构过去,如果我们只有混乱的测试代码,我们那一线重构的希望都没有了。
难以测试
可测试性是衡量代码的一项准则。既然是准则一般都很难达到,如果代码难以添加测试,在尝试几次之后,我们一般都会放弃编写测试的想法。当我们尝试对 一段代码编写测试时发现,这块代码铁板一块,与太多的其他类耦合,需要传入很多重型对象的参数,比如与设备交互的代码,与数据库交互的代码相耦合,这些重 型对象很难模拟或插桩。没有办法,在进度的压力下我们只有放弃添加测试的想法了,那么如上面一样,代码就像草原上奔跑的野兽,失去了控制。
编写可测试性的代码是困难的,要将糟糕的代码改进成可测的代码尤其困难。但有一个诀窍,我们可以先编写测试,用测试驱动出我们的产品代码,这样一开 始我们就获得了一个个测试套件,将我们的产品代码稳稳的固定在那里,就像走钢丝时的保险绳;不仅如此,我们还获得了可测试性的代码。
测试运行太慢
实际上测试运行太慢是一种信号,该信号告诉我们耦合的太紧了。运行一个测试,需要编译加载很多模块。如果运行一个测试需要20分钟,你希望频繁的运 行测试么?如果运行一套测试需要10个小时,你希望测试多久运行一次?测试运行太慢就是第一个被打破的窗户,如果不赶快修补,后面会有更多的窗户被打破。
测试运行太慢,我们就不会频繁的运行测试,测试也就不能提供立即的反馈,这样测试的作用就大打折扣了。
上面主要从代码实践方面来阐释编码中的破窗和如何防止破窗,其实在软件开发的很多方面都存在类似的情况。
源代码管理
有很多团队因为各种各样的原因采用了难以使用的源代码管理工具,或者完全因为厂商对管理层的广告宣传,采用了一个无比重型,好看但不中用的工具。在 经受一两次工具的折磨之后,团队成员就会产生惧怕的心理,尽量的推迟提交代码。提交代码需要足够的频繁,甚至一次有意义的重命名都可以作为一次提交,这样 在代码复查的时候光阅读提交代码的注释就能演示出代码的演化过程。而且,如果每一次成功都有保存,这样在犯错的时候我们有机会后悔,我们有机会回滚到一个 成功的状态。人的大脑虽然非常聪明,但也非常易于出错,特别是在疲劳的时候,如果我们小步前进,小步提交,我们就能停在任何地方。你还记不记得那种必须到 某个时候才能保存当前状态的电脑游戏?
有的时候并不是工具难以使用,而是环境使然。在分布式的团队里,有可能网络不稳定,远程源代码仓库经常不可访问,或者在提交代码时需要连上VPN, 然后再提交,久而久之也会让团队成员懒于提交代码。这样我们就应该采用分布式的源代码管理工具,比如Git。
难以集成
代码写完了并不是开发任务的结束。你还记不记得多少次为了集成产品,解决几个模块之间的冲突而加班加点。敏捷强调及时的反馈,持续的交付。如果集成 一次产品需要几天时间,我们如何做到及时反馈呢?如果集成太困难,大家都会惧怕集成,就会尽量的避免集成,但产品最终是要集成的,所以到了最后期限的时 候,大家都在加班加点,但却不是写代码,而是为了集成。
如果集成太困难,我们为什么不持续的集成呢?所有团队成员都工作在同样的分支上。持续集成服务器不断的签出最新的代码,运行各种各样的测试,最后构 建出可用的软件出来。只要需要,任何时候我们都可以提供可以工作的软件。
可视化
可视化是管理中的铁三角之一。很多管理人员喜欢使用各种各样绚丽的工具绘制出绚丽的图表。比如使用Project做出精确到天的人员计划,使用 PowerPoint做出产品的宏伟蓝图。好像将这些做出来,然后发给大家就有一种这个项目都在我的控制之内的感觉一样。其实不管怎么优秀的软件工具还是 比不上纸和笔。软件打开需要时间,随着软件更新换代,软件体积越来越大,打开一个庞大的Project文件甚至需要一两分钟的时间,而且文档埋藏在电脑文 件系统的深处。找到文档,打开,几分钟就已经过去了,别看这几分钟,久而久之我们就不想再去看这些东西了,我们以为这些东西都装在了我们的脑中,但实际却 没有。花了很多精力编写的需求文档,最后成了一纸空文,当发现与需求不符的时候已经晚了。要防止这种事情的发现,我们就不要打破第一扇窗。
虽然到了二十一世纪,丰田公司还是在很多方面采用原始的看板。软件开发中也是一样,抛弃那些精美的软件吧,将计划,进度,用户故事用最简单的纸和笔 绘制,然后贴在开发人员抬头就可见的墙上。不需要画的多精美,因为越精美就越不想去修改,但软件开发中永恒不变的是变化,我们必须随需而变。
笨重的流程
有的公司给开发、测试、部署规定了严格的流程。开发人员想将产品功能部署到测试环境都需要与很多相关人员交互,提交申请单,然后才能由专人将刚刚修 改的一行代码部署到测试环境中,进行测试。首先不说这个过程中有多少等待,多少浪费。光这笨重的流程就让大家望而却步,进而导致惧怕修改,连好的改进都会 受到抵制。
后记
软件开发的方方面面就像一扇扇窗户,不要打破第一扇窗户,打破了也要赶快去修补,不然软件就会随着窗户一样,一扇扇的被打破,慢慢的腐化下去。
日本的丰田公司,在远远落后于福特和通用之后,采用5S的精益思想【注3】,成为后起之秀,而这5S(整理、整顿、清扫、清洁和素养)最终的目的就是 防止破窗效应。
注1: 经济学上还有一个破窗谬论,但与此文没有关系。
注2 : 要了解破窗效应更多细节可以参见:wiki
注3: 精益思想(Lean)是MIT对丰田生产方式(TPS)进行研究后的产物。关于丰田5S和精益思想(Lean)可以参看丰田的相关著作。
来源:软件开发中的破窗效应 - 横刀天笑 - 博客园 (cnblogs.com)
相关文章:
软件开发中的破窗效应
应该有很多人已经知道破窗效应【注1】这个社会学 (犯罪学)的词语,破窗效应最先由社会学家James Q. Wilson和George L. Kelling在一篇名为《Broken Windows》的文章中提出【注2】: “一个房子如果窗户破了,没有人去修补…...

机器视觉初步6-1:基于梯度的图像分割
把基于梯度的图像分割单独拿出来。 文章目录 一、图像梯度相关算子的原理1. Sobel算子2. Prewitt算子3. Roberts算子 二、python和halcon算子实现1.python实现2.halcon实现 基于梯度的图像分割方法利用像素之间的梯度信息来进行图像分割。 梯度 1是图像中像素灰度值变化最快的…...

从0开始,精通Go语言Rest微服务架构和开发
说在前面 现在拿到offer超级难,甚至连面试电话,一个都搞不到。 尼恩的技术社区中(50),很多小伙伴凭借 “左手云原生右手大数据”的绝活,拿到了offer,并且是非常优质的offer,据说年…...

Sui x KuCoin Labs夏季黑客松|本周Workshop预告
自Sui x KuCoin Labs夏季黑客松推出以来已有四周的时间,期间收获了众多开发者的积极报名和热情参与。随着黑客松报名即将进入尾声,同期举办的Workshop也迎来了本周的最后一波。本周的黑客松Workshop邀请到MoveEX和Mirror World的负责人作为嘉宾为大家带…...

从电源 LED 读取智能手机的秘密?
研究人员设计了一种新的攻击方法,通过记录读卡器或智能手机打开时的电源 LED,使用 iPhone 摄像头或商业监控系统恢复存储在智能卡和智能手机中的加密密钥。 众所周知,这是一种侧信道攻击。 通过密切监视功耗、声音、电磁辐射或执行操作所需…...

【Linux编辑器-vim使用】
目录 Linux编辑器-vim使用1.vim的基本概念2.vim的基本操作3.vim正常模式命令集4.vim末行模式命令集 Linux编辑器-vim使用 1.vim的基本概念 目前了解的vim有三种模式(其实有好多模式),分别是命令模式、插入模式和底行模式,各模式…...

安装Apache mysql php
目录 一.Apache网站服务 Apache——》静态页面处理——》将静态处理交给PHP Apache简介 安装Apache服务 编辑 安装软件思路 二.安装mysql数据库 1. 安装依赖包 2.创建程序用户管理 3.加压安装包 这边就安装完成了编辑 重点来了 报错了 没有空间 我最后的解决 方法…...

【人工智能】— 神经网络、前向传播、反向传播、梯度下降、局部最小值、多层前馈网络、缓解过拟合的策略
【人工智能】— 神经网络、前向传播、反向传播 前向传播反向传播梯度下降局部最小值多层前馈网络表示能力多层前馈网络局限缓解过拟合的策略 前向传播和反向传播都是神经网络训练中常用的重要算法。 前向传播是指将输入数据从输入层开始经过一系列的权重矩阵和激活函数的计算后…...

小文智能自定义变量详解
在小文交互场景设计时,有一个特殊功能,叫做自定义变量。有时,根据外呼对象的不同,需要对用户传达不同的内容,比如称呼、地址、公司名称等等。此时,就可以使用小文交互的自定义变量功能来实现对不同用户呼出…...
平面电磁波的反射与折射,极化滤波作用
目录 引言 反射定律和折射定律 反射系数和折射系数 平面电磁波在理想介质分界面上的全反射和全折射 全反射 全折射 极化滤波作用 平面电磁波在良导体上的反射与折射 引言 再复杂的电磁波我们都可以看作是很多平面电磁波的叠加 我们在前面介绍的时候,我们认…...
键盘当鼠标用
当鼠标坏掉又需要使用电脑时发现触控板也不能用这就很烦那么键盘当鼠标用教程来了 使用键盘当鼠标的步骤如下: 1. 按住“AltShiftNum Lock”快捷键,弹出鼠标键开启咨询框,点击“是”按钮。 小键盘的数字就是方向/和*就是左右键切换5是单击 …...
动态规划part9 | ● 198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III
文章目录 198.打家劫舍思路思路代码官方题解代码 213.打家劫舍II思路思路代码官方代码困难 337.打家劫舍III思路思路代码官方题解代码困难 今日收获 198.打家劫舍 198.打家劫舍 思路 dp含义,偷前i个房,切第i个房偷 dp[i]max(dp[i-2],dp[i-3])nums[i] …...

【k8s系列】一分钟搭建MicroK8s Dashboard
本文基于上一篇文章的内容进行Dashboard搭建,如果没有看过上一篇的同学请先查阅上一篇文章 k8s系列】使用MicroK8s 5分钟搭建k8s集群含踩坑经验 使用MicroK8s搭建Dashboard很简单,只需要在Master节点按照以下几步操作 1.启用Dashboard插件 microk8s en…...

ArcEngine二次开发0——入门(下载 部署 组件学习)
折腾一下ArcGIS Engine二次开发。 目录 1、开发环境配置2、部署一个ArcGIS Engine应用程序3、ArcObject组件学习4、报错及解决4、其他 1、开发环境配置 参考:https://blog.csdn.net/H48662654/article/details/113384150 (使用ArcEngine前,…...

人工智能---D分离
D分离(D-Separation)是一种用来判断变量是否条件独立的图形化方法。相比于非图形化方法,D-Separation更加直观,且计算简单。对于一个DAG(有向无环图)E,D-Separation方法可以快速的判断出两个节点…...

java spring cloud 企业工程项目管理系统源码-全面的工程项目管理
工程项目管理系统是指从事工程项目管理的企业(以下简称工程项目管理企业)受业主委托,按照合同约定,代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 如今建筑行业竞争激烈,内卷严重,…...

2023最新软件测试面试题【1000道题含答案】
1、自动化代码中,用到了哪些设计模式? 单例设计模式 工厂模式PO设计模式数据驱动模式面向接口编程设计模式 2、什么是断言( Assert) ? 断言Assert用于在代码中验证实际结果是不是符合预期结果,如果测试用例执行失败会抛出异常并提供断言日志 3、什么是web自动化测…...

【目标跟踪】MOT数据集GroundTruth可视化
MOT数据集格式简介 MOT15数据集下载:https://pan.baidu.com/s/1foGrBXvsanW8BI4eybqfWg?pwd8888 以下为一行gt示例: 1,1,1367,393,73,225,1,-1,-1,-1 各列数据对应含义如下 <frame>,<id>,<bb_left>,<bb_top>,<bb_width&g…...

软件测试的概念与过程----学习软件测试前的思考
软件测试的概念与过程----学习软件测试前的思考 1、软件测试工作是做什么的?2、那我做软件测试拿到一个软件产品我应该从哪里测试,怎末开始工作?3、测试早做好还是晚一些做好?4、软件测试能将软件测试的一点问题都没有嘛ÿ…...

Streamlit基础教程
streamlit是什么 streamlit是一个开源的python库,它能够快速的帮助我们创建定制化的web应用,而且还非常便于和他人分享,特别是在机器学习和数据科学领域。整个过程不需要你了解任何前端的知识,包括html、css、javascript等&#x…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...

【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:Floyd 快慢指针法(…...