Подтвердить что ты не робот

Как избежать создания очень больших объектов с помощью Driven Driven Design

Мы следим за дизайном, управляемым доменом, для реализации большого веб-сайта.

Однако, поместив поведение на объекты домена, мы заканчиваем некоторые очень большие классы.

Например, на нашем объекте SiteUser у нас есть много методов - например, работа с паролями, история заказов, возврат средств, сегментация клиентов. Все эти методы напрямую связаны с пользователем. Многие из этих методов делегируют внутренне другому дочернему объекту, но это по-прежнему приводит к некоторым очень большим классам.

Я стараюсь избегать раскрытия множества дочерних объектов например user.getOrderHistory(). getLatestOrder().

Какие другие стратегии можно использовать, чтобы избежать этих проблем?

4b9b3361

Ответ 1

Проблемы, которые вы видите, не вызваны Domain Driven Design, а скорее отсутствием разделения проблем. Разработка домена Driven Design - это не только совместное размещение данных и поведения.

Первое, что я бы рекомендовал, - это потратить день или около того, и быстро прочитать Домен Driven Design, который можно скачать бесплатно в Info-Q. Это даст обзор различных типов объектов домена: объектов, объектов значений, служб, репозиториев и фабрик.

Вторая вещь, которую я бы рекомендовал, - прочитать в Принципе единой ответственности.

Третье, что я бы рекомендовал, это то, что вы начинаете погружаться в Test Driven Development. Хотя обучение дизайну путем написания тестов вначале не обязательно сделает вас отличным дизайном, они, как правило, направляют вас к слабосвязанным проектам и раскрывают проблемы дизайна раньше.

В примере, который вы указали, у SiteUser определенно есть слишком много обязанностей. Фактически, у вас может не быть необходимости WebsiteUser вообще, поскольку пользователи обычно представлены ISecurityPrincipal.

Немного сложно предложить точно, как вы должны подходить к своему дизайну с учетом отсутствия бизнес-контекста, но я бы сначала рекомендовал сделать некоторые мозговые штурмы, создав некоторые карточные карты, представляющие каждое из основных существительных, которые у вас есть в вашей системе ( например, клиент, заказ, квитанция, продукт и т.д.). Запишите имена классов кандидатов наверху, какие обязанности, которые вы чувствуете, присущи классу слева, и классы, с которыми он будет взаимодействовать справа. Если какое-либо поведение не похоже, что оно принадлежит ни одному из объектов, это, вероятно, хороший кандидат на обслуживание (т.е. AuthenticationService). Распространите карточки на столе своими колледжами и обсудите. Не делайте слишком много этого, хотя это действительно предназначено только для мозгового штурма. Это может быть немного легче сделать это время от времени, чем с помощью доски, потому что вы можете перемещать вещи.

В долгосрочной перспективе вам действительно нужно подобрать книгу Driven Design от Эрика Эванса. Это большое чтение, но стоит вашего времени. Я также рекомендую вам выбрать Agile Software Development, Principles, Patterns and Practices или Agile Principles, Patterns and Practices в С# в зависимости от вашего языкового предпочтения.

Ответ 2

Хотя у реальных людей много обязанностей, вы направляетесь к

Ответ 3

Я столкнулся с той же проблемой, и я обнаружил, что использование дочерних "менеджеров" объектов было лучшим решением в нашем случае.

Например, в вашем случае у вас может быть:

User u = ...;
OrderHistoryManager histMan = user.getOrderHistoryManager();

Затем вы можете использовать histMan для чего угодно. Очевидно, вы подумали об этом, но я не знаю, почему вы хотите этого избежать. Это разделяет проблемы, когда у вас есть объекты, которые, похоже, слишком много.

Подумайте об этом так. Если у вас был объект "Человек", и вам пришлось реализовать метод chew(). Вы поместите его в объект Human или дочерний объект Mouth.

Ответ 4

Очень простое правило: "Большинство методов в вашем классе HAVE используют большинство переменных экземпляра в вашем классе" - если следовать этому правилу, классы будут автоматически иметь нужный размер.

Ответ 5

Возможно, вам захочется рассмотреть некоторые вещи. Например, Клиенту не требуется иметь свойство Order (или историю заказов) - вы можете оставить их вне класса Customer. Поэтому вместо

public void doSomethingWithOrders(Customer customer, Calendar from, Calendar to) {
    List = customer.getOrders(from, to);
    for (Order order : orders) {
        order.doSomething();
    }
}

вы могли бы сделать:

public void doSomethingWithOrders(Customer customer, Calendar from, Calendar to) {
    List = orderService.getOrders(customer, from, to);
    for (Order order : orders) {
        order.doSomething();
    }
}

Это "слабое" соединение, но все же вы можете получить все заказы, принадлежащие клиенту. Я уверен, что там более умные люди, чем я, у которых есть правильные имена и ссылки, относящиеся к приведенному выше.

Ответ 6

Я считаю, что ваша проблема связана с ограниченным контекстом. Для того, что я вижу, "имея дело с паролями, историей заказов, возмещениями, сегментацией клиентов", каждый из них может быть ограниченным контекстом. Поэтому вы можете рассмотреть возможность разделения вашего сайта на несколько объектов, каждый из которых соответствует контексту. Может возникнуть некоторое дублирование, но вы сосредоточитесь на своем домене и избавитесь от очень больших классов с несколькими обязанностями.