Architecture 不同逻辑层上的接口

Architecture 不同逻辑层上的接口,architecture,Architecture,假设您有一个分为3层的应用程序:GUI、业务逻辑和数据访问。在业务逻辑层中,您描述了您的业务对象:getter、setter、accessor等等。。。你明白了。业务逻辑层的接口保证了业务逻辑的安全使用,因此您调用的所有方法和访问器都将验证输入 当您第一次编写UI代码时,这非常好,因为您有一个可以信任的定义整洁的界面 但棘手的是,当您开始编写数据访问层时,业务逻辑的接口无法满足您的需要。您需要有更多的访问器和获取器来设置隐藏的字段。现在,您不得不侵蚀业务逻辑的接口;现在可以从UI层设置字段,UI

假设您有一个分为3层的应用程序:GUI、业务逻辑和数据访问。在业务逻辑层中,您描述了您的业务对象:getter、setter、accessor等等。。。你明白了。业务逻辑层的接口保证了业务逻辑的安全使用,因此您调用的所有方法和访问器都将验证输入

当您第一次编写UI代码时,这非常好,因为您有一个可以信任的定义整洁的界面

但棘手的是,当您开始编写数据访问层时,业务逻辑的接口无法满足您的需要。您需要有更多的访问器和获取器来设置隐藏的字段。现在,您不得不侵蚀业务逻辑的接口;现在可以从UI层设置字段,UI层没有业务设置

由于数据访问层所需的更改,业务逻辑的接口已经侵蚀到甚至可以使用无效数据设置业务逻辑的程度。因此,接口不再保证安全使用


我希望我把这个问题解释得足够清楚。如何防止接口腐蚀,保持信息隐藏和封装,同时又能满足不同层之间不同的接口需求

我总是创建一个单独的程序集,其中包含:

  • 很多小接口(想想ICreateRepository、IReadRepository、IReadListRepsitory..这个列表还有很多,其中大部分都严重依赖泛型)
  • 很多具体的接口,比如IPersonRepository,都是从IReadRepository继承的,你明白了这一点。
    任何你不能用较小的接口描述的东西,你都要放到具体的接口中。
    只要使用IPersonRepository来声明对象,就可以获得一个干净、一致的界面。但更重要的是,你也可以创建一个类,在它的构造函数中使用f.x.一个ICreateRepository,这样代码就可以很容易地完成一些非常有趣的事情。这里还有业务层中服务的接口
  • 最后,我将所有域对象粘贴到额外的程序集中,只是为了使代码库本身更干净、更松散地耦合。这些对象没有任何逻辑,它们只是描述所有3+层数据的常用方式
顺便问一下,为什么要在业务逻辑层中定义方法来适应数据层?

数据层应该没有理由知道存在业务层。

它可能是一个解决方案,因为它不会侵蚀接口。我想你可以上这样的课:

public class BusinessObjectRecord : BusinessObject
{
}

数据层不应该知道业务逻辑层是什么意思?如何用数据填充业务对象

我经常这样做:

namespace Data
{
    public class BusinessObjectDataManager
    {
         public void SaveObject(BusinessObject object)
         {
                // Exec stored procedure
         {
    }
}

这是一个典型的问题-将域模型与数据库模型分离。有几种方法可以攻击它,在我看来,这实际上取决于你项目的规模。您可以像其他人所说的那样使用存储库模式。如果您使用的是.net或java,则可以使用或

我所做的是使用,因此我首先编写UI和模型层,然后模拟数据层,因此UI和模型是围绕特定于域的对象构建的,然后我将这些对象映射到我正在使用的数据层技术。让数据库决定应用程序的设计,先编写应用程序,然后再考虑数据,这是一个非常糟糕的想法

ps问题的标题有点误导

@Ice^^Heat:


数据层不应该知道业务逻辑层是什么意思?如何用数据填充业务对象

UI向业务层中的ServiceClass请求一个服务,即获取一个对象过滤的对象列表,其中包含所需的参数数据。
然后ServiceClass在数据层中创建一个存储库类的实例,并调用GetList(ParameterType筛选器)。
然后数据层访问数据库,提取数据,并将其映射到“域”程序集中定义的通用格式。
BL不再处理这些数据,因此它将其输出到UI

然后UI想要编辑项目X。它将项目(或业务对象)发送到业务层中的服务。业务层验证对象,如果它正常,则将其发送到数据层进行存储

UI知道业务层中的服务,而业务层又知道数据层


UI负责将用户输入的数据映射到对象,数据层负责将db中的数据映射到对象。业务层保持纯业务状态。:)

所以问题是业务层需要向数据层公开更多功能,而添加此功能意味着向UI层公开太多?如果我正确地理解了您的问题,那么听起来您试图用一个接口来满足太多的需求,这只是导致它变得混乱。为什么不在业务层中有两个接口?一种是UI层的简单、安全的界面。另一个是数据层的较低级别接口

您可以将这种双接口方法应用于任何需要同时传递到UI和数据层的对象

public class BusinessLayer : ISimpleBusiness
{}

public class Some3LayerObject : ISimpleSome3LayerObject
{}

您可能希望将接口分为两种类型,即:

  • 查看接口——这些接口指定您与UI的交互,以及
  • 数据接口——这些接口允许您指定与数据的交互
可以继承和实现这两组接口,以便:

public class BusinessObject : IView, IData
这样,在数据层中,您只需要看到IData的接口实现,而在UI中,您只需要看到
public class BusinessObject : DomainObject

public class ViewManager<T> where T : DomainObject

public class DataManager<T> where T : DomainObject
public class User
{
    private string name;
    private AccountStatus status;

    private User()
    {
    }

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public AccountStatus Status
    {
        get { return status; }
    }

    public void Activate()
    {
        status = AccountStatus.Active;
    }

    public void Suspend()
    {
        status = AccountStatus.Suspended;
    }

    public static User GetById(int id)
    {
        User fetchedUser = new User();

        // Lots of database and error-checking code
        // omitted for clarity
        // ...

        fetchedUser.name = (string) reader["Name"];
        fetchedUser.status = (int)reader["statusCode"] == 0 ? AccountStatus.Suspended : AccountStatus.Active;

        return fetchedUser;
    }

    public static void Save(User user)
    {
        // Code to save User's internal structure to database
        // ...
    }
}