OOAD - Strategie di implementazione

L'implementazione di una progettazione orientata agli oggetti generalmente implica l'utilizzo di un linguaggio di programmazione orientato agli oggetti (OOPL) standard o la mappatura di progetti di oggetti su database. Nella maggior parte dei casi, coinvolge entrambi.

Implementazione utilizzando linguaggi di programmazione

Di solito, il compito di trasformare un progetto di oggetti in codice è un processo semplice. Qualsiasi linguaggio di programmazione orientato agli oggetti come C ++, Java, Smalltalk, C # e Python, include la disposizione per rappresentare le classi. In questo capitolo, esemplifichiamo il concetto usando C ++.

La figura seguente mostra la rappresentazione della classe Circle utilizzando C ++.

Associazioni attuatrici

La maggior parte dei linguaggi di programmazione non fornisce costrutti per implementare direttamente le associazioni. Quindi il compito di attuare le associazioni richiede una riflessione considerevole.

Le associazioni possono essere unidirezionali o bidirezionali. Inoltre, ogni associazione può essere uno-a-uno, uno-a-molti o molti-a-molti.

Associazioni unidirezionali

Per l'implementazione di associazioni unidirezionali, è necessario prestare attenzione in modo che venga mantenuta l'unidirezionalità. Le implementazioni per diverse molteplicità sono le seguenti:

  • Optional Associations- Qui, un collegamento può o non può esistere tra gli oggetti partecipanti. Ad esempio, nell'associazione tra Cliente e Conto corrente nella figura seguente, un cliente può o meno avere un conto corrente.

Per l'implementazione, un oggetto di Conto corrente è incluso come attributo in Cliente che può essere NULLO. Implementazione utilizzando C ++ -

class Customer {
   private:
   // attributes
   Current_Account c; //an object of Current_Account as attribute
   
   public:  

   Customer() {
      c = NULL; 
   } // assign c as NULL

   Current_Account getCurrAc() {
      return c;
   }
   
   void setCurrAc( Current_Account myacc) {
      c = myacc;
   }

   void removeAcc() {  
      c = NULL;
   } 
};
  • One–to–one Associations- Qui, un'istanza di una classe è correlata esattamente a un'istanza della classe associata. Ad esempio, Reparto e Manager hanno un'associazione uno a uno come mostrato nella figura seguente.

Ciò viene implementato includendo in Department, un oggetto di Manager che non dovrebbe essere NULL. Implementazione utilizzando C ++ -

class Department {
   private:
   // attributes
   Manager mgr; //an object of Manager as attribute
   
   public:  
   Department (/*parameters*/, Manager m) { //m is not NULL   
      // assign parameters to variables
      mgr = m;
   } 

   Manager getMgr() {  
      return mgr;  
   }    
};
  • One–to–many Associations- Qui, un'istanza di una classe è correlata a più di un'istanza della classe associata. Ad esempio, considera l'associazione tra Employee e Dependent nella figura seguente.

Ciò viene implementato includendo un elenco di dipendenti nella classe Employee. Implementazione tramite contenitore di elenchi STL C ++ -

class Employee {
   private:
   char * deptName;
   list <Dependent> dep; //a list of Dependents as attribute

   public:  
   void addDependent ( Dependent d) { 
      dep.push_back(d); 
   } // adds an employee to the department

   void removeDeoendent( Dependent d) { 
      int index = find ( d, dep );
      // find() function returns the index of d in list dep
      dep.erase(index);
   }               
};

Associazioni bidirezionali

Per implementare l'associazione bidirezionale, è necessario mantenere i collegamenti in entrambe le direzioni.

  • Optional or one–to–one Associations - Considerare la relazione tra Project e Project Manager che hanno un'associazione bidirezionale uno a uno come mostrato nella figura seguente.

Implementazione utilizzando C ++ -

Class Project {
   private:
   // attributes
   Project_Manager pmgr; 
   public:  
   void setManager ( Project_Manager pm);       
   Project_Manager changeManager();   
};

class Project_Manager {
   private:
   // attributes
   Project pj; 

   public:  
   void setProject(Project p);       
   Project removeProject();   
};
  • One–to–many Associations - Considerare la relazione tra Reparto e Dipendente che hanno un'associazione uno-a-molti come mostrato nella figura seguente.

Implementazione utilizzando il contenitore di elenchi C ++ STL

class Department {
   private:
   char * deptName;
   list <Employee> emp; //a list of Employees as attribute

   public:  
   void addEmployee ( Employee e) { 
      emp.push_back(e); 
   } // adds an employee to the department

   void removeEmployee( Employee e) { 
      int index = find ( e, emp );
      // find function returns the index of e in list emp
      emp.erase(index);
   }               
};

class Employee {
   private:
   //attributes
   Department d;

   public:
   void addDept();
   void removeDept();
};

Implementazione delle associazioni come classi

Se un'associazione ha alcuni attributi associati, dovrebbe essere implementata utilizzando una classe separata. Ad esempio, si consideri l'associazione uno a uno tra il dipendente e il progetto come mostrato nella figura seguente.

Implementazione di WorksOn utilizzando C ++

class WorksOn {
   private:
   Employee e; 
   Project p;
   Hours h;
   char * date;

   public:
   // class methods
};

Vincoli di implementazione

I vincoli nelle classi limitano l'intervallo e il tipo di valori che possono assumere gli attributi. Al fine di implementare i vincoli, un valore predefinito valido viene assegnato all'attributo quando un oggetto viene istanziato dalla classe. Ogni volta che il valore viene modificato in fase di esecuzione, viene verificato se il valore è valido o meno. Un valore non valido può essere gestito da una routine di gestione delle eccezioni o da altri metodi.

Example

Considera una classe Employee in cui l'età è un attributo che può avere valori compresi tra 18 e 60. Il seguente codice C ++ lo incorpora:

class Employee {
   private: char * name;
   int age;
   // other attributes

   public:
   Employee() {                   // default constructor 
      strcpy(name, "");
      age = 18;                // default value
   }
 
   class AgeError {};          // Exception class
   void changeAge( int a) {   // method that changes age 
      if ( a < 18 || a > 60 )  // check for invalid condition
      throw AgeError();        // throw exception
      age = a;			
   }
};

Implementazione di grafici di stato

Esistono due strategie di implementazione alternative per implementare gli stati nei diagrammi delle carte di stato.

Enumerazioni all'interno di Class

In questo approccio, gli stati sono rappresentati da valori diversi di un membro dati (o insieme di membri dati). I valori sono definiti in modo esplicito da un'enumerazione all'interno della classe. Le transizioni sono rappresentate da funzioni membro che modificano il valore del membro dati interessato.

Disposizione delle classi in una gerarchia di generalizzazione

In questo approccio, gli stati sono disposti in una gerarchia di generalizzazione in modo che possano essere indicati da una variabile puntatore comune. La figura seguente mostra una trasformazione dal diagramma del diagramma di stato a una gerarchia di generalizzazione.

Mappatura degli oggetti al sistema di database

Persistenza degli oggetti

Un aspetto importante dello sviluppo di sistemi orientati agli oggetti è la persistenza dei dati. Grazie alla persistenza, gli oggetti hanno una durata maggiore rispetto al programma che li ha creati. I dati persistenti vengono salvati su un supporto di memorizzazione secondario da dove possono essere ricaricati quando necessario.

Panoramica di RDBMS

Un database è una raccolta ordinata di dati correlati.

Un database management system (DBMS) è una raccolta di software che facilita i processi di definizione, creazione, archiviazione, manipolazione, recupero, condivisione e rimozione dei dati nei database.

Nei sistemi di gestione dei database relazionali (RDBMS), i dati vengono archiviati come relazioni o tabelle, in cui ogni colonna o campo rappresenta un attributo e ogni riga o tupla rappresenta un record di un'istanza.

Ogni riga è identificata in modo univoco da un insieme scelto di attributi minimi chiamati primary key.

UN foreign key è un attributo che è la chiave primaria di una tabella correlata.

Rappresentare le classi come tabelle in RDBMS

Per mappare una classe a una tabella di database, ogni attributo è rappresentato come un campo nella tabella. Uno o più attributi esistenti vengono assegnati come chiave primaria o un campo ID separato viene aggiunto come chiave primaria. La classe può essere partizionata orizzontalmente o verticalmente secondo i requisiti.

Ad esempio, la classe Circle può essere convertita in tabella come mostrato nella figura seguente.

Schema for Circle Table: CIRCLE(CID, X_COORD, Y_COORD, RADIUS, COLOR)
Creating a Table Circle using SQL command:
CREATE TABLE CIRCLE (   
   CID	VARCHAR2(4) PRIMARY KEY,
   X_COORD INTEGER NOT NULL,
   Y_COORD INTEGER NOT NULL,
   Z_COORD INTEGER NOT NULL,
   COLOR 
);

Mappatura delle associazioni alle tabelle del database

Associazioni one-to-one

Per implementare associazioni 1: 1, la chiave primaria di una qualsiasi tabella viene assegnata come chiave esterna dell'altra tabella. Si consideri ad esempio l'associazione tra Reparto e Responsabile:

Comandi SQL per creare le tabelle

CREATE TABLE DEPARTMENT ( 
   DEPT_ID INTEGER PRIMARY KEY,
   DNAME VARCHAR2(30) NOT NULL,
   LOCATION VARCHAR2(20),
   EMPID INTEGER REFERENCES MANAGER 
);

CREATE TABLE MANAGER ( 
   EMPID INTEGER PRIMARY KEY,
   ENAME VARCHAR2(50) NOT NULL,
   ADDRESS VARCHAR2(70),
);

Associazioni uno-a-molti

Per implementare le associazioni 1: N, la chiave primaria della tabella sul lato 1 dell'associazione viene assegnata come chiave esterna della tabella sul lato N dell'associazione. Ad esempio, si consideri l'associazione tra Dipartimento e Dipendente:

Comandi SQL per creare le tabelle

CREATE TABLE DEPARTMENT ( 
   DEPT_ID INTEGER PRIMARY KEY,
   DNAME VARCHAR2(30) NOT NULL,
   LOCATION VARCHAR2(20),
);

CREATE TABLE EMPLOYEE ( 
   EMPID INTEGER PRIMARY KEY,
   ENAME VARCHAR2(50) NOT NULL,
   ADDRESS VARCHAR2(70),
   D_ID INTEGER REFERENCES DEPARTMENT
);

Molte-a-molte associazioni

Per implementare le associazioni M: N, viene creata una nuova relazione che rappresenta l'associazione. Ad esempio, considera la seguente associazione tra Employee e Project:

Schema for Works_On Table - WORKS_ON (EMPID, PID, HOURS, START_DATE)

SQL command to create Works_On association - CREA TABELLA LAVORI_ON

( 
   EMPID INTEGER,
   PID INTEGER, 
   HOURS INTEGER,
   START_DATE DATE,
   PRIMARY KEY (EMPID, PID),
   FOREIGN KEY (EMPID) REFERENCES EMPLOYEE,
   FOREIGN KEY (PID) REFERENCES PROJECT 
);

Mappatura dell'ereditarietà alle tabelle

Per mappare l'ereditarietà, la chiave primaria delle tabelle di base viene assegnata come chiave primaria così come la chiave esterna nella tabella o nelle tabelle derivate.

Example