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

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

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

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

 

迪米特法则 (Law of Demeter)

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

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

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

 

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

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

 

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

 

存在的问题

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

640?wx_fmt=png

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

  • 造成了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:

640?wx_fmt=png

 

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

640?wx_fmt=png

 

例子二

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

640?wx_fmt=png

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

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

 

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

640?wx_fmt=png

 

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

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

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

640?wx_fmt=jpeg

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

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

相关文章

【dfs】家族(jzoj 1985)

家族 jzoj 1985 解题思路: 在一个只含空格,‘*’号和小写字母的图上,问有多少个连在一起(上下左右四个方向)的小写字母块 输入样例 4 *zlw**pxh l*zlwk*hx* w*tyy**yyyzzl输出样例 3数据范围 10%的数据&#xf…

51nod1325-两棵树的问题【最大权闭合图,网络流】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1325 题目大意 两棵树。要求选出一组权值和最大的点使得这两个点集在两棵树上都是连通的。 解题思路 我们枚举一个中间点iii,然后从这个点开始扩展连通块。那么如果这个点作为根的话&#x…

【背包】作业(jzoj 1986)

作业 jzoj 1986 解题思路: ‘光光’在暑假有很多作业,但他不能全部做完,他只有一定的时间,某一项作业没做完(有一点没做完也算),他就会有一个不开心值,现在问不开心值最小是多少 …

HDU5875 - Function

HDU5875 - Function 做法&#xff1a;st表二分的经典题。不能使用数学函数log&#xff0c;否则会tle&#xff0c;需要预处理 #include <bits/stdc.h> #define rep(i,a,b) for(int ia;i<b;i) #define per(i,a,b) for(int ia;i>b;--i) #define mem(a,b) memset(a,b,s…

.Net Core中的日志组件(Logging)

1、介绍Logging组件是微软实现的日志记录组件包括控制台(Console)、调试(Debug)、事件日志(EventLog)和TraceSource&#xff0c;但是没有实现最常用用的文件记录日志功能(可以用其他第三方的如NLog、Log4Net。之前写过NLog使用的文章)。2、默认配置新建.Net Core Web Api项目&a…

51nod1551-集合交易【hall定理,最大权闭合图,网络流】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1551 题目大意 nnn个集合&#xff0c;nnn个物品&#xff0c;每个集合有一些物品&#xff0c;一个价钱。满足任意kkk个集合都有kkk种不同的物品。 要求一个最低的价格来购买集合且购买集合数等于里面不同…

HDU5874 - Friends and Enemies

HDU5874 - Friends and Enemies 题意&#xff1a;m个人&#xff0c;n种颜色的石头&#xff0c;两个人不是朋友就是敌人&#xff0c;朋友之间至少有一个同种颜色的石头&#xff0c;敌人之间不能有相同的石头&#xff0c;问用最多种的石头的情况下&#xff0c;n能否满足要求 做法…

纪中C组模拟赛总结(2019.7.9)

成绩&#xff1a; 注&#xff1a;rankrankrank是有算其他dalaodalaodalao的 rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3T4T4T4111hkyhkyhky400400400100100100100100100100100100100100100303030tjhtjhtjh240240240100100100303030101010100100100696969fyfy…

将 ASP.NET Core 2.0 项目升级至 ASP.NET Core 2.1.3X

阅读文本大概需要 3.3 分钟。在上一篇文章《ASP.Net Core 运行错误 Http Error 502.5 解决办法》的最后有提到说&#xff0c;最推荐的升级办法是从2.0升级到2.1X版本.操作如下项目的例子直接使用https://github.com/52ABP/52ABP.School 作为对象&#xff0c;毕竟他正好是.NET C…

CF55D-Beautiful numbers【数位dp】

正题 题目链接:https://www.luogu.com.cn/problem/CF55D 题目大意 求[l,r][l,r][l,r]中有多少个数使得它可以被它的所有非000位整除。 解题思路 因为这些数的lcmlcmlcm一定是lcm(1,2,3,4,5,6,7,8,9,10)2520lcm(1,2,3,4,5,6,7,8,9,10)2520lcm(1,2,3,4,5,6,7,8,9,10)2520的约数…

【DP】合唱队形(jzoj 1122)

合唱队形 jzoj 1122 题目大意&#xff1a; 有n个人&#xff0c;按一定的顺序站成一排&#xff0c;最少减去多少个人可以使队列以一个人为中心&#xff0c;两边分别递减 输入样例 8 186 186 150 200 160 130 197 220输出样例 4数据范围 对于50&#xff05;的数据&#xf…

HDU5877 - Weak Pair

HDU5877 - Weak Pair 做法&#xff1a;dfs的时候&#xff0c;用树状数组维护当前节点到跟节点的权值树状数组&#xff0c;离散化一下即可&#xff0c;类似统计树上逆序对。此题数据范围好像是假的&#xff0c;节点数开到200000可过。 #include <bits/stdc.h> #define pb …

jzoj5248-[NOIP2017提高A组模拟8.10]花花的聚会【倍增,树形dp】

正题 题目链接:https://gmoj.net/senior/#main/show/5248 题目大意 nnn个点的一棵树&#xff0c;有mmm张票(v,k,w)(v,k,w)(v,k,w)表示可以在点vvv买&#xff0c;可以走kkk步以内&#xff0c;价格为www。 一个时间只能有一个票&#xff0c;每次询问一个点到根节点需要的最少票…

【高精】Gift(jzoj(gz) 1763)

Gift jzoj&#xff08;gz&#xff09; 1763 题目大意&#xff1a; 有9个数&#xff1a;a,b,c……i,计算出2a2b……2hi2^a2^b……2^hi2a2b……2hi 输入样例 1 21 30 0 0 0 0 0 0 2147483647输出样例 3223322629数据范围 40% t<1000 100% t<100000 a,b,c,d,e,f,g,h&…

.net core 多版本如何选择

在讲述.net core多版本之前&#xff0c;我们先理解一下.net core sdk与.net core runtime之前的联系与区别&#xff0c;根据官网的解释我们可以简单地理解为&#xff1a;sdk是在开发过程中进行使用&#xff0c;而runtime是在项目发布后作为运行环境进行安装的&#xff0c;runti…

P3226-[HNOI2012]集合选数【状压dp】

正题 题目链接:https://www.luogu.com.cn/problem/P3226 题目大意 1∼n1\sim n1∼n选出一些组成集合&#xff0c;一个集合里如果有xxx则不能有2x,3x2x,3x2x,3x。求有多少合法集合。 解题思路 我们可以构造一个矩阵 13927…2618…412…8… 这样选择一个位置后它相邻的位置就不…

HDU5120 - Intersection

HDU5120 - Intersection 做法&#xff1a;答案就是\(A1 \cap B1 - A2 \cap B1 - A1 \cap B2 A2 \cap B2\)&#xff0c;圆形面积交码了好久&#xff0c;先把两个圆转到x轴上&#xff0c;大的放到原点&#xff0c;小的放在大圆的左边&#xff0c;计算一下交点坐标&#xff0c;然…

【结论】Number(jzoj(gz) 1781)

Number jzoj&#xff08;gz&#xff09; 1781 题目大意&#xff1a; 现在给出一个x&#xff0c;可以把x变为4x3或8x7&#xff0c;问最少变多少次可以把x变为1000000007的倍数 输入输出样例 输入样例#1 125000000输出样例#1 1输入样例#2 281250001输出样例#2 2输入样例…

好代码是管出来的——使用GitHub实现简单的CI/CD

软件开发一般来说是一项团队作业&#xff0c;在本系列文章开始就提到过软件的编码是由一个团队“并行”完成的&#xff0c;为了保证编码任务正常完成&#xff0c;首先引入版本控制工具来完成代码管理&#xff0c;为了保证代码质量引入了代码分析器以及代码测试。版本控制工具可…

HDU5119 - Happy Matt Friends

HDU5119 - Happy Matt Friends 做法&#xff1a;拆成两堆数&#xff0c;分别暴力出两组的所有异或值A,B&#xff0c;枚举A, 将B全部插入Trie树&#xff0c;通过枚举的数每一位的值,确定异或后构成的新树&#xff0c;然后在新树上统计比m大的值的个数即可。 #include <bits/s…