gpt4 book ai didi

c# - 除了实例化 DAL 的 BLL 之外,还有什么选项允许在 n 层解决方案中进行单元测试,而无需将 DAL 暴露给 UI 或 BLL 暴露给 DAL?

转载 作者:太空宇宙 更新时间:2023-11-03 23:25:29 25 4
gpt4 key购买 nike

我有一个分层解决方案如下:

  • UI(用户界面)
  • BLL(业务逻辑层)
  • DAL(数据访问层)
  • SharedEntities(仅包含实体 POCO 的 VS 项目)

我希望 BLL 有一个名为 GetProductList() 的服务,该服务在我的 DAL 层中实现。我考虑过在 BLL 和 DAL 实现中定义一个接口(interface),如下所示:

选项 A:

// Interface defined in BLL 
public interface IDataServices
{
List<Product> GetProductList();
}

// Interface implemented in DAL
public class DataServices : IDataServices
{
Public List<Product> GetProductList()
{
return //do some database work here and return List<Product>;
}
}

如果我想在 DAL 中实现它,那么我必须让 DAL 项目引用 BLL 项目才能看到 IDataServices 的接口(interface)定义。或者,我可以在 DAL 中复制接口(interface)定义,但我最终会得到要维护的重复代码(BLL 和 DAL 中的相同接口(interface)定义)。

选项 B:我可以这样做的另一种方法是忘记接口(interface)的想法,只在 UI 可以使用的 BLL 中进行以下具体类和方法调用:

// Concrete class defined in the BLL
public class DataServices
{
Public List<Product> GetProductList()
{
DAL aDAL = new DAL();
Return (aDAL.GetProductList());
}
}

这很简单,但是 BLL 会看到 DAL 并引用它,但这真的是一件坏事吗?只要 BLL 不使用任何数据库对象(即数据源、连接字符串等)来满足请求并且 DAL 符合匹配我在 BLL DataServices 类中定义的服务的名称,这还不够吗?我听到的关于在另一个数据库引擎中交换的所有讨论仍然可以通过确保下一个 DAL 提供 BLL 在 DataServices 类中标识的相同服务(例如 GetProductList())来完成。在此设置中,UI 仍然不知道有关 DAL 的任何信息,而 DAL 也不知道有关 BLL 的任何信息。如果我接受使用依赖注入(inject)来避免在 BLL 中实例化 DAL 的想法,这将意味着在 UI 中实例化它以传递到 BLL 中。我不想这样做,因为这会让 UI 访问 DAL 方法。

选项 C:我简单地看了一下 Unity Container,但该工具建议在入口点预先注册所有接口(interface)和具体类,这本来是 UI,而这反过来又为 BLL 和 DAL 提供了 UI 可见性,这似乎更糟.我看到了将 MEF 与 Unity 结合使用来解决入口点看到所有层的问题的引用,但我也看到如果你这样做,你就不能真正地对这样的配置进行单元测试。与选项 B 相比,工作量和复杂性似乎很大。

选项 D:我考虑过的另一个选择是在 BLL 和 DAL 之间创建一个外观层(另一个 VS 项目)。这似乎没有多大意义,除非我最终得到了很多与 BLL 无关的 DAL 方法,因此必须隐藏它们;允许 DAL Facade 仅显示 BLL 需要的内容。如果我要交换到另一个数据库中,我仍然需要根据 BLL 的需要创建外观所需的方法,正如我在选项 B 中提到的那样。

因此,基于所有这些,我正在考虑选择选项 B,但我想在这里提供一些社区意见。满足以下条件还能做什么:

  • 1) 不让 UI 看到 DAL
  • 2) 不让DAL看到BLL
  • 3) 该解决方案仍然允许对所有层进行单元测试

最佳答案

您的选项 A(BLL 中的接口(interface),DAL 中的实现)+ 和 IoC 容器是最佳方法。

在设计复杂的软件解决方案时,您必须将其分成更小的部分。

其中一些部分对于解决方案至关重要。它们将是您开发软件的原因,而不仅仅是购买现有解决方案。你必须专注于他们。这些部分将很复杂且难以实现。你对此无能为力。它们必须尽可能得到最好的实现。

也会有简单的作品。易于实现的功能,甚至可以购买。尝试以尽可能少的努力制作这些零件。它们是必要的,但它们不是您受雇的目的。

首先关注困难的部分。那里的业务逻辑会很复杂。业务逻辑将不依赖于您选择的存储解决方案——所以不要让它依赖于您系统中的 DAL 项目。在您的业务逻辑层中为您的实体(如果您遵循 DDD,则聚合)的存储库定义接口(interface)。

您应该能够彻底测试业务逻辑。如果 BLL 依赖于 DAL,则无法执行此操作。

UI 应该与业务逻辑完全分离。 UI 只是用户可以执行的一组用例。因此,它应该向用户提供有限的信息,并且只接受来自用户的有限信息。

要将 UI 与 BLL 分开,请使用单独的 ViewModel 和 Command 类来显示和接受来自用户的信息。在每个用例中使用额外的应用层来编排 BLL。

这种方法众所周知 Hexagonal architecture , Onion architectureClean architecture .域驱动设计书籍中也引用了它。

当然,您需要一个地方将所有这些依赖项放在一起。这个地方是composition root它应该尽可能靠近应用程序入口点。如果您不想引用 UI 项目中的所有层,请将组合根移动到另一个项目。

关于c# - 除了实例化 DAL 的 BLL 之外,还有什么选项允许在 n 层解决方案中进行单元测试,而无需将 DAL 暴露给 UI 或 BLL 暴露给 DAL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33966147/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com