Does Business Logic Layer have access to the database / data access level?

I am a bit confused about the relationship between BLL and DAL. Should BLL encapsulate DAL via dependency injection? Or should the BLL only act on domain objects and save / update the DAL separately?

For example, imagine (in a typical MVC application) an order cancellation function that requires you to update an order and update stock. Would it be what my action would look like?

public ActionResult CancelOrder (Guid orderId) { Order order = orderRepository.Get(orderId); StockItem stockItem = stockRepository.Get(order.StockItemId); _orderService.CancelOrder(order, stockItem); orderRepository.Update(order); orderRepository.Update(stock); Return View(); } 

Or will it be more like the following?

 public ActionResult CancelOrder (Guid orderId) { _orderService.CancelOrder(orderId); Return View(); } (within OrderService) public void CancelOrder(Guid orderId) { Order order = orderRepository.Get(orderId); StockItem stockItem = stockRepository.Get(order.StockItemId); order.Cancelled = true; stockItem.AmountInStock = stockItem.AmountInStock + order.Amount; orderRepository.Update(order); orderRepository.Update(stock); } 

With this option, everything will be processed by the BLL, including data access. Repositories will be introduced to avoid hard communication. Any extraction of the object will then take the form _orderService.GetOrder(orderId); as shown on the path to the repository.

Sorry for the rudeness of the examples, as I don't have much time. Any of what I wrote even remotely makes sense or am I in the desert?

+4
source share
4 answers

Definitely not the first option that embeds your business logic in a controller. The problem is not that the controller accesses the data objects as such, but must follow the procedure defined by the business rules. This procedure does not take place in the controller.

So, you should either go with the second option, or make the Cancel method Order . If you have already written similar code, just skip to the sequence.

+5
source

Think about sharing problems. A controller is an MVC template, which is a PRESENTATION template, so the controller must contain a presentation level of support for presentation logic, and not business logic.

It is agreed that the business logic should be in the domain objects, but there is also some APPLICATION logic, which plays the role of coordinators between repositories, so the service level is knocked down on the road.

Therefore, option 2 should be in your way.

+1
source

You really ask 2 questions here:

What should be in the controller and at the business level?

=> I am inclined to think that the code in your first fragment is the correct level of responsibility for the service of the application level (and, therefore, for the Controller, if you acknowledge that these two options can be compared, which discusses a lot this time). Getting Order from the repository and saving it after the cancel operation is unlikely to be like pure business logic. This has more to do with the surrounding transactions / unit of work and the plumbing of your use case.

I would just change one thing: try to save the changes to all entities affected by your transaction at a time. If you need to manually update each entity that can be changed at the end of the action, this will be a big pain and will unnecessarily pollute the controllers. Create a working system unit (or use an existing implementation) that saves all changes at once and removes all Update () methods in your repositories.

In addition, as John suggests, I also think that a rich Order domain object containing the Cancel() method would be preferable to a service, but this is another discussion.

What should be the relationship between BLL and DAL?

=> BLL should not be tightly connected with DAL and as the most valuable layer, it should not directly refer to external layers. This way you can easily reuse your BLL in another application, with a different DAL, etc.

However, sometimes there are cases when some business objects need direct access to other objects to which they do not yet have a link, which basically means getting them from the database. In other words, some operations in BLL need to talk to repositories. Therefore, I always host repository interfaces in the BLL, but their implementations are in the DAL, and they are injected into the BLL at runtime.

As a result, BLL is only loosely coupled to DAL. It remains unchanged in the sense that it only manipulates facades (vaults) that look like neutral collections of objects and do not forget how data is stored, hydrated, etc.

+1
source

BLL must act on business objects created for your application. He, ideally, should not know about the database and related operations. If you want everything to be closely related, use dependency injection to call methods from your DAL.

0
source

Source: https://habr.com/ru/post/1432447/


All Articles