Подтвердить что ты не робот

Свободная связь и скрытие информации и простота изменения

Я просто читаю Code Complete от Steve McConell, и я думаю о примере, который он дает в разделе о свободной связи. Это о интерфейсе метода, который вычисляет количество праздников для сотрудника, который рассчитывается с даты ввода сотрудника и ее продаж. Автор предлагает указать дату и продажу даты в качестве параметров метода вместо экземпляра сотрудника:

int holidays(Date entryDate, Number sales)

вместо

int holidays(Employee emp)

Аргумент в том, что это отделяет клиента от метода, потому что ему не нужно ничего знать о классе Employee.

Мне пришло в голову две вещи:

  • Предоставление всех параметров, необходимых для вычисления, прерывает инкапсуляцию. Он показывает внутренности метода о том, как он вычисляет результат.

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

Каково ваше мнение?

4b9b3361

Ответ 1

Проблемы, которые я вижу с вашим аргументом номер 2,

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

  • изменение подписи не обязательно "сложнее", особенно в эти дни инструментов, которые будут выделять каждое место вызова одним нажатием кнопки.

И главная проблема с вашим аргументом номер 1 заключается в том, что он просто не нарушает инкапсуляцию, как говорили все остальные. Вы показываете, что, а не то, как это инкапсуляция.

Ответ 2

В конечном итоге проигрывается coupling. От высокого сцепления до низкого, существуют различные классы сцепления:

  • Сопоставление контента (высокое): один модуль изменяет или полагается на внутренние работы другого модуля
  • Общая связь: два модуля используют одни и те же глобальные данные (например, глобальные переменная). Изменение общего ресурс подразумевает изменение всех модули, использующие его.
  • Внешняя связь: два модуля совместно используют внешние данные формат, протокол связи или интерфейс устройства.
  • Управляющая связь: один модуль, управляющий логикой другого, посредством передавая информацию о том, что делать (например, передавая флаг "что делать" ).
  • Штамповая муфта (структурированная структура данных): когда модули совместно используют составную структуру данных и используют только его часть, возможно, другая часть (например, передача целого записать в функцию, которая нужна только одно его поле).
  • Связь данных: когда модули обмениваются данными, например, с параметрами. Каждая точка отсчета является элементарной частью, и это единственные данные, которые совместно (например, передача целого числа в функция, которая вычисляет квадрат корень).
  • Связь (низкая): модули не зависят от каждого другие, вместо этого они используют интерфейс для обмена без параметров сообщения (или события, см. Сообщение прохождение).
  • Отсутствие связи: модули не обмениваются друг с другом.

Передача Employee - это связывание с печатью, которое более тесно связано с соединением данных. Если вы действительно думаете о простоте модификации, низкое сцепление лучше, потому что вам меньше беспокоиться о нежелательных побочных эффектах. Предположим, вы хотите изменить структуру класса Employee. Теперь вам нужно проверить фактическую реализацию функции праздников, чтобы убедиться, что она не нарушает математику.

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

Ответ 3

Для меня "правильный" ответ сводится к тому, что вы определяете API высокого уровня или низкого уровня при создании этой функции. Низкоуровневый API предоставляет гибкость выше удобства для любого конкретного случая и утверждает для int holidays(Date entryDate, Number sales) . Высокоуровневый API разработан для того, чтобы сделать одно дело с максимально возможным удобством для клиента. Это говорит о int holidays(Employee emp), потому что для части вызывающего абонента требуется меньше шаблона (извлечение даты и продаж из класса Employee) и менее подробный.

Ответ 4

1) Предоставление параметров не нарушает инкапсуляцию. Это просто показывает, что эти параметры используются для расчета праздников. "HOW" по-прежнему скрыт внутри метода.

2) Метод отпуска не должен быть частью класса Employee.

Ответ 5

  • Это не нарушение инкапсуляции. Нарушение инкапсуляции будет выявлять внутренние методы, которые он использует для расчета праздников. Предоставление начальных параметров - это то, что определяет API.

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

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

Ответ 6

int holidays(Employee emp)

В этом случае только сотрудник может использовать эту функцию...

Ответ 7

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

Кроме того, я бы не сказал, что вы нарушаете инкапсуляцию, предоставляя параметры для этого метода. Вы можете реализовать Sum(int a, int b) в любом случае, но вы должны сказать мне (как пользователю), что вы ожидаете два числа.

Ответ 8

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

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

Ответ 9

Лучшим наиболее развязанным способом является определение интерфейса IHolidayable

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

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

Ответ 10

int holidays (IHolidayInfo obj)

Возможно, это способ. В этом случае любой объект, реализующий IHolidayInfo, сможет использовать функцию "праздники". Просто альтернатива.