Ответ
Связанность (coupling) — это мера зависимости между модулями или компонентами программной системы. Высокая связанность усложняет поддержку и изменение кода, так как модификация одного модуля требует изменений в других.
Уровни связанности (от лучшего к худшему):
- Data coupling (связь по данным): Модули общаются только через передачу простых параметров.
- Stamp coupling (связь по структуре): Модули передают составные структуры данных (например, объекты), но используют только их часть.
- Control coupling (связь по управлению): Один модуль передает другому флаг или данные, явно управляющие его логикой.
- Common coupling (общая связь): Модули используют общие глобальные данные.
- Content coupling (содержательная связь): Один модуль напрямую изменяет внутренние данные или логику другого (например, через
gotoили изменение приватных полей).
Пример слабой связанности (предпочтительный):
// Модуль OrderProcessor зависит только от абстракции PaymentGateway.
class OrderProcessor {
private PaymentGateway $paymentGateway;
public function __construct(PaymentGateway $gateway) {
$this->paymentGateway = $gateway; // Внедрение зависимости
}
public function process(Order $order): void {
$this->paymentGateway->charge($order->getAmount());
}
}
Пример сильной связанности (проблемный):
// OrderProcessor жестко зависит от конкретного класса PayPal и способа получения данных.
class OrderProcessor {
public function process(int $orderId): void {
$payment = new PayPal(); // Прямое создание зависимости
$order = Order::find($orderId); // Статический вызов, привязка к глобальному состоянию
$payment->charge($order->amount);
}
}
Почему важна слабая связанность: Она повышает тестируемость (легко подменить зависимости заглушками), переиспользуемость и упрощает рефакторинг системы.
Ответ 18+ 🔞
Давай разберем, что такое связанность, без этих заумных учебников. Представь, что твой код — это общага. Связанность — это мера того, насколько твои соседи по блоку в курсе твоих личных дел и лезут в твой холодильник. Высокая связанность — это пиздец, бардак и скандалы на районе: чуть что поменял в своей жизни, а у половины этажа истерика начинается.
Уровни этой самой связанности, от нормы до полного пиздеца:
- Связь по данным (Data coupling). Идеал, мечта. Как с соседом-адекватом: «Друг, передай, пожалуйста, соль». Ты передал соль, он тебе спасибо. Всё. Никто никому не должен, в душу не лезет. В коде это когда модули тупо простые данные друг другу кидают.
- Связь по структуре (Stamp coupling). Уже хуже. Это как ты не просто соль передаёшь, а целую полку из своего шкафа со всеми банками, норами пауков и завалявшимся носком. Сосед берёт только соль, но вынужден принимать весь этот хлам. Модуль получает здоровенную структуру (объект), а юзает из неё одно поле. Подозрение ёбать чувствую к такому.
- Связь по управлению (Control coupling). Вот тут начинается цирк. Ты не просто данные передаёшь, а командуешь: «На, держи флажок. Если он красный — пой песни, если синий — пляши». Один модуль начинает вертеть другим, как хочет. Логика расползается, доверия ёбать ноль.
- Общая связь (Common coupling). А это уже настоящий ад, ёпта. Все модули лезут в один общий, глобальный холодильник. Один сожрал колбасу, другой пописал в молоко. Кто что сделал — хрен поймёшь. Изменение одной переменной где-то в углу ломает всё приложение. Терпения ноль ёбать отлаживать эту хуйню.
- Содержательная связь (Content coupling). Абсолютный пик идиотизма, пиздопроебибна архитектура. Это когда один модуль лезет прямо в кишки другого, меняет его приватные поля или прыгает внутрь его функций через
goto. Это как сосед не просто взял твою соль, а вломился к тебе в комнату, пока ты спишь, и сам её набрал. После такого хочется вилкой в глаз.
Пример, как надо делать (слабая связь, красота):
class OrderProcessor {
private PaymentGateway $paymentGateway;
public function __construct(PaymentGateway $gateway) {
$this->paymentGateway = $gateway; // Подсунули нужный шлюз снаружи
}
public function process(Order $order): void {
$this->paymentGateway->charge($order->getAmount()); // Работает с абстракцией
}
}
Вот это — красота. OrderProcessor не парится, кто именно платит — PayPal, Stripe или картой почтальона Печкина. Ему подсунули интерфейс, он с ним и работает. Тестировать — одно удовольствие, можно заглушку подставить.
А вот пример говнокода (сильная связь, полный распиздяй):
class OrderProcessor {
public function process(int $orderId): void {
$payment = new PayPal(); // Жёстко прибит гвоздями к PayPal! Хуй с горы!
$order = Order::find($orderId); // Лезет в глобальное состояние, как в чужой холодильник
$payment->charge($order->amount);
}
}
Ядрёна вошь! Смотри, что тут творится:
- Создаёт конкретный
PayPalвнутри себя. Захотим поменять на карту — придётся весь этот класс перелопачивать. - Лезут в базу через статический метод
Order::find(). Это та самая общая связь, зависимость от глобального состояния. Протестировать такое в изоляции? Да похуй, невозможно.
Итог: Слабая связанность — это когда твой код модульный, как хороший конструктор. Всё собирается через чёткие разъёмы (интерфейсы). Сильная связанность — это когда всё сварено в одну огромную кашу, и попытка выковырять из неё изюминку грозит тем, что всё накроется медным тазом. Держи зависимости под контролем, не плоди монстров с ушами.