1

Where to place interfaces in a typical multi-layered app with DataAccess, BusinessLogic and an Endpoint modules? I propose 2 options

enter image description here

In both cases there's only dependency from abstractions, but in first one we place interfaces in the same module with implementation, in second - we move all interfaces in the separate module.

I have these pros and cons:

First approach

  • more stupid-simple (why shall we need this extra module? it's too complicated etc)

Second approach

  • more TDD-friendly as it allows us completely to separate from the module that implements contract when we mock it.
  • more DI friendly - we can succeed in complete isolation of modules.

Yet the second option leads to greater overhead and requires more effort while developing.

So, my question is - what approach is generally better (or are there any other, more appropriate options)?

  • In my apps I have an app/interfaces folder, which contains all the interfaces in my application. Inside this folder there are folders such as models, responsible for the model behaviour, modules for modules and so on. I decided to go with this approach rather than having let's say classDirectory/interfaces folder, because I feel like that approach inexplicitly ties the interface to the one concrete class, which does not feel right if you want more classes to implement it. – Andy Sep 5 '15 at 9:59
2

Common practice I have seen in many projects is to store interfaces and associated data structures in a separate project, where all the other projects can reference it.

The reason behind it is, that when you actually implement interfaces you can use any interface without worrying references, because if you can refer the interface you can always use it's implementation with DI, in the actual executable.

1

These days, I have been using the following structure and it's worked pretty well for me so far:

It shows a fictional client/server system with 3 application features or modules called Foo, Bar and Baz. Users can access the system via a command line, UI or web based interface.

This sort of structure is very TDD and DI friendly in my experience.

Features

    Assembly: Contoso.Features.FooFeature
        Folder: Contracts                               contains interfaces unique to "FooFeature"; is available at both client and server ends
        Folder: Models                                  contains models unique to "FooFeature"; is available at both client and server ends
        Folder: Services                                contains services unique to "FooFeature"; is available at both client and server ends
        References:
            * Contoso
    Assembly: Contoso.Features.FooFeature.Services      contains services unique to "FooFeature"; is available only at server end
        References:
            * Contoso
            * Contoso.Features.FooFeature
    Assembly: Contoso.Features.FooFeature.Tests
        Folder: Models                                  contains tests for models unique to "FooFeature"
        Folder: Services                                contains tests for services unique to "FooFeature"
        References:
            * Contoso
            * Contoso.Features.FooFeature
            * Contoso.Features.FooFeature.Services

    Assembly: Contoso.Features.BarFeature
        Folder: Contracts                               contains interfaces unique to "BarFeature"; is available at both client and server ends
        Folder: Models                                  contains models unique to "BarFeature"; is available at both client and server ends
        Folder: Services                                contains services unique to "BarFeature"; is available at both client and server ends
        References:
            * Contoso
    Assembly: Contoso.Features.BarFeature.Services      contains services unique to "BarFeature"; is available only at server end
        References:
            * Contoso
            * Contoso.Features.BarFeature
    Assembly: Contoso.Features.BarFeature.Tests
        Folder: Models                                  contains tests for models unique to "BarFeature"
        Folder: Services                                contains tests for services unique to "BarFeature"
        References:
            * Contoso
            * Contoso.Features.BarFeature
            * Contoso.Features.BarFeature.Services

    Assembly: Contoso.Features.BazFeature
        Folder: Contracts                               contains interfaces unique to "BazFeature"; is available at both client and server ends
        Folder: Models                                  contains models unique to "BazFeature"; is available at both client and server ends
        Folder: Services                                contains services unique to "BazFeature"; is available at both client and server ends
        References:
            * Contoso
    Assembly: Contoso.Features.BazFeature.Services      contains services unique to "BazFeature"; is available only at server end
        References:
            * Contoso
            * Contoso.Features.BazFeature
    Assembly: Contoso.Features.BazFeature.Tests
        Folder: Models                                  contains tests for models unique to "BazFeature"
        Folder: Services                                contains tests for services unique to "BazFeature"
        References:
            * Contoso
            * Contoso.Features.BazFeature
            * Contoso.Features.BazFeature.Services

Apps

    Clients
        Assembly: Contoso.CmdApp                        is the command line application client
            References:
                * Contoso
                * Contoso.Features.FooFeature
                * Contoso.Features.BarFeature
                * Contoso.Features.BazFeature
        Assembly: Contoso.WinApp                        is the Windows application client
            References:
                * Contoso
                * Contoso.Features.FooFeature
                * Contoso.Features.BarFeature
                * Contoso.Features.BazFeature
        Assembly: Contoso.WebApp                        is the Web application client
            References:
                * Contoso
                * Contoso.Features.FooFeature
                * Contoso.Features.BarFeature
                * Contoso.Features.BazFeature

    Servers
        Assembly: Contoso.WebSvcApp                     is the Web application server; exposes services via REST or WCF, etc.
            References:
                * Contoso
                * Contoso.Features.FooFeature
                * Contoso.Features.FooFeature.Services
                * Contoso.Features.BarFeature
                * Contoso.Features.BarFeature.Services
                * Contoso.Features.BazFeature
                * Contoso.Features.BazFeature.Services

Core
    Assembly: Contoso
        Folder: Contracts                               contains interfaces common to the entire system
        Folder: Models                                  contains models common to the entire system
        Folder: Services                                contains services common to the entire system
        References:
            * None
    Assembly: Contoso.Tests
        Folder: Models                                  contains tests for models common to the entire system
        Folder: Services                                contains tests for services common to the entire system
        References:
            * Contoso

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.