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

第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相关的内容就简单介绍这些.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员的碎碎念

数据挖掘敲门砖--Python爬虫入门

? WHAT 数据挖掘是一门综合的技术,随着Ai的兴起,在国内的需求日渐增大。 数据挖掘的职业方向通常有三个,顺便概要地提一下所需的技能(不仅于此) 数据分...

4908
来自专栏斑斓

软件系统的稳定性

软件系统的稳定性,主要决定于整体的系统架构设计,然而也不可忽略编程的细节,正所谓“千里之堤,溃于蚁穴”,一旦考虑不周,看似无关紧要的代码片段可能会带来整体软件系...

8666
来自专栏微信公众号:Java团长

如何扎实自己的Java基础?

JDK其实就是Java SE Development Kit的缩写,要玩好这东西可不简单。JDK主要包含了三部分,第一部分就是Java运行时环境,这其实就是JV...

1143
来自专栏csxiaoyao

USTC高级软件工程课程学习心得

38310
来自专栏张善友的专栏

Web 单点登录系统

对于企业内部系统来说,CAS系统是一个应用最广的开源单点登陆实现了,其实现模仿Kerberos的一些概念,例如KDC、TGS等等,都是来自于Kerberos。具...

29510
来自专栏架构师之旅

3个面试中遇到的问题《JAVA面试题》

面试官:“一个http 请求,接受json数组,数组内容是id,返回用户信息,在测试上是ok的,到预生产就报错了,可能是什么问题?” 我想了想说:“代码一致吗?...

7715
来自专栏大学生计算机视觉学习DeepLearning

c语言课程设计之贪吃蛇代码及思路

5927
来自专栏喔家ArchiSelf

回顾Bob大叔的简洁架构

Robert Martin 就是我们常说的Bob大叔,是码界的骨灰级人物了,在4年前提出了所谓的简洁架构,值得回顾反思一下,看看是否可以借鉴到微服务中呢?

862
来自专栏Kirito的技术分享

一个DDD指导下的实体类设计案例

终于开通原创功能了,大家以后可以在文章下方留言了,欢迎交流。 1 前言 项目开发中的工具类代码总是随着项目发展逐渐变大,在公司诸多的公用代码中,笔者发现了一个...

3837
来自专栏编程一生

架构师之路--应用架构的选型和dubbo

1522

扫码关注云+社区

领取腾讯云代金券