Что такое cohesion и coupling (связанность и связность)?csharp-59

1. Связность

Связность - это мера того, насколько элементы внутри одного модуля (класса, компонента) связаны между собой и работают для достижения единой цели.

Уровни связности :

  1. Функциональная (идеальная): Все элементы модуля работают для выполнения одной задачи
// Пример высокой связности
public class MathCalculator
{
    public double Add(double a, double b) => a + b;
    public double Subtract(double a, double b) => a - b;
    public double Multiply(double a, double b) => a * b;
}
  1. Последовательная: Элементы связаны, так как выход одного является входом другого
  2. Коммуникационная: Элементы работают с одними и теми же данными
  3. Временная: Элементы выполняются в одно и то же время (например, инициализация)
  4. Логическая: Элементы логически связаны, но функционально разные
  5. Случайная (худшая): Нет явной связи между элементами
// Пример низкой связности (антипаттерн)
public class GodClass
{
    public void CalculateInterest() { /*...*/ }
    public void PrintDocument() { /*...*/ }
    public void ConnectToDatabase() { /*...*/ }
}

2. Связанность

Связанность - это мера зависимости между модулями. Показывает, насколько изменения в одном модуле влияют на другие.

Уровни связанности :

  1. Слабая (Loose): Модули взаимодействуют через четко определенные интерфейсы
// Пример слабой связанности
public interface ILogger
{
    void Log(string message);
}

public class OrderProcessor
{
    private readonly ILogger _logger;

    public OrderProcessor(ILogger logger) // DI
    {
        _logger = logger;
    }
}
  1. Умеренная: Модули знают о существовании друг друга, но через абстракции
  2. Контролируемая: Зависимости есть, но они ограничены и понятны
  3. Сильная (Tight): Модули тесно связаны, изменения в одном требуют изменений в других
// Пример сильной связанности
public class OrderProcessor
{
    private readonly FileLogger _logger = new FileLogger();

    public void Process(Order order)
    {
        // ...
        _logger.WriteToFile("Order processed");
    }
}

Взаимосвязь Cohesion и Coupling

Золотое правило: Стремитесь к высокой связности и слабой связанности внутри системы.

Практические примеры:

Плохой дизайн:

  • Низкая связность + Сильная связанность
public class ReportManager
{
    public void GenerateReport()
    {
        var data = new Database().GetData(); // Сильная связанность
        var pdf = new PdfGenerator().Create(data);
        new EmailService().Send(pdf);
    }
}

Хороший дизайн:

  • Высокая связность + Слабая связанность
public class ReportGenerator
{
    private readonly IDataProvider _dataProvider;
    private readonly IDocumentBuilder _documentBuilder;

    public ReportGenerator(IDataProvider provider, IDocumentBuilder builder)
    {
        _dataProvider = provider;
        _documentBuilder = builder;
    }

    public Report Generate() // Высокая связность
    {
        var data = _dataProvider.GetData();
        return _documentBuilder.Build(data);
    }
}

Как достичь хорошего баланса

  1. Принцип единой ответственности (SRP): Класс должен иметь одну причину для изменения
  2. Интерфейсы вместо реализаций: Зависите от абстракций
  3. Закон Деметры: "Не разговаривай с незнакомцами"
  4. Dependency Injection: Внедряйте зависимости вместо их создания
  5. Разделение на слои: Четкие границы между слоями приложения

Метрики для оценки

  1. LCOM (Lack of Cohesion Methods): Показывает уровень связности методов класса
  2. Afferent Coupling: Сколько классов зависят от данного класса
  3. Efferent Coupling: От скольких классов зависит данный класс

Резюмируем:

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