Come con qualsiasi regola, penso che l'importante qui sia considerare lo scopo della regola, lo spirito e non impantanarsi nell'analizzare esattamente come la regola è stata formulata in alcuni libri di testo e come applicarla a questo caso. Non abbiamo bisogno di avvicinarci a questo come avvocati. Lo scopo delle regole è di aiutarci a scrivere programmi migliori. Non è come lo scopo di scrivere programmi è di mantenere le regole.
Lo scopo della regola della responsabilità singola è rendere i programmi più facili da comprendere e mantenere facendo in modo che ciascuna funzione esegua una cosa autonoma e coerente.
Ad esempio, una volta ho scritto una funzione che ho chiamato qualcosa come "checkOrderStatus", che ha determinato se un ordine era in sospeso, spedito, riordinato, qualunque cosa, e restituito un codice che indica quale. Quindi è arrivato un altro programmatore e ha modificato questa funzione per aggiornare anche la quantità disponibile al momento della spedizione dell'ordine. Ciò ha violato gravemente il principio della responsabilità unica. Un altro programmatore che legge quel codice in seguito vedrebbe il nome della funzione, vedrebbe come veniva usato il valore restituito e potrebbe non sospettare mai che abbia fatto un aggiornamento del database. Qualcuno che aveva bisogno di ottenere lo stato dell'ordine senza aggiornare la quantità disponibile sarebbe in una posizione scomoda: dovrebbe scrivere una nuova funzione che duplica la parte dello stato dell'ordine? Aggiungi un flag per dirgli se fare l'aggiornamento db? Eccetera.
D'altra parte, non vorrei precisare ciò che costituisce "due cose". Di recente ho scritto una funzione che invia le informazioni sui clienti dal nostro sistema al sistema del nostro cliente. Tale funzione esegue una riformattazione dei dati per soddisfare le loro esigenze. Ad esempio, abbiamo alcuni campi che potrebbero essere nulli nel nostro database, ma non consentono valori nulli, quindi dobbiamo inserire del testo fittizio, "non specificato" o dimentico le parole esatte. Probabilmente questa funzione sta facendo due cose: riformattare i dati e inviarli. Ma ho deliberatamente messo questo in una singola funzione piuttosto che avere "riformattare" e "inviare" perché non voglio mai, mai inviare senza riformattare. Non voglio che qualcuno scriva una nuova chiamata e non si renda conto che deve chiamare il riformattatore e poi inviarlo.
Nel tuo caso, aggiorna il database e restituisci un'immagine del record scritto come due cose che potrebbero benissimo andare insieme logicamente e inevitabilmente. Non conosco i dettagli della tua applicazione, quindi non posso dire in modo definitivo se questa è una buona idea o meno, ma sembra plausibile.
Se stai creando un oggetto in memoria che contiene tutti i dati per il record, eseguendo le chiamate al database per scrivere questo e quindi restituendo l'oggetto, questo ha molto senso. Hai l'oggetto tra le mani. Perché non restituirlo? Se non restituissi l'oggetto, come lo otterrebbe il chiamante? Dovrebbe leggere il database per ottenere l'oggetto che hai appena scritto? Sembra piuttosto inefficiente. Come avrebbe trovato il disco? Conosci la chiave primaria? Se qualcuno dichiara che è "legale" per la funzione di scrittura restituire la chiave primaria in modo da poter rileggere il record, perché non restituire l'intero record in modo da non doverlo fare? Qual è la differenza?
D'altra parte, se la creazione dell'oggetto è un mucchio di lavoro abbastanza distinto dalla scrittura del record del database e un chiamante potrebbe voler scrivere, ma non creare l'oggetto, ciò potrebbe essere dispendioso. Se un chiamante potrebbe desiderare l'oggetto ma non fare la scrittura, allora dovresti fornire un altro modo per ottenere l'oggetto, il che potrebbe significare la scrittura di codice ridondante.
Ma penso che lo scenario 1 sia più probabile, quindi direi, probabilmente nessun problema.