Reputation: 23
I'm having trouble implementing a simple test application using Clean Architecture.
Describing the test application, it is a simulation of a sales system, with a single use case and divided into 3 packages (DLL, made in C#):
In the Sales.Business package (yellow and pink circles), we will have:
In the Sales.Adapters package (green circle), we will have:
In the Sales.Infrastructure package (blue circle), we will have:
Here is where the problems start.
The "StartOrder" use case needs to access the OrderRepository to save the started order.
Since this would be a violation of the Clean Architecture dependency rules (a high-level element accessing a lower-level element), this access is done via dependency inversion using the IPedidoRepository interface.
So we have the following reference:
StartOrderUseCase --> IPedidoRepository
The IPedidoRepository interface is something like this:
namespace Sales.Adapters;
public interface IOrderRepository
{
...
int SaveOrder(Order order);
...
}
Note that the interface references the domain entity "Order" (and this is acceptable from the point of view of dependency rules), but this creates a circular reference problem in the project because we have:
Sales.Business references Sales.Adapters
And we have:
Sales.Adapters references Sales.Business
If I replace the Order class in this interface with an OrderDTO like this...
namespace Sales.Adapters;
public interface IOrderRepository
{
...
int SaveOrder(OrderDTO order);
...
}
... the problem is the same because the DTO will need to be used both in the Sales.Adapters package and in the Sales.Business package. No matter where I put this OrderDTO, there is always a circular reference.
Does anyone know how to solve this problem?
Upvotes: 1
Views: 942
Reputation: 7546
The problems with any C# "architecture" comes when you need to combine classes/interfaces, so common problem looks like this:
C
| \
A B
Lets imagine you want your code to change as least as possible, so if library created - you want to develop it once and just apply minor bugfixes. So in our case A and B now locked for modification. The only way for us to create new type C is by creating separate library which will hold C.
All in all this "problem" in production is solved by:
PS Im yet to find where this approach is not working. All projects I worked with so far which are not crumbled, usually split like this.
PS 2 Do not try to split Business Layer into multiple libraries or you will get same problem which isharder to solve later.
Upvotes: 1