第1篇: 讲述了如何创造"缝".  "缝"(seam)是需要知道的概念.

第2篇, 避免在构建对象时写出不易测试的代码.

第3篇, 依赖项和迪米特法则.

第4篇, 全局状态引起的问题.

本文是第5篇, 也是最后一篇, 介绍的是单一职责

类做了太多的工作

例子, 某软件公司, 原有项目开发, 测试, 售前, 售后, 财务等员工. 后来由于公司没钱, 裁掉了测试, 让开发兼职; 过了段时间, 又裁掉了需求和售后, 还是由你这个开发来兼职; 再过了段时间, 又裁掉了财务和售前, 还是由你来兼职.

某天上班之后, 你刚想写代码, 就接到了客户来电, 说键盘不好用, 让你去给调试一下. 花了1个小时从客户那里调试回来又刚想写点代码, 某客户说发票没给, 你又去快递发票. 回来之后又想写代码, 又有客户来电话咨询你公司的XXX管理系统, 经过半个小时的讲解, 客户没兴趣. 这时已经到了中午, 你却发现你的本职工作一点都做.

在现实世界中, 给某个员工赋与很多冲突的角色或职责是很不明智的.

在软件开发里也是这样的, 在为一个类赋予太多的职责会引出很多维护和测试的问题.

单一职责

单一职责是面向对象软件设计的准则之一, 它说的是: "一个类只能因为一个原因去改变".

这就是说我们应该增加 因为相同原因而做出改变的东西 的内聚性, 而降低 由于不同原因而做出改变的东西 的耦合性.

这句话通常被描述为: "一个类或一个方法只应该做一件事情, 并且要把它做好".

如果一个类有了太多的职责, 那么职责间的交互就会埋藏于类里, 这样做就很难一次修改一个职责. 对于测试来说, 这些交互之间也没有明显的"缝隙".

依赖项的构建工作并不是目标类本身的职责, 这项工作应该和类本身的职责分开. 所以我们会使用依赖注入配置好的对象. 我们应该对类进行抽取, 让其成为单一职责的类.

引起的问题

如果一个类有多个职责, 那么在测试上它会有以下问题:

  • 如果一个类/方法有太多的功能, 那么针对它的测试就会特别多, 很容易让人难于理解也很难维护.
  • 测试的设置也会更加的麻烦.
  • 由于有多个原因去修改该类, 那么它的测试类/方法就会修改的更加频繁.

危险信号

什么样的类/方法会违反单一职责呢?

  • 如果你在描述该类功能的时候用到了"和", "或", "还", "并且"等词.
  • 类或者方法的代码很多.
  • 注入了太多的依赖项.
  • 一个类改变的太频繁了也可能意味着这个类的职责可能不止一个.

解决方案

如果一个类有很多职责, 那么可以这样做:

  • 识别出类里面各个独立的职责.
  • 给每个职责贴上标签.
  • 解耦, 把其它功能抽取到单独的类, 最后保证每个类都是单一职责.

例子

举一个很简单的典型例子:

这个类, 有4个依赖项, 不算特别多, 但是也不少. 它的名字在这里就是它的描述, 里面包含了"或"的意思. 在它的方法参数里, 有一个标识, 像这样会改变方法的高级行为的标识, 通常就意味着该方法会有不止一个职责. 而方法体里面, 我们可以看到它确实有两个职责, 分别是发送邮件和打电话给客户.

优化后

经过识别, 抽取后, 该类应该分成下面两个类:

EmailCommand:

CallCommand:

这个系列的帖子就到这了.

下面开始介绍TDD.

.NET Core TDD 前传: 编写易于测试的代码 -- 单一职责的更多相关文章

  1. .NET Core TDD 前传: 编写易于测试的代码 -- 缝

    有时候不是我们不想做单元测试, 而是这代码写的实在是没法测试.... 举个例子, 如果一辆汽车在产出后没完成测试, 那么没人敢去驾驶它. 代码也是一样的, 如果项目未能进行该做的测试, 那么客户就不敢 ...

  2. .NET Core TDD 前传: 编写易于测试的代码 一 -- 缝

    转载于: https://www.cnblogs.com/cgzl/p/9365955.html 有时候不是我们不想做单元测试, 而是这代码写的实在是没法测试.... 举个例子, 如果一辆汽车在产出后 ...

  3. .NET Core TDD 前传: 编写易于测试的代码 -- 全局状态

    第1篇: 讲述了如何创造"缝".  "缝"(seam)是需要知道的概念. 第2篇, 避免在构建对象时写出不易测试的代码. 第3篇, 依赖项和迪米特法则. 本文是 ...

  4. .NET Core TDD 前传: 编写易于测试的代码 -- 构建对象

    该系列第1篇: 讲述了如何创造"缝".  "缝"(seam)是需要知道的概念. 本文是第2篇, 介绍的是如何避免在构建对象时写出不易测试的代码. 本文的概念性内 ...

  5. .NET Core TDD 前传: 编写易于测试的代码 -- 依赖项

    第1篇: 讲述了如何创造"缝".  "缝"(seam)是需要知道的概念. 第2篇, 避免在构建对象时写出不易测试的代码. 本文是第3篇, 讲述依赖项和迪米特法则 ...

  6. 新书《编写可测试的JavaScript代码 》出版,感谢支持

    本书介绍 JavaScript专业开发人员必须具备的一个技能是能够编写可测试的代码.不管是创建新应用程序,还是重写遗留代码,本书都将向你展示如何为客户端和服务器编写和维护可测试的JavaScript代 ...

  7. 编写可测试的JavaScript代码

    <编写可测试的JavaScript代码>基本信息作者: [美] Mark Ethan Trostler 托斯勒 著 译者: 徐涛出版社:人民邮电出版社ISBN:9787115373373上 ...

  8. 从一张图开始,谈一谈.NET Core和前后端技术的演进之路

    从一张图开始,谈一谈.NET Core和前后端技术的演进之路 邹溪源,李文强,来自长沙.NET技术社区 一张图 2019年3月10日,在长沙.NET 技术社区组织的技术沙龙<.NET Core和 ...

  9. 编写Avocado测试

    编写Avocado测试 现在我们开始使用python编写Avocado测试,测试继承于avocado.Test. 基本例子 创建一个时间测试,sleeptest,测试非常简单,只是sleep一会: i ...

随机推荐

  1. 巩固java(三)---java修饰符

    正文:               下面的表格列出了java中修饰符的一些信息: 修饰符名称 类型 类 变量 方法 abstract 非访问控制符 抽象类          -- 抽象方法 final ...

  2. phantomjs Can not connect to the Service phantomjs错误

    尝试方法一: 打开hosts文件配置 cat /etc/hosts 添加 127.0.0.1 localhost 重新运行 尝试方法二: 1,抛开服务,直接调用phantomjs定位问题 由于我是从服 ...

  3. BZOJ_1598_[Usaco2008 Mar]牛跑步_A*

    BZOJ_1598_[Usaco2008 Mar]牛跑步_A* Description BESSIE准备用从牛棚跑到池塘的方法来锻炼. 但是因为她懒,她只准备沿着下坡的路跑到池塘, 然后走回牛棚. B ...

  4. [NOIP2002]字串变换 T2 双向BFS

    题目描述 已知有两个字串  A,B  及一组字串变换的规则(至多6个规则): A1−>B1 A2−>B2 规则的含义为:在  A$中的子串  A1可以变换为可以变换为B1.A2可以变换为可 ...

  5. 我的新纪元Day01

    在我刚刚开通博客园后,想了好久.不知道第一次随笔该写点什么,想写些自己学到的知识,但技术上还是菜鸟的我完全不知道我能向别人分享什么,想到这里有些沮丧. 但万事开头难,只要我入了门,广阔的编程语言的世界 ...

  6. 基于Token认证的多点登录和WebApi保护

    在文章中有错误的地方,或是有建议或意见的地方,请大家多多指正,邮箱: linjie.rd@gmail.com 一天张三,李四,王五,赵六去动物园,张三没买票,李四制作了个假票,王五买了票,赵六要直接F ...

  7. 从壹开始 [ Id4 ] 之二║ 基础知识集合 & 项目搭建一

    前言 哈喽大家又见面啦,感觉好久没更新了,这几天看了一本书<解忧杂货铺>,嗯挺好的,推荐一下

  8. 从壹开始 [ Nuxt.js ] 之二 || 项目搭建 与 接口API

    前言 哈喽大家周一好,今天的内容比较多,主要就是包括:把前端页面的展示页给搭出来,然后调通接口API,可以添加数据,这两天我也一直在开发,本来想一篇一篇的写,发现可能会比较简单,就索性把项目搭建的过程 ...

  9. Spring Boot 2.0 图文教程 | 集成邮件发送功能

    文章首发自个人微信公众号: 小哈学Java 个人网站: https://www.exception.site/springboot/spring-boots-send-mail 大家好,后续会间断地奉 ...

  10. Jenkins 集成 SonarQube Scanner

    1.   安装Jenkins 下载安装包,这里我们下载war包 https://jenkins.io/download/ 运行jenkins.war的方式有两种: 第一种:将其放到tomcat中运行( ...