12 - BLL
Business Logic Layer
Refresher of architecture so far
- SQL – DataBase/Tables
- EF – DbContext/DbSet’s
- DAL – UOW/Repositories
- MVC – Controllers/Views (Or rest-api endpoints)
Using repository/UOW directly in controller
- Speedy development - Easy to read
To think about - Business logic in controller - Multiple repositories used - Maintenance in bigger team, in bigger project, over several major iterations
More issues with repositories
- What are we returning? Domain models?
- How to control the amount of data returned?
- We have done the MVC web, now we need to do the Rest services – duplicate business logic in controllers
- Validations, logging, versioning – where these go? Controllers?
- Over time functionality starts to pile up
- Logic just grows and grows
- Controller starts to contain more and more business rules
- Maintainability is lost
- No more clean controllers
BLL and clean controllers
- BLL – Business Logic Layer
- Important layer between presentation layer and DAL/UOW/Repositories
- Generally, controllers only use BLL/Services
- Uow/Repo is responsible for data, BLL/Service for everything else
- End result: clean controllers, reusable business logic
DAO, Repository, Service
Sometimes you need even more granularity in your data access – Data Access Objects are often used as low-level, single technology based data source.
And Repository is used as aggregate over different data sources – database and rest-api based data sources
BLL – Services
- One service can use as many repos as needed
- Also access other services
- Data validation and access is moved from controllers to the service layer
- Data caching is more effective
BLL - Service
What should be in service layer?
- Using multiple repos to compose one response
- Doing something other than direct repo usage
- Storing uploaded data to filesystem
- Requests from external sources
Returning data and domain models
- Using Domain models everywhere
- Everything done in Domain models is instantly accessible/replicated everywhere
- Everything is visible
- How to control the amount of data returned
- Changing Domain also changes field names in service
- Problems in serializing (circular references etc.)
- Just too much data is transferred in every layer – starting with db
DTO – Data Transfer Object 1
- Reduce data complexity and data quantity in between clients and rest service
- Control over data
- Do not confuse DTOs with Domain classes
- DTOs only contain minimum number of properties, typically no computed fields or methods
DTO – Data Transfer Object 2
- As FLAT as possible, no unnecessary relationships with other classes
- Possibility to add info needed by rest client
- DTO does not have to match 1:1 with Domain object
- Gives you 100% control, what is going on in your rest service
- Helps, when domain models and database changes, but rest services must stay the same
- Mainly only properties!
DTO – Data Transfer Object 3
How many layers of objects we need?
- Database objects
- Domain objects (maybe not the same as DB entities)
- DTO’s for internal usage – from repos/dal to controllers
- DTO’s for external usage – from public rest controllers to clients (ViewModel-s in MVC regular web world)
And sometimes even more….
- Internal objects can be changed easily, everything is under your own control
- External objects should be changed almost never – versioning.
DTO – Automapper
- Simple mappings are easy to do
- Complex graphs are hard
- 99% of time is spent in configuring
- Mistakes are hard to find
- Looks fancy, and sales pitch is great
- In actual usage – lots of problems
DTO – Factory
Problem – initializing DTOs all over your code reduces maintainability
- Different methods start to do it differently
- Maintainability is lost, method A changes DTO creation logic, you will forget update method B
- Use Factory pattern
- Create a class, that will create DTOs for us in required form
- In service layer (and repos), at the methods end create DTO using factory methods
- All the code is one location, control over data is maintained
Is this structure always necessary?
- No, it depends on the complexity of application
Doesn’t it take too much time to implement?
- If the lifecycle of your app is longer, then everything is much faster after initial release
- NB! Every web service might have 1+N clients. The less we change our public services, the better.
- It’s scary/complex only on the first try (ok, first few try’s)
Why do we need it?
- Do change our internal logic without touching public services.
- Development cycle is more effective in bigger teams.
- First DTO’s and services for front-end team – and then we can work in parallel tracks with them on the back-end.