Принцип единой ответственности (SRP)
Давайте обсудим принцип единой ответственности (SRP) - один из основных принципов программирования и проектрования. В целом, мы подробно рассмотрим, что это за принцип, и как его реализовать при разработке нашего программного обеспечения на примере кода на Java. Кроме того, мы разберемся, когда этот принцип не нужен.
Принцип единой ответственности
Как следует из названия, этот принцип гласит, что каждый класс (метод) должен иметь одну ответственность, одну единственную цель. Это означает, что класс будет выполнять только одну работу, что приводит нас к выводу, что у него должна быть только одна причина для изменения.
Нам не нужны объекты, которые знают слишком много и имеют несвязанное поведение. Эти классы труднее поддерживать. Например, если у нас есть класс, который мы часто меняем, и по разным причинам, то этот класс должен быть разбит на несколько классов, каждый из которых обрабатывает одну проблему. Конечно, если произойдет ошибка, ее будет легче найти.
Рассмотрим класс, содержащий код, который каким-то образом изменяет текст. Единственной работой этого класса должна быть работа с текстом.
public class TextManipulator { private String text; public TextManipulator(String text) { this.text = text; } public String getText() { return text; } public void appendText(String newText) { text = text.concat(newText); } public String findWordAndReplace(String word, String replacementWord) { if (text.contains(word)) { text = text.replace(word, replacementWord); } return text; } public String findWordAndDelete(String word) { if (text.contains(word)) { text = text.replace(word, ""); } return text; } public void printText() { System.out.println(textManipulator.getText()); } }Хотя код может показаться корректным, это не очень хороший пример SRP. Здесь у нас есть две обязанности: манипулировать текстом и печатать его. Наличие метода, который печатает текст в этом классе, нарушает принцип единой ответственности. Для этого нам следует создать еще один класс, который будет работать только с выводом текста на печать:
public class TextPrinter { TextManipulator textManipulator; public TextPrinter(TextManipulator textManipulator) { this.textManipulator = textManipulator; } public void printText() { System.out.println(textManipulator.getText()); } public void printOutEachWordOfText() { System.out.println(Arrays.toString(textManipulator.getText().split(" "))); } public void printRangeOfCharacters(int startingIndex, int endIndex) { System.out.println(textManipulator.getText().substring(startingIndex, endIndex)); } }Теперь, в этом классе, мы можем создавать методы для стольких вариантов печати текста, сколько мы хотим, потому что это его работа.
Как этот принцип может вводить в заблуждение?
Хитрость внедрения SRP в наше программное обеспечение заключается в знании ответственности каждого класса.
Однако у каждого разработчика есть свое видение цели класса, что делает вещи сложными. Поскольку у нас нет строгих инструкций о том, как реализовать этот принцип, мы остаемся с нашими интерпретациями того, какой будет ответственность.
Это означает, что иногда только мы, разработчики нашего приложения, можем решить, входит ли что-то в область действия класса или нет.
При написании класса по принципу SRP мы должны думать о проблемной области, бизнес-потребностях и архитектуре приложения. Это очень субъективно, что делает реализацию этого принципа сложнее, чем кажется. Это будет не так просто, как пример, который мы рассматриваем в данной статье блога читающего программиста. Это подводит нас к следующему пункту.
Сплоченность
Следуя принципу SRP, наши классы будут придерживаться одной функциональности. Их методы и данные будут иметь одну четкую цель. Это означает высокую когезию, а также надежность, которые в совокупности уменьшают ошибки.
При разработке программного обеспечения, основанного на принципе SRP, важна сплоченность, поскольку она помогает нам найти единые обязанности для наших классов. Эта концепция также помогает нам найти классы, которые несут более чем одну ответственность. Давайте вернемся к нашим методам класса TextManipulator:
... public void appendText(String newText) { text = text.concat(newText); } public String findWordAndReplace(String word, String replacementWord) { if (text.contains(word)) { text = text.replace(word, replacementWord); } return text; } public String findWordAndDelete(String word) { if (text.contains(word)) { text = text.replace(word, ""); } return text; } ...Здесь мы имеем четкое представление о том, что делает этот класс: манипулирование текстом.
Но если мы не думаем о сплоченности и у нас нет четкого определения ответственности этого класса, мы могли бы сказать, что написание и обновление текста - это две разные и отдельные работы. Руководствуясь этой мыслью, мы можем заключить, что это должны быть два отдельных класса: WriteText и UpdateText.
В действительности мы получили бы два тесно связанных класса, которые почти всегда должны использоваться вместе. Эти три метода могут выполнять различные операции, но по существу они служат одной единственной цели: манипулированию текстом. Главное - не переусердствовать.
Одним из инструментов, которые могут помочь достичь высокой согласованности в методах, является LCOM. По существу, LCOM измеряет связь между компонентами класса и их отношение друг к другу.
Вывод
Несмотря на то, что название принципа не требует пояснений, мы видим, как легко его неверно реализовать. Обязательно выделяйте ответственность каждого класса при разработке проекта и уделяйте особое внимание сплоченности.
Как и любые другие принципы программирования, использование SRP должно быть осмысленным и осознанным; не быть самоцелью (если это не учебная программа). Излишняя декомпозиция может сделать приложение более сложным или усложнить сопровождение его - а это вредно.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Читайте также:
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.