Ereditarietà rispetto alla composizione in un'applicazione aziendale

0

Ho un sistema di gestione e monitoraggio della formazione, con una struttura di alto livello come segue:

Abbiamo un ruolo 1 , ad es. Manager, Shift-boss, minatore, ecc. E un Candidato , formazione per quel ruolo. Il ruolo ha un elenco di corsi e le loro materie che il candidato deve completare per qualificarsi per il ruolo. Candidato ha un attributo TrainingHistory , contenente i corsi e gli argomenti che hanno completato, i loro risultati e la data di completamento.

Ora lo vedo come un corso TrainingHistoryCourse is-a , esteso per aggiungere DateCompleted ecc. ma qualcosa mi assilla usare piuttosto qualcosa come TrainingHistoryRecord che ha-un corso . Come posso analizzare ulteriormente questo per determinare quale pattern usare?

Quindi, un ruolo ha una lista di definizioni RoleTask che il Candidato deve essere osservato mentre pratica e un Candidato ha una storia di RoleTaskObservation oggetti che registrano le loro prestazioni in queste attività. Questo è molto simile al requisito del corso / soggetto e al modello cronologico per il candidato, ad eccezione di un livello gerarchico inferiore, ma, un RoleTaskObservation chiaramente non ha un is-a relazione con RoleTask , a meno che non blocchi il naso e preferisco usare ObservedRoleTask .

Preferirei usare lo stesso schema per le strutture soggetto / corso e compito / osservazione, ma penso che mi costringerebbe ad adottare un modello di composizione per TrainingHistoryCourse . Qual è la saggezza qui? Eredita sempre dove possibile e convalidato da un solido è-un'associazione, o preferisci sempre la composizione ovunque sia possibile?

1 Il client ha specificato che questo si chiama JobTitle, ma non sta scrivendo l'app e un JobTitle è solo un attributo di un ruolo. I ruoli di autorizzazione sono gestiti dal framework DevExpress e dai relativi hook di personalizzazione, quindi non ci sarebbe molto poco confusione tra un ruolo aziendale nei miei oggetti dominio e un ruolo di autorizzazione nel codice framework di livello inferiore.

    
posta ProfK 03.11.2011 - 05:18
fonte

2 risposte

3

Chiedo scusa per la verbosità. Vai su Qual è la saggezza qui? se ti piace.

How can I further analyse this to determine which pattern to use?

Continua a identificare i casi d'uso. e assicurati che l'analisi dei requisiti sia completa. Ad esempio, immagina come TrainingHistoryCourse viene utilizzato per la segnalazione di vari dettagli (lavoro del corso specifico) e riepilogo (rapporti di allenamento finali, rapporti sullo stato di avanzamento della gestione). Questo potrebbe informare la struttura di un record di allenamento per esempio.

Ho la sensazione che tu stia cercando di inventare qualcosa per ottenere un "OO design warm fuzzy" (Look - Ereditarietà e composizione!) - e potresti avere delle lacune nell'analisi dei requisiti.

Oggetto / corso

Curriculum è un'idea che può fondere i tuoi concetti di soggetto / corso. curriculum può essere il nostro contenitore generale / Classe per tutti i requisiti di formazione, personalizzato per ogni specifico ruolo

Il ShiftBossCurriculum quindi è una composizione naturalmente * s e * roleTask * s che, una volta completato, qualifica un candidato come Shift -Boss,

compito / osservazione

Il istruttore osserva il candidato che esegue un RoleTask e fa una voce nel candidato < em> TrainingHistoryCourse Training Record

Un candidato completa un determinato corso in un Curriculum . La data di completamento è inserita nel record di allenamento . L'istruttore inserisce le relative osservazioni per quel corso. (fieno! Ho visto un caso d'uso!).

TrainingHistoryCourse

Questo concetto non ha senso. Se si tratta principalmente di una data di completamento del corso, sembra essere un'estensione logica di un record di allenamento, non di THE course stesso.

Record di allenamento

Dalle discussioni precedenti, sembra che un record di allenamento sia una composizione di lavoro, roleTasks e osservazioni.

Potential Inheritance Bases

Ruolo, compito, corso, curriculum, record di allenamento, candidato ... In effetti tutti i tuoi attori e oggetti generali. Dipende da qualsiasi specializzazione / personalizzazione identificata (o futura / potenziale) richiesta da queste cose generali. Finora abbiamo identificato curriculum specialistici, ruoli, corsi e attività. Ma anche allora questo non garantisce che useremo l'ereditarietà; il diavolo è nei dettagli.

Composizione potenziale

Chiaramente curriculum e record di allenamento sono compositi. Ma non a causa dell'osservazione semplicistica che contengono cose (quale oggetto non?). Continua a leggere, Macduff.

Qual è la saggezza qui?

Always inherit where possible and validated by a solid is-a association, or always favour composition wherever possible?

Questo è sbagliato. Il massimo è favorire la composizione sull'ereditarietà. "Sempre" non è lì. Seguendo questa euristica, il tuo software tende ad essere più flessibile, più facile da mantenere, estendere e riutilizzare.

Non andare a inventare la gerarchia dell'ereditarietà dove non esiste. Nel tuo modello di business, c'è davvero bisogno di gestire i corsi come "corsi di matematica" o "corsi a turni di lavoro", ecc.? O sono solo corsi che sono logicamente associati in un "curriculum del boss di turno"? Il nome del corso, il dipartimento del corso, ecc. / Le proprietà saranno riempite in fase di runtime per darci un corso particolare.

Allo stesso modo un curriculum è anche solo un curriculum. Cosa rende un curriculum "capotavola"? Semplicemente una serie diversa di corsi di fronte ai corsi "manager".

Quindi abbiamo identificato un "curriculum" generale, e che componendo con diverse istanze di corsi rende un curriculum diverso. Quindi abbiamo una composizione per fare un curriculum "manager", non una sottoclasse di ManagerCurriculum del curriculum.

Dopo aver identificato un concetto generale, può essere codificato come un'interfaccia (le interfacce possono essere letteralmente interfacce o classi astratte). Cosa fai a qualsiasi corso specifico che fai con qualsiasi corso. ORA abbiamo un codice flessibile, riutilizzabile, estensibile e gestibile.

    
risposta data 20.03.2012 - 14:45
fonte
0

Dovresti sentirti irritato! L'ereditarietà dovrebbe essere utilizzata solo se si introduce una specializzazione della classe genitore. L'aggregazione dovrebbe essere usata quando 1 oggetto consiste in un altro oggetto (diverso) per renderlo intero.

Ecco un esempio di ereditarietà usando il tuo corso, mentre ci spostiamo da destra a sinistra diventiamo più specializzati.

Corso < - MathCourse < - Geometry

In questo esempio TrainingHistoryCourse non ha senso perché non è di per sé una classe, piuttosto una notazione che qualcuno ha preso una lezione.

Che cosa succede se proviamo a utilizzare l'ereditarietà?

Corso < - MathCourse < - Geometria < - TrainingHistryGeometry

Con questo approccio dovremmo aggiungere una nuova specilizzazione di TrainingHistory per ogni classe.

Corso < - TrainingHistoryCourse < - MathCourse < - Geometria

Questo approccio ci farebbe creare una nuova istanza della classe Geometry ogni volta che viene offerta. Questo potrebbe funzionare, ma avremmo bisogno di un'istanza separata del GeometryClass evertime che viene offerto. Il che è strano perché sono la stessa classe appena offerta in momenti diversi.

Salta all'inseguimento

In questo esempio è meglio usare il tuo approccio TrainingHistoryRecord perché ogni studente sta prendendo la stessa classe. Devi solo registrare quando è stata scattata e qual era il loro punteggio.

Alcuni altri esempi

Di solito puoi "sondare" per capire l'approccio migliore

Una macchina è-a veicolo NON una macchina ha-un veicolo

Una berlina è-a auto NON una berlina ha-un auto

Un'auto ha-un motore NON un'auto è-un motore

    
risposta data 19.03.2012 - 21:27
fonte