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

Posted

技术标签:

【中文标题】帮助讨论关注点分离(数据访问与业务逻辑)[关闭]【英文标题】:Help with debate on Separation of concerns (Data Access vs Business Logic) [closed] 【发布时间】:2011-11-03 18:34:36 【问题描述】:

我与我的同事就某些逻辑是否属于数据访问层或业务逻辑层进行了辩论。

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

我的论点是,命中缓存还是命中数据库的决定是 DAL 关心的问题。业务逻辑层不应该关心数据来自哪里,只关心它获取所需的数据。

他的论点是,数据访问层应该是“纯粹的”和“愚蠢的”,任何决定命中缓存还是数据库的逻辑都应该在业务逻辑层中。

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

想法?

【问题讨论】:

这可能更适合programmers.se 【参考方案1】:

将业务逻辑与数据分离的整个目的是,您可以在业务需求或技术变化时将它们换掉。通过混合它们,你正在打败这个逻辑,因此,在理论上你是正确的。然而,在现实世界中,我认为你需要更加务实一些。应用程序的实际预期寿命是多少,技术发生变化的可能性有多大,以及要保持两者完全分开需要多少额外的工作?

【讨论】:

【参考方案2】:

我最初的反应会和你一样,让数据层缓存信息。这甚至可以与订阅数据库更改或实施轮询以确保数据保持最新的策略集成。

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

一个 n 层系统就是这样,您不受要将事物分成多少层的限制。

【讨论】:

【参考方案3】:

我 100% 同意。

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

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

你不想让你的 BLL 被所有这些低级数据逻辑弄得一团糟。

问候

【讨论】:

【参考方案4】:

我知道我迟到了两年多,但我想补充一点:

如果您为 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 引用,这是包装和实例化发生的地方。

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

【讨论】:

【参考方案5】:

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

【讨论】:

以上是关于帮助讨论关注点分离(数据访问与业务逻辑)[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

《Spring实战 第三版》四

Spring学习--面向切面的Spring

UI与数据分离 与 UI的演进

Spring AOP概述

需要有关分层解决方案、关注点分离等方面的建议

用于分离数据访问、业务逻辑和表示的简单优雅模式