Связь, сплоченность и закон Деметры - PullRequest
63 голосов
/ 02 октября 2008

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

Это плохо.

Решение было бы для класса, о котором вы знаете, по сути, выставить простые обертки, которые делегируют ответственность объекту, с которым он связан.

Это хорошо.

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

Это плохо.

Действительно ли это приводит к снижению сплоченности? Это меньшее из двух зол?

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

Ответы [ 6 ]

45 голосов
/ 03 октября 2008

Грэди Буч в «Объектно-ориентированном анализе и проектировании»:

«Идея сплоченности также исходит из структурированного дизайна. Проще говоря, сплоченность измеряет степень связности между элементами одного модуля (и для объектно-ориентированного проектирования, один класс или объект). Наименее желательная форма сплочённость - это сплочённость, в которой совершенно не связанные абстракции брошенный в тот же класс или модуль. Например, рассмотрим класс, содержащий абстракции собак и космических кораблей, поведение которых совершенно не связано. Наиболее желательной формой сплоченности является функциональная сплоченность, при которой элементы класс или модуль все работают вместе, чтобы обеспечить некоторое ограниченное поведение. Таким образом, класс Dog является функционально связным, если его семантика охватывает поведение о собаке, о целой собаке и только о собаке. "

Subsitute Dog с клиентом в приведенном выше, и это может быть немного яснее. Таким образом, цель в действительности состоит в том, чтобы стремиться к функциональной сплоченности и максимально отойти от случайной сплоченности. В зависимости от ваших абстракций, это может быть просто или может потребовать некоторого рефакторинга.

Примечание. Сплоченность применяется к «модулю» в той же степени, что и к одному классу, то есть к группе классов, работающих вместе. Таким образом, в этом случае классы «Заказчик» и «Заказ» по-прежнему имеют приличную сплоченность, поскольку они имеют такие прочные отношения, клиенты создают заказы, заказы принадлежат клиентам.

Мартин Фаулер говорит, что ему было бы удобнее называть его «Предложением Деметры» (см. Статью Насмешки - это не тупики ):

"Тестировщики Mockist больше говорят об избежании" крушения поезда "- цепочек методов в стиле getThis (). GetThat (). GetTheOther (). Избегание цепочек методов также известно как следование Закону Деметры. Хотя цепочки методов запах, противоположная проблема объектов среднего человека, раздутых методами пересылки, - также запах (я всегда чувствовал, что мне было бы удобнее с Законом Деметры, если бы он назывался Предложение Деметры .) "

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

20 голосов
/ 02 октября 2008

Если вы нарушаете Закон Деметры, имея

int price = customer.getOrder().getPrice();

решение не в том, чтобы создать getOrderPrice () и преобразовать код в

int price = customer.getOrderPrice();

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

6 голосов
/ 02 октября 2008

Я думаю, вы, возможно, неправильно поняли, что означает сплоченность. Класс, который реализован в терминах нескольких других классов, не обязательно имеет низкую сплоченность, если он представляет собой четкую концепцию и имеет ясную цель. Например, у вас может быть class Person, который реализуется в терминах классов Date (для даты рождения), Address и Education (список школ, в которые ходил человек). Вы можете предоставить упаковку в Person для получения года рождения, последней школы, в которой учился человек, или штата, в котором он живет, чтобы не раскрывать тот факт, что Person применяется в отношении других классов. Это уменьшило бы сцепление, но сделало бы Person не менее связным.

4 голосов
/ 02 октября 2008

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

Заставь это работать на тебя, не работай на это.

1 голос
/ 02 октября 2008

Я не знаю, действительно ли это снижает сплоченность.

Агрегация / композиция - это все о классе, использующем другие классы для выполнения контракта, который он выставляет посредством своих открытых методов. Классу не нужно дублировать интерфейс связанных объектов. На самом деле он скрывает любые знания об этих агрегированных классах от вызывающего метода.

Чтобы подчиняться закону Деметры в случае нескольких уровней зависимости класса, вам просто нужно применить агрегацию / композицию и хорошую инкапсуляцию на каждом уровне.

Другими словами, каждый класс имеет одну или несколько зависимостей от других классов, однако это только зависимости от ссылочного класса, а не от каких-либо объектов, возвращаемых из свойств / методов.

0 голосов
/ 02 октября 2008

В ситуациях, когда кажется, что существует компромисс между связью и сплоченностью, я, вероятно, спрашиваю себя: «Если бы кто-то уже написал эту логику, и я искал в ней ошибку, куда бы я обратился в первую очередь? ", и напишите код таким образом.

...