Хороший дизайн класса на примере
Я пытаюсь разработать лучший способ разработки класса, который сохраняет свои свойства в базе данных. Возьмем базовый пример a Person
. Чтобы создать нового человека и поместить его в базу данных, я хочу, чтобы свойство DateOfBirth
было необязательным (т.е. NULLable в БД).
Вот мой пример кода:
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-адреса для дизайна хорошего класса.
Ответы
Ответ 1
Во-первых, я поставил бы два отдельных публичных конструктора в 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 кстати?
Ответ 2
С инициализаторами класса С# 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);
Ответ 3
Используйте только конструкторы, если некоторые поля обязательны, поскольку это эффективный способ убедиться, что эти поля указаны.
Я не уверен, должны ли поля быть общедоступными или нет
Поля обычно означают переменные-члены, и они всегда должны быть частными. Что касается свойств, я бы придерживался get/set для объектов базы данных.
Мне также интересно, как я должен иметь дело с необязательными свойствами класса. После заполнения полей, как я могу сохранить их в БД?
Сохранение вещей в базе данных - это совсем другая история. Я бы не стал изобретать свой собственный слой, но использовать уже существующий. Существует целый набор различных ORM: s от очень простой до очень полной версии.
Посмотрите PetaPoco для облегченной альтернативы или nHibernate для более полной версии.
Validation
Один из распространенных способов убедиться, что обязательные поля правильно указаны и получили действительные значения, - использовать фреймворк проверки. Существует один встроенный в .net, называемый DataAnnotations. Google это и посмотрите на некоторые примеры.
Ответ 4
Это нужно проверить с помощью бизнес-правил.
Я имею в виду, если вы хотите использовать очень удобную бизнес-модель, бизнес-объекты должны быть повторно использованы в других местах, и это может означать, что один класс "A" может быть в состоянии "X" в каком-либо бизнесе, но в другой ситуации, тот же класс "А", будет нормально в состоянии "Y".
Там хороший шаблон дизайна, позволяющий реализовать бизнес-валидаторы под названием Спецификация:
Это может быть реализовано многими способами, но одним из самых компактных является построение правил с лямбда-выражениями.
Например:
someAInstance => someAInstance.Name != null && someAInstance.Age > 30
Другим способом является использование существующих библиотек проверки объектов, таких как NHibernate Validator, которые могут использоваться автономно без NHibernate и позволяют добавлять атрибуты в свойства класса, такие как [NotNull]
, [NotNullNotEmpty]
, и более сложные правила, и вы можете либо использовать встроенные, либо вы можете создавать свои собственные.
Подробнее читайте в этой статье (там вы найдете список готовых правил проверки):
Обратите внимание, что одно из важнейших преимуществ NH Validator - его можно использовать на любом уровне, а не только на уровне данных или бизнес-уровня, и поскольку вы можете использовать его без NHibernate, у вас есть легкий, использование и многоуровневый объект проверки достоверности.