Связность (Cohesion) в мобильной разработке: основы, уровни и как повысить

Автор: IT Sectr Опубликовано: 2026-05-13 Время чтения: 9 мин

Cohesion (связность) — это метрика, показывающая, насколько тесно связаны элементы внутри одного модуля или класса. По данным Wikipedia, высокая связность является признаком хорошо спроектированного модуля, где все методы и поля работают над одной задачей. Cohesion напрямую влияет на поддерживаемость кода и противопоставляется coupling — связанности между модулями.

Главное

  • Cohesion — мера того, насколько элементы внутри модуля связаны общей целью
  • Высокая связность облегчает понимание кода, тестирование и внесение изменений
  • Низкая связность означает, что модуль выполняет несколько несвязанных задач
  • Cohesion и coupling — взаимосвязанные метрики: чем выше cohesion, тем ниже coupling
  • Функциональная связность — наивысший уровень, к которому надо стремиться

Что такое Cohesion

Cohesion (связность, зацепление) — метрика, которая оценивает, насколько методы, поля и свойства внутри одного класса или модуля логически связаны между собой. Высокосвязный модуль выполняет одну задачу и содержит только те элементы, которые необходимы для её выполнения. Низкосвязный модуль пытается делать несколько вещей одновременно — методы слабо связаны по смыслу.

В контексте объектно-ориентированного программирования cohesion тесно связан с Single Responsibility Principle (S). Если класс имеет одну чёткую ответственность, его cohesion, как правило, высок. Если класс занимается и UI, и бизнес-логикой, и работой с сетью — cohesion низкий, и такой класс стоит разбить на несколько отдельных классов с более узкой ответственностью.

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

Типы и уровни связности

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

Низкая связность: случайная, логическая и временная

Случайная (coincidental) — наихудший уровень, когда элементы в модуле сгруппированы случайно, без какой-либо логической связи. Пример: класс Utilities, в котором собраны методы форматирования даты, отправки email и расчёта скидки. Такой класс невозможно понять без чтения всех методов, и изменение одного метода может сломать другие только потому, что они находятся рядом.

Логическая (logical) связность — элементы выполняют логически связанные, но разные по сути задачи. Класс с методами parseJSON, parseXML и parseCSV логически связан темой «парсинг», но каждый метод делает принципиально разную работу. Проблема: при добавлении нового формата (YAML) класс растёт, и его интерфейс становится раздутым.

Временная (temporal) связность — элементы сгруппированы по времени выполнения. Класс AppInitializer, который настраивает базу данных, загружает конфиг, инициализирует аналитику — всё это происходит при запуске приложения, но сами задачи не связаны между собой. Лучше разделить их на отдельные Initializer для каждой зоны ответственности.

Средняя связность: процедурная и коммуникационная

Процедурная (procedural) связность возникает, когда элементы объединены последовательностью выполнения. Модуль «Обработка заказа» содержит методы validateCart, processPayment, sendConfirmation — каждый метод вызывается строго после предыдущего. Это лучше случайной или логической связности, но всё ещё не идеал: каждый шаг может быть вынесен в отдельный модуль.

Коммуникационная (communicational) связность — элементы работают с одними и теми же данными. Класс UserService с методами getUser, updateUser, deleteUser объединён общей сущностью User. Это существенно лучше процедурной связности: класс имеет чёткую предметную область. Большинство Repository классов в мобильных проектах имеют коммуникационную связность.

Высокая связность: функциональная

Функциональная (functional) связность — наивысший уровень, когда каждый элемент модуля участвует в выполнении одной задачи. Класс PasswordValidator с единственным методом validate, который проверяет длину, наличие символов и сложность пароля — пример функциональной связности. Если такой класс меняется, то только потому, что изменились правила валидации паролей.

Достижение функциональной связности — основная цель архитектурного рефакторинга. Каждый класс должен иметь ровно одну причину для изменения. В мобильной разработке функциональная связность достигается через выделение отдельных Use Cases, кастомных View, форматтеров и валидаторов. Каждый такой класс — законченный строительный блок с чёткой зоной ответственности.

Cohesion vs Coupling

Cohesion и coupling — две стороны одного качества. Чем выше cohesion внутри модуля, тем, как правило, ниже coupling между модулями. Хорошо спроектированная система одновременно стремится к высокой связности внутри и слабой связанности снаружи. Это правило признаётся фундаментальным в программной инженерии с 1970-х годов.

Соотношение cohesion-coupling можно представить как баланс. Если разработчик жертвует cohesion, объединяя в одном классе несколько задач, соседние модули получают больше зависимостей — им приходится обращаться к этому перегруженному классу для разных целей, что увеличивает coupling. И наоборот, разбиение на мелкие высокосвязные классы уменьшает количество точек взаимодействия между модулями.

На практике это означает: когда вы выделяете новый класс с функциональной связностью, вы одновременно избавляете другие модули от необходимости знать детали его реализации. Например, выделив EncryptionManager в отдельный класс с функциональной связностью, вы даёте другим модулям простой интерфейс encrypt/decrypt без необходимости понимать детали алгоритма шифрования.

kotlin
// Низкая связность — класс делает всё сразу
class UserManager {
    fun fetchAndSaveUser(id: String) { }
    fun parseUserJson(json: String): User { }
    fun displayUserName(user: User): String { }
    fun validateEmail(email: String): Boolean { }
}

// Высокая связность — каждый класс решает одну задачу
class UserRepository {
    fun fetchUser(id: String): User { }
}

class UserJsonParser {
    fun parse(json: String): User { }
}

class UserNameFormatter {
    fun format(user: User): String { }
}

class EmailValidator {
    fun isValid(email: String): Boolean { }
}

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

Как измерять связность в коде

LCOM (Lack of Cohesion of Methods) — наиболее известная метрика для измерения связности класса. LCOM подсчитывает, сколько пар методов не используют общие поля. Значение 0 означает идеальную связность (все методы работают с одними полями), высокое значение — низкую связность. LCOM4 (усовершенствованная версия) учитывает транзитивные связи через другие методы.

В Android-разработке метрики связности можно получить через Detekt с правилом TooManyFunctions. Классы с десятком методов, использующих разные группы полей, скорее всего имеют низкую связность. В iOS SwiftLint имеет правило file_length и function_body_length — косвенные индикаторы: длинные файлы и методы часто сигнализируют о низком cohesion.

Ручной способ оценки: задайте вопрос «Этот класс изменится по одной причине или по нескольким?» Если вы можете назвать более одной независимой причины — класс имеет низкую связность. Второй тест: «Можно ли разделить этот класс на два независимых класса?» Если да — делайте это. Регулярная проверка cohesion на код-ревью предотвращает появление God классов и снижает технический долг.

Как повысить Cohesion в мобильном проекте

Первый шаг — применить Single Responsibility Principle. Каждый класс должен иметь одну чёткую ответственность. Если в классе есть метод, который не относится к его основной задаче, вынесите его в отдельный класс. Техника Extract Class или Extract Delegate в IDE автоматизирует этот процесс. После выделения проверьте, стал ли исходный класс более сфокусированным.

Второй шаг — использовать паттерн Facade для упрощения интерфейса. Если класс предоставляет 20 методов, из которых клиенты используют только 3-4, возможно, у класса низкая связность — он предоставляет слишком много разной функциональности. Сгруппируйте методы по темам и выделите отдельные классы для каждой группы, а исходный класс сделайте фасадом или удалите.

Третий шаг — обратить внимание на группы полей. Если у класса есть поля, которые используются только частью методов — это индикатор низкого cohesion. Разделите класс по группам полей. Например, если класс содержит поля userRepository, networkClient и analyticsTracker, но методы первой группы используют только userRepository, а второй — networkClient — это два разных класса.

Четвёртый шаг — избегать создания «утилитных» классов с произвольными static методами. Каждый static метод, находящийся в классе Utils или Helpers — кандидат на выделение в специализированный класс. FormatUtils.dateToString лучше перенести в DateFormatter, а ValidationUtils.isValidEmail — в EmailValidator. Это повышает cohesion каждого класса и делает код самодокументируемым.

Часто задаваемые вопросы

Всегда ли высокая связность — это хорошо?

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

Чем cohesion отличается от modularity?

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

Как инструменты анализа кода помогают с cohesion?

Detekt для Android и Xcode Analyzer для iOS подсвечивают классы с подозрительно большим количеством методов или полей. IntelliJ IDEA и AppCode имеют визуализацию зависимостей — вы можете увидеть граф связей и обнаружить классы с низкой связностью. SonarQube считает метрики LCOM автоматически.

Может ли у интерфейса быть высокая связность?

Да. Интерфейс с методами connect, disconnect и isConnected имеет высокую связность — все методы относятся к управлению соединением. Интерфейс с методами connect, parseData и renderUI имеет низкую связность. Принцип Interface Segregation (SOLID) требует создавать узкоспециализированные интерфейсы с высокой связностью.

Как проверить cohesion на код-ревью?

Задайте три вопроса: можно ли описать назначение класса одним предложением? Все ли методы поддерживают это назначение? Есть ли в классе поля, которые не используются частью методов? Если ответ на любой вопрос отрицательный — cohesion низкий, и класс стоит разделить.

Итоги

  • Cohesion — метрика внутренней согласованности модуля, показывающая, насколько его элементы связаны общей целью
  • Функциональная связность — наивысший уровень, когда все элементы модуля работают на одну задачу
  • Случайная и логическая связность — худшие уровни, сигнализирующие о необходимости рефакторинга
  • Cohesion и coupling обратно пропорциональны: чем выше связность внутри, тем слабее связанность снаружи
  • LCOM — метрика для численной оценки cohesion, доступная в статических анализаторах
  • Single Responsibility Principle — практический инструмент для достижения высокой связности
  • Избегайте утилитных классов Utils — каждый метод такого класса должен стать отдельным специализированным классом

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также