Как и в случае с любым правилом, я думаю, что здесь важно рассмотреть цель правила, его дух, а не разбираться в том, как именно проанализировать, как было сформулировано правило в каком-то учебнике, и как применить его к этому случаю. Нам не нужно подходить к этому как к адвокатам. Цель правил - помочь нам написать лучшие программы. Это не похоже на то, что целью написания программ является соблюдение правил.
Цель правила единственной ответственности состоит в том, чтобы облегчить понимание и поддержку программ, заставляя каждую функцию выполнять одну самодостаточную, согласованную вещь.
Например, я однажды написал функцию, которую я назвал чем-то вроде «checkOrderStatus», которая определяла, находится ли заказ в ожидании, отправлен, был ли он заказан обратно, и возвращала код, указывающий, какой именно. Затем появился другой программист и изменил эту функцию, чтобы также обновлять имеющееся количество при отправке заказа. Это серьезно нарушило принцип единоличной ответственности. Другой программист, читающий этот код позже, увидит имя функции, увидит, как используется возвращаемое значение, и вполне может никогда не подозревать, что он сделал обновление базы данных. Кто-то, кому нужно получить статус заказа без обновления имеющегося количества, окажется в неловком положении: должен ли он написать новую функцию, которая дублирует часть статуса заказа? Добавить флаг, чтобы сказать, нужно ли делать обновление базы данных? И т.п.
С другой стороны, я бы не стал придираться к тому, что составляет «две вещи». Я только недавно написал функцию, которая отправляет информацию о клиентах из нашей системы в систему нашего клиента. Эта функция выполняет некоторое переформатирование данных в соответствии с их требованиями. Например, у нас есть некоторые поля, которые могут быть нулевыми в нашей базе данных, но они не допускают пустых значений, поэтому мы должны заполнить какой-то фиктивный текст, «не указан», или я забыл точные слова. Возможно, эта функция делает две вещи: переформатировать данные и отправить их. Но я очень сознательно поместил это в одну функцию вместо того, чтобы «переформатировать» и «отправить», потому что я не хочу когда-либо отправлять без переформатирования. Я не хочу, чтобы кто-то писал новый звонок и не понимал, что ему нужно переформатировать, а затем отправить.
В вашем случае обновление базы данных и возврат изображения записанной записи кажутся двумя вещами, которые вполне могут логически и неизбежно сочетаться друг с другом. Я не знаю деталей вашего заявления, поэтому не могу однозначно сказать, хорошая это идея или нет, но это звучит правдоподобно.
Если вы создаете объект в памяти, который содержит все данные для записи, делаете вызовы базы данных, чтобы написать это, а затем возвращаете объект, это имеет большой смысл. У вас есть объект в ваших руках. Почему бы просто не вернуть его? Если вы не вернули объект, как вызывающий абонент получит его? Придется ли ему читать базу данных, чтобы получить объект, который вы только что написали? Это кажется довольно неэффективным. Как он найдет запись? Вы знаете первичный ключ? Если кто-то заявляет, что для функции записи «законно» возвращать первичный ключ, чтобы вы могли перечитать запись, почему бы просто не вернуть всю запись, чтобы вам не пришлось это делать? Какая разница?
С другой стороны, если создание объекта - это куча работы, совершенно отличной от написания записи базы данных, и вызывающая сторона может захотеть сделать запись, но не создать объект, тогда это может быть расточительным. Если вызывающая сторона может захотеть объект, но не выполнить запись, то вам придется предоставить другой способ получить объект, что может означать написание избыточного кода.
Но я думаю, что сценарий 1 более вероятен, поэтому я бы сказал, что, вероятно, нет проблем.