Trying to implement 3-layer (not: tier, I just want to separate my project logically, on one machine) architecture I've found so many different approaches that I'm confused, what's the best way (if there's any) to make that in WinForms app.
Now I have no doubts only about 3 layers that should be present in the project:
In UI I put all the WinForms. There must be also some logic to fill the object with data from controls and pass it to BLL layer.
In DAL I want to put classes and methods for data manipulations using ADO.NET, like:
public class OrderDAL
{
public OrderDAL()
{
}
public int Add(Order order)
{
//...add order to database
}
public int Update(Order order)
{
//...update order in database
}
//...etc.
}
The problem is with BLL and the question - should I use Data Transfer Objects to pass data between layers, or should I pass the whole Class?
If I choose to use DTO, then I've to create additional common class, Order
, that reference to UI, BLL and DAL:
public class Order
{
public int Id { get; set; }
public DateTime Date { get; set; }
public string Number { get; set; }
public string CustomerName { get; set; }
public Order ()
{
}
}
and put the logic separated into BLL:
public class OrderBLL
{
public OrderBLL()
{
}
public int Add(Order order)
{
OrderDAL orderDAL = new OrderDAL();
return orderDAL.Add(order);
}
public int Update(Order order)
{
OrderDAL orderDAL = new OrderDAL();
return orderDAL.Update(order);
}
//...etc.
}
This approach, under different names, is used among others: here or here.
On the other hand, some "wise guys" and their followers (like here) call it Anemic Domain Model and complain it's a bad design and anti-pattern that should not be used.
The pros:
The cons:
So, the opposite approach is to pass the whole object between layers, like here: no DTO, just BLL looking like that:
public class Order
{
public int Id { get; set; }
public DateTime Date { get; set; }
public string Number { get; set; }
public string CustomerName { get; set; }
public Order()
{
}
public int Add()
{
OrderDAL orderDAL = new OrderDAL();
return orderDAL.Add(this);
}
public int Update(Order order)
{
OrderDAL orderDAL = new OrderDAL();
return orderDAL.Update(order);
}
}
The pros:
The cons:
So, it looks like whatever I choose, I'll violate some rules. What's better way then, which should I choose? Maybe there is other approach I haven't found?
Implementing Layered Architecture One could try putting each layer in a separate Maven module, but then capturing the weird relationship between domain and persistence would not be easy. I usually stick with packages and use common sense along with code reviews to make sure that none of the rules are broken.
Business/Service Layer This layer contains logic that will take the requests or objects that are sent from the Presentation Layer and begin to use business rules or business logic to determine how to save or process data.
Clean Architecture is also layered architecture. The layer domain (entities) is in the center surrounded by the application layer (use cases). The outer layer consists of ports and adapters that adapt the application to external systems (web, DB, UI) via controllers, repositories, and presenters.
I don't like DTOs, because they mean creating a dual hierarchy with little or no value.
I also don't like the idea of making model objects responsible for their own persistence. I prefer a separate persistence layer. Why? Model objects don't always need to be persisted to be useful. Business logic and functionality are orthogonal to persistence.
If you have two layers it's possible to keep a one way dependency graph: persistence knows about model, but model does not know about persistence. You end up with a cyclic dependency if model objects are responsible for persistence. You can never test or use model objects without persistence.
My advice? Don't do DTOs. Break out a separate persistence layer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With