Come faccio a creare un modello di dominio che non violi OOP?

1

Il mio gioco legge un numero di file JSON, li deserializza e passa gli oggetti risultanti alle classi che ne hanno bisogno. Questi oggetti deserializzati, che possono essere considerati come il modello di dominio, sono normalmente molto semplici:

public class Settings
{
    public bool FullScreen = false;
    public int WindowWidth = 800;
    public int WindowHeight = 600;
}

Ma uno di questi oggetti non è così semplice:

public class Sprite
{
    [JsonProperty]
    private readonly string assetName;

    [JsonProperty]
    private Vector2 position;

    // other properties...

    public Sprite( string assetName, Vector2 position )
    {
        this.assetName = assetName;
        this.position = position;
    }

    public void Move( Vector2 direction )
    {
        // do move
    }

    // other methods...
}

Le proprietà della classe Sprite sono private perché voglio avere una buona incapsulamento. Ciò significa che ha un costruttore che accetta molti argomenti e molti altri metodi per l'impostazione delle sue proprietà. Inoltre, ogni proprietà ha bisogno di un attributo in modo che possa essere letto dal parser JSON. Sembra un POCO, ma ho letto che POCOs dovrebbe essere la persistenza ignorante. Potrei creare un modello di dominio più semplice che si comporta più come un DTO per soddisfare questo:

public class Sprite
{
    public string AssetName = "default.png";
    public Vector2 Position = Vector2.Zero;
}

Ora la mia classe Sprite è carina e ignorante. Posso scrivere un'altra classe per gestire il tipo di logica aziendale:

public class SpriteWhatever
{
    private Sprite sprite;

    public SpriteWhatever( Sprite sprite )
    {
        this.sprite = sprite;
    }

    public void Move( Vector2 direction )
    {
        // do move
    }

    // other methods...
}

Tuttavia, temo che il mio modello di dominio sia anemico . Per evitare che , potrei semplicemente rendere pubbliche tutte le proprietà della classe Sprite e mantenere tutte le logiche di business al suo interno, ma non ho alcun incapsulamento.

Che cosa dovrei fare?

    
posta David Kennedy 15.02.2014 - 01:09
fonte

2 risposte

3

Penso che il tuo approccio sia nella giusta direzione. Una cosa importante: il tuo modello di dominio non è la classe Sprite ma la classe SpriteWhatever! Un modello di dominio reale è il luogo in cui si trovano le regole e i comportamenti aziendali. Nel tuo esempio, questa è la classe SpriteXXX. La classe Sprite è solo una struttura dati per il trasporto di dati. Ovviamente questa classe è anemica, perché le strutture dati sono anemiche per definizione.

    
risposta data 15.02.2014 - 01:28
fonte
1

Questa è una risposta alla domanda che hai postato nel commento sulla risposta di @ AlfredoCasado. Riguarda solo l'aspetto dell'incapsulamento della tua domanda.

[tl; dr]: La cosa importante sull'incapsulazione è ottenere la funzionalità in metodi / proprietà, non limitando l'accesso ai dati.

Il articolo di Wikipedia sull'incapsulazione menziona queste due definizioni:

  • Un meccanismo linguistico per limitare l'accesso ad alcuni componenti dell'oggetto.
  • Un costrutto linguistico che facilita il raggruppamento dei dati con i metodi (o altre funzioni) che operano su tali dati.

Molti credono che il primo (occultamento dei dati e controllo degli accessi) sia il più importante e l'articolo allude a questo. Nota il commento di Robert Harvey sulle regole: questo è uno che puoi essere meno colpevole di rottura. Il nascondimento dei dati rappresenta circa il 15-20% del beneficio. L'uso di una proprietà per racchiudere un membro, a proposito, non nasconde nemmeno i dati (a meno che non si tratti di un tipo di valore che si sta facendo di sola lettura o restituendo un clone di un tipo di riferimento o immutabile, ma spesso si tratta di OOAD) suggerisce che dovresti restituire un valore da un metodo).

La maggior parte dei vantaggi di Encapsulation deriva dal secondo elemento: raggruppare i dati. Vorrei anche aggiungere, organizzando funzionalità nei metodi di un oggetto (che nasconde anche l'implementazione, ma non è questo il punto). Questo è 80-85% del vantaggio dell'incapsulazione.

Quindi, anziché il consumatore di un oggetto che deve preoccuparsi dei dettagli, puoi fare (e vedere) in poche righe di codice, usando termini tratti dal tuo linguaggio ubiquitario, che hai riportato nei nomi dei metodi, esattamente cosa tu vuoi.

Quindi non importa quanto sei intelligente, il tuo cervello consuma meno cavalli e puoi fare di più. Questa è la "magia" di OO proprio lì. Nascondere i dati non è.

Un'altra nota riguardo l'occultamento dei dati: è solo un suggerimento per i programmatori degli oggetti che hai creato (50-80% del tempo in cui sei tu). Gli sviluppatori possono (e lo vedo tutto il tempo) controllare la tua lezione e rendere pubbliche le cose private. Anche se stai scrivendo librerie in vendita (e chi lo fa?) Possono usare la riflessione per hackerarlo. L'abbiamo fatto nel mio negozio e abbiamo risparmiato un sacco di soldi! A chi importa se la prossima versione si rompe perché l'implementazione era privata? Abbiamo il controllo su quale versione usiamo !!

In conclusione tu devi sapere o notare in entrambi i modi. Se non sai perché è privato, non accetteresti il suggerimento. Se lo fai, non importa. Sì, nascondere i dati spinge gli sviluppatori nella giusta direzione e incoraggia buone pratiche di modellazione. Ecco l'elefante nella stanza: incoraggia tutto ciò che vuoi. Una persona che non conosce OOAD non impara dall'incoraggiamento. Meglio passare il tempo ad insegnare loro.

Wow, è stato lungo.

modifica (vedi commento di @ DavidKennedy85) Sono completamente d'accordo ... tuttavia, organizzare l'implementazione nei metodi di un oggetto (cosa che scommetto che fai) fornisce anche quella funzionalità - un risultato la parte del leone dei benefici dell'incapsulamento. Non sto insinuando che il primo aspetto sia privo di valore - questo è proprio quello che viene insegnato tanto (la maggior parte dell'articolo riflette questo). La citazione che menzionate fa apparire un punto importante - che limita la dimensione della superficie dell'interfaccia a un piccolo sottogruppo intelligentemente succinto. (limitare le interdipendenze). Un altro modo per migliorare gli oggetti è limitare lo stato che l'oggetto conserva, il che significa che ci saranno meno campi da rendere privati. Sono sicuro che siamo d'accordo su queste cose - sto solo evidenziando l'ovvio che per uno sviluppatore giusto per disegnare i suoi oggetti, lei deve iniziare prima sapendo come, poi facendo il disegno, e i campi privati e i metodi diventeranno automaticamente ovvi senza che lei avesse dovuto pensare alla loro accessibilità; tuttavia, concentrarsi innanzitutto sul fatto che alcune cose dovrebbero avere un accesso limitato non è quasi altrettanto utile della montagna di altre "opere d'arte" che è coinvolta in un design appropriato, e se è stato fatto un progetto adeguato, ciò che è pubblico e privato alla fine ha vinto essere la cosa che conta

Un design scadente può esporre se stesso in molti pubblici, ma potrebbe essere un buon progetto. Puoi anche avere un design scadente con pochissimi pubblici.

Ora sto solo sbraitando - ma ho il diritto con ogni altro programmatore uscito da uni che viene detto che sarebbe facile come nascondere i dati e un paio di altri concetti che suonano bene ma sono troppo semplici per essere utile (come 'is-a / has-a'). Non lo è, è molto più difficile, e non mi hanno insegnato le cose importanti!

    
risposta data 15.02.2014 - 18:51
fonte