#6 Classi by-reference | Implementazione (2/2)

Classi By-reference - Implementazioni

In the previous post we saw various implementation techniques for using a class in by-reference mode. The techniques seen in the previous post (variables, FGV, DVR, and SEQ) are all mechanisms external to the class. With these approaches, the class remains by-value. The code outside the object allows the object itself to be used by-reference. Now, we are going to see two techniques internal to the class to turn it into an “intrinsic” by-reference class.

DVR come attributo privato della classe

Abbiamo già visto come un DVR possa essere usato per storicizzare un oggetto by-value. Possiamo però incapsulare il DVR dentro la classe cioè inserire il DVR nei dati privati della classe stessa rendendola a tutti gli effetti una classe by-reference (senza bisogno dei meccanismi visti nella prima parte). Nel dettaglio, per fare ciò, è necessario:

  • Spostare gli effettivi attributi della classe in un cluster privato (meglio un type def). Predisporre un DVR per contenere tale cluster. Il DVR diventa l’unico dato del cluster privato della classe.
Classe by-reference con il DVR privato – dati privati della classe.
  • Realizzare un costruttore (un metodo che possiamo chiamare per esempio init, create o constructor) che inizializza il DVR. Il tipo dato del DVR è il cluster del punto precedente.
Classe by-reference con il DVR privato – costruttore.
  • Realizzare un distruttore che esegue il dispose del DVR. Esempi di nomi per questo metodo possono essere: dispose o distructor.
Classe by-reference con il DVR privato – distruttore.

È buona norma non esporre il reference del DVR, che dovrebbe sempre essere completamente incapsulato nella classe. Le proprietà e i metodi della classe rimangono quelli che avremmo previsto anche se la classe fosse stata by-value. Tuttavia, internamente, la classe accede sempre al proprio DVR interno per ogni operazione (getter, setter e metodi vari).

Classe by-reference con il DVR privato – esempio di setter.

Una classe creata in questo modo può essere considerata intrinsecamente by-reference. Con questo tipo di classi, il filo del relativo oggetto trasporta il reference al DVR. Eventuali biforcazioni del filo duplicano sì l’oggetto ma, grazie alla struttura interna della classe, ciò che si duplica è solo il riferimento al DVR interno alla classe stessa.

Il principale vantaggio di questo approccio è che non sono necessari meccanismi esterni per rendere l’oggetto by-reference semplificando e snellendo in molti casi il codice. Oltre a ciò, si hanno tutti i vantaggi derivanti dall’uso del DVR che abbiamo visto nell’altro post:

  • Meccanismi di protezione per l’accesso al dato.
  • Scalabilità.
  • Migliore efficienza nella gestione della memoria.
  • Tecnologia consolidata.

L’analisi degli svantaggi di questa tecnica merita un discorso approfondito. Vediamoli nel dettaglio:

  • È necessario l’uso del costruttore e del distruttore che rispettivamente creano e distruggono il DVR privato dell’oggetto. È una cosa del tutto normale negli altri linguaggi ma non in G-code. Lo sviluppatore deve quindi esserne a conoscenza.
  • L’oggetto by-reference funziona anche se usato by-value. Sembra un vantaggio ma non sempre lo è. Innanzitutto, una classe by-reference con il DVR privato (se ben fatta) può essere usata come se fosse by-value. Va però considerato il fatto che, se il programmatore non sa che sta maneggiando un oggetto intrinsecamente by-reference, eventuali biforcazioni del filo che trasporta l’oggetto possono dare comportamenti inattesi. Con un oggetto nativamente by-reference, le biforcazioni del filo che trasporta l’oggetto in realtà non duplicano il “dato contenuto”. Lo sviluppatore, ignaro che sta usando un oggetto by-reference, potrebbe volutamente biforcare il filo che trasporta l’oggetto con l’intenzione di ottenere due oggetti indipendenti. Ciò però non accade con un oggetto by-reference, creando comportamenti inattesi.
  • Possibili deadlock (se i suoi metodi non sono implementati correttamente). Poiché potenzialmente ogni metodo, getter e setter accede al DVR, è importante fare attenzione a non chiamare il DVR “ricorsivamente”. All’interno della struttura In Place sarebbe opportuno non chiamare altri metodi che accedono al DVR della classe. Supponiamo per esempio di avere due metodi di una classe metodo1 e metodo2 che accedono entrambi al contenuto del DVR. Il metodo1 inoltre chiama il metodo2 all’interno della struttura In Place. In questo scenario, il metodo1 blocca il DVR, chiama il metodo2 e ne attende il completamento. Il metodo2, a sua volta, attende lo sblocco del DVR da parte del metodo1. I due metodi si attendono a vicenda e si ha una deadlock. Come regola generale, per evitare questa condizione, è buona norma non portare mai il filo che trasporta l’oggetto dentro la struttura In Place così da evitare accessi annidati al DVR.
Classe by-reference con il DVR privato – possibile fonte di deadlock. Se il metodo che si trova nella struttura In Place utilizza il DVR privato della classe, si ha una deadlock.
  • La classe è by-reference ma non le sua classi derivate. Questo è il vero grande svantaggio di questo tipo di classi. Quando si crea una classe derivata da una by-reference con DVR privato, questa classe è a tutti gli effetti una classe by-value. Se la classe derivata non è implementata allo stesso modo della classe madre, il risultato è una classe ibrida: un po’ by-reference e un po’ by-value.
    Inoltre, se volessimo rendere tutte le classi discendenti di tipo by-reference con DVR interno, sarebbe necessario creare un DVR dedicato per ognuna di esse.
SEQ come attributo privato della classe

Abbiamo già visto come un SEQ possa essere usato per storicizzare un oggetto by-value. Come visto per il DVR, possiamo però incapsulare il SEQ dentro la classe cioè inserire il SEQ nei dati privati della classe stessa rendendola a tutti gli effetti una classe by-reference (senza bisogno dei meccanismi visti nella prima parte). Analogamente a quanto visto per il DVR, per fare ciò, è necessario:

  • Spostare gli effettivi attributi della classe in un cluster privato (meglio un type def). Il SEQ diventa l’unico dato del cluster privato della classe.
Classe by-reference con il SEQ privato – dati privati della classe.
  • Realizzare un costruttore (un metodo che possiamo chiamare per esempio init, create o constructor) che inizializza il SEQ. Il tipo dato del SEQ è il cluster del punto precedente.
Classe by-reference con il DVR privato – costruttore.
  • Realizzare un distruttore che esegue il dispose della coda SEQ. Esempi di nomi per questo metodo possono essere: dispose o distructor.
Classe by-reference con il DVR privato – distruttore.

Anche in questo caso, il SEQ dovrebbe sempre essere incapsulato nella classe. Le proprietà e i metodi della classe rimangono quelli che avremmo previsto anche se la classe fosse stata by-value. Tuttavia, internamente, la classe accede sempre al proprio SEQ interno per ogni operazione (getter, setter e metodi vari).

Classe by-reference con il DVR privato – esempio di setter.

Una classe creata in questo modo può essere considerata intrinsecamente by-reference. Con questo tipo di classi, il filo del relativo oggetto trasporta il reference al SEQ. Eventuali biforcazioni del filo duplicano sì l’oggetto ma, grazie alla struttura interna della classe, ciò che si duplica è solo il riferimento al SEQ interno alla classe stessa.

Vantaggi e svantaggi dell’uso del SEQ come attributo interno della classe sono del tutto identici a quelli visti con il DVR.

Conclusioni

In questo post diviso in due parti abbiamo visto le principali tecniche per ottenere classi by-reference. In particolare, nel primo post abbiamo visto meccanismi esterni alla classe per poterla utilizzare by-reference. Nel secondo post abbiamo poi visto meccanismi interni alla classe per trasformarla in una classe by-reference “intrinseca”.
Nei prossimi post vedremo i design pattern più diffusi e più utili compatibili con l’ambiente LabVIEW.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Scroll to Top