良好的课堂设计

时间:2011-05-25 13:38:57

标签: c# c#-4.0

我正在努力找出设计一个在数据库中保留其属性的类的最佳方法。我们来看一个Person的基本例子。要创建一个新人并将其放在数据库中,我希望DateOfBirth属性是可选的(即在数据库中为NULL)。

这是我的示例代码:

namespace BusinessLayer
{
    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }
    }
}

我不确定这些字段是否应公开。我应该这样做:

class Program
{
    static void Main(string[] args)
    {
        Person person1 = new Person("Kate","Middleton",null);
    }
}

或者像这样:

class Program
{
    static void Main(string[] args)
    {
        Person person1 = new Person();
        person1.FirstName = "Kate";
        person1.LastName = "Middleton";
    }
}

我也想知道我应该如何处理类的可选属性。填写完字段后,如何将它们保存到数据库中?我有一个DatabaseComponenet类来保存信息。保存到数据库时如何处理可选项?

那么,我会做这样的事情:

public int Save()
{
    int personId;
    personId = DatabaseComponent.InsertPerson(FirstName, LastName, DateOfBirth);
    return personId;
}

感谢您的帮助!关于良好班级设计的一些有用的URL也将受到赞赏。

4 个答案:

答案 0 :(得分:19)

首先,我将两个不同的公共构造函数放到Person:

namespace BusinessLayer
{
    class Person
    {
        public Person(string firstName, string lastName): this(firstName, lastName, DateTime.Now)
        {}

        public Person(string firstName, string lastName, DateTime birthDate)
        {
            FirstName = firstName;
            LastName = lastName;
            DateOfBirth = birthDate;
        }

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime DateOfBirth { get; set; }
    }
}

这允许你写两个

var p = new Person("Marilyin", "Manson");
var p2 = new Person("Alice", "Cooper", new DateTime(...));

var p = new Person { FirstName="Marilyn", LastName="Manson" };

我不明白你为什么要限制只有一种形式。

对于DatabaseComponent,我强烈建议您编写一个方法,允许您保存Person而不是隐式声明的签名。

那是因为,如果有一天改变了Person的定义方式,你可能不得不在调用Save()方法的每个点上更改代码。只保存一个Person,您只需要更改Save()实现。

你不打算顺便使用ORM吗?

答案 1 :(得分:11)

使用C#3.0类初始化程序,我不再需要提供允许我初始化所有属性的构造函数:

var person1 = new Person
{
    FirstName = "Kate";
    LastName = "Middleton";
};

Save方法而言,我通常将它们放在一个单独的存储库类中:

public int Save(Person person) 
{
    ...
}

然后当我需要救一个人时:

var person1 = new Person
{
    FirstName = "Kate";
    LastName = "Middleton";
};
var id = new PersonsRepository().Save(person1);

答案 2 :(得分:5)

如果某些字段是必需,则仅使用构造函数,因为这是确保指定这些字段的有效方法。

  

我不确定这些字段是否应公开

字段通常表示成员变量,而且应始终为私有变量。至于属性,我会坚持使用get / set作为数据库对象。

  

我也想知道我应该如何处理类的可选属性。填写完字段后,如何将它们保存到数据库中?

将内容保存到数据库是一个完全不同的故事。我不会尝试创建自己的图层,而是使用现有的图层。有一整套不同的ORM:从非常简单到非常完整的功能。

请查看PetaPoco以获取轻量级替代方案,或nHibernate查看更多功能完整替代方案。

<强>验证

确保正确指定必填字段并获得有效值的一种常用方法是使用验证框架。内置于.net中的一个名为DataAnnotations。谷歌,看看一些例子。

答案 3 :(得分:0)

应使用业务规则进行检查。

我的意思是,如果你想要一个非常可重复使用的商业模式,业务对象应该在不同领域的其他地方重新使用,这可能意味着同一类“A”在某些业务中的状态“X”可能没问题,但是在另一种情况下,同一类“A”在“Y”状态下会很好。

有一个很好的设计模式,允许您实现名为规范的业务验证器:

这可以通过很多方式实现,但最紧凑的方法之一是使用lambda表达式构建规则。

例如:

someAInstance => someAInstance.Name != null && someAInstance.Age > 30

另一种方法是使用现有的对象验证库,例如NHibernate Validator,它可以在没有NHibernate的情况下单独使用,并允许您将属性放在类的属性中,如[NotNull][NotNullNotEmpty]和更复杂的规则,你可以使用内置的,也可以自己构建。

通过阅读本文了解更多信息(在那里您可以找到开箱即用的验证规则列表)

请注意,NH Validator最重要的优点之一是它可用于任何层,不仅可用于数据或业务层,而且您可以在没有NHibernate的情况下使用它,您可以轻松,易于使用使用和多层对象验证器。