День 1134. #DDD
Коллекции и Одержимость Примитивными Типами. Окончание
Начало
Пользовательские классы коллекций
А что насчёт коллекций? Допустим, у нас есть следующий класс:
public class Customer
{
public IReadOnlyList<Order> Orders { get; }
}
Может коллекция должна быть представлена специальным классом, например:
public class Customer
{
public OrderList Orders { get; }
}
Это зависит. Если в коллекции необходимо реализовать дополнительные бизнес-правила или инварианты, может быть хорошей идеей создать пользовательский класс. В противном случае оно того не стоит.
Рассмотрим примеры выше.
1. Коллекция сущностей
public IReadOnlyList<Order> Orders { get; }
Какие бизнес-правила могут быть реализованы в этой коллекции? Допустим, не может быть повторяющихся заказов. Требует ли это введения нового класса? Нет. Чтобы соблюсти это бизнес-правило, все новые заказы должны проходить валидацию. Но нам не нужен для этого отдельный класс, эту ответственность может взять на себя сам класс Customer.
Нам нужно, чтобы свойство Orders не могло быть изменено напрямую, а это уже сделано путем представления этого свойства как IReadOnlyList. Значит нужно изменить класс Customer, добавив метод с необходимой проверкой:
public class Customer
{
private List<Order> _orders;
public IReadOnlyList<Order> Orders => _orders;
public void AddOrder(Order order)
{
if (_orders.Contains(order))
throw new Exception();
_orders.Add(order);
}
}
В некотором роде Customer уже представляет собой пользовательский класс, инкапсулирующий коллекцию Orders.
2. Пользовательский класс коллекции
Если коллекция не принадлежит никакой другой сущности, то имеет смысл создать для неё отдельный класс. Например, если вам нужно отслеживать всех пользователей, которые в данный момент находятся в сети, лучше всего представить их в виде пользовательского класса:
public class OnlineUsers
{
private List<User> _users;
public void ForceLogOff(long userId)
{
// …
}
}
Здесь подразумевается, что, помимо собственно коллекции, необходимы некоторые дополнительные функции (например, описанный выше метод ForceLogOff), в противном случае класс OnlineUsers не нужен.
Итого
Одержимость примитивными типами — это использование примитивных типов для моделирования предметной области.
Вам может понадобиться или не понадобиться отдельный класс для коллекции. Если коллекция представляет собой набор связанных сущностей, присоединённых к родительской сущности, то эта родительская сущность фактически действует как пользовательский класс. Отдельный класс для самой коллекции не нужен.
Если же коллекция является коллекцией корневого уровня, то для неё нужен пользовательский класс (при условии, что помимо самой коллекции необходимы дополнительные функции).
Источник: enterprisecraftsmanship.com/posts/c…bsession