I would distinguish between interfaces like this:
-
Standalone interfaces whose purpose you can describe without talking about the rest of your project. Put these in a single dedicated “interface assembly”, which is probably referenced by all other assemblies in your project. Typical examples:
ILogger,IFileSystem,IServiceLocator. -
Class coupled interfaces which really only make sense in the context of your project’s classes. Put these in the same assembly as the classes they are coupled to.
An example: suppose your domain model has a
Bananaclass. If you retrieve bananas through aIBananaRepositoryinterface, then that interface is tightly coupled to bananas. It is impossible to implement or use the interface without knowing something about bananas. Therefore it is only logical that the interface resides in the same assembly asBanana.The previous example has a technical coupling, but the coupling might just be a logical one. For example, a
IFecesThrowingTargetinterface may only make sense as a collaborator of theMonkeyclass even if the interface declaration has no technical link toMonkey.
My answer does depend on the notion that it’s okay to have some coupling to classes. Hiding everything behind an interface would be a mistake. Sometimes it’s okay to just “new up” a class, instead of injecting it or creating it via a factory.