title: Where to define the interfaces for a repository in an layered architecture?
body: <p><strong>Background</strong></p>
  
  <p>I'm trying to create a simple application to really understand the whole stack of DDD+TDD+etc. My goal is to dynamically inject the DAL repository classes at runtime.  This keeps my 
  Domain and Application Services layers testable.  I plan on using "poor man's DI" to accomplish
  this for now ... so I would do this in a simple Console application near startup:</p>
  
  <pre>
  
      // Poor man's DI, injecting DAL repository classes at runtime
      var productRepository = new SimpleOrder.Repository.ProductRespository();
      var customerRepository = new SimpleOrder.Repository.CustomerRepository();
      var orderRepository = new SimpleOrder.Repository.OrderRepository();
  
      // Constructor injection into this class in the Application Services layer,
      // SimpleOrder.ApplicationFacade
      OrderEntry oe = new OrderEntry(customerRepository, orderRepository, productRepository);
  
  </pre>
  
  <p>To accomplish this dependency injection, I've created three repository interfaces: </p>
  
  <pre>
  -- ICustomerRepository
  -- IOrderRepository
  -- IProductRespository
  </pre>
  
  <p>A typical implementation:</p>
  
  <pre>
  
      namespace SimpleOrder.Domain.Interfaces
      {
          public interface ICustomerRepository
          {
              Customer GetCustomerById(int customerId);
              void SaveCustomer(Customer customer);
          }
      }
  
  </pre>
  
  <p>** Notice that SaveCustomer references the Customer model class defined in the domain layer.  This is typical of the other repositories.</p>
  
  <p>HOWEVER I'm not sure which project / layer they should be implemented in.  I have 5 projects in a solution:</p>
  
  <ol>
  <li><p><strong>SimpleOrder.ConsoleClient (presentation)</strong>
  -- I want to inject the specific implementation of the domain from here as the application</p></li>
  <li><p><strong>SimpleOrder.ApplicationFacade (application services)</strong>
  -- chunky higher-level, coarser-grained methods orchestrating lower-level methods in the domain</p></li>
  <li><p><strong>SimpleOrder.Contracts</strong>
  -- DTO classes used for communication between presentation and application services</p></li>
  <li><p><strong>SimpleOrder.Domain (domain / bll)</strong>
  -- domain model classes Customer, Order, OrderItem, Product</p></li>
  <li><p><strong>SimpleOrder.Repository (dal)</strong>
  -- implements the repository interfaces</p></li>
  </ol>
  
  <p>Here are my options as I see it:</p>
  
  <p><strong>Option 1:</strong> Define the repository interfaces in SimpleOrder.Contracts ...</p>
  
  <p>PRO: this is where I <em>think</em> they should belong because I created this to share contracts between various concerns / layers.  ex., DTOs are defined here.</p>
  
  <p>CON: however the method signatures in of each interface references Domain model classes.<br>
  This means that I would have to add a reference to the SimpleOrder.Domain, but when the 
  SimpleOrder.Contracts is referenced in another project, it will have to carry 
  SimpleOrder.Domain along for the ride.  This doesn't feel right.</p>
  
  <p><strong>Option 2:</strong> Same scenario as above, but I ALSO define interfaces for each Domain model
  class in the SimpleOrder.Contracts so I can break the coupling of the repository interfaces to the actual model classes.</p>
  
  <p>Example:</p>
  
  <pre>
  
      namespace SimpleOrder.Domain.Interfaces
      {
          public interface ICustomerRepository
          {
              ICustomer** GetCustomerById(int customerId);
              void SaveCustomer(ICustomer customer);
          }
  
          public interface ICustomer
          {
              int CustomerId { get; set; }
              string Name { get; set; }
              System.Collections.Generic.List Orders { get; }
          }
      }
  
  </pre>
  
  <p>IMPACT: Each domain model class would have to implement his related interface.  i.e.,</p>
  
  <pre>
  
      public class Customer : SimpleOrder.Domain.Interfaces.ICustomer
      {
          public Customer()
          {
              _orders = new List();
          }
  
          public int CustomerId { get; set; }
          public string Name { get; set; }
  
          private List _orders;
          public virtual List Orders {
              get { return _orders; }
          }
      }
  
  </pre>
  
  <p>PRO: Fixes Option 1's problem.</p>
  
  <p>CON: This explodes the number of files (and the perceived complexity) in the project because
  each domain class now has an associated interface. </p>
  
  <p><strong>Option 3:</strong> Define the repository intefaces in the SimpleOrder.Domain</p>
  
  <p>IMPACT: In order to inject the concrete repository classes into the application services layer (SimpleOrder.ApplicationFacade project) from the SimpleOrder.ConsoleClient at runtime, SimpleOder.ConsoleClient will ALSO need a reference to SimpleOrder.Domain.</p>
  
  <p>PRO: This ALSO solves Option 1</p>
  
  <p>CON: I was trying to avoid referencing the domain layer from the presentation layer directly because now the presentation layer can know too much about the domain layer.  When I replace the console application in the future with a WPF or ASP.NET MVC app in the future, I risk second and subsequent presentation layer implementations from attempting to call methods in the Model instead of the Application Services layer. (However I do consider this in Option 4.)</p>
  
  <p><strong>Option 4:</strong> Put the interfaces in SimpleOrder.Domain, then reference the SimpleOrder.Domain from the SimpleOrder.ConsoleClient.  </p>
  
  <p>PRO: Fixes all the problems above.</p>
  
  <p>CON: This doesn't feel right because I would be providing access from the presentation layer
  directly to the lower-level methods in the Domain layer when I should <em>only</em> be providing
   access to the higher-level chunky methods in the SimpleOrder.ApplicationFacade.</p>
  
  <p><strong>QUESTION</strong>
  I've tried each of these, but have settled on Option 4, HOWEVER that leaves a bad taste in my mouth about it.  Is there a better option?  Am I on the right track here?</p>