54gxzq
Last Updated: February 25, 2016
·
3.032K
· sohape
76b8f1cdc23ee81baea0ce69c186d096

File nesting with interfaces

Mads Kristensen created yet another extension to Visual Studio. This one is called File Nesting, and can be found here.

Essentially it allows you to nest files under each other in the Visual Studio solution explorer. This modifies the csproj file, specifying that the nested file depends on the other file. This is useful for nesting related files, to keep the solution explorer free from clutter (or at least cut down on the clutter). The examples he use is to nest minified JavaScript files under their non-minified source. This makes perfect sense, as you normally do not need to poke around in the minified files.

The first thing I thought about when seeing this new extension was if I could use it to nest implementations under their interface. This might sound like a bad idea to you, and I can not make up my mind if I want to do it or not.

Because I use a lot of dependency injection in my code I end up with a lot of loosely coupled "service" classes. Each of these classes implement an interface, and so I have two files pr "service". I usually like to group those two files in a folder, to keep them together in the solution explorer, like this:

list of my services folder structure

However this poses a few minor problems:

  • I get a lot of folder clutter
  • I get more complicated namespaces

Both of these issues are of course just small annoyances - but the File Nesting extension has been created exactly for avoiding these small annoyances.

So using File Nesting I can avoid the extra folders, and instead my solution explorer looks like this:

list of nested services collapsed

The actual implementation is now nested under each of the interfaces, so if you want to navigate to it in solution explorer, then you have to expand on the interface:

one service interface expanded

Navigating to the implementation using Visual Studio or ReSharper shortcuts still work in the same way (Ctrl+T (Visual Studio shortcut scheme), or Ctrl+N (IntelliJ IDEA shurtcut scheme)).

What do you think of this approach? - Is it a bad practice, or do you like the idea of getting a smaller solution explorer?

Say Thanks
Respond

12 Responses
Add your response

12635
9e7edadef42e0718983f1e6962203c53

I never understand tightly coupling interfaces with concrete implementations in the same project, so I'd say bad practice, but that's just me. :)

over 1 year ago ·
12639
7a1054e17f3c41c66b1b28d4d6b09379

@Stevenbey, think of it as the default implementation to make consumption and sub classing easier for other developers who have to implement the interface :)

over 1 year ago ·
12640
76b8f1cdc23ee81baea0ce69c186d096

@stevenbey, I completely understand your viewpoint, and that is also why I am hesitant to use it everywhere. However there is nothing in the code that makes them tightly coupled, it is only the appearance in the solution explorer. In that respect, my previous way of structuring, using folders, looks just as bad I guess?

What structuring do you use? - I think it is often overkill to put interfaces in their own assembly, especially when you, like me, use interfaces everywhere. But, I am very interested to hear about other approaches :)

over 1 year ago ·
12658
Default profile 0 normal

If you only have one implementation of an interface, why would you ever induce the complexity of debugging and following code logic? DI and IOC are useful tools in some scenarios, however using them for the sake of using them like this is just a waste of time and effort.

over 1 year ago ·
12659
76b8f1cdc23ee81baea0ce69c186d096

@jameshancock10 I respectfully disagree. It is true that most of the interfaces I make only ever get one implementation for production code, however they get mocked or stubbed for unit testing. Splitting up the code into small reusable parts makes it much easier to write unit tests, and I would argue that it also makes the code much easier to maintain. This adheres to the SOLID principles: http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

over 1 year ago ·
12663
Default profile 0 normal

I've worked on these projects where this is done. What you get is code that you can't ever discover what's going on because when you right click and go to definition you get an interface and can't find the implementation that is going to actually execute. If there is one, all you've accomplished is to make debugging and finding code MUCH harder.

This makes new team members and people that have to maintain your code have A HUGE LEARNING CURVE and basically makes your code impenetrable.

Worse, doing Unit Tests based on mocked/stubbed functions defeats the concept of "unit tests"

So again, you're looking for a solution caused by a problem that should never exist.

DI and IOC work well for plugins. I.e. functionality where you need to blind call on an interface and have it point to something that was dynamically loaded.

If that's not the problem you're solving, then you're missing the point and causing yourself a ton of extra work and making your project incredibly hard to maintain for absolutely 0 benefit (And if your reason for doing something that makes all of your coding and maintenance vastly harder is to make testing easier, then you've just shot yourself in the foot.)

over 1 year ago ·
12668
76b8f1cdc23ee81baea0ce69c186d096

@jameshancock10 I respect your opinion, but I do not agree with you. I think code that adheres to the SOLID principles is MUCH easier to maintain than code that doesn't. I have worked with both as well. If you do not split up your classes and functions, then you end up with very large functions and very large classes. This makes it difficult to keep your code DRY, and it makes it difficult to see what is going on.

You argue that it is difficult to find the classes that implement an interface - I do not agree, Visual Studio or ReSharper can do that for you. With the approach I have described in this blog post it should be very simple to find the implementation for an interface since it is nested under the interface in the solution explorer.

You argue that mocks and stubs are not for unit tests - again I do not agree. Mocks and stubs are made exactly for unit tests. In a unit test you are only interested to test a very small part of your code - one function, or possibly only part of a function. You do not want to test your dependencies in a unit test, so you mock them.

So, using dependency injection is a no brainer for me, but that was actually not the topic of this blog post :)

over 1 year ago ·
12672
9e7edadef42e0718983f1e6962203c53

@vincpa I understand the reason but thanks.

over 1 year ago ·
12674
9e7edadef42e0718983f1e6962203c53

@sohape my use of the phrase 'tightly coupled' may have been slightly erroneous but what I meant was that, even if you don't use the concrete class (e.g. when mocking/stubbing the interface for your tests), it's always 'there' (in the library). I know this is a little OCD but, like I said, that's just me.

I completely agree with you concerning interfaces in their own project. I've seen so many examples of it and it drives me crazy (to the point of frothing at the mouth ;).

I structure solutions with a 'base' project and then implementation projects. The 'base' project contains all of the entities that are used in the application and has a folder structure that reflects the application's architecture. It also contains the interfaces for the application. For example:

Data/
IRepository
IUserRepository
Commands/
ICommand
IUserCommand
Services/
IService
IUserService
IFileBundleService
IFileReaderService

Then, I name the implementation projects to follow the folder structure (e.g *.Services or *.Commands) or, where appropriate, with the technology that they're using (e.g. *.Data.SqlClient).

Of course, YMMV =)

over 1 year ago ·
12677
76b8f1cdc23ee81baea0ce69c186d096

@stevenbey Thanks for getting back to me :)

That sounds like an interesting approach. I don't suffer from the same OCD as you though, so I don't have a problem with the classes being there. However, I am open for trying other approaches, so I might give your approach a try in my next project - thanks!

over 1 year ago ·
12683
7a1054e17f3c41c66b1b28d4d6b09379

@sohape I have the same approach and nest my concrete classes under their interfaces. I have never nested a class unless it is being used or registered with a DI container. To me, having interfaces or contracts in a separate assembly is a false sense of loose coupling. If you have an interface and it has only one implementation, to me it makes sense.

At the end of the day it's a team decision, and a decision which won't start or finish your project on time and under budget :D

over 1 year ago ·
12684
76b8f1cdc23ee81baea0ce69c186d096

@vincpa Nice to know - thanks!

I agree - this is a team decision, but it is also nice to get input from outside the team :)

over 1 year ago ·