Лекция
Привет, Вы узнаете о том , что такое зацепление , Разберем основные их виды и особенности использования. Еще будет много подробных примеров и описаний. Для того чтобы лучше понимать что такое зацепление , зависимость, связанность, связность, ооп , настоятельно рекомендую прочитать все из категории Объектно-ориентированное программирование ООП.
Программист должен стремиться к достижению low coupling (низкой связанности) и high cohesion (высокого сцепления) при работе над кодовой базой, рассмотрим как это достигается
Связность и связанность - два понятия которые очень часто употребляются вместе. Они описывают качества которые должны иметь модули. Связность характеризует взаимосвязи между модулями, а связанность описывает связь функций внутри модуля. Низкая связанность вызывает ситуацию, когда модуль выполняет различные не связанные задачи, и начинает создавать проблемы когда модуль становится большим.
Связность ( англ. Coupling ) или зависимость ( англ. Dependency ) это мера в которой модуль (компонент) программы зависит от каждого другого модуля (использует какую-то информацию о нем).
Связность обычно противопоставляется связанности . Метрики программного обеспечения связность и связанность, изобретенные Ларри Константином , первым разработчиком Structured Design, который также был первым их сторонником (смотрите также SSADM ). Слабая связность часто является признаком хорошо структурированной компьютерной системы, и хорошей архитектуры, и в сочетании с высокой связанностью позволяет достичь хорошей прочитности и пидтримуваности кода.
Связанность (или прочность) ( англ. Cohesion ) в программировании - это мера того, насколько связанным код в одном модуле программы (например через общую семантику). Методы оценки связанности варьируются от качественных оценок текста программы с использованием рубрик с герменевтическим подходом к количественным измерений степени связанности кода программы. Связанность - ординальное величина , и обычно в разговоре выражается как "высокая связанность" или "низкая связанность". Модулям с высокой связанностью отдается предпочтение, так как высокая связанность ассоциируется с несколькими желательными чертами программного обеспечения, включая отказоустойчивость , надежность , способность к повторному использованию , и понятность, в то время как низкая связанность ассоциируется с нежелательными чертами, такими как сложность поддержки, тестирования, повторного использования и понимания.
Cвязность характеризует то, насколько хорошо все методы класса или все фрагменты метода соответствуют главной цели, — иначе говоря, насколько сфокусирован класс. Стив Макконнелл
Связанность часто противопоставляется связности - другому понятию, однако высокая связанность часто коррелирует с слабой связностью . Метрики программного обеспечения такие как связанность и связность изобретены Ларри Константином и базируются на характеристиках "добрых" практик программирования, которые уменьшают затраты на модификацию и поддержку.
Связность может быть "слабой" (или "низкой") или "сильной" ( "высокой").
Рассмотрим некоторые виды связности в порядке от самых высоких до самых низких:
Связность по содержанию (сильная)
Появляется, когда один модуль модифицирует или зависит от внутреннего содержания другого модуля (например, использует его переменные).
Поэтому изменение способа, которым второй модуль обрабатывает данные, потребует изменения зависимого модуля.
Связность по общности данных
Когда два модуля имеют общие глобальные данные (глобальные переменные).
Изменение общего ресурса предполагает изменение всех модулей что его используют.
внешняя связность
Появляется когда два модуля разделяют навязанный извне формат данных, протокол коммуникации или интерфейс устройства. Обычно это связано с взаимодействием с внешними инструментами или аппаратурой.
связность контроля
Появляется когда один модуль контролирует ход работы другого, передавая ему информацию о том, что делать.
Зависимость-штамп (зависимость от структурированных данных)
когда модули имеют общую сложную структуру данных, и используют только ее части, возможно разные (например функции передается запись, хотя она требует лишь его часть).
связность данных
Связность данных возникает когда модули делятся общими данными через, например, параметры. Каждое данное является элементарным, и единственным которое делится (например передача числа функции вычисляемый квадратный корень).
Связность за сообщения (слабая)
Слабый тип связности. Достигается с помощью децентрализации состояния (в объектах). Взаимодействие компонентов производится через параметры и обмен сообщениями .
Связность отсутствует
Модули вообще не взаимодействуют между собой.
связность подкласса
Описывает взаимосвязь между предком и потомком. Потомок привязан к предку, а предок нет.
временная связность
Когда два действия упакованы в один модуль лишь потому, что они могут происходят одновременно.
В недавней труда другие концепции связности были изучены и использованы в качестве признаков различных принципов модульности, используемых на практике.
Сильно связные системы обычно демонстрируют следующие характеристики разработки, которые часто рассматриваются как недостатки:
Независимо от силы связности, производительность системы уменьшается через создание сообщений и параметров, их передачи, трансляцию и интерпретацию. Смотрите событийно-ориентированное программирование .
Затраты на создание сообщений
Создание любого сообщения требует дополнительных затрат как процессора так и памяти. Создание целочисленного сообщение (которое может быть ссылкой на строку, массив или другую структуру данных) требует меньших затрат, чем создание сложного сообщение такого как например в SOAP . Для оптимизации нужно уменьшать длину сообщения и увеличивать степень содержания которая в него вкладывается.
Расходы на передачу сообщений
Так как для получения содержания, сообщение нужно передать полностью, нужно это оптимизировать. Короче сообщения передаются и принимаются быстрее.
Расходы на трансляцию сообщений
Протоколы сообщений, и они сами часто содержат избыточную информацию (например описание пакета и его структуры). Поэтому получатель часто требует преобразования сообщения в простую форму, удалением дополнительных символов информации о структуре и / или приведением типа значений до нужного. Для оптимизации процессов трансляции сообщение опять же таки иметь как можно меньшую длину, за как можно большего содержания.
Расходы на интерпретацию сообщений
все сообщения имеют интерпретироваться приемником. Простые сообщение, такие как цели, могут не требовать дополнительной обработки. Тем не менее, сложные сообщения, например в SOAP , требуют парсера и преобразования строк для воспроизведения содержания.
Одним из подходов к уменьшению связности является функциональное проектирование , которое пытается ограничить ответственности модулей в функциональности.
Слабая связность возникает тогда, когда один модуль взаимодействует с другим через простой и стабильный интерфейс и его не волнует как реализован другой модуль. (смотрите: Инкапсуляция ).
Такие системы как CORBA или COM позволяют объектам взаимодействовать между собой без необходимости знать что-нибудь о реализации друг друга. Обе системы даже позволяют взаимодействие между объектами написанными на разных языках.
В книге "Software Engineering" связность описывает вариант метрики связанной с этим термином.
Для связности данных и потока управления:
Для глобальной связности:
Для связности сред:
Coupling(C) имеет тем большее значение, чем более связным является модуль. Об этом говорит сайт https://intellect.icu . Это число варьируется от примерно 0.67 (слабая связность) до 1.0 (сильная связность)
Например, если модуль имеет только один входной и один выходной параметры:
Если модуль имеет 5 входных и выходных параметров, такое же число контрольных параметров, и использует 10 глобальных переменных, вызывает 3 модуля, и вызывается четырьмя,
В ООП , если методы некоторого класса обычно подобные во многих аспектах, то класс считается имеющей высокую связанность.
Связанность уменьшается если:
Недостатками низкой (слабой) связанности являются:
Связанность это качественная мера, то есть текст программы исследуется по рубрикам, для классификации связанности.
Виды связанности в порядке от худшего к лучшему:
Случайная связанность (худшая)
Случайная связанность возникает тогда, когда части модуля добавляются в него произвольным образом; единственным их связывает то, что они входят в одного модуля (например класс " Utilities»).
логическая связанность
части модуля группируются вместе потому что они по логике выполняют одну функцию, даже если они разные по природе. Например группировки всех подпрограмм обработки ввода с клавиатуры и мыши.
темпоральная связанность
части модуля группируются в зависимости от того в какой момент времени возникает необходимость их применения. Например функции вызываемых после обнаружения ошибки, которые закрывают открытые файлы, записывают ошибку в журнал, и сообщают пользователя.
процедурная связанность
части модуля группируются потому что они все придерживаются определенной последовательности действий. Например функции проверяющих разрешения для файла, и после этого его открывают.
коммуникационная связанность
части модуля группируются потому что они работают с одними и теми же данными.
последовательная связанность
части модуля группируются том, что вывод одной части передается на вход другой, как в конвейере. Например функции читающих данные из файла, обрабатывают их и пишут назад.
Функциональная связанность (лучшая)
части модуля группируются том, что они вместе работают над другом, четко обозначенным задачам для того модуля. Например лексический анализ текста или XML.
Исследования многих людей, таких как Ларри Константин , Edward Yourdon , и Steve McConnell показывают, что два первых вида связанности плохие, коммуникационная и последовательная связанности достаточно хорошие и функциональная - лучшая, хотя не всегда достижима. Бывают случаи, когда коммуникационная связанность - это лучшее что может быть достигнуто при данных обстоятельствах.
Связанность содержимого (content coupling)
Связанность через общее (common coupling)
Связанность через внешнее (external coupling)
Связанность по управлению (control coupling)
Связанность по структурированным данным (data-structured coupling, stamp couplig)
Связанность через данных (data coupling)
Связанность по сообщениям (message coupling)
Отсутствие связанности (no coupling)
Концептуальная модель связности
Зацепление, сцепление, сопряжение (англ. coupling) — способ и степень взаимозависимости между программными модулями ; сила взаимосвязей между модулями ; мера того, насколько взаимозависимы разные подпрограммы или модули .
Сильное зацепление рассматривается как серьезный недостаток, поскольку затрудняет понимание логики модулей, их модификацию, автономное тестирование, а также переиспользование по отдельности. Слабое зацепление, напротив, является признаком хорошо структурированной и хорошо спроектированной системы, и, когда оно комбинируется с сильной связностью, соответствует общим показателям хорошей читаемости и сопровождаемости.
Метрики зацепления и связности были придуманы Ларри Константином, изначальным разработчиком структурного проектирования , который был также ранним сторонником таких концепций (см. также SSADM).
Слабое зацепление является одним из шаблонов GRASP Крэйга Лармана
Связность и зацепление модулей
Типы зацепления, согласно стандарту ISO/IEC/IEEE 24765-2010, включают:
Зацепление по общей области
Тип зацепления, при котором два программных модуля совместно используют общую область данных.
Зацепление по содержимому
Тип зацепления, при котором некоторые или все программные модули включены в некоторый модуль как составные части.
Зацепление по управлению
Тип зацепления, при котором один программный модуль обменивается данными с другим модулем с явной целью повлиять на его последующее выполнение.
Зацепление по данным
Тип зацепления, при котором выходные данные одного программного модуля служат входными данными другого модуля.
Смешанное зацепление
Тип зацепления, при котором различные подмножества значений некоторого элемента данных используются в нескольких программных модулях для разных и несвязанных целей.
Патологическое зацепление
Тип зацепления, при котором один программный модуль зависит от деталей внутренней реализации другого модуля или влияет на них.
Существуют различные методы уменьшения зацепления (англ. decoupling). Как правило, они описаны в виде шаблонов проектирования. Одним из ключевых методов является инверсия управления , и, в частности, внедрение зависимости.
Снизить зацепление также помогает использование многослойной архитектуры приложений, например Model-View-Controller, Model-View-Presenter , Model-View-ViewModel и т.п.
Закон Деметры (Law of Demeter, LoD) — набор правил проектирования при разработке программного обеспечения, в частности объектно-ориентированных программ, накладывающий ограничения на взаимодействия объектов (модулей).
Обобщенно, закон Деметры является специальным случаем слабой связанности (loose coupling). Правила были предложены в конце 1987 в северо-восточном Университете (Бостон, Массачусетс, США).
Говоря упрощенно, каждый программный модуль:
должен обладать ограниченным знанием о других модулях: знать о модулях, которые имеют «непосредственное» отношение к этому модулю.
должен взаимодействовать только с известными ему модулями «друзьями», не взаимодействовать с незнакомцами.
обращаться только к непосредственным «друзьям».
Общее описание правила: Объект A не должен иметь возможность получить непосредственный доступ к объекту C, если у объекта A есть доступ к объекту B и у объекта B есть доступ к объекту C.
Таким образом, код a.b.Method() нарушает Закон Деметры, а код a.Method() является корректным.
Преимущества закона Деметры
Преимуществами закона Деметры является то, что код, разработанный с соблюдением данного закона, делает написание тестов более простым, а разработанное программное обеспечение менее сложно при поддержке и имеет большие возможности повторного использования кода. Так как объекты являются менее зависимыми от внутренней структуры других объектов, контейнеры объектов могут быть изменены без модификации вызывающих объектов (клиентов).
Недостатки закона Деметры
Недостатком закона Деметры является то, что иногда требуется создание большого количества малых методов-адаптеров (делегатов) для передачи вызовов метода к внутренним компонентам.
однако иногда может потребоваться высокая связанность(tight coupling)
слабая связанность несет в себе накладные расходы - не только операционные накладные расходы, но и накладные расходы на проектирование и управление . Мелкомасштабные сервисы могут дать вам большую развязку, но только если у вас есть управленческие возможности для их эффективной координации. В социотехнических системах фрагментация может снизить эффективность в целом, если не будет надлежащего сотрудничества .
В то время как coupling довольно интуитивное понятие (почти ни у кого нет трудностей с ним), тогда как cohesion труднее понять. Более того, различия между ними часто кажутся неясными. Это неудивительно: идеи, лежащие в основе этих терминов, схожи. Тем не менее, они действительно отличаются.
Cohesion представляет собой степень, в которой часть кодовой базы образует логически единую атомарную единицу (юнит).
Он также может указать на количество связей внутри некоторой кодовой единицы. Если число мало, то, вероятно, границы для блока выбраны неправильно, код внутри блока логически не связан.
Блок (юнит) здесь необязательно является классом. Это может быть метод, класс, группа классов или даже модуль: понятие cohesion (а также coupling) применимо на разных уровнях.
С другой стороны, coupling представляет собой степень взаимосвязи между блоками. Другими словами, это количество соединений между двумя или более блоками. Чем меньше число , тем ниже coupling.
По сути, высокий cohesion означает хранение связанных друг с другом частей кода в одном месте. В то же время низкий coupling заключается в максимально возможном разделении несвязанных частей кодовой базы.
Теоретически рекомендации выглядят довольно просто. Однако на практике вам нужно достаточно глубоко погрузиться в предметную модель вашего программного обеспечения, чтобы понять, какие части вашей кодовой базы на самом деле связаны.
Это означает, что в отличие от такого показателя, как цикломатическая сложность , степень cohesion и coupling не может быть измерена напрямую. Это сильно зависит от семантики кода.
Возможно, отсутствие объективности в этой рекомендации является причиной того, что ей часто так трудно следовать.
Этот принцип имеет прямое отношение к другому принципу: разделение проблем (Separation of Concerns). Эти две рекомендации очень похожи с точки зрения лучших практик, которые они предлагают.
Помимо кода, который одновременно имеет высокий cohesive и слабый coupling, существует, по крайней мере, еще три типа:
Давайте рассмотрим их.
1. Идеальным является код, который следует рекомендациям. У него слабый coupling и высокий cohesive. Мы можем проиллюстрировать такой код следующим образом:
На рисунке выше круги одного цвета представляют части кодовой базы, связанные друг с другом.
2. God Object (божественный объект) является результатом введения высокого cohesion и высокого coupling. Это анти-паттерн в основном означает один фрагмент кода, который выполняет всю работу сразу:
Другое название такого кода - Big Ball of Mud (Большой шар /ком грязи).
3. Третий тип имеет место, когда границы между различными классами или модулями выбраны плохо:
В отличие от God Object, код этого типа имеет границы. Проблема здесь в том, что они выбраны неправильно и часто не отражают фактическую семантику домена. Такой код довольно часто нарушает Single Responsibility Principle (Принцип единой ответственности).
4. Деструктивная развязка (decoupling)– самый интересный случай. Это может происходить, когда программист пытается так сильно развязать кодовую базу, что код полностью теряет фокус:
Последний тип заслуживает более подробного обсуждения.
Часто, когда разработчик пытается реализовать рекомендации по низкому coupling, высокому cohesion, он или она прикладывает слишком много усилий к реализации первой рекомендации (низкий coupling) и полностью забывает о другой. Это приводит к ситуации, когда код действительно разделен (decoupled), но в то же время не имеет четкой направленности. Его части настолько отделены друг от друга, что становится трудно или даже невозможно понять их значение. Эта ситуация называется деструктивной развязкой (destructive decoupling).
Давайте рассмотрим пример:
Этот код является результатом деструктивной развязки. Вы можете видеть, что, с одной стороны, класс Order полностью отделен от Product и даже от OrderLine. Он делегирует логику расчета специальному интерфейсу IOrderPriceCalculator; создание OrderLine выполняется фабрикой.
В то же время этот код совершенно бессвязный (incohesive). Классы, семантика которых тесно связана, теперь отделены друг от друга. Это довольно простой пример, поэтому скорее всего вы понимаете, что здесь происходит, но представьте, как сложно было бы понять такой код, описывающий какую-то незнакомую модель предметной области. В большинстве случаев отсутствие согласованности делает код нечитаемым.
Деструктивная развязка часто идет рука об руку с подходом « интерфейсы повсюду». То есть соблазн заменить каждый конкретный класс интерфейсом, даже если этот интерфейс не представляет собой абстракцию.
Итак, как бы мы переписали приведенный выше код? Как-то так:
Таким образом, мы восстановили связи между Order, OrderLine и Product. Этот код является кратким и цельным (cohesive).
Тут я немного не согласен с автором оригинала. Но скорее всего он просто не стал заморачиваться, так как это простой пример кода. Однако я все же хочу указать на этот спорный момент. Поскольку Order и Product могут быть разными агрегатами или даже находится в разных сервисах (микросервисах, если проект достаточно большой), то во время добавления OrderLine ( метод AddLine) лучше не передавать объект product, а использовать его id.
Важно понимать связь между cohesion и coupling. Невозможно полностью разделить кодовую базу без нарушения ее согласованности. Точно так же невозможно создать полностью цельный (cohesive) код без введения ненужного coupling, но такое отношение встречается редко, потому что, в отличие от cohesion, концепция coupling более или менее интуитивно понятна.
Баланс между ними является ключом к созданию кодовой базы с высоким (но не полностью) cohesion и слабым coupling (но не полностью развязанным).
Как упоминалось ранее, cohesion и coupling могут применяться на разных уровнях. Уровень класса наиболее очевиден, но он не единственный. Примером здесь может служить структура папок внутри проекта:
На первый взгляд , проект хорошо организован: есть отдельные папки для сущностей, фабрик и так далее. Однако ему не хватает cohesion.
Он попадает в 3-ю категорию на нашей диаграмме: плохо выбранные границы. Хотя внутренние компоненты проекта действительно слабо связаны, их границы не отражают их семантику.
Структура проекта с высоким cohesion (и слабым coupling) была бы следующая:
Таким образом, мы сохраняем связанные классы вместе. Более того, папки в проекте теперь структурированы по семантике модели предметной области, а не по назначению утилиты. Эта версия относится к первой категории, и настоятельно рекомендуется сохранить такое разделение в своем решении.
Понятие cohesion похоже на Принцип единой ответственности. SRP утверждает, что класс должен нести единую ответственность (единую причину для изменения), что аналогично тому, что делает код с высоким cohesion.
Разница здесь в том, что, хотя высокий cohesion подразумевает, что код имеет схожие обязанности, но это необязательно означает, что код должен иметь только одну. Можно сказать, что SRP в этом смысле более строгий.
Давайте подведем итоги:
Представленные результаты и исследования подтверждают, что применение искусственного интеллекта в области зацепление имеет потенциал для революции в различных связанных с данной темой сферах. Надеюсь, что теперь ты понял что такое зацепление , зависимость, связанность, связность, ооп и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Объектно-ориентированное программирование ООП
Комментарии
Оставить комментарий
Объектно-ориентированное программирование ООП
Термины: Объектно-ориентированное программирование ООП