В чем разница между Cohesion (связность) и Coupling (связанность)?

Ответ

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

  • Связность (Cohesion) — мера того, насколько тесно связаны обязанности внутри одного модуля (класса, метода). Высокая связность — это хорошо.
  • Связанность (Coupling) — мера того, насколько сильно один модуль зависит от других модулей. Низкая связанность — это хорошо.

Цель: Стремиться к High Cohesion (высокой связности) и Low Coupling (низкой связанности).

Пример на Java:

// Пример НИЗКОЙ связности и ВЫСОКОЙ связанности (плохо)
// Класс делает слишком много: логирует, валидирует, сохраняет в БД и шлет email.
// Он сильно зависит от множества внешних сервисов.
class OrderProcessor {
    private Logger logger;
    private DbService db;
    private EmailService email;
    private Validator validator;

    public void process(Order order) {
        logger.log("Start");
        if (validator.isValid(order)) {
            db.save(order);
            email.sendConfirmation(order);
        }
        logger.log("End");
    }
}

// Пример ВЫСОКОЙ связности и НИЗКОЙ связанности (хорошо)
// Каждый класс имеет одну четкую ответственность.
// OrderService зависит только от абстракций (интерфейсов).
class OrderService {
    private OrderRepository repository; // Интерфейс
    private ConfirmationSender sender; // Интерфейс

    public void placeOrder(Order order) {
        // Высокая связность: метод делает одну вещь — оформляет заказ.
        repository.save(order);
        sender.send(order);
    }
}

interface OrderRepository { void save(Order order); }
interface ConfirmationSender { void send(Order order); }

// Конкретные реализации можно подменить, например, для тестов.
class SqlOrderRepository implements OrderRepository { /* ... */ }
class EmailConfirmationSender implements ConfirmationSender { /* ... */ }

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

Ответ 18+ 🔞

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

Речь про Связность (Cohesion) и Связанность (Coupling). Запомнить просто: первое — про то, что внутри одного куска кода, второе — про то, как он снаружи с другими кусками общается.

  • Связность (Cohesion) — это, грубо говоря, насколько твой класс или метод не страдает раздвоением личности. Если он занимается чем-то одним, определённым — это высокая связность, и это охуенно. Если же он внутри себя и в БД пишет, и письма рассылает, и логи рисует, и погоду на завтра вычисляет — это низкая связность, и это пиздец как плохо. Это как если бы твой холодильник вдруг начал ещё и телевизор показывать, и кофе молоть. Непонятно, ебать, зачем он нужен и как это чинить.
  • Связанность (Coupling) — это мера того, насколько твой модуль привязан к другим модулям хуями стальными. Если чтобы поменять одну строчку в одном классе, тебе надо перелопатить ещё десять других — это высокая связанность, и это пиздец. Наша цель — низкая связанность, чтобы всё было на слабых, гибких связях, как через вилку и розетку. Вынул одну штуку, воткнул другую — и всё работает.

Суть всей этой движухи проста, как три копейки: надо стремиться к High Cohesion (высокой связности) и Low Coupling (низкой связанности). Если это есть — ты красавчик. Если нет — готовься к волнению ебать, когда придётся что-то менять.

Смотри, как это выглядит в коде:

// Пример того, как делать НЕ НАДО. Низкая связность, высокая связанность.
// Класс-универсал, швейцарский нож, манда с ушами. Делает всё подряд.
// И привязан ко всему на свете конкретными реализациями. Чихает один — болеют все.
class OrderProcessor {
    private Logger logger; // Конкретный класс
    private DbService db; // Конкретный класс
    private EmailService email; // Конкретный класс
    private Validator validator; // Конкретный класс

    public void process(Order order) {
        logger.log("Start");
        if (validator.isValid(order)) {
            db.save(order);
            email.sendConfirmation(order);
        }
        logger.log("End");
    }
}

// Пример того, как делать НАДО. Высокая связность, низкая связанность.
// Класс OrderService чётко знает свою работу: оформить заказ. Всё.
// И зависит он не от конкретных железных ящиков, а от абстрактных "розеток" (интерфейсов).
// Хочешь поменять базу данных или способ оповещения? Да похуй! Подключаешь другую реализацию.
class OrderService {
    private OrderRepository repository; // Абстракция! Интерфейс!
    private ConfirmationSender sender; // Абстракция! Интерфейс!

    public void placeOrder(Order order) {
        // Высокая связность: метод делает одну понятную вещь — оформляет заказ.
        repository.save(order);
        sender.send(order);
    }
}

// Объявили "розетки". Контракты на то, что класс должен уметь делать.
interface OrderRepository { void save(Order order); }
interface ConfirmationSender { void send(Order order); }

// А вот "вилки" — конкретные реализации. Их можно плодить и менять, не трогая основной сервис.
class SqlOrderRepository implements OrderRepository { /* ... */ }
class EmailConfirmationSender implements ConfirmationSender { /* ... */ }

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