OOAD - Estratégias de Implementação

A implementação de um projeto orientado a objetos geralmente envolve o uso de uma linguagem de programação orientada a objetos (OOPL) padrão ou o mapeamento de projetos de objetos para bancos de dados. Na maioria dos casos, envolve ambos.

Implementação usando linguagens de programação

Normalmente, a tarefa de transformar o design de um objeto em código é um processo direto. Qualquer linguagem de programação orientada a objetos, como C ++, Java, Smalltalk, C # e Python, inclui provisão para representar classes. Neste capítulo, exemplificamos o conceito usando C ++.

A figura a seguir mostra a representação da classe Circle usando C ++.

Implementando Associações

A maioria das linguagens de programação não fornece construções para implementar associações diretamente. Portanto, a tarefa de implementar associações requer uma reflexão considerável.

As associações podem ser unidirecionais ou bidirecionais. Além disso, cada associação pode ser um para um, um para muitos ou muitos para muitos.

Associações Unidirecionais

Para a implementação de associações unidirecionais, deve-se tomar cuidado para que a unidirecionalidade seja mantida. As implementações para diferentes multiplicidades são as seguintes -

  • Optional Associations- Aqui, um link pode ou não existir entre os objetos participantes. Por exemplo, na associação entre Cliente e Conta Corrente na figura abaixo, um cliente pode ou não ter uma conta corrente.

Para implementação, um objeto de Conta Corrente é incluído como um atributo em Cliente que pode ser NULO. Implementação usando 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- Aqui, uma instância de uma classe está relacionada a exatamente uma instância da classe associada. Por exemplo, Departamento e Gerente têm uma associação um para um, conforme mostrado na figura abaixo.

Isso é implementado incluindo no Departamento, um objeto de Gerente que não deve ser NULL. Implementação usando 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- Aqui, uma instância de uma classe está relacionada a mais de uma instância da classe associada. Por exemplo, considere a associação entre Funcionário e Dependente na figura a seguir.

Isso é implementado incluindo uma lista de Dependentes na classe Employee. Implementação usando o contêiner de lista C ++ STL -

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);
   }               
};

Associações bidirecionais

Para implementar a associação bidirecional, os links em ambas as direções precisam ser mantidos.

  • Optional or one–to–one Associations - Considere a relação entre o Projeto e o Gerente de Projeto tendo uma associação bidirecional um para um, conforme mostrado na figura abaixo.

Implementação usando 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 - Considere a relação entre Departamento e Funcionário tendo uma associação de um para muitos, conforme mostrado na figura abaixo.

Implementação usando o contêiner de lista 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();
};

Implementando Associações como Classes

Se uma associação tiver alguns atributos associados, ela deve ser implementada usando uma classe separada. Por exemplo, considere a associação um para um entre Funcionário e Projeto, conforme mostrado na figura abaixo.

Implementação de WorksOn usando C ++

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

   public:
   // class methods
};

Implementação de restrições

As restrições nas classes restringem o intervalo e o tipo de valores que os atributos podem assumir. Para implementar restrições, um valor padrão válido é atribuído ao atributo quando um objeto é instanciado a partir da classe. Sempre que o valor é alterado em tempo de execução, é verificado se o valor é válido ou não. Um valor inválido pode ser tratado por uma rotina de tratamento de exceção ou outros métodos.

Example

Considere uma classe Employee em que idade é um atributo que pode ter valores no intervalo de 18 a 60. O código C ++ a seguir o 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;			
   }
};

Implementando gráficos de estado

Existem duas estratégias de implementação alternativas para implementar estados em diagramas de gráficos de estados.

Enumerações dentro da classe

Nessa abordagem, os estados são representados por diferentes valores de um membro de dados (ou conjunto de membros de dados). Os valores são definidos explicitamente por uma enumeração dentro da classe. As transições são representadas por funções de membro que alteram o valor do membro de dados em questão.

Organização de classes em uma hierarquia de generalização

Nessa abordagem, os estados são organizados em uma hierarquia de generalização de uma maneira que podem ser referidos por uma variável de ponteiro comum. A figura a seguir mostra uma transformação do diagrama de gráfico de estado em uma hierarquia de generalização.

Mapeamento de Objetos para Sistema de Banco de Dados

Persistência de objetos

Um aspecto importante do desenvolvimento de sistemas orientados a objetos é a persistência dos dados. Por meio da persistência, os objetos têm vida útil mais longa do que o programa que os criou. Os dados persistentes são salvos no meio de armazenamento secundário de onde podem ser recarregados quando necessário.

Visão geral do RDBMS

Um banco de dados é uma coleção ordenada de dados relacionados.

Um sistema de gerenciamento de banco de dados (DBMS) é uma coleção de software que facilita os processos de definição, criação, armazenamento, manipulação, recuperação, compartilhamento e remoção de dados em bancos de dados.

Em sistemas de gerenciamento de banco de dados relacional (RDBMS), os dados são armazenados como relações ou tabelas, onde cada coluna ou campo representa um atributo e cada linha ou tupla representa um registro de uma instância.

Cada linha é identificada exclusivamente por um conjunto escolhido de atributos mínimos chamados primary key.

UMA foreign key é um atributo que é a chave primária de uma tabela relacionada.

Representando Classes como Tabelas em RDBMS

Para mapear uma classe para uma tabela de banco de dados, cada atributo é representado como um campo na tabela. Um atributo existente (s) é atribuído como uma chave primária ou um campo de ID separado é adicionado como uma chave primária. A classe pode ser particionada horizontalmente ou verticalmente de acordo com os requisitos.

Por exemplo, a classe Circle pode ser convertida em tabela, conforme mostrado na figura abaixo.

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 
);

Mapeamento de associações para tabelas de banco de dados

Associações Um para Um

Para implementar associações 1: 1, a chave primária de qualquer tabela é atribuída como a chave estrangeira da outra tabela. Por exemplo, considere a associação entre Departamento e Gerente -

Comandos SQL para criar as tabelas

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),
);

Associações Um para Muitos

Para implementar associações 1: N, a chave primária da tabela no lado 1 da associação é atribuída como a chave estrangeira da tabela no lado N da associação. Por exemplo, considere a associação entre Departamento e Funcionário -

Comandos SQL para criar as tabelas

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
);

Associações muitos para muitos

Para implementar associações M: N, uma nova relação é criada que representa a associação. Por exemplo, considere a seguinte associação entre Funcionário e Projeto -

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

SQL command to create Works_On association - CRIAR TABELA DE TRABALHOS_ON

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

Mapeamento de herança para tabelas

Para mapear a herança, a chave primária da (s) tabela (s) base é atribuída como a chave primária, bem como a chave estrangeira na (s) tabela (s) derivada (s).

Example