Объяснение двух важных показателей качества в ООП

Модульное программирование (согласно Википедии) — это метод проектирования программного обеспечения, в котором особое внимание уделяется разделению функциональности программы на независимые взаимозаменяемые модули, каждый из которых содержит все необходимое для выполнения только одного аспекта желаемой функциональности. . Это означает, что если вы не пишете сценарий нового фильма Звездные войны и если вы разрабатываете программное обеспечение, вы не пишете весь сценарий программного обеспечения в одном файле, подобно Илиаде. Разделив всю концепцию на более мелкие части, модули, вы занимаетесь ими по отдельности и выстраиваете связь этих модулей друг с другом при создании целого.

Основная цель модуляризации — сделать программный проект более простым, управляемым и масштабируемым. Давайте смоделируем преимущества:

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

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

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

Повторное использование. Вам не нужно будет снова и снова писать один и тот же код. Просто возьмите тот, который вы уже написали, и используйте его в другом месте.

Если какая-то функция вызывает проблемы, вы просто исправляете эту конкретную функцию. Вам не нужно посещать все части программного обеспечения, которые используют эту функцию.

Будет намного проще рефакторить ваш код. Кроме того, будет легче работать вместе с членами команды. Каждый человек может работать над своим модулем и т. д.

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

Связь

Сцепление — это степень взаимозависимости между программными модулями. Он указывает, сколько информации один класс имеет о другом классе. Если информация передается от одного класса к другому напрямую, то можно сказать, что связь здесь жесткая, однако, если между ними есть интерфейс, то можно сказать, что она слабосвязанная. Мы должны сделать нашу структурукак можно более свободной.

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

Вот различные типы муфт от худшего к лучшему:

Связь контента: случаи, когда классы зависят от внутренних структур друг друга и их реализации, происходят из-за неправильных абстракций. Это создает проблему обновления/изменения вместе. Изменение одного приводит к изменению другого. По мере роста программы эта проблема становится неразрешимой.

В приведенном ниже примере, если мы изменим класс KeyReader, нам придется изменить связанные поведения Console, поскольку они связаны друг с другом.

Общая связь: зависимости от глобальных данных и переменных. Если вы измените глобальную переменную, это повлияет на все, что с ней связано.

Внешняя связь: если компонент или система, которые они используют вместе со структурами, навязывают формат, интерфейс, структуру данных и т. д., это вызовет внешнюю связь.

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

Связь структурированных данных. Это зависимость, которую создают структуры, передавая друг другу сложные структуры данных. То, что отправляется, является структурой данных, а не объектом.

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

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

Объекты со связью сообщений предоставляют услуги друг другу, данные остаются только в качестве материала при предоставлении этой услуги. Прямого доступа к данным нет. То есть это не обмен данными, это обмен услугами.

Нет связи: связи нет. Совершенно разные юниты.

В ООП есть и другие типы связи:

Связь наследования: это связь.

Абстрактная связь: связь с абстрактными классами. Может быть как is-a, так и has-сцепление (полиморфизм).

Сплоченность

Сплоченность — это степень, в которой две или более частей системы связаны между собой, и то, как они работают вместе для создания чего-то более ценного, чем отдельные части. «Целое больше, чем сумма частей». Мы определенно хотим более сплоченных структур.

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

Сильная связность делает ваш код более легким для понимания (более низкая сложность) и поддержки. А также, увеличивает возможность повторного использования.

Теперь давайте рассмотрим некоторые типы сплоченности от худшего к лучшему. Для демонстрации мы будем использовать абстрактные классы в сценариях Python.

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

Логическая связность. Это классы, которые объединяются, думая, что они относятся к одному и тому же понятию, хотя на самом деле они разные. Лучше, чем совпадение, есть хотя бы низкий уровень смысловой связи. Все методы в приведенном ниже классе связаны с чтением, но между ними нет семантического единства. Какой объект читает и статью, и базу данных?

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

Процедурная связность. Это функциональное разделение работ, связанных с предметом, сверху донизу и объединение их всех в один класс.

Коммуникативное/информационное единство. Оно объединяет структуры, работающие с одними и теми же данными. Это видно в тех случаях, когда обработка данных выходит на первый план.

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

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

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

В приведенном ниже примере класс Phone одновременно подключается и отправляет данные. Мы разделили этот класс на два, чтобы сделать его более сплоченным. DataHandler обрабатывает передачу данных, а PhoneConnection отвечает за соединения.

Заключение

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

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

Дальнейшее чтение





Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Присоединяйтесь к нашему сообществу Discord.