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

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

本文是第3篇, 讲述依赖项和迪米特法则.

迪米特法则 (Law of Demeter)

还是使用建造汽车的例子. 生产汽车的时候需要轮胎, 组装时需要什么型号的轮胎, 就请求该型号的轮胎, 然后相关人员会从库房把该型号的轮胎送到产线用于组装.

我相信很少有汽车厂会这样做: 生产汽车时, 汽车组装工拿着库房的钥匙, 自己去库房从各种各样的轮胎中找所需要的型号..

这就是违反迪米特法则的一个例子.

迪米特法则大概的意思是: "只访问你自己创建的对象, 或者作为参数传给你的对象. 不要通过其它对象间接的访问对象"

用一句话归纳迪米特法则就是: "只与直系朋友交谈, 不要和陌生人交谈".

注意: 迪米特法则其实并不算严格的法则, 它只是一个非常有益的指导性原则.

存在的问题

用代码形容上面的例子就是:

这违反了迪米特法则, 导致了以下问题:

  • 造成了BenzCar和Warehouse以及MichelinTire之间的紧耦合, 而实际上BenzCar只需要MichelinTire.

  • 测试时, 设置会很麻烦. 代码里Warehouse是直系朋友, MichelinTire是陌生人. 我们需要为Warehouse和MichelinTire同时设置测试替身.

  • 真正需要的依赖项没有明确在构造函数里定义. 这里Warehouse相当于是一个容器, 测试时, 我们可能会不知道要为Warehouse里的哪个东西做测试替身.

危险信号

下列写法可能意味着您的代码违反了迪米特法则:

  • 代码里有这样的调用: "warehouse.getTire.getMichelinTire", 有一连串的点".". 但是有时候这样做是可以的, 例如流畅(fluent)形式的建造者模式就可以, 因为fluent接口通常会返回对象本身, 然后再去使用该对象.

  • 依赖于容器. 例如把 IocContainer作为依赖注入使用.

  • 依赖项的名称为XxxContext, XxxContainer, XxxEnvironment, XxxManager, XxxServiceLocator.

  • 测试时需要创建返回mocks的mock对象.

  • 测试时的设置非常麻烦.

解决办法

解决办法就是遵从迪米特法则.

只注入我们直接需要的依赖项, 直接使用它们. 这样就会保证依赖项很明确, 测试的时候一眼就能看出依赖于哪些对象.

代码示例

例子一

下面这个违反了迪米特法则, 直接注入的是Warehouse, 而实际用到的却是MichelinTire:

正确的做法是, 注入直接使用的依赖项:

例子二

下面的代码也违反了迪米特法则, 它注入了一个容器类的对象:

这个ServiceLocator就相当于是一个容器. 这样用的话, 写测试的人可能根本无法知道需要使用容器里面的哪个对象.

你也许会说这样做灵活(我以前也经常这样做), 但是重构的时候, 这里很容易出错, 因为根本看不出来真正依赖的是哪个对象.

正确的做法还是应该注入直接需要的依赖项:

Law of Demeter相关的内容就简单介绍这些.

原文地址:https://www.cnblogs.com/cgzl/p/9389176.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

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

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

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

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

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

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

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

  4. 单元测试:如何编写可测试的代码及其重要性

    原文来自互联网,由长沙DotNET技术社区编译.如译文侵犯您的署名权或版权,请联系小编,小编将在24小时内删除.限于译者的能力有限,个别语句翻译略显生硬,还请见谅. 作者:谢尔盖·科洛迪(SERGEY ...

  5. 如何编写可测试的代码 哈利勒的方法论

    Understanding how to write testable code is one of the biggest frustrations I had when I finished sc ...

  6. ORAN专题系列-18:5G O-RAN FrontHaul前传接口互操作性测试规范IOT概述与总体架构

    前言: 前传接口(FrontHual)是传统的BBU与RU之间的接口,在O-RAN之前,前传接口虽然定义了物理连接的CPRI标准,但CPRI之上承载的M plane和S/C/U plane的IQ数据, ...

  7. 用java写穿越火线代码_编写可测试的 JavaSript 代码

    无论我们使用和Node配合在一起的测试框架,例如Mocha或者Jasmine,还是在像PhantomJS这样的无头浏览器中运行依赖于DOM的测试,和以前相比,我们有更好的方式来对JavaScript进 ...

  8. ORAN专题系列-19:5G O-RAN FrontHaul前传接口M Plane互操作性测试IOT规范

    前言: 在<ORAN专题系列-18:5G O-RAN FrontHaul前传接口互操作性测试规范IOT概述与总体架构>阐述了5G O-RAN FrontHaul前传接口互操作性测试规范IO ...

  9. 《编写可测试的JavaScript代码》——1.4 小结

    本节书摘来自异步社区<编写可测试的JavaScript代码>一书中的第1章,第1.4节,作者: [美]Mark Ethan Trostler 译者: 徐涛 更多章节内容可以访问云栖社区&q ...

最新文章

  1. 未来全球15大热门研究方向出炉!
  2. Docker - Tips
  3. Overlay 网络 — Overview
  4. 08-cmake语法-set()
  5. 初识ABP vNext(5):ABP扩展实体
  6. python读取word图片_Python中如何读取Word中的图片
  7. 【报告分享】迈向更好的教育:未来教育的技术空间研究报告.pdf(附下载链接)
  8. 如何利用Camtasia为视频添加注释?
  9. java中的控制执行流程
  10. cisco5525防火墙***流量分离即***和nat并存的配置方式
  11. HTML5响应式手机模板:h5手机抽奖游戏活动页面集合模板 HTML+CSS+JavaScript
  12. word制作表格并打印
  13. 2019软科【世界一流计算机学科排名】公布!
  14. Egyptian Miracle Technical Service Support
  15. influxDB快速入门实战教程
  16. 安装win7x64、x86总提示文件出错或安装大型软件出错或0x0000001a、0x0000003b蓝屏
  17. 如何快速剪辑多个视频,将视频分段保存导出播放
  18. 头文件 INTRINS.H 的用法
  19. 【译】AN1297:使用Silicon Labs蓝牙协议栈的定制测向解决方案
  20. 物联网卡智能净水器打造智慧洁净生活

热门文章

  1. 神经网络- receptive field
  2. 自动判断PC端、手机端跳往不同的域名JS实现代码
  3. 图片压缩上传Thumbnailator 插件
  4. 段落排版--行间距, 行高(line-height)
  5. Linux集群服务知识点总结及通过案例介绍如何实现高性能web服务(三)
  6. windows phone 8 的新特性
  7. C#学习笔记(十四):StatusBar控件
  8. 茫茫内存,我该如何用 windbg 找到你 ?
  9. Dotnet的数据定位和匹配
  10. Abp vNext 后台作业hangfire