Mentre ci sono alcune scuole di pensiero sull'orientamento agli oggetti che insistono nel combinare le entità dati con la logica per allineare le classi con le entità fisiche , questa non è assolutamente una linea guida che dovresti seguire a meno che tu non creda veramente che sia la soluzione migliore al tuo particolare problema (Questo approccio può naturalmente prestarsi ad alcuni problemi, ma spesso causa più problemi di quanti ne risolva se seguiti ciecamente). Esistono altre scuole di pensiero che enfatizzano la netta separazione delle preoccupazioni e danno la priorità ai Principi SOLID ".
Le entità fisiche come classi sono una prospettiva valida sulla progettazione della classe, ma sono anche estremamente limitanti e forniscono solo una prospettiva ristretta che non risolve problemi su come le classi possono interagire tra loro, come testarle o cosa succede quando la logica comportamentale potrebbe coinvolgere più entità fisiche. Né considera necessariamente il modo in cui il software cambia e si evolve nel tempo, man mano che i suoi requisiti cambiano o vengono rilevati problemi nell'implementazione originale.
È importante tenere a mente gli obiettivi dell'orientamento agli oggetti piuttosto che considerarli come un insieme di regole da seguire. In generale, gli obiettivi consistono nel raggruppare i comportamenti (metodi) logicamente correlati in classi, mantenendo una netta separazione tra classi / comportamenti diversi non correlati. La misura in cui decidi di farlo dipende da te, ma puoi spesso prendere molte decisioni in base al fatto che qualcosa "si senta" utile nel modo in cui strutturi il tuo programma.
Se qualcosa non sembra utile, o sembra controproducente, o porta a un codice che sembra "disordinato" e inutilmente complesso, allora questo dovrebbe essere un motivo sufficiente per non farlo. Prendete invece in considerazione le implicazioni pratiche, ad esempio se rende il vostro codice più facile da testare unitamente o se la logica alla base della vostra struttura di codice sarebbe immediatamente ovvia per gli altri sviluppatori che stanno cercando di ragionare sul vostro codice. Prendi in considerazione principi come KISS , DRY e YAGNI .
Sembra estremamente improbabile che qualsiasi logica aziendale / applicativa debba mai preoccuparsi delle specifiche delle operazioni CRUD relative a un archivio dati, quindi sembrerebbe piuttosto strano avere il metodo DealDamage
nella stessa classe di un Save
o Read
metodo; il semplice buonsenso impone che queste cose probabilmente non siano correlate.
Ad esempio, il tuo metodo DealDamage
probabilmente non si comporterà diversamente se i dati sono memorizzati in un database SQL rispetto a quelli memorizzati in un file Flat o in un archivio NoSQL, quindi da un punto logico / semantico di vedere ha senso tenerli separati. Inoltre, se il tuo metodo DealDamage
si comporta diversamente a seconda di tali elementi, potrebbe essere un indicatore di un possibile problema nella progettazione o un problema con il modo in cui i requisiti sono specificati.
Non c'è assolutamente nulla di sbagliato nella programmazione orientata agli oggetti con la creazione di semplici modelli di "entità" il cui scopo è semplicemente quello di contenere i dati che sono stati recuperati da un database. Né c'è qualcosa di sbagliato nella creazione di classi comportamentali stateless che non hanno dati propri e operano interamente su quei modelli di entità, infatti un tale design è abbastanza tipico in un Layered Architecture , e anche necessario se stai costruendo un sistema basato su Architettura dei microservizi .
Naturalmente, dipende dalle tue esigenze in merito alla necessità o al beneficio di uno di questi stili architettonici. In generale, qualsiasi tipo di app molto piccola o banale potrebbe non ottenere molto beneficio dalla netta separazione delle preoccupazioni che si otterrebbero da un design più complesso, e si può ottenere un funzionamento del codice abbastanza velocemente con l'approccio Just Do It che tende a ignorare eventuali preoccupazioni più ampie sulla progettazione / architettura o possibili cambiamenti futuri.
I progetti più complessi hanno lo scopo di risolvere una moltitudine di problemi che le persone generalmente associano a sistemi più grandi, le cui esigenze sono più complesse e in continua evoluzione. Soprattutto quando la complessità di questi sistemi li renderebbe difficili da testare o cambiare in modo affidabile come un monolite. La separazione tra strati / moduli / sottosistemi consente di sviluppare separatamente questi diversi componenti, più facilmente riutilizzati da altri sistemi, più flessibili / scalabili per soddisfare i requisiti futuri e più facili da ragionare su altri sviluppatori.