O Projeto:
O projeto tem por objetivo a reprogramação e aperfeiçoamento da ferramenta ProSpec, uma ferramenta CASE para desenvolvimento de aplicações cliente/servidor, capaz de gerar código em C++ a partir de especificações dos requisitos das aplicações a ser desenvolvidas.
Meu estágio baseou-se no estudo do sistema VRC atual, utilizado pela Itautec. Como o VRC atualmente é uma linguagem de comandos, toda a análise pode ser feita por um analisador léxico, a menos de um comando introduzido pelo Prof. V.W.Setzer como extensão do VRC.
Continuamos um
trabalho recente do Prof. Setzer, que começou a fazer a análise
das planilhas de
especificação usando o FLEX; atualmente estamos analisando
todos os comandos do VRC.
Com alguns exemplos de planilhas e seus respectivos códigos
gerados, introduzimos comandos em C++ para gerar código para as
planilhas, além de detecção e reportagem de erros léxicos
durante a análise.
Paralelamente, integramos o analisador léxico com o analisador sintático ESLL(1) desenvolvido pelo Prof. Setzer e por Joaquim Campos Salles como pacote de análise sintática. O analisador sintático encarregou-se de verificar e efetuar recuperação de erro de expressões no comando introduzido pelo prof.Setzer.
Através de um trabalho realizado pelo prof.Setzer e implementado inicialmente por Alvaro Motta em Delphi, o dicionário de dados foi re-estruturado para o ambiente gráfico (Windows). Implementei uma classe em C++ para conexão remota ao banco de dados (ACCESS) utilizando driver de comunicação com base de dados ODBC.
Após integração do SintaxGraphDesigner com o analisador sintático ESLL(1), iniciamos um estudo para geração automática do analisador léxico a partir de especificações de uma aplicação definida pelo usuário.
Histórico de desenvolvimento e utilização no mercado:
A ferramenta e método VRC originou-se de um sistema desenvolvido por E.Marussi na segunda metade da década de 1980, denominado LDT. Na época, utilizava-se apenas main-frames, cujos CPD`s dedicavam seu trabalho à manutenção de sistemas desenvolvidos. A ferramenta VRC fez com que o CPD dirigido por Marussi na Microlite passasse a dedicar cerca de 7 % de seus custos à manutenção de sistemas, e 93 % ao desenvolvimento de novos sistemas.
Em 1988 foi feita uma pesquisa no IME-USP que resultou numa implementação de um sistema denominado I-M-E, cuja implementação gerava código Pascal. Neste trabalho, foi feita uma resenha exaustiva sobre Tabelas de Decisão. Um método de dedução de estruturas de processos baseados nas estruturas dos dados de entrada, válido para o LDT, o I-M-E ou o VRC foi publicado em [LDT].
Em 1987, a Itautec associou-se a Marussi para utilização do LDT no desenvolvimento dos sistemas internos da empresa, na época baseados em main-frame, gerando código em Cobol.
No início dos anos 90, a Itautec migrou seu ambiente de produção de main-frames para computador AS/400 fabricado pela Itec, associado da Itautec, ocasião em que o LDT mostrou-se de extrema valia pois possibilitou que todos os sistemas internos da empresa desenvolvidos para main-frame fossem integralmente reaproveitados na plataforma AS/400 sem nenhuma reprogramação.
Em 1994, a Itautec decidiu investir no desenvolvimento de um gerador de código C++ para o LDT adequando-o a arquitetura Cliente /Servidor. A ferramenta resultante desse desenvolvimento recebeu o nome de Sistema VRC e passou a ser usada no desenvolvimento de todos os aplicativos comercializados pela empresa, além dos próprios sistemas internos.
O IPT, em parceria com a Itautec desde 1996, vem utilizando o VRC como única ferramenta empregada no desenvolvimento do projeto ACT - Automação Comercial Total, um complexo sistema para automação de retaguarda de estabelecimentos de distribuição (varejo e atacado), sendo responsável por mais de 1,6 milhões de linhas de código em C++ , proporcionando excelente ganho de produtividade se comparado com valores médios publicados de custo por linha de código (Custo LOC).
Melhorias previstas para o ProSpec:
Estão previstas as seguintes etapas para o projeto total:
- Reprogramação do gerador de código a partir das planilhas atuais
- Desenvolvimento de um interpretador de descrições de processo, possibilitando o teste de descrições sem a necessidade dos passos de geração de código em C++, sua compilação e execução
- Geração de código para depuração em tempo de execução, referenciando as descrições dos processos
- Expansão dos comandos de acesso aos banco de dados, com referência às ligações entre tabelas em lugar das equações de junção ("join"), eliminando a necessidade de uso de SQL
- Expansão de comandos com sintaxe limitada
- Criação de interface gráfica para descrição de processos a partir de padrões gráficos para cada comando da linguagem e uso das variáveis e estruturas dos bancos de dados graficamente a partir do dicionário de dados
- Elevação dos processos a nível de classes e orientação a objetos, com herança e polimorfismos, possibilitando a criação de bibliotecas reutilizáveis de descrições de processos
- Expansão dos comandos de acesso ao banco de dados a fim de permitir que comandos de acesso referenciem tabelas explicitamente, sem necessidade de criação e compilação prévias de visões de usuários
- Introdução de especificações de paralelismo decorrentes do novo paradigma de especificação de processos
- Substituição da interface atual de manipulação dos itens do dicionário de dados de tipo texto para interface padrão Windows
- Desenvolvimento de interface gráfica para projeto do banco de dados a nível do Modelo de Entidades e Relacionamentos, possibilitando a visão do banco de dados nesse nível
- Alteração do gerador de código para otimizar o código gerado pelas Tabelas de Decisão; adicionar otimizações locais e globais
Estas alterações têm por finalidade tornar a utilização do VRC mais simples, aumentando ao mesmo tempo seu poder de expressão, além de otimizar o código gerado, resultando menor tempo para desenvolvimento de sistemas e programas mais eficientes.
O VRC abrange quatro elementos fundamentais:
1) Método VRC de projeto de sistemas.
2) Linguagem de especifiacação de processos (Linguagem VRC)
3) Ambiente de desenvolvimento
4) Ambiente de execução.
1. Método VRC
O método de projeto de sistemas consiste na especificação de passos que devem ser seguidos no projeto, dividindo em processos e subprocessos.
Ela é adaptada às peculiaridades de especificaçõe de processos da linguagem VRC, incluindo um padrão de nomenclatura dos diversos componentes de uma aplicação, inclusive para modelos de referência, para certos processamentos padronizados que ocorrem com grande frequência. <voltar ao topo>
2. Linguagem VRC
Impõe novo paradigma de contrução de algorimos e portanto de programas, o Paradigma de Super-Estruturação, que propõe o tratamento de um conjunto abstrato de dados por um processo ou sub-processo, descrito em muito alto nível as especificações dadas pelo usuário em planilhas, que são posteriormente lidas pelo compilador para gerar o programa-objeto.
As planilhas consistem de três etapas:
I - Inicialização: executada uma única vez, para todo o conjunto abstrato, antes de iniciar a execução repetitiva das operações sobre cada um de seus elementos
P - Principal: opera sobre cada um dos elementos do conjunto abstrato, inclusive sua leitura e demais operações que são feitas
F - Finalização: opera sobre o conjunto abstrato como um todo, de forma análoga a etapa inicial, exceto que a sua execução é efetivada após o tratamento de todos os elementos do conjunto abstrato
Cada uma destas etapas pode estar dividida em três fases consecutivas:
L - Leitura: obtenção de dados a serem processados, tanto de arquivos fisicos como de tabelas e sequencias. Trata de escolher dentro do conjunto qual o elemento a ser tratado num determinado momento, independente de qual o suporte fisico em que esta o conjunto
D - Decisão: descrição das condições a serem testadas sobre os dados selecionados, o que é feito por meio de Tabelas de Decisão [I-M-E] e de Consistência
T - Transformação: fase de execução das operações escolhidas na fase anterior sobre os dados selecionados
As divisões são fisicamente separadas e executadas nesta ordem. Assim, a especificação de um processo ou sub-processo neste método é uma sequência de instruções que obedecem a execução das etapas inicial, principal e final, e a execução de cada uma dessas etapas produz a execução das fases de seleção , escolha e transformação, também nesta ordem. <voltar ao topo>
3. Ambiente de Desenvolvimento
Dicionário de Dados: Centraliza descrição dos dados que não fazem parte dos programas como nas linguagens algorítmicas. Impõe nomenclatura padronizada, garantindo consistência, aumentando a legitibilidade e compreensão da especificação dos processos e permitindo mudanças rápidas de formato.
Gerador de Código: Varre as especificações de processos, usando Dicionário de Dados e descrição das plataformas, para geração de código C++ para a plataforma de destino.
4. Ambiente de Execução
Código executável compilado a partir do programa C++ produzido pelo gerador de código, utilizando conjunto de componentes reutilizáveis chamados dinamicamente pelos códigos executáves.
Os componentes reutilizáveis permitem independência em relação à plataforma de execução que chega ao nível de uniformizar a descrição de processos tanto para as máquinas servidoras como para as máquinas clientes: usando-se o VRC, o desenvolvedor não precisa levar em conta as diferenças existentes entre os dois tipos de plataformas.
5. Consequências da especificação de processos através da linguagem VRC:
* A possibilidade de introduzir rapidamente alterações posteriores nos programas, uma vez que as alterações são feitas nas descrições dos processos, e não nos códigos gerados, bastando apenas a re-compilação dessas descrições gerando-se novos programas. Assim trabalha-se apenas no alto nivel da especificação de processos em VRC, diminuindo drasticamente o custo de manutenção.
* A independência em relação a plataforma (hardware, sistema operacional, sistema gerenciador de banco de dados) onde o programa gerado deve ser processado. A descrição dos processos não é alterada; apenas muda-se o gerador de codigo e o ambiente de execução.
* Alto nível de especificação da linguagem, diminuindo a necessidade de programadores com conhecimentos dos detalhes dessas plataformas.
* A independência do VRC em relação ao tipo de plataforma (cliente ou servidor) permite a geração de várias versões de distribuição coexistente sem custao adicional, permitindo o teste e comparacao de diferentes configurações.
Planilhas de Descrição
Estrutura:
* Descrição geral do programa
* Subdivisão em etapas
* Telas empregadas na entrada de dados(fase de leitura)
* Arquivos lidos(fase de leitura)
* Tabela de decisão e consistência(fase de decisao)
* Rotinas de transformação (fase de transformação)
* Mmensagens de consistência (especificadas junto com a fase final)
(Atualmente, o VRC não utiliza tabelas de consistência e em consequência, nem as tabelas de mensagens de consistência.)
Mecanismo adequado para especificação de decisões de um problema, desde o projeto até sua documentação.
Histórico:
1957 ~ 1960: primeiros trabalhos de Tabelas de Decisão (apesar de já serem conhecidas e utilizadas largamente fora do ambiente de processamento de dados). O uso desta técnica nesta área teve inicio com o Projeto de Sistemas Integrados da General Eletric em novembro de 1957 que tinha como objetivo acompanhar e controlar o processo de produção de um produto desde a recepção do pedido ate o acabamento final . Devido a dificuldade em expressar a lógica complexa do problema através de mecanismos até então utilizados, o grupo responsável desenvolveu as tabelas de decisao e um processo computacional para automatizar a tradução da tabela, implementado de interpretadores.
1961 e 1962: desenvolvimento em processadores de Tabelas de Decisão
1966: desenvolvimento de pré-processadores.
Estrutura:
Sets (Para cada letra, relaciona uma expressão regular) |
||||
Conditions (Descrição das condições) |
||||
Actions (Para cada coluna, as ações associadas, enumeradas por ordem de execução) |
2. Rotinas de Transformação
Executa comandos sequencialmente. Nestas rotinas é possível utilizar comandos em linguagem de alto nível para execução condicional de dados ("if") e repetição de uma subsequência de comandos com número de repetições bem definidas("for"), alteração de valores do dicionário de dados, entre outros.
Um Exemplo de Planilha
|
![]() |
Código Gerado:
Referente ao cabeçalho a área de trabalho:
//Inicializações de
classes e variáveis de acordo com especificações da planilha e
ambiente
....
// Layout's das areas de
trabalho
VRLayOut *cVRLPCS730;
VRLayOut *cVRLPCS73W;
typedef struct {
struct {
char CD_EMP[3];
char CD_LJ[4];
char ID_PROD[13];
char CD_T_PEDI[1];
char CDTOPRCARQ[1];
char CD_FRMAPRC[1];
char D_INILAPRC[8];
char D_FNL_APRC[8];
char CDTETBORIG[1];
char ID_PEDIPAI[6];
char CD_T_EMB[4];
} ENTRADA;
struct {
char Q_PRODPEDI[9];
char V_LQDO_UNT[13];
char V_LQDO[13];
char V_TT_CMPD[15];
char Q_TT_CMPD[12];
char CD_RTNO[1];
} SAIDA;
char Q_BNFCRCBR[12];
char QTTBNFCRCB[12];
} wkPCS730;
typedef struct {
struct {
struct {
char CD_EMP[3];
........
//Definição de funções para alocação de memória, destrutores, etc.
Referente à Tabela de Decisão:
BOOL PASCAL
CVrcPCS730::DECIDE_PF( void )
{
if( fOk && ( ( ( IGUAL(
lpParams->ENTRADA.CDTOPRCARQ, 0, 1, 0, "A", 4, 1, 0
) ) )
&& ( ( IGUAL( lpParams->ENTRADA.CD_FRMAPRC, 0, 1, 0,
"1", 4, 1, 0 ) ) ) ) )
{
fOk = SEQF( fOk, LIMPAR_CAMPOS );
fOk = SEQF( fOk, BUSCAR_PED_PEPDA5
);
fOk = SEQF( fOk, ERRO_NAO_EXISTE
);
}
else if( fOk && ( ( ( IGUAL(
lpParams->ENTRADA.CDTOPRCARQ, 0, 1, 0, "A", 4, 1, 0
) ) )
&& ( ( IGUAL( lpParams->ENTRADA.CD_FRMAPRC, 0, 1, 0,
"2", 4, 1, 0 ) ) ) ) )
{
fOk = SEQF( fOk, LIMPAR_CAMPOS );
fOk = SEQF( fOk, BUSCAR_PED_PEPDA3
);
fOk = SEQF( fOk, ERRO_NAO_EXISTE
);
}
else if( fOk && ( ( ( IGUAL(
lpParams->ENTRADA.CDTOPRCARQ, 0, 1, 0, "B", 4, 1, 0
) ) ) ) )
{
fOk = SEQF( fOk, LE_PEAGR2 );
fOk = SEQF( fOk, LE_PEPED1 );
}
if( !fOk )
return FALSE;
return TRUE;
}
Referente às Rotinas de Transformação e Transporte de Dados
BOOL PASCAL
CVrcPCS730::COMPARAR_QTDE( void )
{
MOVE( lpParams->SAIDA.V_LQDO, 1, 13, 2, dCalcTmp, 2, 19,
6 );
dCalcTmp = CALCULA( 2, lpParams->SAIDA.Q_PRODPEDI, 1,
15, 2
,"- ",
lpParams->SAIDA.Q_PRODATND, 1, 13, 2 );
MOVE( SIS_N_DIFF, 1, 15, 2, dCalcTmp, 2, 19, 6 );
if( fOk && (
( ( ( MENOR( PEPED1->D_EMIS, 1, 8, 0,
lpParams->ENTRADA.D_INILAPRC, 1, 8, 0 ) ) ||
( MAIOR(
PEPED1->D_EMIS, 1, 8, 0, lpParams->ENTRADA.D_FNL_APRC, 1,
8, 0 ) ) ) )
{
MOVE( lpParams->SAIDA.CD_RTNO, 1, 13, 2,
"T", 1, 13, 2 );
return TRUE;
}
MOVE( lpParams->SAIDA.V_LQDO_UNT, 1, 13, 2,
"P", 1, 13, 2 );
{
MOVE(X1, SIS-N-TESTE, 8, 2);
MOVE(X2, SIS-N-DIFF, 5, 2);
MOVE(X3, PEPDA1->TIPOS.ORDEM, 5, 2);
MOVE(X4, -X3);
MOVE(X5, X4 * X2);
MOVE(X1, X1 - X5);
MOVE( lpParams->SAIDA.Q_PRODPEDI, 1, 9, 3, X1 );
}
if( !fOk )
return FALSE;
return TRUE;
}
.......
Código gerado automaticamente pelo Analisador Léxico: finalizações relacionadas aos dados
int PASCAL
CVrcPCS730::VInd( int iIndice, int iLimite )
{
int iResult;
iResult = pAplicacao->ValidaIndice( iIndice,
iLimite );
return( iResult );
}
void PASCAL
CVrcPCS730::InicioProcesso(void FAR* lpvAreaIn,
void FAR* lpvAreaOut,
void FAR* lpvAreaCom,
void FAR* lpvAreaExc )
{
fOk = TRUE;
InfoResultCmd.lpInfoErro =
&InfoResultCmd.InfoErro;
PreparaArea( lpParams, sizeof( wkPCS730 ), NULL, 0
);
pAplicacao->ObjetoAcionado( lpInfoResultCmd,
lpvAreaIn, lpvAreaOut, lpvAreaCom, lpvAreaExc, lpInfoEvento );
InfoResultCmd.hResultado=pAplicacao->BuscaArquivoODBC(
"PEPDA5", 0, sPEPDA5, &pInfPEPDA5, lpInfoResultCmd
);
assert( !IsBadReadPtr( pInfPEPDA5, sizeof( CVrcODBC
)));
InfoResultCmd.hResultado=pAplicacao->BuscaArquivoODBC(
"PEPDA3", 0, sPEPDA3, &pInfPEPDA3, lpInfoResultCmd
);
assert( !IsBadReadPtr( pInfPEPDA3, sizeof( CVrcODBC
)));
InfoResultCmd.hResultado=pAplicacao->BuscaArquivoODBC(
"PEPED1", 0, sPEPED1, &pInfPEPED1, lpInfoResultCmd
);
assert( !IsBadReadPtr( pInfPEPED1, sizeof( CVrcODBC
)));
InfoResultCmd.hResultado=pAplicacao->BuscaArquivoODBC(
"PEAGR2", 0, sPEAGR2, &pInfPEAGR2, lpInfoResultCmd
);
assert( !IsBadReadPtr( pInfPEAGR2, sizeof( CVrcODBC
)));
InfoResultCmd.hResultado=pAplicacao->BuscaArquivoODBC(
"PEPDA1", 0, sPEPDA1, &pInfPEPDA1, lpInfoResultCmd
);
assert( !IsBadReadPtr( pInfPEPDA1, sizeof( CVrcODBC
)));
}
void PASCAL
CVrcPCS730::FimProcesso( void )
{
pInfPEPDA5->FechaArquivoGCODBC( lpInfoResultCmd
);
pInfPEPDA3->FechaArquivoGCODBC(
lpInfoResultCmd );
pInfPEPED1->FechaArquivoGCODBC(
lpInfoResultCmd );
pInfPEAGR2->FechaArquivoGCODBC(
lpInfoResultCmd );
pInfPEPDA1->FechaArquivoGCODBC( lpInfoResultCmd
);
}