Единственная ответственность и зависимости - PullRequest
7 голосов
/ 12 ноября 2011

Если объект имеет Одиночную ответственность , может быть приемлемо следующее:

public class Person
{
   public string Name;
   public DateTime DateOfBirth;

   private IStorageService _storageService;

   public Person(IStorageService storageService)
   {
      _storageService = storageService
   }

   public void Save()
   {
        _storageService.Persist(this);
   }
}

, то есть с использованием предоставленного соавтора (что также помогает предотвратить анемию модели предметной области).

Или должно быть:

public class Person
{
   public string Name;
   public DateTime DateOfBirth;

   public Person()
   {
   }


}
public class StorageService
{
    public void Persist(Person p)
    {
    }
}

Ответы [ 6 ]

10 голосов
/ 12 ноября 2011

может ли быть приемлемо следующее?

класс Person {
Person (IStorageService) {} ...
void Save () {} ...
}

Эта зависимость не имеет смысла.

Хотя он не сильно связывает Person с Storage, поскольку он не связывает их с специфической реализацией хранилища, я утверждаю, что любая такая зависимость не имеет смысла.

Методы как глаголы

Думайте о методах класса как о глаголах, которые будут выполняться этим типом. Вы говорите экземпляру этого типа «сделать что-то» в отношении его локального домена.

Что это значит, когда я, как человек, Save?

  • Я сменил поставщика страховых услуг и сократил свои расходы на 15%?
  • Я искупительное божество?
  • Я загрузил свою душу в автомат?

Служба хранения может и должна Save. Люди не могут Save, и не должны рекламировать, что они могут.

Попытка поднять это в

SaveTo может иметь больше смысла - то есть public void SaveTo(IStorageService storage).

Но тогда вы говорите, что человек отвечает за знание того, как сохранить себя в хранилище. На мой взгляд, это нарушение SRP . Он также показывает отсутствующий фрагмент анализа домена .

Домен для Person не будет содержать ничего о сохранении, хранении и т. Д. Он будет содержать взаимодействия между людьми и другими вещами на этом уровне домена. Область сохранения данных - лучшее место для метода Save.

Если Person находится в проблемной области (на этом уровне абстракции), то Storage находится в области решения.

Как вы должны отделить свою логику

У вас есть три элемента логики:

  1. Person - знает о "вещах человека"
  2. Storage - знает о конкретном типе хранилища и о том, как получить к нему доступ
  3. Storage of Person - знает о том, как человек должен посвятить себя хранению

Следуя моему совету выше, я бы оставил Person стоять самостоятельно. Однако вы можете либо разделить логику для Storage и Storage of Person, либо объединить их.

Подход, который использует ORM , заключается в разделении всех трех концепций. «Отображение» в «Объектно-реляционном отображении» - это то, где «Хранение личности» инкапсулировано.

Этот подход позволяет вашей логике Storage сосредоточиться на потенциально сложной задаче чтения конфигурации хранилища, подключения к хранилищу, обеспечения быстрого хранения, выбора альтернативных методов хранения и т. Д. Он также удаляет любую зависимость от модели вашего основного домена, поэтому код хранилища может быть использован любой другой моделью домена.

4 голосов
/ 12 ноября 2011

Если вы внимательно прочитаете определение SRP , вы заметите, что определение ответственности является причиной для изменения .

Первая версия может иметь две причины для изменения:

  • Изменения в API постоянства
  • Форма его значения изменяется

Таким образом, он не придерживается SRP, в то время как вторая версия делает.

4 голосов
/ 12 ноября 2011

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

Кроме того, вы можете сериализовать 2-ю версию, что может быть полезно. Вы, вероятно, не сможете сериализовать первую версию со ссылкой на IStorageService.

0 голосов
/ 28 августа 2017

Согласно принципу единой ответственности класс должен иметь только одну причину для изменения. Причина или источник изменений - разные бизнес-отделы, для которых мы создаем и разрабатываем разные классы.

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

Хотя в первом приведенном вами примере очевидно, что возможны два источника изменений: менеджер клиента (для управления именем клиента, датой рождения) и администратор базы данных / дизайнер схемы (сохранение клиента в базе данных). Так что это явно нарушает ПСП.

Во втором примере вы управляете двумя разными источниками изменений в двух разных классах. Итак, я бы сказал, что второй пример верен. Хотя я бы изменил название класса :).

0 голосов
/ 12 ноября 2011

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

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

Рассмотрение анемичной области можно было бы устранить, если иметь богатые взаимодействия. Возможно, вы моделируете школу, и Person - это объект, который может быть учеником или учителем, а Class - это совокупность учеников и учителя. Тогда у вас будет какая-то концепция myTeacher.Assign (домашнее задание, класс) или что-то в этом роде. Именно так я бы лично обогатил свою модель предметной области - путем моделирования реальных концептуальных взаимодействий между объектами вашего домена, а не путем «моделирования» их взаимодействия с вашим кодом доступа к данным.

Только мои два цента.

0 голосов
/ 12 ноября 2011

Я обнаружил, что чем полнее и проверено пространство имен вашего домена, тем лучше качество вашего приложения. Сохраняющиеся сущности не принадлежат модели предметной области, поэтому я разделяю их.

...