当前位置:  开发笔记 > 程序员 > 正文

不同逻辑层的接口

如何解决《不同逻辑层的接口》经验,为你挑选了2个好方法。

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

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

但是这里有一个棘手的部分,当你开始编写数据访问层时,业务逻辑的接口无法满足你的需求.您需要有更多的访问器和getter来设置隐藏/曾经隐藏的字段.现在你被迫侵蚀了业务逻辑的界面; 现在可以从UI层设置字段,UI层没有业务设置.

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

我希望我能够清楚地解释这个问题.如何防止接口侵蚀,维护信息隐藏和封装,还能满足不同层之间不同的接口需求?



1> Wheelie..:

如果我正确理解了这个问题,那么您已经创建了一个域模型,并且您希望编写一个对象关系映射器来映射数据库中的记录和域对象.但是,您担心使用"管道"代码来污染您的域模型,这些代码是读取和写入对象字段所必需的.

退一步,你基本上有两种选择,把数据映射代码放在哪里 - 在域类本身或外部映射类中.第一个选项通常称为Active Record模式,其优点是每个对象都知道如何保持自身并对其内部结构有足够的访问权限,以允许它执行映射而无需公开非业务相关字段.

例如

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
        // ...
    }
}

在此示例中,我们有一个对象,表示具有Name和AccountStatus的用户.我们不希望允许直接设置Status,可能是因为我们想要检查更改是否是有效的状态转换,因此我们没有setter.幸运的是,GetById和Save静态方法中的映射代码可以完全访问对象的名称和状态字段.

第二个选项是让第二个类负责映射.这样做的好处是可以分离出业务逻辑和持久性的不同问题,从而使您的设计更加可测试和灵活.此方法的挑战是如何将名称和状态字段公开给外部类.一些选项是:1.使用反射(对于深入挖掘对象的私有部分没有任何疑虑)2.提供特别命名的公共设置器(例如,在其前面添加"私有"一词)并希望没有人意外地使用它们3如果您的语言支持它,请将setter设为内部,但授予您的数据映射器模块访问权限.例如,在.NET 2.0中使用InternalsVisibleToAttribute或在C++中使用友元函数

有关更多信息,我建议使用Martin Fowler的经典着作"企业架构模式"

但是,作为一个警告,在开始编写自己的映射器之前,我强烈建议使用第三方对象关系映射器(ORM)工具,如nHibernate或Microsoft的Entity Framework.我参与了四个不同的项目,由于各种原因,我们编写了自己的映射器,很容易浪费大量时间来维护和扩展映射器,而不是编写提供最终用户价值的代码.到目前为止,我已经在一个项目中使用了nHibernate,虽然它最初的学习曲线相当陡峭,但你早期投入的回报却相当可观.



2> Dan..:

这是一个经典问题 - 将您的域模型与数据库模型分开.有几种方法可以攻击它,这在很大程度上取决于我认为项目的大小.您可以像其他人所说的那样使用存储库模式.如果您使用的是.net或java,则可以使用NHibernate或Hibernate.

我所做的是使用测试驱动开发,所以我首先编写我的UI和模型层,并且模拟数据层,因此UI和模型是围绕特定于域的对象构建的,然后我将这些对象映射到我正在使用的技术数据层.让数据库确定应用程序的设计是一个非常糟糕的主意,首先编写应用程序并稍后考虑数据.

ps问题的标题有点误导

推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有