Когда именно класс / пакет зависит от другого? - PullRequest
7 голосов
/ 03 сентября 2011

Многие статьи / книги / .... говорят о зависимости класса или пакета, мало кто объясняет, что это такое.Я нашел некоторые определения, но они различаются и, вероятно, не охватывают все случаи.Например:

Дальнейшие аспекты, которые следует учитывать, - это параметры метода, внедрение зависимостей, аспектно-ориентированное программирование, универсальные шаблоны.Есть еще аспекты?

Итак, вы можете дать (формальное) определение зависимости между классами и пакетами, которое защищено от ошибок и охватывает все эти случаи и аспекты?

Ответы [ 3 ]

3 голосов
/ 03 сентября 2011

Если вы запрашиваете зависимость в контексте инверсии управления или внедрения зависимости, то, вероятно, вам интересны классы, которые напрямую взаимодействуют друг с другом. Это в основном означает параметры и свойства конструктора.

В контексте доменной диаграммы UML вас, вероятно, интересует зависимость "реального мира". Собака нуждается в еде. Это зависимость. Метод собаки Bark() возвращает объект Sound: это не то, что вас интересует, в модели домена UML. Собака не зависит от звуков, чтобы существовать.

Вы могли бы пойти философски и по этому вопросу: все классы зависят друг от друга в достижении общей цели; (надеюсь) отличное программное обеспечение.

Итак, в общем, зависимость или связь не являются вопросом да или нет. Это действительно зависит от контекста и от степени связи (слабой, сильной). Я думаю, это объясняет, почему существует много разных определений зависимости.

2 голосов
/ 06 сентября 2011

Некоторое время назад я написал сообщение в блоге на эту тему: Понимание кода: статические и динамические зависимости . По сути, вам необходимо различать статические зависимости , которые разрешаются компилятором во время компиляции, и динамические зависимости , которые разрешаются средой выполнения (JVM или CLR). ) во время выполнения.

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

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

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

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

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

1 голос
/ 03 сентября 2011

Этот пост о статической зависимости - для динамической зависимости и разницы, см. Ответ Патрика Смаккья.

Простым для понимания способом: объект (класс или пакет) A зависит от объекта B, когда A не может использоваться автономно без B.

Наследование, агрегация, состав, все они вводят зависимость между связанными объектами.

так что нет никакой зависимости от интерфейса?

есть, но интерфейс служит только клеем.

как насчет наследования?

см. Выше.

так что зависимость - это переходные отношения не только для пакетов, но и на уровне класса?

да.

а как вы определяете "полагается"?

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


Обновление:

Так что, если у вас есть интерфейс A в пакете P1, а класс C в пакете P2 использует A в качестве

  • параметр метода или
  • локальная переменная вплетается в C через AOP или
  • class C implements A или
  • class C<E extends A>,

тогда C зависит от A, а P2 зависит от P1.

Но если интерфейс A реализован программами класса B и класса C для интерфейса A и использует B только посредством внедрения зависимостей, то C по-прежнему (статически!) Зависит только от A, а не от B, поскольку точка внедрения зависимостей является то, что это не делает склеенные компоненты зависимыми.

...