Mor*_*ten 27 tdd unit-testing dependency-injection coding-style interface
我目前正在阅读Rober Martin(UncleBob)的"清洁代码",并且一般都喜欢UncleBob的沉思.但是,当我读到他避免使用像"IPerson"这样的接口前缀时,我有点困惑.他说:"我不希望我的用户知道我正在为他们提供一个界面".
从TDD /注入角度思考,我总是非常有兴趣告诉我正在处理接口的类的"用户".主要原因是我认为接口在系统的不同"代理"之间收缩.在我的系统的一个角落工作的代理,不应该知道另一个代理工作的具体实现; 他们只应该交换合同,并期望在不知道如何履行合同的情况下履行合同.另一个但也非常重要的原因是可以完全模拟界面,从而使单元测试更容易.你可以在具体课上嘲笑多少是有限的.
因此,我更愿意想象我确实在交接接口......或者以接口作为参数.但是因为UncleBob是我们社区中的重量级冠军,而我只是另一位flyweigth桌面骑师,我想知道我是否遗漏了一些东西.
我坚持使用接口是不对的?
小智 57
我们已经习惯了Java和C#中的一些约定; 但这是倒退的.例如,从技术角度来看,将私有变量放在每个类顶部的惯例是非常愚蠢的.关于班级最重要的事情是它的公共方法.在最重要的事情,我们的东西隐藏隐私屏障后面,都是实例变量.那么我们为什么要把它们放在首位呢?
接口前面的"I"是另一种向后的惯例.当您传递对对象的引用时,您应该期望它是一个接口.接口应该是默认的; 所以没有必要做一些额外的事情,比如使用我的前缀,宣布你正在做每个人都希望你做的事情.如果我们为传递具体类的异常条件保留一个特殊标记会更好(尽管仍然是错误的).
使用I的另一个问题是(奇怪地)我们使用它来传达使用接口的实现决策.通常我们不希望实施决策如此大声地表达,因为这使得它们难以改变.例如,考虑一下,如果您认为IFoo确实应该是抽象类而不是接口,可能会发生什么.您应该将名称更改为Foo或CFoo,还是ACFoo?
我能听到车轮转过头来.你在想:"是的,但界面在语言中占有特殊的位置,因此用特殊的命名约定标记它们是合理的." 确实如此.但是整数在语言中也有一个特殊的位置,我们不再标记它们(不再是).此外,问问自己,为什么界面在语言中有特殊的地位?
Java和C#中的接口背后的整个想法是一个警察.语言设计者可能刚刚使用了抽象类,但他们担心实现多重继承的困难.所以他们与自己做了一个后台交易.他们发明了一种人造结构(即接口),将提供一些多重继承的权力,他们受限正常类单继承.
这是语言设计者做出的最糟糕的决定之一.他们发明了一种新的重量级语法元素,以排除有用且功能强大(尽管有争议)的语言特性.接口不是为了启用而发明的,它们被发明为禁用.界面是设计师用语言进行的黑客攻击,他们不想解决更难的MI问题.因此,当您使用I前缀时,您将成为语言历史上最大的黑客之一的焦点.
下次你写这样的函数签名时:
public void myFunction(IFoo foo) {...}
Run Code Online (Sandbox Code Playgroud)
问自己这个:"为什么我想知道IFoo的作者使用'界面'这个词?它对我来说有什么区别,不管他是使用'界面'还是'阶级'还是'结构'? 这是他的事,不是我的! 所以他为什么要强迫我把这个伟大的我放在他的类型名称面前来了解他的事情?他为什么不把他的声明拉上来并保持他的私密性?
如果你在谈论.NET,那么I一开始的接口是无处不在的,丢弃它们会让每个人都感到困惑.
另外,我更愿意
public class Foo : IFoo {}
Run Code Online (Sandbox Code Playgroud)
比
public class FooImpl : Foo {}
Run Code Online (Sandbox Code Playgroud)
这一切都归结为个人偏好,我自己做了一段时间玩这个想法,但我回到了I前缀.因人而异
我认为接口在系统的不同"代理"之间收缩.在我的系统的一个角落工作的代理,不应该知道另一个代理工作的具体实现; 他们只应该交换合同,并期望在不知道如何履行合同的情况下履行合同.另一个但也非常重要的原因是可以完全模拟界面,从而使单元测试更容易.你可以在具体课上嘲笑多少是有限的.
所有这一切都是正确的 - 但它如何需要接口的命名约定?
基本上,为接口添加"I"前缀只是匈牙利符号无用的另一个例子,因为在静态类型语言中(唯一一种接口作为语言结构有意义),你总能轻松快速地找出什么是通常是在IDE中将鼠标悬停在它上面.
| 归档时间: |
|
| 查看次数: |
2322 次 |
| 最近记录: |