Прошу помощи с пониманием single responsibility principle на примере метода и класса
Есть метод, который возвращает лист с именами csv файлов, найденных в папке с программой:
public static List<string> GetListOfTables() { var tables = new List<string>(); do { tables = Directory.GetFiles(".", "*.csv").Select(file => Path.GetFileName(file)).ToList(); if (tables.Count == 0) { Output.Invoke("\nNo .csv files are found, " + "please put a table csv file in the program folder and press <Enter> to continue"); while (Console.ReadKey(true).Key != ConsoleKey.Enter) { } } } while (tables.Count == 0); return tables; }
В нем встроенна валидация (вместо исключения), что если файлов не найдено, юзеру нужно скопировать файл в папку и нажать на клавишу.
У данного метода единственная отвественность (в итоге возвращает лист, а проверка - это всего лишь проверка) или множественная (возвращает лист и проверяет корректность действий пользователя)?
Ведь можно создать отдельный метод ValidationCsvFiles с блоком проверки и затем включить или делегировать его в основной метод?
- Есть класс, который возвращает лист с данными из конкретного файла
static class CsvParser
{
public static List<string> GetListOfTables() { }
public static List<List<object>> GetTable(string tableName) { }
}
У данного класса единственная ответственность (в итоге возвращает лист с данными, а лист со списком файлов - это вспомогательный инструмент) или множественная (возвращает лист с данными и лист с файлами)
Ведь лист с файлами можно реализовать в другом классе?
Ответы (1 шт):
В книге "Чистая Архитектура ..." Роберт Мартин утверждает что традиционно принцип единственной ответственности описывается так:
Модуль должен иметь одну и только одну причину для изменения
Программное обеспечение изменяется для удовлетворения нужд пользователей и заинтересованных лиц. Пользователи и заинтересованные лица как раз и есть та самая "причина для изменения", о которой говорит принцип. Фактически принцип можно перефразировать так:
Модуль должен отвечать за одного и только за одного пользователя или заинтересованное лицо.
Стоит сразу оговориться что пользователь это не "ну такая тетенька которая ...". Чтобы не раздувать ответ переписыванием всей главы, рекомендую приобрести книгу и прочитать дальнейшие пояснения что подразумевается под пользователем (или актором) и модулем в данном случае.
Признаки нарушения принципа единственной ответственности по Мартину:
- Непреднамеренное дублирование. Например, класс имеет несколько методов, в которых используются похожие фрагменты кода. Можно эти фрагменты привести к общему виду и вынести в отдельный метод, чтобы избежать дублирования. Но с другой стороны, теперь стало труднее вносить изменения в один из методов, не затрагивая другие. Это признак того, что класс возможно нарушает принцип единственной ответственности. Нарушает или нет, зависит от того используются ли эти методы одним актором или многими.
- Конфликты при слиянии рабочих веток в Git. Обычно в команде каждый человек работает над своей задачей (если конечно команда не практикует парное программирование). Если изменения двух программистов затрагивают один и тот же файл, то может возникнуть необходимость разрешать конфликты при слиянии веток. Это тоже признак того, что возможно нарушается принцип единственной ответственности.
Подытожим: принцип единственной ответственности не о том, можно ли или нет разбить модуль на еще более мелкие модули, отвечающие за еще более узкую область. Такое дробление не всегда улучшает код, а порой приводит к смешным последствиям. Таким как эта нашумевшая история: NPM и left-pad: мы разучились программировать?.
Принцип единственной ответственности о том, как избежать трудностей при изменении кода в будущем.