Desenvolvimento - PHP

Reúso em nível de geradores de aplicação como elemento de ganho de produtividade em programação orientada a objeto

Este documento conceitua e utiliza uma metodologia de desenvolvimento de Geradores de Aplicação, procedimento este que possibilita a criação de um exemplo específico para programação orientada a objetos sob C++.

por Bernardino de Jesus Sanches



1 INTRODUÇÃO

1.1 Conceitos

1.1.1 Reúso

Reúso de Software é o aproveitamento de ativos existentes de alguma forma quando do desenvolvimento de produtos de software. Entende-se por ativos os produtos, prontos ou quase prontos, necessários dentro do ciclo de vida do desenvolvimento de software, incluídos os componentes de software, ambiente de teste, projeto e documentação. [Lim, 2002].

1.1.2 Geradores de aplicação

Geradores de aplicação, traduzem especificações em programas. Tais especificações descrevem o problema a ser resolvido pelo programa. Nesse sentido, um gerador de aplicação opera de forma similar a um compilador de linguagem, que traduz informações de alto nível em implementações de baixo nível. [Cleaveland. 1988].

1.1.3 Programação orientada a objetos

Programação orientada a objetos (OOP) parte de uma representação próxima do mundo real para confecção de programas. A idéia geral é que, em vez de especificar estruturas de dados e então escrever programas que operem sobre esses dados, especificam-se propriedades (tanto atributos, quanto operações) de entidades chamadas objetos. Essas entidades possuem três propriedades principais, quais sejam o controle de autorização, a organização dos objetos em taxonomias e o polimorfismo destes.

O controle de autorização estabelece quem pode acessar tais atributos e operações, procedimento que constitui o encapsulamento. Já a organização dos objetos em taxonomias, permite que as classes derivadas herdem propriedades das classes base (herança é o grande mecanismo de reúso). A terceira propriedade importante de objetos é o polimorfismo, observado no exemplo seguinte: o condutor de um veículo varia em especialização, treinamento, etc, conforme este veículo seja uma motocicleta, um carro de passeio, um ônibus. Desse modo, havendo um veículo a ser conduzido, o programa poderia selecionar um condutor adequado, em tempo de execução (sem saber a priore que tipo de veículo estaria na fila). Essa capacidade de escolher a operação adequada em tempo de execução é também chamada de amarração tardia.

1.1.3.1 Herança

Uma das pedras angulares da OOP é a Herança, tendo em vista que permite a criação de classificações hierárquicas. A partir da utilização da herança, é possível criar uma classe geral definidora de características comuns para um conjunto de itens relacionados. Essa classe, por sua vez, pode ser herdada por outras classes mais específicas, cada uma adicionando somente as características que lhe são únicas como classe derivada. [SCHILDT, GUNTLE, 2001]

Herança em OOP viabiliza duas arquiteturas bem distintas:

1) taxonomia - esta primeira arquitetura permite que uma classe ou base, a qual possui um conjunto de atributos e operações, tenha derivações, também chamadas de classes derivadas, Estas últimas, por sua vez, constituem cada qual um nó da taxonomia, herdando atributos e operações de sua classe base (direta ou indireta). Ao passo que se especializam até o seu nível, contribuem geralmente com novos atributos e operações, Essa arquitetura tem como espelho a classificação de espécies, por exemplo a taxonomia dos vegetais em que um nó inicia a classificação das samambaias, outro das orquídeas, e assim por diante;

2) interface - já esta segunda arquitetura possibilita que uma classe base, abstrata, declare a interface de um conjunto de classes. Cada classe derivada realiza as funções definidas pela interface segundo suas características individuais. Note-se que o princípio básico é a delegação de tarefa, dessa forma, a interface opera num paradigma semelhante ao da área de vendas, entre cliente e fábrica). [VOTRE, 1998].

Conseqüentemente, a orientação a objetos não só decompõe sistemas complexos em partes menores correspondentes às entidades do mundo real, como também coloca essas entidades em uma taxonomia de relacionamento de herança denotando o seguinte:

TAXONOMIA

Mamífero (inicial) é um novo nó do reino animal, assim, todo mamífero "É-UM" animal, herdando características. Desse modo, toda baleia "É-UM" mamífero e herda as características deste grupo, dentre elas amamentar filhotes.

Em termos de reúso de código, uma subclasse herda direta ou indiretamente da superclasse todo e qualquer código que seja escrito para esta.

Exemplo de Herança em PHP

<?php

/**
** Esta classe base representa os mamíferos
*/
class Mamifero
{
var $tamanho, $peso, $inteligencia,  $nome;
function mamifero() { }    // Uma forma de construtor em PHP
                           // outra é _Contructor() PHP5
function getInteligencia() {
return $this->inteligencia;
}
function getNome() {
return $this->nome;
}
function setNome($val) {
$this->name=$val;
}
}
class Cachorro extends Mamifero
{
var $dono;
var $nivel;

function Cachorro()
{
$this->inteligencia = "Baixo";
$this->getInteligencia();  // Marca o nível da inteligencia do cachoro como baixa
$this->setNome("Lulu");
}
function temDono(){}
function setDono($val) {
$this->dono=$val;
}
function getDono() {
return $this->dono;
}
}
class Homem extends Mamifero
{
var $casado;

function Homem()
{
$this->inteligencia = "Alto";
$this->getInteligencia();  // Marca o nível da inteligencia do cachoro como baixa
$this->setNome("Jose");
}
function eCasado(){}
function setCasado($val) {
$this->casado=$val;
}
function getCasado() {
return $this->casado;
}
}

?>

Através da palavra chave EXTENDS uma classe derivada herda as características de uma classe base.

No exemplo das subclasses Cachorro e Homem, estas herdam variáveis e métodos da superclasse Mamíferos. INTERFACE

As interfaces definem uma linha entre as especificações do que uma abstração realiza e a implementação do modo como isso é realizado pela abstração. Uma interface é uma coleção de operações utilizadas para especificar um serviço de uma classe ou de um componente.

Também são empregadas para visualizar, especificar, construir e documentar a coesão interna do sistema. Os tipos e funções fornecem um mecanismo para fazer a modelagem da conformação estática e dinâmica da interface em um contexto específico.

Bem estruturada, a interface fornece uma clara separação entre a visão interna de uma abstração e torna possível compreensão e o acesso à abstração sem necessidade de aprofundamento nos detalhes de sua implementação. [G. BOOK; J. RUMBUGH; I. JACOBSON, 2000].

Interface é um tipo especial de definição de classe: uma classe sem código associado a ela, com uma lista de métodos. Esses métodos não têm funcionalidade, mas forçam o programador a defini-los na classe que implementa a interface. O código PHP abaixo exemplifica uma interface e sua implementação:

<?php   // A Interface

interface Motocicleta{

function DaPartida();
function ParaMotor();

}
?>

 <?php                 //  A Implementação

require("interface.php");

class YamahaGoldStar implements Motocicleta{
    
    function DaPartida(){
       return true;
    }
    function ParaMotor(){
       return true;
    }
   function LigaRadio(){
       return true;
    }

}
class Vespa implements Motocicleta{
    
    function DaPartida(){
       return true;
    }
    function ParaMotor(){
       return true;
    }
}
$moto = new YamahaGoldStar;

echo($moto->DaPartida());
$ves = new Vespa;

echo($ves->DaPartida());
?> 

1.1.3.2 Encapsulamento

Encapsulamento separa interface e implementação (inacessível no alcance arquivo - alcances: namespace, arquivo, função, bloco de classe) dando ao projetista liberdade de mudar a representação interna, seja buscando velocidade, robustez ou economia de espaço, sem afetar as aplicações que reúsam o tipo.

Pode substituir busca seqüencial por busca binári ou por leitura em árvore numa lista de nomes, sem que o usuário do tipo altere as chamadas (por exemplo de navegação na lista).

Portanto, encapsular dá muito mais flexibilidade aos tipos abstratos construídos pelas classes. [VOTRE, 1998].

Este mecanismo vincula o código e os dados que ele manipula e mantém ambos seguros contra interferência e abuso externos. Em linguagem orientada a objetos, o código e os dados podem ser combinados de maneira que uma "caixa preta" autocontida seja criada. Quando código e dados são vinculados dessa forma, um objeto é criado. Dessa maneira, um objeto é o dispositivo que suporta o encapsulamento. Dentro de um objeto, código, dados ou ambos podem ser privados a esse objeto ou públicos.

Código ou dados privados são conhecidos e acessíveis somente por outra parte do objeto. Isto é, o código ou os dados privados podem não ser acessados por um pedaço do programa que existe fora do objeto. Quando o código ou os dados são públicos, outras partes de seu programa podem acessá-los, mesmo se eles forem definidos dentro de um objeto. Em geral, as partes públicas de um objeto são utilizadas para fornecer uma interface controlada para os elementos privados do objeto.[SCHILDT, GUNTLE. 2001]

O PHP, em sua versão mais recente a 5.0.0, proporciona três tipos de controle de acesso a variáveis e métodos: Public, Protected and Private.

Public: O métodos ou variáveis podem ser acessados por código de programa fora da classe.
Private: Somente métodos da mesma classe podem acessar métodos ou variáveis da classe.
Protected: Somente métodos da mesma classe ou de classes derivadas podem acessar métodos ou variáveis protegidos (protected).

Abaixo um exemplo para os três tipos de controle de acesso.

<?php
class modelo   // Definição da classe
{
  private $x;
  public function public_modelo() 
{
      print("Eu sou public");
 }

  protected function protected_modelo() 
{
       $this->private_modelo();

 //Ok como estamos na 
// mesma classe podemos acessar 
// métodos privados

         print("Eu sou protected");
  }
  private function private_modelo() 
  {
       $this->x = 3;
       print("Eu sou private");
  }
}  // fim da classe

class modelo2 extends modelo    
          // Define modelo2 que herda modelo
{
     public function display() 
{
    $this->protected_modelo();
    $this->public_modelo();
    	
// $this->private_modelo();   Invalido! a função é private  na classe base
  }
}  // fim da classe derivada

$x = new modelo();    // Construtor PHP
$x->public_modelo();
//$x->protected_modelo();  // Invalido não pode chamar métodos  protected
                           // for a da classe ou classe derivada 
//$x->private_modelo();    //Invalido métoddos private só podem ser 
                           // usados dentro da classe
$x2 = new modelo2();       // Construtor da sub clase
$x2->display();
?>

Recomendação: Variáveis devem ser sempre declaradas como private, acessar variáveis não é uma boa prática de OOP, é sempre melhor prover um método para ler ou atualizar variáveis. 1.1.3.3 Polimorfismo

Polimorfismo é caracterizado pela frase "uma interface, múltiplos métodos". Em termos simples o polimorfismo é o atributo que permite a uma interface ser realizada com uma classe geral de ações. A ação específica selecionada é determinada pela natureza exata da situação. Um exemplo do mundo real de polimorfismo é um termostato. Independentemente de que tipo de forno sua casa tem (gás, óleo, elétrico etc.), o termostato funciona da mesma maneira.[SCHILDT,CUNTLE,2001].

O polimorfismo permite que a mesma mensagem seja tratada por um conjunto de tipos de dados relacionados através de herança. O polimorfismo auxilia a reutilização ao permitir que novos componentes, criados por especialização, sejam utilizados no mesmo ambiente onde já existam os componentes antigos, sem que seja necessário modificar o ambiente de ativação.[COLEMAN , 1996].

Polimorfismo dispensa-nos da missão, muitas vezes impossível, de listar todos os casos e tratá-los um a um. Por exemplo, na classe Figura, especializada como Círculo, Retângulo, Triângulo, Quadrado, Elipse, etc. a operação de rodar a figura de um certo ângulo tem uma solução limpa via polimorfismo. O casamento (entre o objeto e a operação) ocorre durante a execução, pela classe do objeto em foco). Isso recebe também o nome de amarração tardia(delay bind). A grande virtude do polimorfismo é que se criacão um conjunto aberto, no sentido de aceitar mais uma classe sem alterar a parte já realizada. [VOTRE, 1998].

1.1.3.4 Template

Template é uma fôrma de códigos fonte, recebendo um ou mais argumentos, e que generaliza funções ou classes.

Template de classe é uma metaclasse, e define a fôrma de uma classe. Ao se construir um objeto de um template de classe, o compilador cria o código fonte C++ adequado conforme os argumentos e define a classe. [VOTRE, 1998].

Nesse sentido o programa gerador aqui apresentado trabalha a classe padrão e os argumentos como um tamplate.

1.1.3.5 Namespace

Um namespace é uma região declarativa opcionalmente nomeada (pode ser anônima) que cria subdivisões do alcance global. As entidades declaradas dentro dele permitem acesso qualificado eliminando conflitos. Pode ser estendido em vários pontos, em diferentes unidades de tradução. Isso é muito útil, pois em cada ponto pode-se ter um namespace especializado do tamanho justo, segundo a necessidade naquele ponto. [VOTRE, 1998].

Namespace permite particionar o espaço de nomes globais criando uma região declarativa. Em essência, um namespace define um escopo. [SCHILDT, GUNTLE, 2001].

1.2 Justificativa para o trabalho

1.2.1 A grande armadilha do reúso

O reúso, uma das grandes molas do desenvolvimento por objetos, contém uma grande armadilha, que precisa ser gerenciada: como a análise tende a ser por domínio e não por aplicação, o analista é tentado a colocar muito entulho nas classes (na hipótese de que alguém possa precisar um dia).

Por exemplo, ao modelar uma classe pessoa, pode ser tentado a colocar muitos dados sobre o cabelo, ou sobre os olhos, ou os dentes, inúteis em todas as aplicações em que a classe será usada (diz-se que a análise fica aberta à direita, sem fim). [VOTRE, 1998].

1.2.3 O reúso de objetos

Embora todos que trabalham com desenvolvimento orientado a objetos (OO) saibam dos benefícios do reúso de objetos, poucos descobrem a fundamental regra de que o reúso deve estar presente para o sucesso do trabalho com tecnologia de objetos, especialmente quando construímos grandes aplicações. [McClaure, 1996].

1.2.4 Objetos quase prontos

Pelos ensinamentos de Votre e McClure, fica clara a necessidade de reúso dos objetos. Ocorre porém, que em alguns casos esses objetos precisam de uma modificação para serem reusados. Um caso típico são os objetos desenvolvidos para manutenção de tabelas de banco de dados, nesse sentido, o presente artigo traz uma colaboração ao apresentar um gerador de aplicação que transforma uma classe modelo em outra conforme a tabela a ser trabalhada.

2 METODOLOGIA

Para o desenvolvimento deste trabalho seguimos a metodologia de divisão da construção de geradores de aplicação em passos . [Cleaveland, 1988]

  • Reconhecimento do Domínio

  • Definição dos limites do Domínio

  • Definição de um modelo significativo

  • Definição das partes variáveis e invariáveis

  • Definição das especificações de entrada

  • Definição do produto final esperado

  • Implementação do gerador de aplicação

2.1 Reconhecimento do Domínio.

A aplicabilidade do gerador de aplicação criado neste trabalho será um programa escrito em C++ e terá como domínio a criação de programas de computador para a Internet escritos na linguagem PHP (acrônimo recursivo para "Hypertext Preprocessor" - www.php.net) , para manutenção em tabelas de banco de dados relacional.

2.2 Definição dos limites do Domínio.

O limite de atuação do artefato criado é a transformação necessária de uma classe modelo para manutenção em tabelas de banco de dados para atuar com uma determinada estrutura de dados especificada.

2.3 Definição de um modelo significativo.

A verificação do artefato criado será feita através de sua submissão ao interpretador PHP.

2.4 Definição das partes variáveis e invariáveis.

Como partes variáveis do projeto temos: a tabela que será tratada pelo aplicativo gerado, as colunas dessas tabelas, os tipos de dados das colunas e seus valores iniciais. Como partes invariáveis temos toda a tecnologia de uso da classe, bem como seus métodos.

2.5 Definição das especificações de entrada.

Como especificações de entrada temos:

1) As informações relativas à tabela a ser tratada.

2) A classe modelo.

3) Programa em PHP modelo

Tanto a classe quanto os programas foram baseados naqueles constantes do livro Programando em PHP [Soares, 2002].2.6 Definição do produto final esperado.

O produto final esperado é um programa em C++ que, seguindo as especificações de entrada, crie um programa fonte em linguagem PHP que, submetidos ao interpretador de mesmo nome, execute operações em uma determinada tabela de banco de dados com operações de: Seleção , Inclusão, Alteração e Exclusão de linhas.

2.7 Implementação do gerador de aplicação.

A implementação do gerador de aplicação se dará através da execução do programa em C++ compilado.

3 RECURSOS COMPUTACIONAIS NECESSÁRIOS

Para implementação deste trabalho foi considerada como premissa básica a utilização de software livre, com o objetivo de possibilitar que o modelo apresentado seja experimentado por qualquer pessoa interessada, bastando baixar pela Internet os aplicativos necessários. Neste trabalho foram utilizados os seguintes:

* interpretador PHP www.php.net

* Servidor de páginas APACHE (www.apache.org)

* Navegador Netscape (www.netscape.com)

* Compilador C++ (www.gnu.org)

* Sistema operacional Linux processando em PC compatível.

* Gerenciador de banco de dados MYSQL www.mysql.com

4 ESPECIFICAÇÃO DO GERADOR

O gerador foi dividido nas seguintes funções:

a) Pedir ao operador o nome da tabela a ser processada

b) Ler um arquivo texto com as especificações das tabelas existentes, escolher a tabela desejada e guardar os valores em memória

c) Ler um arquivo texto contendo a classe modelo e substituir as partes variáveis conforme dados guardados do arquivo de especificações de tabelas.

d) Ler um arquivo texto com um programa modelo e criar um novo com as devidas alterações das partes variáveis.

5 ARQUIVO DE ESPECIFICAÇÕES DAS TABELAS

O arquivo de especificações das tabelas tem a seguinte estrutura de dados:

Sendo que:

     A = Tipo de linha  ([TB] = Início de tabela
                         [Pk] = Coluna chave primária
     B = Nome da tabela ou coluna
     C = Tipo de dado da coluna
     D = Valor Inicial na criação do registro
     E = Indicador se coluna aparece em consulta

6 PARTES VARIÁVEIS DA CLASSE MODELO

São partes variáveis da classe padrão:

  1. O nome da tabela, identificado pela constante [TB].

  2. O nome das colunas identificado pelas constantes :
    1. [CV] colunas com prefixo de atributos da classe.

    2. [CF] colunas que serão tratadas na função construtora da classe.

    3. [CIA] colunas que farão parte da inclusão de dados em tabelas.

    4. [CIB] colunas que serão valorizadas para a inclusão de linhas em tabelas.

    5. [CA] colunas que serão atualizadas.

    6. [CH] coluna chave primária da tabela.

    7. [CSA] colunas que são objeto de consulta.

    8. [CSB] colunas que são mostradas em consultas.

7 A CLASSE MODELO

Parte do código

<?php

class [TB] {

var $bd;
var $qry;
var $frn;
[CV]

function [TB]($bd) {
$this->bd = $bd;
$this->qry = new consulta($bd);       // Instancia um objeto da clase consulta
$this->frn = new [TB]($bd);
[CF]
}

function incluir() {
if($this->validar()) {
$sql = "INSERT INTO [TB](";
[CIA]
$sql. = ") VALUES(";
[CIB]
$sql. = ")";
$this->qry->executa($sql);
return $this->qry->res;
}
return false;
}

8 O GERADOR DE APLICAÇÃO

#include <stdio.h>
#include <conio.h>
#include <iostream.h>
#include <string.h> 
#include "gera.h"   // header gerador

int main(void){

gerador gg;    // instancia a classe gerador

if(gg.abretabela() &&
   gg.carregatabela()){

 gg.processa_modelo_de_classe();

 gg.processa_modelo_de_programa();

 printf("%s","Processamento executado com   sucesso");

}
else
   printf("%s","Processamento nao executado");

}	 // Fim do main()

Este programa usa um header específico gera.h.

9 CONCLUSÃO

Este trabalho demonstra de forma simples e eficiente que o desenvolvimento de trabalhos repetitivos no desenvolvimento de sistemas, mesmo os de tecnologia avançada como o uso de Internet e orientação a objetos, podem ser tratados através de Geradores de Aplicação. Isso justifica o esforço despendido no desenvolvimento destes geradores.

AGRADECIMENTOS

Ao Dr. Vilmar Pedro Votre pelo incentivo e apoio.

REFERÊNCIAS BIBLIOGRÁFICAS

BOOCH, G., RUMBAUGH, J., JACOBSON, I., UML Guia do Usuário, 2000.

CLEAVELAND ,J.C. Building Application Generators. IEEE Software, 25-33, Jul. 1988

COLEMAN, D., Desenvolvimento Orientado a Objetos, 1996 Editora CAMPUS

LIN, W.C., Rapid A.I. Development , 2002

McCLAURE, C. Experiences from the OO Playing field, 1996

SCHILDT, H., GUNTLE G., Borland C++ Builder "Referência Completa", 2001 Editora Campus

VOTRE, V. P., C++ Explicado e Aplicado, Ed. Independente, 1998

YAROSHENKO, O., Beginner´s Guide to C++ 1999 : WROX Press.

Autor:

Prof. Msc. Bernardino de Jesus Sanches

- Consultor de Informática
- Professor da Universidade de Sorocaba no curso de Sistemas de Informação

Orientador:

Prof. Dr. Prof. Dr. Vilmar Pedro Votre

- Diretor da Faculdade de Computação e Informática da Universidade Mackenzie

Bernardino de Jesus Sanches

Bernardino de Jesus Sanches - Consultor de Informática. Professor da Universidade de Sorocaba no curso de Sistemas de Informação.