Where should I put interfaces and implementations
I have Domain assembly and SqlServerRepository assembly.
SqlServerRepository assembly has a reference on Domain assembly, Domain assembly doesn't have reference on other assemblies.
Domain assembly has interface IRepository (and others for repository), because domain logic works only with interface types and doesn't think about concrete types.
SqlServerRepository assembly implements interface IRepository (which is contained in the Domain assembly).
And it's ok, I can mock IRepository, can use OracleRepository implementation and another...
But I think I have some architecture problem...
- SqlServerRepository can't work without the Domain assembly
- On another hand, if I put interfaces in SqlServerRepository assembly, the Domain will not work without SqlServerRepository assembly, and if I create OracleServerRepository assembly, I must use SqlServerRepository too, because I put the interfaces in the SqlServerRepository and Domain alredy uses them.
- Where should I map database objects to domain? In the SqlServerRepository or in the Domain assembly?
I thought about an assembly which contains only interfaces, and Domain and SqlServerRepository reference it, but I think it is overhead for my project (microservice)
So, what must I do?
The repository interfaces belong in the domain (or rather where your services are, but they are typically part of the domain).
The reason is that the repository contracts are created and driven from functionality that the domain need. Without the domain you would not have any repositories.
SqlServerRepository can't work without the Domain assembly
Correct. And as I stated above. You would not have a SqlServerRepository if it weren't for the functionality required by the domain.
Where should I map database objects to domain? In the SqlServerRepository or in the Domain assembly?
In the repository assembly as it's an implementation detail for the specific data layer abstraction. If you had put them in the domain, the domain would have been forced to have knowledge about implementation details of every persistence layer that you are using (like oracle, sqlserver, files or whatever).
Nothing says that SQL Server and Oracle should persist the information using the same database schema. Tables, views etc might vary depending on the pros/cons that the DB engine has.
I'd suggest you implement things using ports and adapters [Hexagonal architecture]. Following assembly can work for microservices
- Core.Domain : You can put all domain objects here.
- Common.ServiceContracts : It can contain all the service contracts for different services.
- MyService : It has the service implementation class. It will also have the interfaces for infrastructure. Infrastructure could be database, logging etc. You can expose interface to convert domain to infrastructure objects e.g. IDomain1Mapper.
- Infrastructure : It can have class like SQLDomain1Mapper, OracleDomain1Mapper and so on. They all will implement IDomain1Mapper. Same is the case for the other domain classes.
MyService assembly will refer to Common.ServiceContracts, Infrastructure and Core.Domain.
You can mock any repository/domain in the MyService assembly as per wish. Service consumer can consume MyService assembly.