0

在我们的系统中,我们的域只是一堆与沼泽标准相关的 poco,我们使用 NHibernate 和所有延迟加载等来补充和持久化对象数据

可以说我在域中有结构。(这是我即时创建的一个纯示例)

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public int Id { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string Postcode { get; set; }
    public Region Region { get; set; }
}

public class Region
{
    public int Id { get; set; }
    public string Name { get; set; }
    public CountryCode CountryCode { get; set; }
}

public class CountryCode
{
    public string Name { get; set; }
    public string Code { get; set; }
    public CostCode CostCode { get; set; }
}

public class CostCode
{
    public string Name { get; set; }
    public string Description { get; set; }
}

现在说客户想要为自己获取 CostCode.Name 值的名称,在客户中有一个方法会更好吗?

    public string GetCountryCostName()
    {
        return Address.Region.CountryCode.CostCode.Name; 
    }

或者这样做会更好吗,这样客户和其他对象就具有获取信息的功能

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }

    public string GetCountryCostName()
    {
        return Address.GetCountryCostCodeName();
    }
}

public class Address
{
    public int Id { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string Postcode { get; set; }
    public Region Region { get; set; }

    public string GetCountryCostCodeName()
    {
        return Region.GetCountryCostCodeName();
    }
}

public class Region
{
    public int Id { get; set; }
    public string Name { get; set; }
    public CountryCode Country { get; set; }

    public string GetCountryCostCodeName()
    {
        return Country.GetCostCodeName();
    }

}

public class CountryCode
{
    public string Name { get; set; }
    public string Code { get; set; }
    public CostCode CostCode { get; set; }

    public string GetCostCodeName()
    {
        return CostCode.Name;
    }
}

public class CostCode
{
    public string Name { get; set; }
    public string Description { get; set; }
}

现在使用第一种方式,Nhibernate 将创建一个单一的 sql 来水合它创建的所有代理,但是第二种方式如果我在延迟加载如何与 NHibernate 一起工作方面是正确的,它将在访问函数时创建许多较小的 sql 语句。那么从 OO 设计和性能的角度来看,哪种方法是最好的方法呢?

问候

光盘

4

1 回答 1

2

从 SQL 和“代码如何执行”的角度来看,这两种方法是相同的。NHibernate 不会为包含Address.Region.CountryCode.CostCode.Name. 这需要 NHibernate 进行一些非常复杂的代码自省。相反,每个many-to-one属性都设置有延迟加载代理对象。每当您访问代理对象上的非 id 属性时,NHibernate 将确保该对象已从数据库中初始化。

从设计的角度来看,您所问的几乎是得墨忒耳法则的精髓。得墨忒耳法则会说第二个选项,每个班级只与它的近邻交谈,更好。但是,问题的每一方面都有利有弊。阅读维基百科文章了解更多详情。

我认为重点是尽量减少受给定更改影响的代码量。如果关于如何访问该值的某些内容必须在该链的中间进行更改,那么您只需更改一半的类。但是,假设 Customer 是唯一真正需要此信息的类。在那种情况下,我认为最好选择第一个选项,忽略得墨忒耳法则。是的,您正在向客户提供有关数据结构其余部分的深入知识,但如果该结构发生变化,您只需更改客户中的一种方法,其余部分不用管。

对于空值,特别是如果数据库允许这些值为空,您不希望将其留给异常处理。对选项 #1 执行此操作会更好:

public virtual string GetCountryCostName()
{
    if (Address == null || Address.Region == null || Address.Region.CountryCode == null || Address.Region.CountryCode.CostCode == null)
        return null;
    return Address.Region.CountryCode.CostCode.Name; 
}

对于选项 #2:

public virtual string GetCostCodeName()
{
    if (Address == null)
        return null;
    return Address.GetCostCodeName();
}

// etc...

现在,如果所有这些关系都需要NOT NULL由数据库中的外键强制执行,您可以选择跳过if (... == null)检查,因为在那种情况下遇到 null 确实是一个例外情况,这就是例外的用途。

PS我真的很喜欢这个答案

于 2013-10-17T15:32:43.887 回答