Книга: Программист-прагматик. Путь от подмастерья к мастеру

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

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

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

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

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

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

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. Разработчики, которые боятся изменить программу, поскольку они не уверены, как и на чем скажется это изменение.

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

Оглавление книги


Генерация: 2.479. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз