Стандарты программирования на С++

         

Обсуждение


Предпочитайте определять абстрактные интерфейсы и выполнять наследование от них. Абстрактный интерфейс представляет собой абстрактный класс, составленный полностью из (чисто) виртуальных функций и не обладающий состояниями (членами-данными), причем обычно без реализации функций-членов. Заметим, что отсутствие состояний в абстрактном интерфейсе упрощает дизайн всей иерархии (см. соответствующие примеры в [Meyers96]).

Желательно следовать принципу инверсии зависимостей (Dependency Inversion Principle, DIP; см. [Martin96a] и [Martin00]). Данный принцип состоит в следующем.

Высокоуровневые модули не должны зависеть от низкоуровневых. И те, и другие должны зависеть от абстракций.

Абстракции не должны зависеть от деталей; вместо этого детали должны зависеть от абстракций.

Из DIP следует, что корнями иерархий должны быть абстрактные классы, в то время как конкретные классы в этой роли выступать не должны (см. рекомендацию 35). Абстрактные базовые классы должны беспокоиться об определении функциональности, но не о ее реализации.

Принцип инверсии зависимостей имеет три фундаментальных преимущества при проектировании.

Повышение надежности. Менее стабильные части системы (реализации) зависят от более стабильных частей (абстракций). Надежный дизайн — тот, в котором воздействие изменений ограничено. При плохом проектировании небольшие изменения в одном месте расходятся кругами по всему проекту и оказывают влияние на самые неожиданные части системы. Именно это происходит, когда проект строится на конкретных базовых классах.

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

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




Содержание  Назад  Вперед