帮助讨论关注点分离(数据访问与业务逻辑)

时间:2011-08-25 14:40:00

标签: data-access-layer bll loose-coupling tightly-coupled-code

我和我的同事讨论过某些逻辑是属于数据访问还是业务逻辑层。

场景是,BLL需要一些数据才能使用。该数据主要存在于数据库中。我们希望缓存该数据(使用System.Runtime.Caching),以便在后续请求中快速使用。该体系结构使得DAL和BLL位于同一个盒子和不同的程序集中(同一解决方案中的项目)。所以不用担心在电线上打DAL或类似的东西。

我的论点是,打击缓存与数据库的决定是DAL的一个问题。业务逻辑层不应该关心数据来自何处,只关心它获取所需的数据。

他的论点是数据访问层应该是“纯粹的”和“愚蠢的”,并且任何决定使用缓存与数据库相关的逻辑应该在业务逻辑层中。

在我看来,当他的目标是保持松散耦合时,他所说的正在破坏关注点的分离并导致层次更加紧密耦合。我可以看到BLL可能想要控制它的位置,如果它是一个特定的程序/ ui函数来决定数据的去向,但这不是这里的情况。这只是一个非常简单的缓存场景,数据库是主数据存储。

思想?

5 个答案:

答案 0 :(得分:1)

我100%同意你的意见。

缓存是DAL的一部分,不属于BLL。

让我们以休眠为例,它使用缓存系统来存储您的实体。 Hibernate负责并知道如何控制他的缓存(脏读,刷新数据等)

您不希望使用所有这些低级数据逻辑混乱BLL。

此致

答案 1 :(得分:1)

我认为缓存应该在业务层完成。当您尝试从DAL获取数据时,您可以检查数据是否在缓存system.runtime.caching中可用,然后使用缓存数据,否则从数据库中获取数据。此外,如果由于某种原因想要使缓存无效,可以稍后通过调用业务中的函数来实现。

答案 2 :(得分:0)

将业务逻辑与数据分离的全部目的是,您可以将它们作为业务需求或技术更改进行交换。通过混合它们,你正在击败这种逻辑,因此,在理论层面上你是正确的。然而,在现实世界中,我认为你需要更加务实。应用程序的实际预期寿命是什么,技术发生变化的可能性是多少,以及保持两者完全分离需要多少额外工作?

答案 3 :(得分:0)

我的初始反应与您的相同,让数据层缓存信息。这甚至可以与策略相结合,以订阅数据库中的更改,或实施轮询以确保数据保持最新。

但是,如果您打算在其他项目中重复使用数据层,或者即使不是,那么在现有项和数据层之间实现新的业务层来处理缓存决策可能不是一个坏主意。因为最终,缓存不仅仅是一个性能问题,它确实涉及有关并发性和其他事项的业务决策。

n层系统就是这样,你并不局限于想要分成多少级别。

答案 4 :(得分:0)

我知道我比赛迟了两年但是我想补充一点:

如果您为DAL定义了一个接口,您可以编写一个跟随该接口的缓存机制并管理“缓存与命中数据源”的关注点,而不需要技术或源特定的DAL代码担心它没有BLL不必担心它。例如:

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);
    }
}

如果我需要为一个东西检查多个数据源,我会使用相同的方法:编写一个IThingsGateway的实现来处理处理各种数据源的逻辑,委托给适当的...然后在CachingThingsGateway中包含 。客户端代码最终将从某个工厂或容器中获取IThingsGateway引用,这是进行包装和实例化的地方。

所有这一切都不需要额外的努力。如果使用缓存,则无论如何都必须编写该代码,并且将其放在具有相同接口的另一个类中所产生的开销在最坏情况下是最小的。