Принципы SOLID: принцип единственной ответственности
Принцип единственной ответственности — The Single Responsibility Principle или SRP — один из пяти основных принципов объектно-ориентированного программирования и проектирования, сформулированных Робертом Мартином.
Принцип декларирует, что каждый объект должен иметь одну обязанность и эта обязанность должна быть полностью инкапсулирована в класс, а все его сервисы должны быть направлены исключительно на обеспечение этой обязанности.
Следование принципу заключается обычно в декомпозиции сложных классов, которые делают сразу много вещей, на простые, отвественность которых очень специализирована. Но также и объединении в отдельный класс однотипной функциональности, которая может оказаться распределённой по многим классам, может рассматриваться как следование этому принципу.
Проектирование классов с направленностью на обеспечение единственной обязанности упрощает дальнейшие модификации и сопровождение, так как проще разобраться в одном блоке функциональности, нежели распутывать сложные взаимосвязи между различными функциональными блоками. Также при модификации логики в одном месте приложения снижаются риски возникновения проблем в других «неожиданных» его местах.
Следование SRP весьма полезная практика с точки зрения повторного использования кода. Сложные объекты с комплексными зависимостями обычно очень сложно использовать повторно, особенно если нужна только часть реализованного в них функционала. А небольшие классы с чётко очерченным функционалом, напротив, проще использовать повторно, так как они не избыточные и редко тянут за собой существенный объём зависимостей.
Наиболее ярким анти-паттерном, нарушающим принцип единственной ответственности, является использование God-объектов, которые «слишком много знают» или «слишком много умеют». Возникают такие «божественные объекты» обычно из-за любви разработчиков к абстракции — если возводить абстракцию в абсолют, то вполне можно любой объект реального мира отразить в приложении в виде экзепляра некого универсального класса. На словах это даже может выглядеть логично, но на практике почти всегда это приводит к проблемам сопровождаемости. Обычно такие объекты становятся центральной частью системы, а их модификация крайне сложна, так как становится очень сложно предсказать, как изенение кода для решения текущей задачи может сказаться на ранее реализованной функциональности.
На самом деле, как и любые другие принципы, SRP требует сознательного и осмысленного применения. Чрезмерная декомпозиция может оказаться и вредной, если она приводит к большей сложности или усложняет сопровождение.
Например, часто используемый во фреймворках паттерн ActiveRecord нарушает принцип единственной ответственности. ActiveRecord реально объединяет в себе очень много функциональных возможностей и часто смешивает бизнес-логику и работу со слоем хранения. При этом использование ActiveRecord часто является удобным и целесообразным. На этом примере становится ясно, что SRP — это не догма, а нарушение этого принципа вполне может быть логичным и целесообразным.
- Принцип единственной ответственности
- Принцип открытости / закрытости
- Принцип подстановки Барбары Лисков
- Принцип разделения интерфейса
- Принцип инверсии зависимостей