32

To be interchangable and testable, normally services with logic needs to have interface, e.g.

public class FooService: IFooService 
{ ... }

Design-wise, I agree with this, but one of the things that bothers me with this approach is that for one service you will need to declare two things (the class and the interface), and in our team, normally two files (one for the class and one for the interface). Another discomfort is the difficulty in navigation because using "Go to definition" in IDE (VS2010) will point to the interface (since other classes refer to the interface), not the actual class.

I was thinking that writing IFooService in the same file as FooService will reduce the above weirdness. After all, IFooService and FooService are very related. Is this a good practice? Is there a good reason that IFooService must be located in its own file?

svick
  • 9,999
  • 1
  • 37
  • 51
Louis Rhys
  • 6,042
  • 11
  • 42
  • 59
  • 3
    If you only ever have one implementation of a particular interface there's no real logical need for the interface. Why not use the class directly? – Joris Timmermans Sep 11 '12 at 12:02
  • 14
    @MadKeithV for loose coupling and testability? – Louis Rhys Sep 11 '12 at 12:11
  • 14
    @MadKeithV: you are correct. But when you write unit tests for code that relies on IFooService, you will typically provide a MockFooService, which *is* a second implementation of that interface. – Doc Brown Sep 11 '12 at 13:33
  • 6
    @DocBrown - if you have multiple implementations then obviously the comment goes away, but so does the utility of being able to go directly to the "single implementation" (because there are at least two). Then the question becomes: what information is in the concrete implementation that shouldn't already be in the interface description/documentation at the point where you are using the interface? – Joris Timmermans Sep 11 '12 at 13:47
  • 1
    Blatant self-advertising: http://stackoverflow.com/questions/5840219/why-should-we-place-interfaces-with-classes-that-use-them-rather-than-those-that/5844125#5844125 – Marjan Venema Sep 11 '12 at 19:29
  • 1
    Instead of using "Go To Definition" (F12) use "Go To Implementation" (Ctrl-F12), this points to the class instead of the interface. – Fred Oct 10 '16 at 08:38

11 Answers11

26

It doesn't have to be in its own file, but your team should decide on a standard and stick to it.

Also, you're right that "Go to definition" takes you to the interface, but if you have Resharper installed, it's only one click to open a list of derived classes/interfaces from that interface, so it's not a big deal. That's why I keep the interface in a separate file.

 

Vikhram
  • 101
  • 4
Scott Whitlock
  • 21,874
  • 5
  • 60
  • 88
  • 5
    I agree on this answer, after all the IDE should adjust to our design and not the other way around, right? – marktani Sep 11 '12 at 12:34
  • 2
    Also, without Resharper, F12 and Shift+F12 pretty much do the same thing. Not even a right click away :) (to be fair, it will only take you to direct uses of the interface, not sure what the Resharper version does) – Daniel B Sep 11 '12 at 12:58
  • @DanielB: In Resharper, Alt-End goes to the implementation (or presents you with a list of possible implementations to go to). – StriplingWarrior Sep 11 '12 at 16:58
  • @StriplingWarrior then it seems like it's exactly what vanilla VS does, too. F12 = go to definition, Shift+F12 = go to implementation (I'm pretty sure this works without Resharper, although I do have it installed, so it's difficult to confirm). It's one of the most useful navigation shortcuts, I'm just spreading the word. – Daniel B Sep 13 '12 at 13:44
  • @DanielB: The default for Shift-F12 is "find usages." http://www.jetbrains.com/resharper/webhelp/Reference__Keyboard_Shortcuts.html – StriplingWarrior Sep 13 '12 at 15:51
  • 2
    Not sure if this has changed but for anybody that finds this now Control-F12 in VS takes me to the implementation of an interface or displays a list of all implementations if there are multiple. – Marie Apr 19 '18 at 15:08
18

I think you should keep them separate files. As you said, the idea is to remain testable and interchangeable. By placing the interface in the same file as your implementation, you are associating the interface with the specific implementation. Should you decide to create a mock object or another implementation, the interface will not be logically separate from FooService.

Brad S
  • 291
  • 1
  • 5
12

According to SOLID, not only should you create the interface, and not only should it be in a different file, it should be in a different assembly.

Why? Because any change to a source file that compiles into an assembly requires recompilation of the assembly, and any change to an assembly requires recompilation of any dependent assembly. So, if your aim, based on SOLID, is to be able to replace an implementation A with an implementation B, while the class C dependent on interface I doesn't have to know the difference, you have to make sure the assembly with I in it doesn't change, thus protecting the usages.

"But it's just a recompile" I hear you protest. Well that may be, but in your smartphone app, which is easier on your users' data bandwidth; downloading one binary that changed, or downloading that binary and five others with code that depends on it? Not every program is written to be consumed by desktop computers on a LAN. Even in that case, where bandwidth and memory are cheap, smaller patch releases can have value because they're trivial to push out to the entire LAN through Active Directory or similar domain management layers; your users will wait only a few seconds for it to be applied the next time they log in instead of a few minutes for the whole thing to be reinstalled. Not to mention that, the fewer assemblies that must be recompiled when building a project, the faster it will build, making you more productive because you spend less time sitting around waiting for 50 assemblies to build for each change you make.

Now, the disclaimer: This is not always possible or feasible to do. The easiest way to do this is to create a centralized "interfaces" project. This has its own downsides; code becomes less reusable because the interface project AND the implementation project have to be referenced in other apps reusing the persistence layer or other key components of your app. You can overcome that problem by splitting the interfaces into more tightly coupled assemblies, but then you have more projects in your app which makes a full build very painful. The key is balance, and maintaining the loosely-coupled design; you can usually move files around as necessary, so when you see that a class will need many changes, or that new implementations of an interface will be needed regularly (perhaps to interface with newly-supported versions of other software, or file types, etc) you can sever it from its interface and protect usages from knowledge of those changes.

KeithS
  • 21,994
  • 6
  • 52
  • 79
9

Why is having separate files a discomfort? For me, it's much neater and cleaner. It's common to create a subfolder named "Interfaces" and stick your IFooServer.cs files there, if you want to see fewer files in your Solution Explorer.

The reason the interface is defined in its own file is for the same reason that classes are usually defined in their own file: project management is simpler when your logical structure and file structure are identical, so you always know which file a given class is defined in. This can make your life easier when debugging (exception stack traces usually give you file and line numbers) or when merging source code in a source control repository.

Avner Shahar-Kashtan
  • 9,166
  • 3
  • 29
  • 37
6

It is often a good practice to let your code files contain only a single class, or a single interface. But these coding practices are a means to an end - to better structure your code making it easier to work with. If you, and your team, find it easier to work with if the classes are kept together with their interfaces, by all means do so.

Personally I prefer to have the interface and class in the same file when there is just one class that implements the interface, such as in your case.

In regards to the problems you have with navigation, I can highly recommend ReSharper. It contains some highly useful shortcuts for jumping directly to the method implementing a specific interface method.

Pete
  • 8,916
  • 3
  • 41
  • 53
  • 3
    +1 for pointing out that the team's practices should dictate the file structure and for having the contrary to norm approach. –  Sep 11 '12 at 13:42
3

Interfaces belong to their clients not to their implementations, as defined in Agile Principles, Practices and Patterns by Robert C. Martin. Thus, combining interface and implementation in the same place is against it's principle.

Client code depends on the interface. This allows the possibility of compiling and deploying the client code and the interface without the implementation. Than you can have different implementations working like plugins to the client code.

UPDATE: This is not an agile-only principle here. The Gang of Four in Design Patterns, back in '94, are already talking about clients adhering to interfaces and programming to interfaces. Their view is similar.

Patkos Csaba
  • 2,054
  • 12
  • 16
  • 1
    The use of Interfaces goes well beyond the domain that Agile possesses. Agile is a development methodology which uses language constructs in particular ways. An Interface is a language construct. –  Sep 11 '12 at 13:39
  • 1
    Yes, but the interface still belongs to the client and not the implementation, regardless of the fact that we are talking about agile or not. – Patkos Csaba Sep 11 '12 at 14:29
  • I am with you on this. – Marjan Venema Sep 11 '12 at 19:28
3

There are many times where you want your interface to be not only in a separate file to the class, but even in a separate assembly altogether.

For example, a WCF Service Contract interface can be shared by both client and service if you have control over both ends of the wire. By moving the interface into its own assembly, it will have fewer assembly dependencies of its own. This makes it much easier for the client to consume, loosening the coupling with its implementation.

StuartLC
  • 1,246
  • 8
  • 14
2

It rarely, if ever, makes sense to have a single implementation of an interface1. If you put a public interface and a public class implementing that interface into the same file, good chances are that you do not need an interface.

When the class that you co-locate with the interface is abstract, and you know that all implementations of your interface should inherit that abstract class, locating the two in the same file makes sense. You should still scrutinize your decision to use an interface: ask yourself if an abstract class by itself would be fine, and drop the interface if the answer is affirmative.

Generally, though, you should stick to the "one public class/interface corresponds to one file" strategy: it is easy to follow, and it makes your source tree easier to navigate.


1 One notable exception is when you need to have an interface for testing purposes, because your choice of mocking framework placed this additional requirement on your code.
Sergey Kalinichenko
  • 17,393
  • 4
  • 57
  • 73
  • 5
    It is in fact a quite normal pattern to have one interface for one class in .NET, as it allows unit tests to substitute dependencies with mocks, stubs, spys, or other test doubles. – Pete Sep 11 '12 at 13:37
  • 2
    @Pete I edited my answer to include this as a note. I would not call this pattern "normal", because it lets your testability concern "leak" into your main code base. Modern mocking frameworks help you overcome this problem to a large extent, but having an interface there definitely simplifies things a lot. – Sergey Kalinichenko Sep 11 '12 at 13:51
  • So what happens when that one implementation becomes two? Not everyone has a refactoring assistant that can generate an interface from a pre-existing class. Now you not only have to do that, but change all usages. – KeithS Sep 11 '12 at 14:31
  • 2
    @KeithS A class without an interface should be in your design only when you are dead-certain that it does not make any sense to subclass it, and you make that class `sealed`. If you suspect that you may at some time in the future add a second subclass, you put in an interface right away. P.S. A decent-quality refactoring assistant can be yours at a modest price of a single ReSharper license :) – Sergey Kalinichenko Sep 11 '12 at 14:42
  • But now you seem to be backpedalling; you're saying it should only not have an interface if it's not subclassed and is sealed, but you say that it would be rare to have a single implementation of an interface. So, I infer you're telling me most of my classes should be sealed. That's not SOLID either; it's a violation of OCP to have to go back in and unseal a class to derive from it, because the class is literally closed to extension, requiring change. – KeithS Sep 11 '12 at 14:53
  • @KeithS That's a wrong inference: I'm saying that a class should not have an interface and be sealed only when you know that it does not make sense to subclass it. Additionally, testability concerns may forse you to add an interface, even though it does not make sense to subclass. In all other cases you should have an interface, and you should also put it in a separate file. – Sergey Kalinichenko Sep 11 '12 at 15:02
  • 1
    @KeithS And yes, all of your classes that are not specifically designed for subclassing should be sealed. In fact, wish classes were sealed by default, forcing you to designate classes for inheritance explicitly, in the same way that the language currently forces you to designate functions for overriding by marking them `virtual`. – Sergey Kalinichenko Sep 11 '12 at 15:03
  • 2
    @KeithS: What happens when your one implementation becomes two? The same as when your implementation changes; you change the code to reflect that change. YAGNI applies here. You're never going to know what is going to change in future, so do the simplest thing possible. (Unfortunately testing messes with this maxim) – Groky Sep 11 '12 at 18:00
1

Putting a class and an interface into the same file puts no limits on how either can be used. An interface can still be used for mocks etc in just the same way, even if it is in the same file as a class which implements it. The question could be perceived purely as one of organisational convenience, in which case I would say do whatever makes your life easier!

Of course, one could argue that having the two in the same file might lead the unwary to consider them to be more programmatically coupled than they really are, which is a risk.

Personally, if I came across a codebase which used one convention over the other I wouldn't be too concerned either way.

Holf
  • 111
  • 3
  • It's not just an "organisational convenience"...it is also a matter of risk management, deployment mgmt, code traceability, change control, source control noise, security mgmt. There are many angles to this question. – TSmith Jun 05 '19 at 20:35
0

I personally don't like the "I" in front of an interface. As a user of such a type I'don't want to see that this is a interface or not. The type is the interesting thing. In terms of dependencies your FooService is ONE possible implementation of IFooService. The interface should be near of the place where it is used. On the other hand the implementation should be at a place where it can be easily changed without effecting the client. So, I would prefer two files - normally.

ollins
  • 161
  • 4
  • 2
    As a user, I want to know whether a type is an interface, because for example it means I can't use `new` with it, but on the other hand, I can use it co- or contra-variantly. And the `I` is an established naming convention in .Net, so it's a good reason to adhere to it, if only for consistency with other types. – svick Sep 11 '12 at 12:40
  • Starting with `I` in interface was only the introduction to my arguments about the separation in two files. The code is better readable and it makes the inversion of the dependencies more clear. – ollins Sep 11 '12 at 12:57
  • 4
    Like it or not, using an 'I' in front of an interface name is a de-facto standard in .NET. Not following the standard in a .NET project would in my point of view be a violation of the 'principle of least astonishment'. – Pete Sep 11 '12 at 13:23
  • My main point is: separate in two files. One for the abstraction and one for the implementation. If the use of the `I` is normal in your environment: Use it! (But I don't like it :) ) – ollins Sep 11 '12 at 13:34
  • And in the case of P.SE, prefixing I in front of an interface makes it more apparent that the poster is talking about an interface, not inheriting from another class. –  Sep 11 '12 at 13:40
0

Coding to interfaces can be bad, is in fact treated as an anti-pattern for certain contexts, and is not a law. Usually a good example of coding to interfaces anti-pattern is when you have an interface that only has one implementation in your application. Another would be if the interface file becomes so bothersome that you have to hide its declaration in the implemented class's file.

Shivan Dragon
  • 4,583
  • 5
  • 24
  • 31
  • having only one implementation in your application of an interface isn't necessarily a bad thing; one could be protecting the application against technology change. For example, an interface for a data-persistence technology. You would only have one implementation for the current data-persistence technology while protecting the app if that were to change. So there would only be one imp at that time. – TSmith Jun 05 '19 at 20:41