问题描述
我目前正在阅读清洁代码作者:Rober Martin(UncleBob),并且一般都喜欢UncleBob的作品。但是,我有点困惑,当我读到,他避免了前缀的接口,如IPerson。他说我不想让我的用户知道我正在给他们一个接口。
在TDD /注入透视下,我总是非常感兴趣地告诉我的类的用户,我在一个接口。主要原因是我考虑了系统的不同代理之间的Interfaces合同。一个代理在我的系统的一个角落工作,不应该知道另一个代理工作的具体实现;他们只应该交换合同,并期望合同在不知道如何实现。另一个,但也很重要的原因是,一个接口可以完全嘲笑,从而使单元测试更容易。有一个限制,你可以模拟一个具体的类。
因此,我更喜欢可视化我确实正在处理一个接口...或者将一个接口作为参数。但是,因为UncleBob是我们社区的重量级冠军,而我只是另一个flyweigth桌面骑师,我想知道如果我缺少的东西。
我坚持我在接口中是错误的
在Java和C#中有许多约定,我们已经习惯了;但是是向后。例如,将私有变量放在每个类的顶部的惯例从技术角度来看是相当愚蠢的。一个类最重要的是它的公共方法。至少重要的事情,我们隐藏在隐私屏障后面的事物是实例变量。那么为什么要把它们放在顶部?
接口前面的I是另一个向后的约定。当您传递对对象的引用时,您应该期望它是一个接口。接口应该是默认的;所以没有必要做额外的事情,如使用一个前缀,宣布你在做什么,每个人都希望你做。如果我们为传递具体类的例外条件保留一个特殊标记,那么会更好(但仍然错误)。
使用I,是(奇怪)我们使用它来传递使用接口的实现决策。通常我们不希望执行决定表达得这么大,因为这使得它们难以改变。例如,考虑如果你决定IFoo真的应该是一个抽象类而不是一个接口,可能会发生什么。你应该更改名字为Foo还是CFoo,还是ACFoo?
我可以听到车轮转动。你在想:是的,但是界面在语言中有一个特殊的地方,所以用一个特殊的命名约定来标记它们是合理的。确实如此。但整数在语言中也有特殊的地方,我们不再标记它们。
在Java和C#中,接口背后的整体理念是一个失败。语言设计师可以只使用抽象类,但他们担心实现多重继承的困难。所以他们自己做了后房交易。他们发明了一个人造结构(即接口),它提供了一些多重继承的力量,他们将普通类限制为单继承。
这是语言设计师做出的最糟糕的决定之一。他们发明了一个新的和重量级的语法元素,以便排除一个有用的和强大的(尽管有争议的)语言特性。接口没有被发明来启用,他们被发明以禁用。接口是设计人员在不想解决MI的更难的问题的语言中的一个黑客。因此,当您使用I前缀时,您会在语言历史上最大的黑客之一上引起大的注意。
下一次写这样的函数签名时:
public void myFunction(IFoo foo){...}
$问自己这个问题:为什么我想知道IFoo的作者使用了'interface'这个词?对我来说有什么区别,不管他是用interface 'or'class'or even'struct'?这是他的事,不是我的!那么,为什么他强迫我知道他的生意,把这个伟大的大我在他的类型名称前面? 他把他的声明拉起来,让他的私人离开我的脸?
I am currently reading "Clean Code" By Rober Martin (UncleBob), and generally loving the musings of UncleBob. However, I got a bit confused, when I read that he avoids prefixing interfaces like "IPerson". He states "I don't want my users knowing that I'm handing them an interface".
Thinking in TDD/injection perspective, I will always be very interested in telling the "users" of my classes that I am handing on an interface. The primary reason is that I consider Interfaces contracts between the different "agents" of a system. An agent working with one corner of my system, should not know the concrete implementation of another agents work; they should only exchange contracts, and expect the contracts to be fulfilled without knowing how. The other, but also very important, reason is that an interface can be mocked fully, and thus making unit-testing much easier. There are limits to how much you can mock on a concrete class.
Therefore, I prefer to visualize that I am indeed handing on an interface... or taking an interface as argument. But since UncleBob is a heavyweight champ in our community, and I am just another flyweigth desk jockey, I would like to know if I am missing something.
Is it wrong for me to insist on I's in interfaces??
解决方案There are a number of conventions in Java and C# that we have grown comfortable with; but that are backwards. For example, the convention of putting private variables at the top of each class is quite silly from a technical point of view. The most important things about a class are it's public methods. The least important things, the things we hide behind a privacy barrier, are the instance variables. So why would we put them at the top?
The "I" in front of interfaces is another backwards convention. When you are passed a reference to an object, you should expect it to be an interface. Interfaces should be the default; so there is no point in doing something extra, like using an I prefix, to announce that you are doing what everyone expects you to do. It would be better (though still wrong) if we reserved a special marker for the exceptional condition of passing a concrete class.
Another problem with using I, is that (oddly) we use it to communication the implementation decision of using an interface. Usually we don't want implementation decisions expressed so loudly, because that makes them hard to change. Consider, for example, what might happen if you decided that IFoo really ought to be an abstract class instead of an interface. Should you change the name to Foo or CFoo, or ACFoo?
I can hear the wheels turning in your head. You are thinking: "Yeah, but interfaces have a special place in the language, and so it's reasonable to mark them with a special naming convention." That's true. But integers also have a special place in the language, and we don't mark them (any more). Besides, ask yourself this, why do interfaces have a special place in the language?
The whole idea behind interfaces in Java and C# was a cop-out. The language designers could have just used abstract classes, but they were worried about the difficulties of implementing multiple inheritance. So they made a back-room deal with themselves. They invented an artificial construct (i.e. interfaces) that would provide some of the power of multiple inheritance, and they constrained normal classes to single inheritance.
This was one of the worst decision the language designers made. They invented a new and heavyweight syntax element in order to exclude a useful and powerful (albeit controversial) language feature. Interfaces were not invented to enable, they were invented to disable. Interfaces are a hack placed in the language by designers who didn't want to solve the harder problem of MI. So when you use the I prefix, you are putting a big spotlight on one of the largest hacks in language history.
The next time you write a function signature like this:
public void myFunction(IFoo foo) {...}
Ask yourself this: "Why do I want to know that the author of IFoo used the word 'interface'? What difference does it make to me whether he used 'interface' or 'class' or even 'struct'? That's his business, not mine! So why is he forcing me to know his business by putting this great big I in front of his type name? Why doesn't he zip his declarations up and keep his privates out of my face?"
这篇关于前缀接口与I?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!