Ответ
Cohesion (Связность) — это мера того, насколько тесно связаны и сфокусированы на одной задаче обязанности внутри одного модуля (класса, компонента). Coupling (Связанность) — это мера того, насколько сильно один модуль зависит от других модулей.
Цель: Стремиться к высокой связности (High Cohesion) и низкой связанности (Low Coupling). Это фундаментальный принцип проектирования, ведущий к поддерживаемому, тестируемому и гибкому коду.
Высокая связность (High Cohesion)
Класс с высокой связностью делает одну четко определенную вещь. Все его методы и свойства тесно связаны с его основной ответственностью.
Пример класса с высокой связностью:
// Этот класс отвечает только за логирование. Все его методы связаны с этой одной задачей.
public class FileLogger
{
private readonly string _logFilePath;
public FileLogger(string logFilePath) => _logFilePath = logFilePath;
public void LogInfo(string message) => WriteToFile($"[INFO] {DateTime.Now}: {message}");
public void LogError(string message, Exception ex) => WriteToFile($"[ERROR] {DateTime.Now}: {message} - {ex.Message}");
private void WriteToFile(string text) => File.AppendAllText(_logFilePath, text + Environment.NewLine);
}
Низкая связанность (Low Coupling)
Модули с низкой связанностью минимально зависят от внутреннего устройства друг друга. Зависимости управляются через абстракции (интерфейсы).
Пример низкой связанности (внедрение зависимости):
// OrderService зависит от абстракции ILogger, а не от конкретной реализации.
// Это снижает связанность и упрощает тестирование.
public class OrderService
{
private readonly ILogger _logger;
private readonly IOrderRepository _repository;
// Зависимости внедряются извне
public OrderService(ILogger logger, IOrderRepository repository)
{
_logger = logger;
_repository = repository;
}
public void ProcessOrder(Order order)
{
_logger.LogInfo("Processing order " + order.Id);
// Логика обработки...
_repository.Save(order);
}
}
Пример высокой связанности (плохая практика):
public class OrderService
{
// Прямое создание зависимостей внутри класса делает его тесно связанным с конкретными реализациями.
private FileLogger _logger = new FileLogger("log.txt");
private SqlOrderRepository _repository = new SqlOrderRepository();
// ...
}
Итог: Высокая связность и низкая связанность делают код более модульным, что упрощает его понимание, изменение, повторное использование и модульное тестирование.
Ответ 18+ 🔞
Давай разберем эту тему, как будто объясняю за пивом, а не на скучной лекции. Представь, что код — это твоя квартира.
Связность (Cohesion) — это насколько в одной комнате лежат вещи одной хуёвой тематики. Высокая связность — это когда на кухне у тебя холодильник, плита и кастрюли, а не гантеля рядом с сковородкой, а в углу ещё и аквариум с рыбками. Всё по делу, всё для одной цели: готовить жрать.
Пример высокой связности, норм:
// Этот класс — просто повар на кухне. Только логирует, и всё.
public class FileLogger
{
private readonly string _logFilePath;
public FileLogger(string logFilePath) => _logFilePath = logFilePath;
public void LogInfo(string message) => WriteToFile($"[INFO] {DateTime.Now}: {message}");
public void LogError(string message, Exception ex) => WriteToFile($"[ERROR] {DateTime.Now}: {message} - {ex.Message}");
private void WriteToFile(string text) => File.AppendAllText(_logFilePath, text + Environment.NewLine);
}
Видишь? Никаких посторонних движений. Не пытается заодно и заказ в базу сохранить. Просто пишет в файл. Красота.
Связанность (Coupling) — это насколько твои комнаты прикручены друг к другу намертво. Низкая связанность — это когда чтобы поменять лампочку в прихожей, тебе не нужно ломать стену на кухне. Всё на винтиках, всё на абстракциях.
Пример низкой связанности, умно:
// OrderService не парится, кто там конкретно логирует или сохраняет. Ему похуй, лишь бы контракт соблюдали.
public class OrderService
{
private readonly ILogger _logger;
private readonly IOrderRepository _repository;
// Подсовываем ему зависимости снаружи, как в USB-порт
public OrderService(ILogger logger, IOrderRepository repository)
{
_logger = logger;
_repository = repository;
}
public void ProcessOrder(Order order)
{
_logger.LogInfo("Processing order " + order.Id);
// Какая-то своя магия...
_repository.Save(order);
}
}
А теперь смотри, как НЕ НАДО делать. Высокая связанность — это пиздец и хаос:
Пример высокой связанности (делай так, и тебя уволят):
public class OrderService
{
// Жёсткая привязка, как сварка. Хочешь поменять логгер? Переписывай класс, ебать его в сраку.
private FileLogger _logger = new FileLogger("log.txt");
private SqlOrderRepository _repository = new SqlOrderRepository();
// ...
}
Это как встроить микроволновку прямо в стену на бетон. Захотел новую — долби перфоратором. Заебёшься.
Суть в чём:
Стремись к высокой связности (чтобы класс делал одно дело, а не всё подряд, как швейцарский нож, которым только гвозди выдирают) и к низкой связанности (чтобы модули общались через интерфейсы, а не цеплялись друг за друга, как пьяные друзья).
Итог: когда связность высокая, а связанность низкая, код живёт долго и счастливо. Его легче тестировать (подсовываешь заглушки), легче менять (вырвал один модуль — вставил другой) и понимать (не нужно держать в голове всю вселенную). В общем, красота, а не жизнь.