Вопрос ставит ложную дилемму. Правильное применение принципа ЯГНИ не является чем-то несвязанным. Это один из аспектов хорошего дизайна. Каждый из принципов SOLID также является аспектом хорошего дизайна. Вы не можете всегда полностью применять каждый принцип в любой дисциплине. Реальные проблемы накладывают много сил на ваш код, и некоторые из них выдвигают противоположные направления. Принципы дизайна должны учитывать все это, но ни один из принципов не подходит для всех ситуаций.
Теперь давайте посмотрим на каждый принцип с пониманием того, что, хотя они могут иногда тянуться в разных направлениях, они никоим образом не конфликтуют друг с другом.
YAGNI был задуман для того, чтобы помочь разработчикам избежать какой-то особой переделки: то, что происходит от создания неправильной вещи. Это достигается за счет того, что мы избегаем принимать ошибочные решения слишком рано, основываясь на предположениях или прогнозах относительно того, что, по нашему мнению, изменится или потребуется в будущем. Коллективный опыт говорит нам, что когда мы делаем это, мы обычно ошибаемся. Например, YAGNI бы сказать вам , чтобы не создавать интерфейс с целью повторного использования , если вы не знаете сейчас , что вам нужно несколько исполнителей. Точно так же YAGNI бы сказать , не создают «ScreenManager» для управления единой формы в приложении , если вы не знаете , прямо сейчас , что вы будете иметь более одного экрана.
Вопреки тому, что думают многие, SOLID - это не возможность повторного использования, универсальность или даже абстракция. SOLID предназначен для того, чтобы помочь вам написать код, подготовленный к изменениям , не говоря о том, что это за конкретное изменение. Пять принципов SOLID создают стратегию для построения кода, который является гибким, но не слишком универсальным, и простым, но не наивным. Правильное применение кода SOLID создает небольшие, сфокусированные классы с четко определенными ролями и границами. Практический результат состоит в том, что для любого необходимого изменения требований, необходимо затронуть минимальное количество классов. И точно так же, для любого изменения кода, существует минимальное количество «пульсаций» для других классов.
Рассматривая пример ситуации, которую вы имеете, давайте посмотрим, что скажут YAGNI и SOLID. Вы рассматриваете общий интерфейс хранилища из-за того, что все хранилища выглядят одинаково снаружи. Но ценность общего, универсального интерфейса - это возможность использовать любой из реализаторов, не зная, какой именно он является. Если в вашем приложении нет места, где это было бы необходимо или полезно, YAGNI говорит, что не делайте этого.
Есть 5 твердых принципов, чтобы смотреть на. S является единственной ответственностью. Это ничего не говорит об интерфейсе, но может сказать что-то о ваших конкретных классах. Можно утверждать, что обработку самого доступа к данным лучше всего возложить на один или несколько других классов, в то время как ответственность репозиториев заключается в переводе из неявного контекста (CustomerRepository неявно является хранилищем для сущностей Customer) в явные обращения к Обобщенный API доступа к данным с указанием типа объекта Customer.
О является открытым-закрытым. Это в основном о наследовании. Это применимо, если вы пытаетесь извлечь свои репозитории из общей базы, реализующей общие функциональные возможности, или если вы ожидаете получить дополнительную информацию из разных репозиториев. Но вы не, так что это не так.
L является лисковской заменяемостью. Это применимо, если вы намеревались использовать репозитории через общий интерфейс репозитория. Он накладывает ограничения на интерфейс и реализации, чтобы обеспечить согласованность и избежать специальной обработки для различных имплементаторов. Причина этого заключается в том, что такая специальная обработка подрывает назначение интерфейса. Возможно, будет полезно рассмотреть этот принцип, поскольку он может предостеречь вас от использования общего интерфейса репозитория. Это совпадает с руководством YAGNI.
Я является интерфейсом сегрегации. Это может применяться, если вы начинаете добавлять различные операции запроса в свои репозитории. Разделение интерфейса применяется в тех случаях, когда вы можете разделить члены класса на два подмножества, где одно будет использоваться определенными потребителями, а другое другими, но ни один потребитель не будет использовать оба подмножества. Руководство состоит в том, чтобы создать два отдельных интерфейса, а не один общий. В вашем случае маловероятно, что выборка и сохранение отдельных экземпляров будут использоваться одним и тем же кодом, который будет выполнять общие запросы, поэтому может быть полезно разделить их на два интерфейса.
D - инъекция зависимостей. Здесь мы возвращаемся к той же точке, что и S. Если вы разделили использование API доступа к данным на отдельный объект, этот принцип говорит, что вместо того, чтобы просто обновлять экземпляр этого объекта, вы должны передать его при создании хранилище. Это облегчает управление временем жизни компонента доступа к данным, открывая возможность делиться ссылками на него между вашими репозиториями, не прибегая к созданию единого пакета.
Важно отметить, что большинство принципов SOLID не обязательно применяются на данном конкретном этапе разработки вашего приложения. Например, следует ли вам прервать доступ к данным, зависит от того, насколько это сложно, и хотите ли вы проверить свою логику хранилища, не обращаясь к базе данных. Похоже, это маловероятно (к сожалению, на мой взгляд), поэтому, вероятно, в этом нет необходимости.
Таким образом, после всего этого мы находим, что YAGNI и SOLID действительно предоставляют один общий надежный совет, имеющий непосредственное отношение: вероятно, нет необходимости создавать общий универсальный интерфейс хранилища.
Вся эта осторожная мысль чрезвычайно полезна в качестве учебного упражнения. Как вы учитесь, это отнимает много времени, но со временем вы развиваете интуицию и становитесь очень быстрыми. Вы будете знать, что нужно делать, но вам не нужно думать обо всех этих словах, если кто-то не попросит вас объяснить, почему.