Сведение связанности к минимуму




 

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

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

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

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

public void plotDate(Date aDate Selection aSelection) {

TimeZone tz =

ASelection.getRecorder().getLocation().getTimeZone();

...

}

Но теперь подпрограмма построения графика без особой надобности связана с тремя классами – Selection, Recorder и Location. Этот стиль программирования резко увеличивает число классов, от которых зависит наш класс. Почему это плохо? Потому что при этом увеличивается риск того, что внесение несвязанного изменения в другой части системы затронет вашу программу. Например, если сотрудник по имени Фред вносит изменение в класс Location так, что он непосредственно более не содержит TimeZone, то вам придется внести изменения и в свою программу.

Вместо того чтобы продираться через иерархию самостоятельно, просто спросите напрямую о том, что вам нужно:

public void plotDate(Date aDate, TimeZone aTz) {

...

}

plotDate(someDate, someSelection.getTimeZone());

Мы добавили метод к классу Selection, чтобы получить часовой пояс от своего имени; подпрограмме построения графика неважно, передается ли часовой пояс непосредственно из класса Recorder, от некоего объекта, содержащегося в Recorder, или же класс Selection сам составляет другой часовой пояс. В свою очередь, подпрограмма выбора должна запросить прибор о его часовом поясе, оставив прибору право получить его значение из содержащегося в нем объекта Location.

Непосредственное пересечение отношений между объектами может быстро привести к комбинаторному взрыву [28] отношений зависимости. Признаки этого явления можно наблюдать в ряде случаев:

1. В крупномасштабных проектах на языках С или С++, где команда компоновки процедуры тестирования длиннее, чем сама программа тестирования.

2. «Простые» изменения в одном модуле, распространяющиеся в системе через модули, не имеющие связей.

3. Разработчики, которые боятся изменить программу, поскольку они не уверены, как и на чем скажется это изменение.

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

 

Закон Деметера для функций

 

Закон Деметера для функций [LH89] пытается свести к минимуму связывание между модулями в любой программе. Он пытается удержать вас от проникновения в объект для получения доступа к методам третьего объекта. Краткое содержание данного закона представлено на рисунке 5.1.

Создавая «скромную» программу, в которой закон Деметера соблюдается в максимально возможной степени, мы можем добиться цели, выраженной в следующей подсказке:

 

 

Подсказка 36: Минимизируйте связывание между модулями

 

А не все ли равно?

 

Оказывает ли следование закону Деметера (каким бы хорошим он не был с точки зрения теории) реальную помощь в создании программ, более простых в сопровождении?

Исследования [ВВМ96] показали, что классы в языке С++ с большими совокупностями откликов менее ошибкоустойчивы, чем классы с небольшими совокупностями (совокупность откликов представляет собой число функций, непосредственно вызываемых методами конкретного класса).

Рис. 5.1. Закон Деметера для функций

 

Поскольку следование закону Деметера уменьшает размер совокупности отклика в вызывающем отклике, то классы, спроектированные данным образом, также будут менее склонны к наличию ошибок (см. [URL 56], где приводится более подробная информация о статьях и других источниках по проекту Деметера).

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

Как и при использовании любой методики, вы должны взвесить все «за» и «против» для конкретного приложения. В проекте схемы базы данных обычной практикой является «денормализация» схемы для улучшения производительности: нарушение правил нормализации в обмен на скорость выполнения. Подобного же компромисса можно достичь и в этом случае. На самом деле, обращая закон Деметера и плотно связывая несколько модулей, вы можете получить существенный выигрыш в производительности. Ваша конструкция работает прекрасно, пока она известна и приемлема для этих связываемых модулей.

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-03-31 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: