ахах, нет просто не пойму, в какой компонент лучше выделить файл и его десериализованные данные. Если JsonFile, JsFile, ImageFile, то получается куча классов, которые наследуются от File, но отличаются парой полей всего лишь
Да вот сам задумался, а в чем ответственность каждого класса. Судя по всему — исключительно в хранении специфичных для этого формата полей (если сериализация/десериализация происходит в другом месте)
SRP это про "причины для изменений". Грубо говоря если у штуки только одна причина для изменений то все хорошо. Например если при изменении формата скажем тебе надо и чтение и запись менять - то все в целом хорошо.
Есть еще ISP который может тебя "попросить" для чтения и для записи отдельные интерфейсики сделать просто что бы клинтский код которому нужно только читать мог только от чтения зависеть, но "класс" при этом может просто оба интерфейса имплементить и все будет хорошо.
На счет конкретно твоего вопроса - есть некий "сторадж" который умеет хранить "файлы". "файлы" (их базовый контракт) могут предоставлять свое бинарное представление скажем для стораджа (или стрим или чего еще). То есть "файл" это просто "файл". При этом могут быть более конкретные реализации JsonFile и т.д. - тут уже LSP вступает в силу. Стораджу должно быть пофигу - любой подставь долно работать.
В этом случае "то как представлять файл" зона ответственности файла, а то как их на диск писать - зона ответственности стораджа. Почему? Потому что формат может поменяться - это про файлы. Одна причина для изменений. Ну и сторадж сегодня ты в файлик на диске пишешь а завтра на S3 - другая причина для изменений.
вся суть эти SRP и прочих солидов в том что бы ты дробил модули по тому как они будут меняться - что бы потенциально уменьшить каскад изменений. Если ты еще open/close будешь соблюдать что "изменения" все должны быть вообще добавлением новых вещей (через точки расширения) и никогда больше чем один модуль по одной причине меняться не будет.
Сразу стоит оговориться что "проектировать по SOLID" в этом ключе = знать будущее. Ты можешь будущее предсказывать. можешь ошибаться. Но лучше SOLID использовать для проверки надо ли чего рефакторить. Не случайно дядя Боб про солиды после рефакторинга в своих этих аджайл девелопер книжках рассказывает. Эти принципы никогда не подразумевались что "всегда соблюдаются". Это просто "хорошие критерии которые позволяют уменьшить количество боли при внесении изменений в систему".
Спасибо большое за развёрнутый ответ, действительно стало понятнее! Сохранил.
Взглянуть на srp с той стороны, чтобы меньше надо было переписывать — прикольно.
Правда под понятие «одна причина для изменений» тоже можно подогнать что угодно, типа «изменились внешние факторы» = одна причина для изменений, которая подойдёт вообще ко всему. Или «изменилась строка 1 и строка 2» = две причины изменений, принцип нарушен, все. Тут как-то интуитивно эту грань надо чувствовать что ли.
тут не про "переписывать" скорее а про то как в целом ты вносишь изменения в систему. Грубо говоря соблюдение этих всех принципов ставит целью:
- уменьшить скоуп изменений - в целом позволить тебе делать стратегию "делать новое и заменять им старое" вместо "перехерачить" - тупо лучше рисками управлять выходит. Обратная совместимость все дела. Оч полезный скил в условиях continious delivery/trunk based development - уменьшить "влияние" кода на другие части (то самое приславутое low coupling/high cohesion)
ну и да, все это подразумевает постоянный рефакторинг, ревью имплементации (ну то есть оглядываться назад периодически), анализ потока изменений требований (кто почему зачем хочет менять).
чем больше проект - тем больше в этом всем можно увидеть смысл. На маленьких задачах прочувствовать профит от этого тяжело, потому люди часто кидаются в оверинжениринг и потом обвиняют в этом все эти принципы