Help discussing separation of concerns (Data Access vs Business Logic)

I had a discussion with my colleague about whether a certain logic belongs to the level of access to data or business logic.

Scenario - BLL needs some data to work. This data is mainly stored in a database. We want to cache this data (using System.Runtime.Caching) so that it is quickly accessible on subsequent requests. The architecture is such that DAL and BLL live on the same box and in different assemblies (projects in one solution). Therefore, do not worry about pressing DAL on a wire or something like that.

My argument is that the decision to delete the cache and database is a DAL problem. The level of business logic does not have to worry about where the data comes from, only to get the data it needs.

His argument is that the level of data access should be β€œclean” and β€œstupid,” and any logic for this solution to go into the cache and database must be at the level of business logic.

In my opinion, what he says undermines the separation of problems and makes the layers more closely connected when the goal is to keep things loosely connected. I can see where the BLL may want to control this, if it is a specific program / ui function, to decide where to go for the data, but it just isn't. This is just a very simple caching scenario when the database is the main data warehouse.

Thoughts?

+2
source share
5 answers

I agree with you 100%.

Caching is part of DAL and is not owned by BLL.

Take hibernate as an example, it uses a caching system to store your entity. Hibernate answers and knows how to control its cache, (dirty reading, data flushing, etc.)

You don't want to clutter your BLL with all this low-level data logic.

Hi

+1
source

I believe caching should be done at the business level. At the moment when you are trying to get data from the DAL, you can check if the data is available in the .runtime.caching cache system, and then use the cache data, otherwise retrieve the data from the database. Moreover, if you want to invalidate the cache for some reason, you can do this by calling a function in the business later.

+1
source

The whole purpose of separating business logic from data is that you can replace them in accordance with business requirements or technological changes. By mixing them, you defeat this logic, and therefore, at the theoretical level, you are right. However, in the real world, I think you need to be a little more pragmatic. What is the real lifespan of the application, what is the likelihood that the technology will change, and what additional work will be associated with having two clean finishes?

0
source

My initial reaction will be the same as yours so that the data layer caches information. It can even be integrated with a strategy for signing changes to a database or for conducting a survey to ensure the data is always up to date.

However, if you intend to reuse the data layer in other projects, or even if it is not, it might be a good idea to implement a new business layer between the existing and the data layer to handle caching decisions. Since ultimately caching is not just a performance issue, it is related to concurrency business decisions and other issues.

An n-level system is that you are not limited by how many levels you want to separate.

0
source

I know that I was two years late for the game, but I wanted to add something:

If you have an interface specific to your DAL, you can write a caching mechanism that follows that interface and manages the "cache against problems with the data source", without using the DAL code associated with the technology or source code to worry about it and without BLL to worry about it. Example:

internal interface IThingsGateway { public Thing GetThing(int thingId); public void UpdateThing(ThingUpdateInfo info); } internal class MsSqlThingsGateway : IThingsGateway { // implementation specific to MsSql here } internal class CachingThingsGateway : IThingsGateway { private IThingsGateway underlyingImplementation; public CachingThingsGateway(IThingsGateway implementation) { this.underlyingGateway = implementation; } public Thing GetThing(int thingId) { if (this.HasCachedThing(thingId)) { return this.GetCachedThing(thingId); } var thing = this.underlyingGateway.GetThing(thingId); this.SetCachedThing(thingId); return thing; } public void UpdateThing(ThingUpdateInfo info) { this.underlyingGateway.UpdateThing(info); this.ClearCachedThing(info.ThingId); } } 

And I would use the same approach if I needed to check several data sources for something: write an implementation of IThingsGateway , which handles the logic of manipulating various data sources, delegating the relevant information ... then we finish that in CachingThingsGateway . Client code will eventually receive an IThingsGateway link from some factory or container where the wrapping and instantiation will take place.

And all this really does not require much effort. If you use caching, you will have to write this code anyway, and the overhead created by putting it in another class with the same interface is minimal in the worst case.

0
source

All Articles