Are there established alternatives to ISomething /

2019-03-18 23:57发布

The .NET standard of prefixing an interface name with an I seems to be becoming widespread and isn't just limited to .NET any more. I have come across a lot of Java code that uses this convention (so it wouldn't surprise me if Java used it before C# did). Also Flex uses it, and so on. The placing of an I at the start of the name smacks of Hungarian notation though and so I'm uncomfortable with using it.

So the question is, is there an alternative way of denoting that Something is an interface, rather than a class and is there any need to denote it like this anyway. Or is it a case its become a standard and so I should just accept it and stop trying to stir up "religious wars" by suggesting it be done differently?

9条回答
萌系小妹纸
2楼-- · 2019-03-19 00:28

I would just accept it, to be honest. I know what you mean about being a bit like Hungarian notation (or at least abuse of the same) but I think it gives sufficient value to be worth doing in this case.

With dependency injection being in vogue, often I find I end up with an interface and a single production implementation. It's handy to make them easily distinguishable just with the I prefix.

One little data point: I work with both Java and C# a fair amount, and I regularly find myself having to check which types in Java are actually interfaces, particularly around the collection framework. .NET just makes this simple. Maybe it doesn't bother other people, but it bothers me.

+1 for IFoo from me.

查看更多
We Are One
3楼-- · 2019-03-19 00:29

My main assumption is that the most important thing is to maintain readability in domain part of the implementation. Therefore:

  • If you have one behaviour and one possible implementation, then just don't create an interface:

    public class StackOverflowAnswerGenerator { }

  • If you have one behaviour and many possible implementations, then there is no problem and you can just drop the "I", and have:

    public interface StackOverflowAnswerGenerator {}

    public class StupidStackOverflowAnswerGenerator : StackOverflowAnswerGenerator {}

    public class RandomStackOverflowAnswerGenerator : StackOverflowAnswerGenerator {}

    public class GoogleSearchStackoverflowAnswerGenerator : StackOverflowAnswerGenerator {}

    //...

  • The real problem comes when you have one behaviour and one possible implementation but you need an interface to describe its behaviour (for example for convenient testing, because of convention in your project, using some library/framework which enforces this, ...). Possible solutions, other from prefixing the interface are:

    a) Prefix or suffix the implementation (as stated in some other answers in this topic)

    b) Use a different namespace for interface:

    namespace StackOverflowAnswerMachine.Interfaces { public interface StackOverflowAnswerGenerator {} }

    namespace StackOverflowAnswerMachine { public class StackOverflowAnswerGenerator : Interfaces.StackOverflowAnswerGenerator {} }

    c) Use a different namespace for implementation:

    namespace StackOverflowAnswerMachine { public interface StackOverflowAnswerGenerator {} }

    namespace StackOverflowAnswerMachine.Implementations { public class StackOverflowAnswerGenerator : StackOverflowAnswerMachine.StackOverflowAnswerGenerator {} }

Currently I'm experimenting with the last possibility. Note that in the implementation source file you can still have "using StackOverflowAnswerMachine;" and have convenient access to the domain objects.

UPDATE: Although I still think the last possibility is the cleanest, it's one drawback is that even though "using StackOverflowAnswerMachine;" gives you access to all domain objects you must prefix all domain interfaces not to be confused with their implementations. That may feel like something not very convenient but in clean design usually a class doesn't use many other domain objects, and mostly you need to use the prefix only in field declaration and constructor parameter list. So, that is my current recommendation.

The client of domain functionality shouldn't need to know whether they're using an interface, an abstract class or a concrete class. If they need to know this, then there is some serious problem in such a project, because it has domain logic and infrastructural concerns mixed on the same abstraction layer. Therefore I recommend "a" or "c" solutions.

查看更多
Emotional °昔
4楼-- · 2019-03-19 00:35

For .NET, Microsoft's Framework Design Guidelines book absolutely recommends it, and yes, it is very much standard. I have never seen it done otherwise, and to create a new convention would only serve to confuse people.

I should add that I dislike Hungarian notation too, but this and the case of prefixing class variables with an underscore are good exceptions to me, because they make code so much more readable.

查看更多
登录 后发表回答