【问题标题】:How to reduce complexity in a facade implementation?如何降低外观实现的复杂性?
【发布时间】:2013-11-26 04:12:41
【问题描述】:

正如您在下图中所见,我正在研究一种架构设计的概念验证,该设计将满足我的研究小组的需求。它们是:

  • 可重用的业务逻辑组件
  • 解耦数据模型
  • 分离的前端(即 Web ui、服务、控制台应用等)
  • 所有组件(前端除外)都应该是完全可单元测试的(例如使用模拟)。

为了实现这一点,我们引入了一个“胶水”组件(Glue.ConsoleApp),它基本上是一个外观模式实现。每个前端都会有一个对应的门面。这是一个简单的 C# 解决方案,显示了分离组件的极简实现。

外观将所有组件链接在一起,但我认为代码仍然过于复杂。我正在努力解决这样一个事实,即为了完全分离所有层,它们都需要定义自己的实体来使用,并且粘合层必须进行大量映射(这就是我使用 ValueInjecter 的原因,一个库使大部分工作自动化)。

下面是一个示例方法,展示了在一个方法中使用三个不同的类来表示 InvoiceLine 的复杂性:

using Database = ArchitecturePoC.DataAccess.Database;
using InvoiceProcessing = ArchitecturePoC.BusinessLogic.InvoiceProcessing;

public static Dictionary<Entities.Invoice, List<Entities.InvoiceLine>> GetAllInvoicesWithInvoiceLines()
{
    Dictionary<Entities.Invoice, List<Entities.InvoiceLine>> result = new Dictionary<Entities.Invoice, List<Entities.InvoiceLine>>();

    Database.InvoiceMapper invoiceMapper = new Database.InvoiceMapper();
    Dictionary<Database.Entities.Invoice, List<Database.Entities.InvoiceLine>> invoicesWithInvoiceLines = invoiceMapper.GetAllInvoicesWithInvoiceLines();

    foreach (KeyValuePair<Database.Entities.Invoice, List<Database.Entities.InvoiceLine>> invoiceWithInvoiceLines in invoicesWithInvoiceLines)
    {
        List<Entities.InvoiceLine> subResult = new List<Entities.InvoiceLine>();

        foreach (Database.Entities.InvoiceLine invoiceLine in invoiceWithInvoiceLines.Value)
        {
            Entities.InvoiceLine resultInvoiceLine = new Entities.InvoiceLine();
            resultInvoiceLine.InjectFrom(invoiceLine);
            subResult.Add(resultInvoiceLine);
        }

        Entities.Invoice resultInvoice = new Entities.Invoice();
        resultInvoice.InjectFrom(invoiceWithInvoiceLines.Key);

        result.Add(resultInvoice, subResult);
    }

    return result;
}

我担心我将这种“干净的分离”误认为最终会给我带来比我想要的更多的担忧。我可以想象立面迅速变得非常大并且难以维护。您对降低这种复杂性有什么建议吗?

旁注:我查看了看起来很有趣的域事件模式,但我不确定如何将其应用于这种情况。

【问题讨论】:

  • 各层中的实体之间有什么区别?我通常有一个集中的域,我从我的所有项目中引用它。您可能必须为业务实体创建另一种“风格”的唯一情况可能是您需要 DTO 在接口之间进行通信(例如 WebServices)。
  • 实体并没有太大的不同。只是我们希望能够在完全不同的解决方案中重新使用 InvoiceProcessor。由于 InvoiceProcessor 有自己的类,这应该很容易。

标签: c# architecture facade


【解决方案1】:

我在您的架构中看到的问题是 3 个不同的实体文件夹。对我来说,实体是与业务/领域相关的概念,它们应该只在业务层中定义。相反,我倾向于调用在服务层和表示层 DTO 之间共享的对象。它们可以是业务实体的准确反映,也可以是更部分或更精细的东西。至于数据访问层,如果您使用对象关系映射器,它将允许您透明地保存来自业务层的实体,您无需声明实体的 DAL 版本。您可以在 DAL 中拥有以您的实体命名的 DAORepositories,但它们不是实体,而是操纵它们。

这并没有删除所有映射,但我担心在分层架构中无论如何都会有一些映射has to be done

作为旁注,我不明白为什么你应该为每个字体末端都有一个外观项目。这将意味着大量的代码重复。通常应用程序具有某种服务层,作为所有表示层的业务操作的单一外观。

【讨论】:

  • 感谢您花时间思考这个架构。我想了很多,你的回答很有启发性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-07
  • 1970-01-01
相关资源
最近更新 更多