如何完全分离业务和数据层?

时间:2009-06-30 22:52:08

标签: c# design-patterns

我目前在我的应用程序中的单个项目中代表我的业务层和数据层。我对两组课程之间的关注点有很好的分离。但是,我的数据层类作为参数并返回我的业务对象。因此,我将拥有松散类似的代码(请不要过于批评此代码,我的生产代码看起来不像这样):

//business class fragment
public bool Save()
{
    if(this.IsValid)
    {
       //DataProvider is one of many data access classes that implement an IDataProvider interface.  Switched elsewhere in the class.  This allows switching of Database providers, xml, etc.
       DataProvider.Save(this);
       return true;
    }
    return false;
}

public List<MyBusinessObject> GetObjectsByCriteria(string criteria)
{
    return DataProvider.GetMyBusinessObjectsByCriteria(criteria);
}

我不希望我的业务类必须处理DataSet,而不是让我的数据层类处理Business Classes。

我已经在数据访问对象或数据传输对象上阅读了很多内容以解决这个问题,但这似乎是这些模式的反模式案例。

我该怎么办?如何优雅地实现我的应用程序的这两层完全分离?

6 个答案:

答案 0 :(得分:2)

这是一个更普遍的问题,而不仅仅是如何将域模型与数据访问分开。当您尝试将应用程序逻辑与域模型,应用程序逻辑中的表示模型等分开时,会出现同样的问题。

常见的解决方案是一种称为依赖注入(DI)的技术。有些人还将其称为控制反转(IoC)。

关于这个主题的开创性文本是Martin Fowler的文章Inversion of Control Containers and the Dependency Injection pattern,但是从那时起我们已经走了很长的路,所以一定要检查一些最近的文本。

您可以手动实施DI,例如described in this blog post,或者您可以让DI容器(即框架)为您完成工作。

Common DI Container是:

答案 1 :(得分:2)

我认为你不能将两者完全分开,但你可以确保依赖性不是双向的。

我认为定义一些事情非常重要:

  1. 模型对象(例如,人员,地址,订单等)
  2. 持久层(例如,DAO,存储库等)
  3. 服务层(其方法映射到用例,了解工作单元等的接口)
  4. 网页或视图层(网页应用的控制器/网页,桌面小工具)。
  5. 持久性,服务和视图层知道模型对象;模型对象无视它们所在的层。

    图层的依赖关系是单向的,并且会回流到前面:

    • persistence-&GT;模型
    • service-&gt; model,persistence
    • view-&gt; model,service

    您可以从后到前进行单元测试,因为依赖项可以轻松进行模拟。

    不可能没有依赖关系,但是你应该设计它们以便没有循环。

    唯一具有依赖关系的类是没有人调用的类,并且从不调用另一个类。它既没有用,也没有一个有价值的设计目标。

答案 2 :(得分:1)

将持久性逻辑从业务对象中拉出,并将它们放入数据Adapter中。它的工作方式类似于.NET中现有的适配器(OleDbDataAdapter)。这样,您还可以分离业务对象和持久性逻辑。

您的客户端代码会更加冗长,但我认为这确实是真正分离图层的最佳方式。

答案 3 :(得分:0)

执行此操作的流行模式是存储库模式。在这种情况下,Repository充当使用集合语义的外观,完全隐藏持久数据所在的位置,无论是文件系统还是数据库。您可以实现它来访问数据,然后将数据映射到您想要使用的任何类型。

您可能会将域驱动设计作为您正在使用的Active Record模式的替代方案。

答案 4 :(得分:0)

您应该查看DAO模式(数据访问对象)。 http://en.wikipedia.org/wiki/Data_Access_Object

最好的是,使用准备好的DAO构造(弹簧加载)。看看http://trac.synyx.org/hades

DAO不是反模式!将它们与Spring和泛型一起使用,你不必关心;)

每次层之间都有连接!完全分离它们意味着它们无法进行通信(因此它们没用)。

使用基本的CRUD操作或动态查找器,只要它具有语义意义。

答案 5 :(得分:0)

n层设计:在业务逻辑层中,您可以创建数据访问类和数据操作类。总是编程到界面。