Course program← Объектно ориентированное программирование
1История ООП
2Объект и Класс
3Базовые концепции ООП
4Принцип проектирования GRASP
5Принцип проектирования SOLID
6Паттерны GOF

Low Coupling (Слабое зацепление)

This lesson is not translated yet – the Russian original is below.

TODO: отвалидировать – текст собран автоматически из материалов курса на Google Drive, проверьте формулировки и код.

Степень связности – мера неотрывности элемента от других элементов. Слабое зацепление – это оценочная модель, которая подсказывает, как распределить обязанности.

Каким бывает класс со слабым зацеплением

  • имеет слабую зависимость от других классов;
  • не зависит от внешних изменений: правка в одном классе слабо влияет на остальные;
  • прост для повторного использования.

Чем плохо сильное зацепление

  • затрудняется понимание логики модулей;
  • усложняется модификация программы;
  • появляются проблемы с тестированием;
  • отдельный модуль невозможно переиспользовать.
// Сильное зацепление: сервис намертво привязан к конкретной СУБД
public class ReportService
{
    private readonly PostgresConnection _db = new PostgresConnection();
}

// Слабое зацепление: зависимость от абстракции, а не от реализации
public class ReportService
{
    private readonly IReportStorage _storage;

    public ReportService(IReportStorage storage) => _storage = storage;
}
// Сильное зацепление: сервис намертво привязан к конкретной СУБД
class ReportService {
private:
    PostgresConnection db_;
};

// Слабое зацепление: зависимость от абстракции, а не от реализации
class ReportService {
public:
    explicit ReportService(IReportStorage& storage) : storage_(storage) {}

private:
    IReportStorage& storage_;
};
// Сильное зацепление: сервис намертво привязан к конкретной СУБД
type ReportService struct {
	db *PostgresConnection
}

// Слабое зацепление: зависимость от интерфейса, а не от реализации
type ReportStorage interface {
	Save(report Report) error
}

type ReportService struct {
	storage ReportStorage
}

func NewReportService(storage ReportStorage) *ReportService {
	return &ReportService{storage: storage}
}
# Сильное зацепление: сервис намертво привязан к конкретной СУБД
class ReportService:
    def __init__(self) -> None:
        self._db = PostgresConnection()

# Слабое зацепление: зависимость от абстракции, а не от реализации
class ReportService:
    def __init__(self, storage: ReportStorage) -> None:
        self._storage = storage
// Сильное зацепление: сервис намертво привязан к конкретной СУБД
class ReportService {
    private readonly db = new PostgresConnection();
}

// Слабое зацепление: зависимость от абстракции, а не от реализации
class ReportService {
    constructor(private readonly storage: ReportStorage) {}
}
// Сильное зацепление: сервис намертво привязан к конкретной СУБД
public class ReportService {
    private final PostgresConnection db = new PostgresConnection();
}

// Слабое зацепление: зависимость от абстракции, а не от реализации
public class ReportService {
    private final ReportStorage storage;

    public ReportService(ReportStorage storage) {
        this.storage = storage;
    }
}
// Сильное зацепление: сервис намертво привязан к конкретной СУБД
class ReportService {
    private val db = PostgresConnection()
}

// Слабое зацепление: зависимость от абстракции, а не от реализации
class ReportService(private val storage: ReportStorage)

Второй вариант можно протестировать, подставив хранилище в памяти, и перевести на другую СУБД, не трогая сам сервис.