红灯-绿灯-重构

news2024/10/6 1:41:08
  1. 代码在周期内的状态:处于红灯状态时,代码不管用,处于绿灯状态时,一切都想预期的那样工作,但并不一定是最佳的,到了重构阶段,我们知道测试很好的覆盖了各项功能,可以充满信息地修改他,让他变得更好

  2. 编写一个测试:

    1. 每次添加新功能时,都要首先编写一个测试,当前处于红灯状态,因为测试执行时以失败告终,即测试对代码的期望和代码实际的功能之间存在差距,更具体的说,没有代码满足最后一个测试的期望,因为我们还没有编写这样的代码,在这个阶段,可能所有的测试都通过了,但这表示存在问题
  3. 运行所有测试并确认最后一个未通过:

    1. 确认最后一个测试未通过后,就能断定他不会在没有引入新代码的情况下错误通过,如果这个测试通过了,就意味着要么相关功能早就存在,要么测试本身存在误报的问题,如果测试无论怎么实现都能通过,就意味着他毫无价值,应该删除。最后一个测试不仅必须未通过,还必须是预期原因导致的,在这个阶段,我们依然处于红灯状态,运行测试,但最后一个未通过
  4. 编写实现代码

    1. 这个阶段的目标是编写代码使最后一个测试通过。不要试图让代码完美无缺,也不要为编写花过多时间。即便编写的不好或者不是最后的,也没有关系,后面还有改进的机会。我们的真实意图是打造一个由测试构成的安全网,并确认这些测试都能通过。不要试图引入最后一个测试未描述的功能。要想引入新功能,必须回到第一步,先编写新测试。然而,仅当所有既有测试都通过后,我们才能这么做。在这个阶段,我们依然处于红灯状态。虽然已编写的代码可能让所有测试都通过,但这种假设还未得到证实。
  5. 运行所有测试

    1. 应运行所有测试,而不是只运行最后编写的那个测试,这至关重要。你刚编写的代码可能让最后一个测试得以通过,但同时破坏了其他功能。通过运行所有测试,不仅可确认最后一个测试的实现是正确的,还可确认它没有破坏整个应用程序的完整性。如果整个测试集执行速度缓慢,就昭示着测试编写得不好或者代码耦合度太高。耦合度太高将导致难以隔离外部依赖,进而增加执行测试所需的时间。在这个阶段,我们处于绿灯状态:所有测试都通过,且应用程序的行为符合预期
  6. 重构

    1. 前面所有步骤都是必不可少的,但这一步是可选的。虽然很少在每个周期结束后都进行重构,但迟早需要甚至必须这样做。并非每个测试的实现都需要重构;没有明确的规定说什么时候该重构、什么时候不用重构。一旦认为可以更佳或更优的方式重写代码,那就是重构的最佳时机。
    2. 什么样的代码需要重构呢?这个问题不好回答,因为重构的原因有很多:代码难以理解、代码位置不合理、代码重复、名称没有清晰阐述意图、方法太长、类的功能太多等——这个清单可不断列下去。不管原因是什么,最重要的规则是重构不能改变任何既有功能。
  7. 重复

    1. 所有步骤都完成后(其中重构是可选的),再重复它们。编写110行代码后就切换到下一步,因此整个周期的持续时间为几秒几分钟。如果更长,就说明测试的范围太大,应将其分成多个更小的测试。一定要快速前进,快速失败并更正,然后再重复。
  8. 案例:3*3的棋盘下棋

    1. 实现

      public class TicTacToeSpec { 
       @Rule 
       public ExpectedException exception = 
       ExpectedException.none(); 
       private TicTacToe ticTacToe; 
       @Before 
       public final void before() { 
       ticTacToe = new TicTacToe(); 
       } 
       @Test 
       public void whenXOutsideBoardThenRuntimeException() 
       { 
       exception.expect(RuntimeException.class); 
       ticTacToe.play(5, 2); 
       } 
      }
      
      1. expected属性,你可以用它来指定一个Throwble类型,如果方法调用中抛出了这个异常,这条测试用例就算通过了

      2. 这个测试中,我们指出调用方法ticTacToe.play(5,2)时,期望的结果是引发RuntimeException异常,这个测试只需创建方法play,并确保他在参数x小于1或者大于3时引发RuntimeException异常

      3. 应该测试三次,第一次运行时,他应该不通过,因为此时还没有方法play,添加这个方法后,测试也应该不通过,因为他没有引发异常RuntimeException,第三次运行时应该通过,因为他实现了与这个测试相关联的所有代码

    2. 测试

      1. 验证Y轴

      2. @Test 
         public void whenYOutsideBoardThenRuntimeException() { 
         exception.expect(RuntimeException.class); 
         ticTacToe.play(2, 5); 
         }
        
    3. 实现

      1. public void play(int x, int y) { 
         if (x < 1 || x > 3) { 
         throw 
         new RuntimeException("X is outside board"); 
         } else if (y < 1 || y > 3) { 
         throw 
         new RuntimeException("X is outside board"); 
         } 
         }
        
      2. 为让最后一个测试通过,添加一条“检查参数Y是否在棋盘内”的else子句。

    4. 测试

      1. 确定棋子在棋盘边界内后,还需确保它放在未被别的棋子占据的地方

      2. @Test 
         public void whenOccupiedThenRuntimeException() { 
         ticTacToe.play(2, 1); 
         exception.expect(RuntimeException.class); 
         ticTacToe.play(2, 1); 
         }
        
    5. 实现

      1. 为实现最后一个测试,应将既有棋子的位置存储在一个数组中。每当玩家放置新棋子时,都应确认棋子放在未占用的位置,否则引发异常

      2. private Character[][] board = {{'\0', '\0', '\0'}, 
         {'\0', '\0', \0'}, {'\0', '\0', '\0'}}; 
         public void play(int x, int y) { 
         if (x < 1 || x > 3) { 
         throw 
         new RuntimeException("X is outside board"); 
         } else if (y < 1 || y > 3) { 
         throw 
         new RuntimeException("Y is outside board"); 
         } 
         if (board[x - 1][y - 1] != '\0') { 
         throw 
         new RuntimeException("Box is occupied"); 
         } else { 
         board[x - 1][y - 1] = 'X'; 
         } 
         }
        
    6. 重构

      1. 重构play方法

      2. public void play(int x, int y) { 
         checkAxis(x); 
         checkAxis(y); 
         setBox(x, y); 
         } 
         private void checkAxis(int axis) { 
         if (axis < 1 || axis > 3) { 
         throw 
         new RuntimeException("X is outside board"); 
         } 
         } 
         private void setBox(int x, int y) { 
         if (board[x - 1][y - 1] != '\0') { 
         throw 
         new RuntimeException("Box is occupied"); 
         } else { 
         board[x - 1][y - 1] = 'X'; 
         } 
         }
        
  9. 编写一个测试,发现他不能通过,编写实现代码,发现所有测试都通过,只要有机会就重构代码使其变得更好,并重复这个过程

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

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

相关文章

408笔记|随笔记录|自用|2

文章目录 cache和TLB查找总结 接上篇选择题 打开同一个文件共享同一个内存索引结点 cache和TLB cache由SRAM组成&#xff0c;TLB通常由相联存储器组成&#xff0c;可以由SRAM组成。 DRAM需要不断刷新&#xff0c;性能比较低。 TLB缺失可以由软件或者硬件处理&#xff0c;cac…

JC系列CAN通信说明

目录 一、CAN协议二、指令格式三、通信接线3.1、一对一通信3.2、组网通信 四、寄存器定义五、指令说明4、读取电源电压5、读取母线电流6、读取实时速度8、读取实时位置10、读取驱动器温度11、读取电机温度12、读取错误信息32、设定电流33、设定速度35、设定绝对位置37、设定相对…

Java-进阶二

ArrayList的源代码分析&#xff08;扩容原理&#xff09; 1 使用空参构造的集合&#xff0c;在底层创建一个容量为0的数组。2 添加第一个元素时&#xff0c;底层会扩容创建一个容量为10的数组。3 存满时会扩容1.5倍。4 如果一次添加多个元素&#xff0c;1.5倍还放不下&#xff…

机器学习/数据分析--用通俗语言讲解时间序列自回归(AR)模型,并用其预测天气,拟合度98%+

时间序列在回归预测的领域的重要性&#xff0c;不言而喻&#xff0c;在数学建模中使用及其频繁&#xff0c;但是你真的了解ARIMA、AR、MA么&#xff1f;ACF图你会看么&#xff1f;&#xff1f; 时间序列数据如何构造&#xff1f;&#xff1f;&#xff1f;&#xff0c;我打过不少…

提升客户满意度,数字化售后工单系统的实施策略

售后工单系统助企业优化运营&#xff0c;提升客户满意度。涵盖技术支持、维修服务、客户反馈管理等应用场景。ZohoDesk凭高效定制成企业首选。未来趋势包括AI、物联网、AR/VR技术集成&#xff0c;提升服务智能化水平。 一、售后工单系统的重要性 售后工单系统是企业用来管理和…

基于Java的GeoTools对Shapefile文件属性信息深度解析

目录 前言 一、Shapefile的属性列表信息 1、属性表格信息 2、属性表格包含的要素 二、GeoTools对属性表格的解析 1、常规解析方法 2、基于dbf文件的属性信息读取 三、总结 前言 ESRI Shapefile&#xff08;shp&#xff09;&#xff0c;或简称shapefile&#xff0c;是美…

SQL优化 - 排序

文章目录 排序和索引降序索引 FilesortORDER BY 顺序问题ORDER BY LIMIT 排序和索引 如果ORDER BY操作使用了索引&#xff0c;那么就可以避免排序操作&#xff0c;因为索引本身就是按索引 key 排好序的。那什么情况下&#xff0c;ORDER BY会走索引呢&#xff1f; 例如&#…

专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结

目录 搜索 vs 深度优先遍历 vs 深度优先搜索 vs 宽度优先遍历 vs 宽度优先搜索 vs 暴搜 1.深度优先遍历 vs 深度优先搜索(dfs) 2.宽度优先遍历 vs 宽度优先搜索(bfs) 2.关系图暴力枚举一遍所有的情况 3.拓展搜索问题全排列 决策树 1. 计算布尔⼆叉树的值&#xff08;medi…

CF2013E Prefix GCD

【题目大意】 给定一个长度为 n n n 的数列 a 1 … n a_{1 \dots n} a1…n​&#xff0c;你可以将 a 1 … n a_{1 \dots n} a1…n​ 按照任意顺序进行重排&#xff0c;使得&#xff1a; ∑ i 1 n gcd ⁡ { a 1 , a 2 , a 3 , … , a n } \sum\limits_{i1}^{n}\gcd\left \{…

10.5学习

1.GateWay GateWay⽬标是取代Netflflix Zuul&#xff0c;它基于Spring5.0SpringBoot2.0WebFlux等技术开发&#xff0c;提供统⼀的路由⽅式&#xff08;反向代理&#xff09;并且基于 Filter(定义过滤器对请求过滤&#xff0c;完成⼀些功能) 链的⽅式提供了⽹关基本的功能&…

探索 Python 虚拟环境的奥秘:virtualenv 的魔法世界

文章目录 探索 Python 虚拟环境的奥秘&#xff1a;virtualenv 的魔法世界背景&#xff1a;为何选择 virtualenv&#xff1f;虚拟环境的守护者&#xff1a;virtualenv 是什么&#xff1f;安装 virtualenv&#xff1a;简单几步&#xff0c;开启隔离之旅掌握 virtualenv 的基本用法…

Relu激活

ReLU&#xff08;Rectified Linear Unit&#xff09;激活函数 是卷积神经网络&#xff08;CNN&#xff09;以及许多深度学习模型中最常用的激活函数之一。它的主要作用是引入非线性&#xff0c;使模型能够学习和表达更复杂的特征。以下是对ReLU激活函数的详细解释。 1. ReLU的…

C语言进阶版第16课—自定义类型:结构体

文章目录 1. 结构体类型的声明和初始化2. 结构体自引用3. 结构体内存对齐3.1 结构体内存对齐规则3.2 修改默认对齐数 4. 结构体传参4. 结构体实现位段5. 位段使用的注意事项 1. 结构体类型的声明和初始化 结构体在使用之前都要对其类型进行声明&#xff0c;关键字是struct&…

15分钟学 Python 第36天 :Python 爬虫入门(二)

Python 爬虫入门&#xff1a;环境准备 在进行Python爬虫的学习和实践之前&#xff0c;首先需要准备好合适的开发环境。本节将详细介绍Python环境的安装、必要库的配置、以及常用工具的使用&#xff0c;为后续的爬虫编写奠定坚实的基础。 1. 环境准备概述 1.1 为什么环境准备…

mp4转gif在线转换怎么转?7个视频转动图方法不容错过!(超简单)

mp4转gif在线转换怎么转&#xff1f;如今&#xff0c;将mp4视频转换为gif动图格式&#xff0c;满足了人们对易于分享和网络传播内容的需求。与mp4视频相比&#xff0c;gif动图文件体积相对较小&#xff0c;几乎所有网络平台都支持这种格式&#xff0c;无需额外安装插件或软件。…

CSID-GAN:基于生成对抗网络的定制风格室内平面设计框架论文阅读

CSID-GAN: A Customized Style Interior Floor Plan Design Framework Based on Generative Adversarial Network 摘要前言II. CSID-GAN METHODA. Overall FrameworkB. Algorithm and Loss Function III. DATASETS AND EVALUATION METRICSA. DatasetsB. Evaluation Metrics IV.…

信息安全工程师(34)访问控制模型

前言 访问控制模型是实现访问控制的基础&#xff0c;不同的访问控制模型提供了不同的访问控制策略和机制&#xff0c;以适应不同的安全需求。 一、自主访问控制模型&#xff08;DAC&#xff09; 定义&#xff1a;指资源的所有者有权决定谁可以访问其资源以及访问的方式。资源的…

如何实现事件流操作

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了通道相关的内容,本章回中将介绍StreamProvider组件.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 在Flutter中Stream是经常使用的组件,对该组件的监听可void main() {///让状态栏和程序的appBar融为一体…

macos安装mongodb

文章目录 说明安装和配置安装mongodb配置PATH变量 验证日志及数据存放目录 mac启动和关闭mongodb后台启动失败问题mongodb-compass(GUI) 说明 Homebrew core 列表目前已经将 MongoDB 移除,不再为其提供支持。但是使用国内镜像的brew还是可以安装的&#xff01;这里直接从官网下…

使用 Python 代码连接 PostgreSQL

Python 是一个功能非常强大的编程语言&#xff0c;尤其在与数据库交互时&#xff0c;提供了丰富的解决方案。在实际项目中&#xff0c;我们经常需要通过 Python 连接并操作数据库。为了简化这种操作&#xff0c;ORM&#xff08;对象关系映射&#xff09;框架提供了便利。ORM 能…