Help with debate on Separation of concerns (Data Access vs Business Logic) [closed]

允我心安 提交于 2019-12-06 11:04:41

I agree with you 100%.

Caching is part of the DAL and does not belong in the BLL.

Let's take hibernate as an example, it use a caching system to store your entity's. Hibernate is responsible and know how to control his cache, (dirty read, flushing data etc)

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

Regards

I believe that the caching should be done in the business layer. The moment you try to get the data from DAL, you can check if the data is available in cache system.runtime.caching, then use cache data otherwise fetch data from the database. Moreover if you want to invalidate cache due to some reason, you can do it by calling a function in the business later.

The whole purpose in separating business logic from data is so that you can swap them out as business requirements or technology changes. By intermixing them, you are defeating this logic, and therefore, on a theoretical level you are correct. In the real world however, I think you need to be a bit more pragmatic. What's the real life expectancy of the application , what is the likelihood that the technology is going to change, and how much extra work is involved in keeping the two cleanly separated?

My initial reaction would be the same as yours, to let the data layer cache the information. This can even be integrated in with a strategy to subscribe to changes in the database, or implement polling to ensure the data is kept up-to-date.

However, if you intend to re-use the data layer in other projects, or even if not, it might not be a bad idea to implement a new business layer between the existing one and the data layer to handle caching decisions. Because ultimately, caching is a not just a performance issue, it does involve business decisions about concurrency and other matters.

An n-tier system is just that, you're not limited on how many levels you want to seperate things into.

I know I'm over two years late to the game but I wanted to add something:

If you have an interface defined for your DAL, you can write a caching mechanism that follows that interface and manages 'cache vs. hit the data source' concerns without the technology or source-specific DAL code having to worry about it and without the BLL having 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 this same approach if I needed to check multiple data sources for a thing: write an implementation of IThingsGateway that handles the logic of juggling the various data sources, delegating to the appropriate one... then wrap that in the CachingThingsGateway. Client code will ultimately obtain an IThingsGateway reference from some factory or container, which is where the wrapping and instantiating would occur.

And all of this really doesn't take that much extra effort. If you use caching you will have to write that code anyways, and the overhead generated by putting it in another class with the same interface is minimal at worst.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!