Linea guida: Implementazione di classi
In questa linea guida viene descritto come implementare classi che utilizzano l'ambiente di modellazione RAD6.0.
Relazioni
Descrizione principale

Implementazione di operazioni

Per implementare le operazioni, procedere nel seguente modo:

  • Scegliere un algoritmo.
  • Scegliere le strutture di dati appropriate agli algoritmi.
  • Definire le nuove classi e operazioni secondo necessità.
  • Creare il codice dell'operazione.
Scegliere un algoritmo

Molte operazioni sono semplici abbastanza per essere implementate dall'operazione e la relativa specifica.

Gli algoritmi non banali sono necessari principalmente per due motivi: per implementare le operazioni complesse per cui viene fornita una specifica e per ottimizzare le operazioni per cui viene utilizzato un semplice ma inefficace algoritmo.

Scegliere le strutture di dati appropriate agli algoritmi

La scelta degli algoritmi coinvolge la scelta della struttura di dati su cui agiscono. Molte implementazioni di strutture di dati sono classi di contenitore, come matrici, liste, code, pile, insiemi, bag e relative variazioni. La maggior parte dei linguaggi orientati agli oggetti e gli ambienti di programmazione forniscono librerie di classe con questi tipi di componenti riutilizzabili.

Definire le nuove classi e operazioni secondo necessità

Le nuove classi possono essere istituite per conservare risultati intermedi, ad esempio. È possibile aggiungere alla classe nuove operazioni di basso livello per decomporre un'operazione complessa. Tali operazioni sono spesso riservate alla classe, cioè non visibili all'esterno della stessa classe.

Creare il codice dell'operazione

Scrivere il codice per l'operazione iniziando con la relativa dichiarazione di interfaccia. Seguire le linee guida di programmazione applicabili.

Implementazione di stati

Lo stato di un oggetto può essere implementato attraverso il riferimento ai valori dei suoi attributi, senza alcuna rappresentazione speciale. Le transizioni di stato per tale oggetto saranno implicite nel cambiamento dei valori degli attributi e i comportamenti variabili vengono programmati attraverso dichiarazioni condizionali.  Tale soluzione non è soddisfacente per il comportamento complesso poiché porta solitamente a strutture complesse difficili da modificare quando vengono aggiunti più stati o il comportamento cambia.

Se il comportamento dell'elemento di progettazione (o i relativi costituenti) dipende dallo stato, ci saranno di solito uno o più diagrammi di stato che descrivono il comportamento degli elementi di modello nell'elemento di progettazione. Tali diagrammi vengono utilizzati come input importante durante l'implementazione.

Le macchine a stati mostrate nei diagrammi di stato rendono esplicito lo stato di un oggetto e le transizioni e il comportamento richiesto vengono delineati in modo chiaro. Una macchina a stati può essere implementata nei seguenti modi:

  • Le macchine a stati semplici possono essere implementate definendo un attributo che elenca i possibili stati e utilizzando l'attributo per selezionare il comportamento per i messaggi in arrivo. Ad esempio, in una istruzione switch in Java o C++. Questa soluzione non si adatta molto bene alle macchine a stati complesse e può portare a ridotte prestazioni di esecuzione. Consultare [DOUG98], capitolo 4, 4.4.3 per un esempio di questo metodo
  • Le macchine a stati più complesse possono utilizzare il pattern di stato. Consultare [GAM94] per una descrizione del pattern di stato. [DOUG98], capitolo 6, 6.2.3, Pattern di stato, descrive anche questo approccio
  • Un approccio gestito da tabelle funziona meglio per le macchine a stati molto complesse dove la facilità di modifica è un criterio. In questo approccio, sono presenti voci per ogni stato in una tabella dove la voce associa gli input agli stati che si succedono e alle azioni di transizione associate. Consultare [DOUG98], capitolo 6, 6.2.3, Pattern di tabella di stato, per un esempio di questo metodo.

Le macchine a stati con stati secondari simultanei possono essere implementate delegando la gestione dello stato agli oggetti attivi, uno per ogni stato simultaneo, perché gli stati simultanei rappresentano calcoli indipendenti (che possono, tuttavia, interagire). Ogni stato secondario può essere gestito utilizzando una delle tecniche descritte in precedenza.

Utilizzo della delega per riutilizzare l'implementazione

Se è possibile implementare una classe o parti di essa utilizzando una classe esistente, utilizzare la delega piuttosto che l'eredità.

Per delega si intende l'implementazione della classe con l'aiuto di altre classi. La classe fa riferimento a un oggetto dell'altra classe utilizzando una variabile. Quando un'operazione viene chiamata, si chiama un'operazione nell'oggetto riferito (della classe riutilizzata) per l'esecuzione attuale. In tal modo, delega la responsabilità all'altra classe.

Implementazione di associazioni

Un'associazione a una via viene implementata come puntatore, un attributo che contiene un riferimento di oggetto. Se la molteplicità è uno, viene implementata come un semplice puntatore. Se la molteplicità è molti, viene implementata come insieme di puntatori. Se la molteplicità molti è ordinata, è possibile utilizzare un elenco al posto di un insieme.

Un'associazione a due vie viene implementata come attributi in entrambe le direzioni, utilizzando tecniche per associazioni a una via.

Un'associazione qualificata viene implementata come una tabella di ricerca (ad esempio, una classe Smalltalk Dictionary) nell'oggetto qualificante. I valori del selettore nella tabella di ricerca sono i qualificatori e i valori di destinazione sono gli oggetti dell'altra classe.

Se è necessario accedere ai valori del qualificatore in ordine, i qualificatori possono essere organizzati in una matrice o in una struttura ad albero ordinata. In questo caso il tempo di accesso sarà proporzionale a log N dove N è il numero dei valori del qualificatore.

Se i qualificatori vengono presi da un insieme limitato compatto, i valori del qualificatore possono essere mappati in un intervallo di interi e l'associazione può essere implementata in modo efficiente come una matrice. Questo approccio è più attraente se l'associazione è popolata prevalentemente completa piuttosto che in modo sparso ed è ideale per gli insiemi limitati completamente popolati.

La maggior parte dei linguaggi orientati agli oggetti e gli ambienti di programmazione forniscono librerie di classe con componenti riutilizzabili per implementare diversi tipi di associazioni.

Implementazione di attributi

Gli attributi vengono implementati in uno dei tre modi seguenti: utilizzando tipi primitivi incorporati, utilizzando una classe esistente o definendo una nuova classe. La definizione di una nuova classe è spesso più flessibile, ma introduce azioni indirette non necessarie. Ad esempio, un numero di previdenza sociale di un impiegato può essere implementato con attributo di tipo String o come nuova classe.

Illustrazione di implementazioni di attributo alternative

Implementazioni alternative di un attributo.

Può accadere che gruppi di attributi vengano combinati in nuove classi, come mostra il seguente esempio. Entrambe le implementazioni sono corrette.

Implementazione attributi in Linea a classe Point

Gli attributi in Linea vengono implementati come associazioni a una classe Point.