Domanda

ho avuto una discussione sul posto di lavoro in materia di "Inheritance nel modello di dominio sta complicando la vita agli sviluppatori". Sono un programmatore OO così ho iniziato a cercare gli argomenti che avendo eredità nel modello di dominio sarà facilitare la vita degli sviluppatori in realtà invece di avere commuta in tutto il luogo.

Quello che mi piacerebbe vedere è questo:

class Animal {

}

class Cat : Animal {

}

class Dog : Animal {

}

Che l'altro collega sta dicendo è:

public enum AnimalType {
    Unknown,
    Cat,
    Dog
}

public class Animal {

    public AnimalType Type { get; set; }

}

Come lo convinco (i link sono BENVENUTI ) che una gerarchia di classi sarebbe meglio che avere una proprietà enum per questo tipo di situazioni?

Grazie!

È stato utile?

Soluzione

Ecco come ho ragione su di esso:

Solo l'uso di successione se il ruolo / tipo non cambierà mai. per esempio.

utilizzando l'ereditarietà per cose come:

Fireman <- Employee <-. Persona è sbagliato

non appena Freddy il vigile del fuoco cambia lavoro o diventa disoccupato, dovete ucciderlo e ricreare un nuovo oggetto del nuovo tipo con tutti i vecchi rapporti ad essa collegati.

Quindi la soluzione ingenuo al problema di cui sopra potrebbe essere quella di dare una proprietà jobTitle enum alla classe persona. Questo può essere sufficiente in alcuni scenari, ad esempio, se non hai bisogno di comportamenti molto complessi associati al ruolo / tipo.

Il modo più corretto sarebbe quello di dare alla classe persona un elenco di ruoli. Ogni ruolo rappresenta per esempio un lavoro con un arco di tempo.

per es.

freddy.Roles.Add(new Employement( employmentDate, jobTitle ));

o se questo è eccessivo:

freddy.CurrentEmployment = new Employement( employmentDate, jobTitle );

In questo modo, Freddy può diventare uno sviluppatore w / o che dover uccidere lui per primo.

Tuttavia, tutte le mie divagazioni non hanno ancora risposto, se è necessario utilizzare una gerarchia di enum o tipo per l'jobTitle.

In puro in mem oo direi che è più corretto utilizzare l'ereditarietà per le jobtitles qui.

Ma se si sta facendo la mappatura O / R si potrebbe finire con un modello di dati troppo complicati po 'dietro le quinte se il mapper cerca di mappare ogni sottotipo di una nuova tabella. Quindi, in questi casi, vado spesso per l'approccio enum se non v'è alcun reale comportamento / nel complesso associati con i tipi. Posso vivere con un "se il tipo == JobTitles.Fireman ..." se l'utilizzo è limitato e rende le cose easer o meno complesso.

es. il progettista Entity Framework 4 for .NET può mappare solo ogni tipo di sub in una nuova tabella. e si potrebbe ottenere un modello di brutto o un sacco di join quando si esegue una query del database w / o alcun beneficio reale.

Comunque faccio uso di successione se il tipo / ruolo è statica. per esempio. per i prodotti.

si potrebbe avere CD <- Prodotto e prenotare <- Prodotto. Ereditarietà vince qui, perché in questo caso è più probabile avere diverso stato associato con i tipi. CD potrebbe avere un certo numero di beni tracce mentre un libro potrebbe avere numero di proprietà pagine.

Così, in breve, dipende; -)

Inoltre, alla fine della giornata si è molto probabile che finire con un sacco di affermazioni in entrambi i casi di commutazione. Diciamo che si desidera modificare un "prodotto", anche se si utilizza l'ereditarietà, probabilmente si dovrà codice come questo:

if (prodotto Libro)         Response.Redicted ( "~ / EditBook.aspx id?" + Product.id);

A causa codifica l'URL di modifica libro nella classe di entità sarebbe semplicemente brutto quanto costringerebbe i tuoi entités affari di conoscere la struttura del sito, ecc.

Altri suggerimenti

enumerazioni sono buoni quando:

  1. L'insieme dei valori è fisso e mai o molto raramente cambia.
  2. Si vuole essere in grado di rappresentare un'unione di valori (cioè bandiere conciliano).
  3. Non è necessario allegare altro stato ad ogni valore. (Java non ha questa limitazione.)

Se si potesse risolvere il problema con un numero, un enum è probabile che una buona misura e più sicuri tipo. Se avete bisogno di maggiore flessibilità rispetto al precedente, quindi è probabile che le enumerazioni non la risposta giusta. Utilizzando classi polimorfiche, è possibile:

  1. staticamente garantire che tutti i comportamenti tipo-specifico viene gestito. Ad esempio, se avete bisogno di tutti gli animali essere in grado di Bark(), rendendo classi Animal con un metodo astratto Bark() farà si che il controllo del compilatore per voi che ogni sottoclasse implementa esso. Se si utilizza un enum e un grande switch, non farà in modo che hai gestito tutti i casi.

  2. È possibile aggiungere nuovi casi (tipi di animali nel tuo esempio). Questo può essere fatto attraverso file di origine, e anche nell'ambito dei pacchetti. Con un enum, una volta che hai dichiarato, è congelato. estensione a tempo indeterminato è uno dei punti di forza principali della programmazione orientata agli oggetti.

E 'importante notare che l'esempio del vostro collega non è in diretta opposizione al tuo. Se vuole il tipo di un animale per essere una proprietà esposta (che è utile per alcune cose), è ancora possibile farlo senza usare un enum, utilizzando il tipo di oggetto modello :

public abstract class AnimalType {
    public static AnimalType Unknown { get; private set; }
    public static AnimalType Cat { get; private set; }
    public static AnimalType Dog { get; private set; }

    static AnimalType() {
        Unknown = new AnimalType("Unknown");
        Cat = new AnimalType("Cat");
        Dog = new AnimalType("Dog");
    }
}

public class Animal {
    public AnimalType Type { get; set; }
}

Questo vi dà la comodità di un enum: si può fare AnimalType.Cat e si può ottenere il tipo di un animale. Ma ti dà anche la flessibilità di classi: è possibile aggiungere campi a AnimalType per archiviare i dati supplementare con ogni tipo, aggiungere metodi virtuali, ecc Ancora più importante, è possibile definire nuovi tipi di animali da solo la creazione di nuove istanze di AnimalType

mi piacerebbe esorto a riconsiderare: in un modello di dominio anemico (per le osservazioni di cui sopra ), i gatti non si comportano in modo diverso rispetto ai cani, quindi non c'è il polimorfismo. Tipo di un animale è in realtà solo un attributo. E 'difficile vedere che cosa acquista ereditarietà lì.

Avere un enum è come una festa per tutte quelle persone Open/Closed Principle is for suckers.

E 'davvero vi invita a verificare se un animale è di un certo tipo e quindi applicare la logica personalizzata per ogni tipo. E che può rendere il codice orribile che rende davvero difficile continuare a costruire sul sistema.

La cosa più importante OOPS mezzi modellare la realtà. L'ereditarietà ti dà la possibilità di dire gatto è un animale. Animale non dovrebbe sapere se un gatto ora gridare e poi decidere che è supponiamo di Meow e non corteccia, incapsulamento viene sconfitto lì. Meno codice come ora non c'è bisogno di fare altro se come hai detto.

Entrambe le soluzioni sono a destra. Si dovrebbe guardare quali tecniche si applica meglio a voi problema.

Se il programma utilizza alcuni oggetti diversi, e non aggiunge nuove classi, la sua migliore per stare con le enumerazioni.

Ma se si programma utilizza un sacco di oggetti diversi (classi diverse), e aggiungere nuove classi, in futuro, meglio provare la strada eredità.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top