代码之家  ›  专栏  ›  技术社区  ›  JamesStuddart

业务层结构,如何构建自己的业务层结构?

  •  3
  • JamesStuddart  · 技术社区  · 14 年前

    我非常喜欢我的开发选择,当然它并不适合所有的场景。

    我现在正在做一个新的项目,我正试着用我平时的工作方式玩一玩,试着看看我能不能把它清理干净。因为我一直是一个非常坏的孩子,一直把太多的代码在表示层。

    我通常的业务层结构如下(it的基本视图):

      • 服务
          • 食物帮手
          • 食物工作流
        • Bah组件
          • 帮手
          • BAH工作流
      • 公用事业
        • 普通
        • 异常处理程序
        • 进口商

    现在有了上面的内容,我可以通过Foo对象和Bah对象各自的助手直接保存它们。

    XXXHelpers允许我保存、编辑和加载相应的对象,但是我应该将保存对象和子对象的逻辑放在哪里呢。

    例如:

    • 雇员
    • 员工详情
    • 员工会员

    目前我会把这些都建立在表示层,然后把它们传递给他们的助手,我觉得这是错误的,我认为数据应该传递到业务层表示层上面某个地方的一个点,然后在那里整理出来。

    但我有点不知所措,我该把这个逻辑放在哪里,该怎么称呼这个行业,它会作为雇员经理归入公用事业还是类似的行业?

    你会怎么做?我知道这都是偏好。

    更详细的布局

    工作流包含直接对数据存储库的所有调用,例如:

    public ObjectNameGetById(Guid id)
    {
        return DataRepository.ObjectNameProvider.GetById(id);
    }
    

    然后帮助程序提供程序访问工作流:

    public ObjectName GetById(Guid id)
    {
        return loadWorkflow.GetById(id);
    }
    

    然后在Helper中进行几个调用,这些调用可以执行其他操作并以不同的方式返回数据,一个坏的例子是public GetByIdAsc和GetByIdDesc

    通过使用DataRepository来分离对数据模型的调用,这意味着可以将模型换成另一个实例(这是我们的想法),但是ProviderHelper没有被分解,因此它不可交换,因为它是硬代码。

    projectName.Core

    projectName.Business
        - Interfaces
            - IDeleteWorkflows.cs
            - ILoadWorkflows.cs
            - ISaveWorkflows.cs
            - IServiceHelper.cs
            - IServiceViewHelper.cs
        - Services
            - ObjectNameComponent
                - Helpers
                    - ObjectNameHelper.cs
                - Workflows
                    - DeleteObjectNameWorkflow.cs
                    - LoadObjectNameWorkflow.cs
                    - SaveObjectNameWorkflow.cs
        - Utilities
            - Common
                - SettingsManager.cs
                - JavascriptManager.cs
                - XmlHelper.cs
                - others...
    
            - ExceptionHandlers
                - ExceptionManager.cs
                - ExceptionManagerFactory.cs
                - ExceptionNotifier.cs
    
    
    projectName.Data
        - Bases
            - ObjectNameProviderBase.cs
        - Helpers
            - ProviderHelper.cs
        - Interfaces
            - IProviderBase.cs
        - DataRepository.cs
    
    projectName.Data.Model
        - Database.edmx
    
    projectName.Entities (Entities that represent the DB tables are created by EF in .Data.Model, this is for others that I may need that are not related to the database)
        - Helpers
            - EnumHelper.cs
    

    项目名称。呈现

    (取决于应用程序的调用)

    projectName.web
    projectName.mvc
    projectName.admin
    

    测试项目

    projectName.Business.Tests
    projectName.Data.Test
    
    2 回复  |  直到 14 年前
        1
  •  3
  •   deepcode.co.uk    14 年前

    所以,您描述的问题非常常见-我会采取不同的方法-首先是逻辑层,其次是实用程序和助手名称空间,我会尝试完全解决这些问题-我马上告诉您原因。

    但首先,这里我比较喜欢的方法是非常常见的企业体系结构,我将试着简单地强调一下,但还有更深入的内容。它确实需要一些思想上的根本性改变——使用NHibernate或实体框架允许您直接查询对象模型,并让ORM处理诸如与数据库的映射和延迟加载关系等事情。这样做将允许您在域模型中实现所有业务逻辑。

    第一层(或解决方案中的项目);

    域模型-表示问题空间的对象。这些是包含所有关键业务逻辑的普通旧CLR对象。这就是示例对象所在的位置,它们的关系将表示为集合。在这个层中没有任何东西处理持久性等,它只是对象。

    YourApplication.Data

    存储库类-这些类处理获取域模型的聚合根。

    例如,在示例类中,您不太可能希望查看EmployeeDetails而不同时查看Employee(我知道这是一个假设,但您得到了要点-发票行是一个更好的示例,您通常会通过发票获得发票行,而不是单独加载它们)。因此,存储库类(其中每个聚合根有一个类)将负责使用所讨论的ORM从数据库中获取初始实体,实现任何查询策略(如分页或排序)并将聚合根返回给使用者。存储库将使用当前的活动数据上下文(NHibernate中的ISession)——会话的创建方式取决于您正在构建的应用程序的类型。

    你的应用程序.工作流

    • 也可以称为您的应用程序。服务,但这可能会与web服务混淆

    其他层则取决于您的体系结构和正在实现的应用程序。

    如果您使用web服务来分发您的层,那么您将创建DTO契约,该契约仅表示您在域和使用者之间公开的数据。您将定义汇编器,这些汇编器将知道如何将数据从域中移入和移出这些协定(您永远不会通过网络发送域对象!)

    在这种情况下,您还将创建客户机,您将使用上面在表示层中定义的操作和数据契约,可能直接绑定到DTO,因为每个DTO都应该是视图特定的。

    如果您不需要分发您的层,记住分布式体系结构的第一条规则是不要分发,那么您将直接从内部使用工作流/服务和存储库asp.net、mvc、wpf、winforms等。

    这样就只剩下建立数据上下文的地方了。在web应用程序中,每个请求通常都是非常独立的,因此请求范围的上下文是最好的。这意味着上下文和连接在请求开始时建立,并在请求结束时释放。让您选择的IoC/依赖注入框架为您配置每个请求组件是很简单的。

    依赖注入

    以上所有内容都将首先定义为接口,具体实现通过IoC和依赖注入框架实现(我更喜欢castlewindsor)。这允许您独立地隔离、模拟和单元测试各个层,并且在大型应用程序中,依赖注入是一个救命稻草!

    那些命名空间

    如果需要包装通用框架类型代码,请添加MyApp.Framework 项目和相关名称空间。如果你正在添加一个新的模型活页夹,把它放进去MyApp.Framework.Mvc,如果是常见的日志记录功能,请将其放入MyApp.Framework.Logging 等等。在大多数情况下,不需要引入实用程序或helpers命名空间。

    总结

    所以这只是表面现象-希望能有所帮助。这就是我今天开发软件的方式,我故意尽量简短—如果我能详细说明任何细节,请告诉我。最后一点要说的是,以上是合理的大规模开发-如果你写的记事本版本2或公司电话簿,以上可能是完全过度!!!

    干杯 托尼

        2
  •  0
  •   JamesStuddart    14 年前

    这页上有一个很好的图表和关于应用程序布局的描述,alhtough进一步看了这篇文章应用程序没有被分割成物理层(单独的项目)- Entity Framework POCO Repository