Come modellare un semplice file system con il diagramma delle classi UML

6

Voglio modellare un file system che contiene sia file che directory e le directory possono contenere file o altre directory.

Questo è quello che ho raggiunto finora:

In OOSE book , tuttavia, viene presentato un modello simile:

Ora ho due domande:

  1. Mi chiedo perché l'autore non abbia utilizzato un'interfaccia per rappresentare il tipo astratto FileSystemElement ? Non sta utilizzando un'interfaccia per questo tipo corretta?

  2. Come sappiamo, i file e le directory devono avere nomi con un vincolo simile (ad esempio, una lunghezza massima di 256 caratteri). Pertanto, sarebbe bello se modifico questo in FileSystemElement . Ma una interfaccia non può avere un attributo astratto , quindi devo ripetere l'attributo nome in Directory e Classi file . C'è qualche soluzione migliore per questo problema?

posta Isaac 27.04.2012 - 15:50
fonte

5 risposte

1

I wonder why the author did not use an Interface to represent the abstract type FileSystemElement? Isn't using an interface for this type correct?

Sarebbe corretto, nella misura in cui un modello UML valido, come sarebbe usare una classe base astratta. La decisione di progettazione dipende da altri fattori, spesso legati al linguaggio di implementazione.

But an interface cannot have a abstract attribute, so I have to repeat name attribute in both Directory and File classes. Is there any better workaround for this problem?

Un'interfaccia può avere attributi e si presume che siano astratti. Come questi attributi astratti vengono tradotti in codice reale utilizzeranno idiomi diversi per ciascun linguaggio di implementazione e spesso idiomi diversi tra utenti diversi dello stesso linguaggio di implementazione. A livello di UML, non è affatto una limitazione.

As we know, files and directories must have names with similar constraint (e.g. maximum length of 256 characters). Therefore, it would be nice if I model this in the FileSystemElement.

Non vi è alcun motivo per cui non è possibile inserire un vincolo UML su un attributo dell'interfaccia. { Name.Length <= 256 } può essere messo su un attributo posseduto da un'interfaccia proprio come se si trattasse di un attributo posseduto da un altro classificatore. Il modo in cui verrà implementato sarà diverso sia nel linguaggio di implementazione sia nella strategia di implementazione - forse si dispone di una funzione di validazione che prende un'istanza dell'interfaccia, chiede il nome e verifica la lunghezza. La conversione dei vincoli UML nel codice non segue necessariamente l'eccezione "lanciare un'eccezione se si tenta di chiamare il getter", sebbene spesso lo faccia.

È possibile che l'autore del libro OOSE avesse in mente qualche strategia di implementazione, e quindi utilizza una classe concreta. Molto ciò che farei dipende da che cosa sono le classi - ad esempio, se sono solo segnaposto per i frammenti di percorso e si affidano a qualcos'altro per creare un flusso che apre il file, è possibile testarli completamente senza avere un interfaccia per deridere, quindi non mi preoccuperei di aggiungere altro strato di astrazione. Se avessero avuto operazioni dirette per restituire flussi o eseguire altre operazioni su file system, potrei usare un'interfaccia in modo da poter essere derisi per il test. Né è corretto, e quale è un adattamento migliore per i requisiti non può essere determinato da due diagrammi UML molto piccoli.

Una rapida scansione del libro OOSE che colleghi per confermare che si tratta di diagrammi di classe molto negli stessi termini di ER-Diagrams e considerando di rappresentare le relazioni tra i nomi, non quello che gli oggetti fanno . Vorrei mettere in guardia sul fatto che se si considerano i nomi in relazione statica si sta parlando di codice procedurale piuttosto orientato agli oggetti - forse è per questo che si sta scoprendo che il modello presentato nel libro si concentra su tipi concreti con attributi piuttosto che un'interfaccia di operazioni. O forse sta solo cercando di dimostrare diversi tipi di associazioni e non vale la pena guardarlo troppo profondamente!

    
risposta data 10.02.2013 - 23:05
fonte
4

Isn't using an interface for this type correct?

L'utilizzo di un'interfaccia in questo caso funzionerebbe, ma dovresti duplicare il comportamento tra Directory e File (come avere un massimo di 256 caratteri per il nome). Faresti meglio a rendere FileSystemElement una classe astratta (supponendo che il tuo linguaggio di scelta lo supporti). Ciò risponde anche alla tua seconda domanda: una classe astratta può fornire un comportamento predefinito per i suoi figli. Puoi semplicemente dichiarare la proprietà Name all'interno della classe genitore, con le validazioni associate, ecc. In questo modo, Directory e File erediteranno la proprietà e il comportamento. Non dovrai ridefinire nulla nella classe Directory of File. Nessuna duplicazione del codice.

    
risposta data 27.04.2012 - 16:58
fonte
0

Mi piace il fatto che tu abbia aggiunto un'associazione tra il file e la directory (anche se non hai specificato la molteplicità). Ora come da vostre domande:

I wonder why the author did not use an Interface to represent the abstract type FileSystemElement? Isn't using an interface for this type correct?

Sei corretto, potrebbe essere stata utilizzata un'interfaccia. Tuttavia, non è la scelta migliore. Come sai, un'interfaccia non ti consente di aggiungere codice di implementazione ai suoi metodi. È preferibile utilizzare una classe anziché un'interfaccia perché è possibile includere dettagli di implementazione dei metodi che si vedono in comune tra le sottoclassi. In questo caso, potresti voler condividere la convalida della proprietà del nome, per esempio.

As we know, files and directories must have names with similar constraint (e.g. maximum length of 256 characters). Therefore, it would be nice if I model this in the FileSystemElement. But an interface cannot have a abstract attribute, so I have to repeat name attribute in both Directory and File classes. Is there any better workaround for this problem?

In c # è possibile definire zero, una o più proprietà come parte di un'interfaccia, ad esempio:

public interface IFileSysElement
{
    // Property declaration:
    string ElementName
    {
        get;
        set;
    }
...
}

Quindi non è un problema in realtà.

Il problema che vedo con il modello del libro è che avere un'associazione tra una classe e una classe secondaria è ingombrante (per me). Un altro punto da considerare è il fatto che il nome FileSystemElement è il nome relativo (ad esempio, myFile.txt). Hai bisogno di un'altra proprietà o metodo per costruire o recuperare il nome completo del file per (ad esempio C: \ Temp \ myFile.txt). Questo è l''identificatore aziendale' per entrambe le classi.

    
risposta data 28.04.2012 - 00:34
fonte
0

Si chiama Pattern Composito e come tale non possiede un'Associazione tra il Composito (Directory) e il Foglia (File). Penso che sia stato un incidente grafico nella prima immagine, anche se tecnicamente non suggerisce un'associazione tra loro due - sembra proprio uno.

    
risposta data 10.02.2013 - 17:22
fonte
-1

L'approccio di classe base ha senso a causa del problema sollevato nella seconda domanda. Una classe base ti consente di avere tale attributo e di non ripeterti su controlli di validità ecc.

D'altra parte il tuo approccio all'interfaccia ha senso perché ti offre più flessibilità. Supponiamo di voler aggiungere un terzo tipo di FileSystemElement che non ha un attributo name. E forse questo terzo tipo si presta a usare una classe base molto diversa. Ma vuoi comunque affrontare tutti e tre i tipi dalla classe Directory. Non puoi farlo con una classe base.

Quindi, vediamo se possiamo combinare le funzioni. Il motto qui è separazione delle preoccupazioni .

  1. preoccupazione: indirizza tutti gli elementi di un filesystem allo stesso modo.
  2. preoccupazione: condividi l'implementazione del nome tra la Directory e la classe File.

Non possiamo fare entrambe le cose con una sola tecnica, ma nulla ci impedisce di usarle entrambe contemporaneamente! Creiamo un'interfaccia FileSystemElement e lascia che Directory e File lo implementino. Inoltre crea una classe base (possibilmente astratta) chiamata ad es. NamedFileSystemElement con l'attributo desiderato. Ora lascia che Directory e File ereditino da NamedFileSystemElement. Vedi, il meglio di entrambi i mondi.

    
risposta data 27.04.2012 - 19:57
fonte

Leggi altre domande sui tag