Является ли высокая сплоченность синонимом принципа единой ответственности?

Является ли высокая сплоченность синонимом принципа единой ответственности? Если нет, то чем они отличаются?


person user1483278    schedule 26.06.2012    source источник


Ответы (4)


Это не одно и то же.

У вас может быть очень сплоченный класс, у которого нет единственной ответственности.

person Oded    schedule 26.06.2012
comment
И наоборот, может быть правдой: класс, реализующий единственную ответственность, можно связать с миллионом вещей. - person bluevector; 27.06.2012
comment
@jonnyGold - Высокая сплоченность (внутри класса) и сцепление - тоже разные вещи ... - person Oded; 27.06.2012
comment
Верно. Однако они (сцепление и сплоченность) часто рассматриваются как противоположности, не так ли? - person bluevector; 27.06.2012
comment
@jonnyGold - внутри класса, когда вы пытаетесь следовать принципам хорошего дизайна. - person Oded; 27.06.2012
comment
1. У вас может быть очень сплоченный класс, не несущий единственной ответственности. Я предполагаю, что это происходит, когда в классе нет членов? 2 - Предполагая, что у класса есть члены, я до сих пор не совсем понимаю, чем они отличаются - в конце концов, их определения почти идентичны - person user1483278; 27.06.2012
comment
@ user1483278 - Я имел в виду всего одну-единственную ответственность. - person Oded; 27.06.2012
comment
@Oded - Вы имеете в виду, что класс Highly Cohesive может иметь НЕСКОЛЬКО тесно связанных обязанностей, в то время как класс, придерживающийся SRP, будет иметь только ОДНУ ответственность? - person user1483278; 27.06.2012
comment
@ user1483278 - Да. Все сводится к тому, что называют ответственностью. Например, класс доступа к данным может быть очень сплоченным, но если он обрабатывает и запросы, и команды, кто-то, использующий CQRS, сочтет это нарушающим SRP. - person Oded; 27.06.2012
comment
Так это тоже зависит от контекста? То есть, если кто-то не знает или не заботится о CQRS, то для него вполне разумно рассматривать этот класс как принадлежащий к SRP? - person user1483278; 27.06.2012
comment
@ user1483278 - В этом конкретном примере. Хотя, если класс делает что-либо, кроме доступа к данным, он все равно может нарушить SRP. - person Oded; 27.06.2012
comment
Роберт Мартин создал SRP, и он считает его просто еще одним способом определения сплоченности и взаимосвязи. - person jaco0646; 05.03.2019

Вы спросили: Если нет, то чем они отличаются?

Принцип единой ответственности

Выбросьте все, что, как вы думаете, означает этот принцип.

Роберт С. Мартин официально определяет этот принцип как:

У класса должна быть только одна причина для изменения

Большинство людей, определяющих SRP, неверны. SRP обычно неправильно объясняют как:

Класс Employee не должен UpdateDemographics() и SendMessage(), это считается двумя обязанностями ... помещать SendMessage() в класс сообщений !!

^^ Неправильно

vv справа

Роберт С. Мартин говорит

Ответственность - это не то, что «делает код». (НДЦ 2012)

Роберт С. Мартин определяет SRP как:

Любой модуль должен быть ответственным только перед одним человеком - [роль]. (НДЦ 2012)

Когда Заинтересованная сторона просит изменить сортировку данных в представлении, руководство не должно волноваться и беспокоиться о том, что алгоритмы сломаются. Потому что модуль, который обрабатывает сортировку в представлении, несет ответственность только перед заинтересованной стороной, а модуль, который обрабатывает алгоритм подсчета итоговых данных, отвечает только перед бизнес-аналитиком. Итак, когда Бизнес-аналитик просит внести изменения в алгоритм, не стоит опасаться, что View изменится.

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

Имея это в качестве новой основы для определения SRP, теперь вы можете применить то, что, как вы думали, было ранее SRP, и сделать определение более детальным. Никто не говорит, что весь ваш интерфейсный код должен быть объединен в один модуль, а весь внутренний код - в один модуль.

Высокая сплоченность

Представьте, что у вас есть метод decimal CalculatePayFor(Employee) и другой метод void Pay(Employee).

Принадлежат ли они друг другу? Может быть служба, которая выполняет всевозможные вычисления, и может быть служба, которая не делает ничего, кроме оболочки SOAP для оплаты человеческих ресурсов. Возможно, Pay(Employee) взывает к CalculatePayFor(Employee), но то, что в них есть слово Pay, не означает, что они принадлежат друг другу!

Как мне создать сплоченность? - Нет. Сплоченность - это то, что вы наблюдаете. Что вы делаете: Не рвите на части то, что принадлежит друг другу.

Можно создать класс для каждого публичного метода, который вам нужен. У каждого класса теперь есть один общедоступный метод, и все это представляет собой четко определенный беспорядок. У вас есть классы с именами PayrollClass1 и PayrollClass2, потому что один выполняет вычисления в одном направлении, а другой - в двух направлениях.

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

Однако вы можете заметить, что CalculatePayFor(Employee) и Pay(Employee) на самом деле ОЧЕНЬ сильно связаны. Они как чертовски супружеская пара и прекрасно смотрятся вместе. Когда методы явно связаны друг с другом, вы не хотите разрывать их. Понаблюдайте за их естественным состоянием и создайте заказник. Это Поддержание высокой сплоченности. Вы не создаете это, вы это наблюдаете.

На самом деле это помогает правильное дублирование кода. Например, PayrollService.CalculatePayFor(Employee) имеет тот же точный код, что и ReportService.CalculatePayFor(Employee). Это плохо? Конечно, нет. Если высшее руководство просит внести изменения в расчет заработной платы сотрудников для отчетности, это другая ответственность, чем если бы Х.Р. велит вам внести изменения в расчет для налоговых целей для фактического метода оплаты.

Подождите, он только что перепутал SRP и Cohesion? Нет, но я рад, что ты понял путаницу. Что, если ReportService проникнет в класс PayrollService и использует его метод? Затем, когда он изменяется для законных целей оплаты, все отчеты меняются ... но руководство этого не хотело !!! Таким образом, поскольку Cohesion заставляет методы оставаться в своих классах, а SRP заставляет модули оставаться в пределах одного приложения, ReportService вынужден копировать / вставлять метод из класса PayrollService. Теперь они могут меняться независимо друг от друга.

Но что, если вы этого не хотите? Что ж, в коде есть много мест, где исключено дублирование. Но чаще всего алгоритмы придерживаются самих себя и изменяются независимо от зависимостей. Даже если это означает дублирование. Это просто зависит от того, что нужно. Но разделение проблем, единоличная ответственность, сплоченность и СУХОЙ (не повторяйся) - это разные идеи.

Примечание: СУХОЙ не означает, что никогда не будет дублирования. Как я уже упоминал: много раз у вас может быть дублированный код, потому что бизнес-правила схожи для разных задач и имеют разные причины для изменения.

person Suamere    schedule 12.01.2016
comment
Никто не прокомментировал конкретное место, которое я действительно ожидал. Так что я буду. Маловероятно, что Payroll.CalculatePay и Report.CalculatePay должны сильно отличаться. Но вы обнаружите, что, хотя вычисления глубокого ядра всегда должны быть одинаковыми, материалы более высокого уровня о том, как он организует, группирует, сортирует, фильтрует и преобразует эти данные, будут различаться между ними. В этом смысле ReportService будет вызывать PayrollMicroService для получения основных деталей. Но каждая служба будет преобразовывать эти данные по-своему. Просто чтобы успокоить там все опасения :) - person Suamere; 27.09.2020

Это не синоним. SRP (принцип единой ответственности) - это когда вы гарантируете, что у ваших классов будет только одна ответственность. Конечно, это увеличивает сплоченность ваших классов.

Но вы можете иметь высокую сплоченность, не следуя букве SRP.

Вот хороший источник по этому поводу.

person Marcelo Assis    schedule 26.06.2012

По словам Роберта Мартина, собственными словами Роберта Мартина,

Если вы подумаете о [SRP], то поймете, что это просто еще один способ определения сплоченности и сцепления. Мы хотим увеличить взаимосвязь между вещами, которые меняются по одним и тем же причинам, и мы хотим уменьшить взаимосвязь между теми вещами, которые меняются по разным причинам.

См. Также: Разница между принципом единой ответственности и разделением проблем.

person jaco0646    schedule 04.03.2019