aula 03 conceitos e princípios de modularidade 2...
Post on 13-Apr-2018
234 Views
Preview:
TRANSCRIPT
Aula 03Conceitos e Princípios de Modularidade 2
Alessandro Garcia
LES/DI/PUC-Rio
Agosto 2016
Mar 2009 2 /32Alessandro Garcia © LES/DI/PUC-Rio
Avisos
• NOTA 1 – Os horários de monitoria serão nos seguintes
horários:
– 4ª. Feira, 17:00 – 19:00
– 6ª. Feira, 12:00 – 14:00
– Monitor: Leonardo e Alexander
• NOTA 2: A maioria dos exemplos usados nesta aula são
parte do arcabouço de teste disponível no website
• NOTA 3: Reposição do conteúdo da aula passada
Fixando conceitos importantes…
• O que é interface? módulo cliente? módulo servidor?
• Interface provida?
• Interface requerida?
• O que é modulo?
Ago 2009 3 /26Alessandro Garcia © LES - DI/PUC-Rio
4 /32Alessandro Garcia © LES/DI/PUC-Rio
Módulo: definição geral
• De forma geral: é qualquer unidade que podemos tratar de
forma independente em um sistema de software
– “uma unidade lógica de um programa com interface bem
definida que pode ser compilada e testada de forma
independente” [Staa, 2000]
• duas propriedades são de importância: modularidade lógica e
modularidade física
– interface bem definida: provida e requerida
• idealmente: deveria ser totalmente explícita
• objetivos:
– a especificação ou implementação interna é substituível!
– facilitar compreensão, uso, manutenção do módulo
Mar 2009 5 /32Alessandro Garcia © LES/DI/PUC-Rio
Especificação
• Objetivo dessa aula
– Ilustrar conceitos da última aula no contexto de programas C
– Estudar em detalhe o que vêm a ser módulos
– Estudar características da interface de módulos
• Referência básica:
– Capítulo 5 do livro texto
Ago 2009 6 /26Alessandro Garcia © LES - DI/PUC-Rio
Sumário
• Módulos em C:
– separação de interfaces providas e implementação
• Sintaxe de interfaces
• Semântica de interfaces
• Compatibilidade de interfaces
7 /32Alessandro Garcia © LES/DI/PUC-Rio
O que é módularidade lógica?
• Objetivo: cada módulo lógico deveria corresponder a um
módulo físico
• Um módulo lógico deve implementar ou disponibilizar
exatamente um conceito (abstração)
• exatamente: nem mais nem menos características do que as
necessárias e suficientes para realizar plenamente o conceito
• Exemplos
– Pilha
– Árvore
– Aluno
– Professor
– Departamento
– Curso
– Admissão
Mar 2009 8 /32Alessandro Garcia © LES/DI/PUC-Rio
Composiçãointerna de um módulo
FunçãoInterna 1
FunçãoInterna 2
TipoInterno 1
DadoInterno 1
interface de plataforma
Arquivo Janela Metafile
DadoExternado 1
ClasseExternada 1
interfaceencapsulada
Módulo deDefinição
Módulo deImplementação
TipoExternado 1
MóduloA
MóduloB
MóduloX
DadoD
FunçãoF 2
ClasseY
interfacerequerida
FunçãoExternada 1
arquivo header
arquivo *.c file
lista de includes
interface provida
Função
Externada 2Tipo
ExternadoX
Arquivos
Parte de
Declaração
Parte de
Implementação
9 /32Alessandro Garcia © LES/DI/PUC-Rio
O que é um módulo físico?
• Um módulo físico é uma unidade de compilação
– é composto por um ou mais arquivos de texto código fonte
necessários para que possa ser compilado com sucesso
• Exemplo
– O módulo físico de teste específico TestArv.c é composto por:
#include <string.h>
#include "generico.h"
#include "lerparm.h"
#include "tst_espc.h"
#include "arvore.h"
além de TestArv.c
Interface da biblioteca de C
Interface da biblioteca do
arcabouço de apoio ao teste
Interface padrão do módulo de
teste específico
Interface do módulo sob teste
Código fonte do módulo de
teste específico
Items de interface requerida pelo módulo TestArv
Exemplo de Módulo em C
10 /26Alessandro Garcia © LES - DI/PUC-Rio
• Módulo árvore implementa uma estrutura genérica de
árvores binárias
• manipuláveis através de um conjunto limitado de funções
• detalhes internos (organização de dados) não são visíveis para os
usuários da estrutura árvore
Exemplo de Módulo em C
11 /26Alessandro Garcia © LES - DI/PUC-Rio
• Módulo árvore implementa uma estrutura genérica de
árvores binárias
• manipuláveis através de um conjunto limitado de funções
• detalhes internos (organização de dados) não são visíveis para os
usuários da estrutura árvore
Exemplo de Módulo em C
12 /26Alessandro Garcia © LES - DI/PUC-Rio
Discutindo
Estrutura do arquivo ARVORE.h
Estrutura do arquivo ARVORE.c
Investindo em modularidade...
• Por que separar interface da implementação de módulos?
Ago 2009 13 /26Alessandro Garcia © LES - DI/PUC-Rio
Mar 2009 14 /32Alessandro Garcia © LES/DI/PUC-Rio
Módulos em C
• Módulo de declaração ( x.h)
• ou header file
– estabelece a interface externada do módulo
• documentação da interface
• código da interface
– destina-se a
• programadores clientes do módulo
• programadores desenvolvedores ou mantenedores do
correspondente módulo de implementação
• testadores usando teste caixa-preta
• aos redatores da documentação para o usuário
• ao compilador
– ao compilar um módulo cliente
– ao compilar o correspondente módulo de implementação
Mar 2009 15 /32Alessandro Garcia © LES/DI/PUC-Rio
Módulos em C
• Módulo de implementação ( x.c )
– contém
• a inclusão do módulo de declaração próprio
• as inclusões de todos módulos de declaração dos quais é cliente
• especificação e implementação do dados manipulados pelo módulo
– estruturas de dados (e.g. estrutura do nó e cabeça da árvore)
– as declarações de elementos encapsulados
• o código executável do módulo
– código das funções
– destinam-se
• aos programadores desenvolvedores ou mantenedores
– lêem e interagem inúmeras vezes com o texto
• ao compilador
Interface implícita…
Ago 2009 16 /26Alessandro Garcia © LES - DI/PUC-Rio
int ARV_InserirEsquerda( char ValorParm )
{
int CondRet ;
tpNoArvore * pCorr ;
tpNoArvore * pNo ;
/* Tratar vazio, esquerda */
CondRet = CriarNoRaiz( ValorParm ) ;
if ( CondRet != 0 )
{
return 1 ;
} /* if */
/* Criar nó à esquerda de folha */
pCorr = pArvore->pNoCorr ;
if ( pCorr == NULL )
{
return 2 ;
} /* if */
if ( pCorr->pNoEsq == NULL )
{
pNo = CriarNo( ValorParm ) ;
if ( pNo == NULL )
{
return 8 ;
} /* if */
pNo->pNoPai = pCorr ;
pCorr->pNoEsq = pNo ;
pArvore->pNoCorr = pNo ;
return 0 ;
} /* if */
/* Tratar não folha à esquerda */
return 3 ;
} /* Fim função: ARV Adicionar filho à esquerda */
?
?
Possíveis valores de retorno indicando
eventos para a função/módulo cliente
?
?
?
Interface implícita…
Ago 2009 17 /26Alessandro Garcia © LES - DI/PUC-Rio
int ARV_InserirEsquerda( char ValorParm )
{
int CondRet ;
tpNoArvore * pCorr ;
tpNoArvore * pNo ;
/* Tratar vazio, esquerda */
CondRet = CriarNoRaiz( ValorParm ) ;
if ( CondRet != 0 )
{
return 1 ;
} /* if */
/* Criar nó à esquerda de folha */
pCorr = pArvore->pNoCorr ;
if ( pCorr == NULL )
{
return 2 ;
} /* if */
if ( pCorr->pNoEsq == NULL )
{
pNo = CriarNo( ValorParm ) ;
if ( pNo == NULL )
{
return 8 ;
} /* if */
pNo->pNoPai = pCorr ;
pCorr->pNoEsq = pNo ;
pArvore->pNoCorr = pNo ;
return 0 ;
} /* if */
/* Tratar não folha à esquerda */
return 3 ;
} /* Fim função: ARV Adicionar filho à esquerda */
inserção foi OK
estrutura da árvore
está errada
Possíveis valores de retorno indicando
eventos para a função/módulo cliente
não criou nó raiz
faltou memória ao alocar dados
tentou inserir em um nó que não
é folha a esquerda
Passo 2: Indicando os símbolos com…
Ago 2009 18 /26Alessandro Garcia © LES - DI/PUC-Rio
ARV_tpCondRet ARV_InserirEsquerda( char ValorParm )
{
ARV_tpCondRet CondRet ;
tpNoArvore * pCorr ;
tpNoArvore * pNo ;
/* Tratar vazio, esquerda */
CondRet = CriarNoRaiz( ValorParm ) ;
if ( CondRet != ARV_CondRetNaoCriouRaiz )
{
return CondRet ;
} /* if */
/* Criar nó à esquerda de folha */
pCorr = pArvore->pNoCorr ;
if ( pCorr == NULL )
{
return ARV_CondRetErroEstrutura ;
} /* if */
if ( pCorr->pNoEsq == NULL )
{
pNo = CriarNo( ValorParm ) ;
if ( pNo == NULL )
{
return ARV_CondRetFaltouMemoria ;
} /* if */
pNo->pNoPai = pCorr ;
pCorr->pNoEsq = pNo ;
pArvore->pNoCorr = pNo ;
return ARV_CondRetOK ;
} /* if */
/* Tratar não folha à esquerda */
return ARV_CondRetNaoEhFolha ;
} /* Fim função: ARV Adicionar filho à esquerda */
… significados dos
eventos
Mar 2009 19 /32Alessandro Garcia © LES/DI/PUC-Rio
Passo 1: Tipo com lista de eventos/***********************************************************************
*$TC Tipo de dados: ARV Condicoes de retorno
************************************************************************/
typedef enum {
ARV_CondRetOK = 0 ,
/* Executou correto */
ARV_CondRetNaoCriouRaiz = 1 ,
/* Não criou nó raiz */
ARV_CondRetErroEstrutura = 2 ,
/* Estrutura da árvore está errada */
ARV_CondRetNaoEhFolha = 3 ,
/* Não é folha relativa à direção de inserção desejada */
ARV_CondRetArvoreNaoExiste = 4 ,
/* Árvore não existe */
ARV_CondRetArvoreVazia = 5 ,
/* Árvore está vazia */
ARV_CondRetNohEhRaiz = 6 ,
/* Nó corrente é raiz */
ARV_CondRetNaoPossuiFilho = 7 ,
/* Nó corrente não possui filho na direção desejada */
ARV_CondRetFaltouMemoria = 8
/* Faltou memória ao alocar dados */
} ARV_tpCondRet ;
Evento normal
Eventos excepcionais
Passo 2: Indicando os símbolos com…
Ago 2009 20 /26Alessandro Garcia © LES - DI/PUC-Rio
ARV_tpCondRet ARV_InserirEsquerda( char ValorParm )
{
ARV_tpCondRet CondRet ;
tpNoArvore * pCorr ;
tpNoArvore * pNo ;
/* Tratar vazio, esquerda */
CondRet = CriarNoRaiz( ValorParm ) ;
if ( CondRet != ARV_CondRetNaoCriouRaiz )
{
return CondRet ;
} /* if */
/* Criar nó à esquerda de folha */
pCorr = pArvore->pNoCorr ;
if ( pCorr == NULL )
{
return ARV_CondRetErroEstrutura ;
} /* if */
if ( pCorr->pNoEsq == NULL )
{
pNo = CriarNo( ValorParm ) ;
if ( pNo == NULL )
{
return ARV_CondRetFaltouMemoria ;
} /* if */
pNo->pNoPai = pCorr ;
pCorr->pNoEsq = pNo ;
pArvore->pNoCorr = pNo ;
return ARV_CondRetOK ;
} /* if */
/* Tratar não folha à esquerda */
return ARV_CondRetNaoEhFolha ;
} /* Fim função: ARV Adicionar filho à esquerda */
… significados dos
eventos
Vide exemplo de código distribuído
• O que falta nas declarações dos arquivos do
modulo ARVORE?
• Onde isso deveria estar declarado?
21 /26Alessandro Garcia © LES - DI/PUC-Rio
Tornando eventos explícitos na interface…
Ago 2009 22 /26Alessandro Garcia © LES - DI/PUC-Rio
/*******************************************************************
****
*
* $FC Função: ARV Adicionar filho à esquerda
*
* $EP Parâmetros
* $P ValorParm - valor a ser inserido no novo nó.
*
* $FV Valor retornado
* ARV_CondRetOK
* ARV_CondRetNaoCriouRaiz
* ARV_CondRetErroEstrutura
* ARV_CondRetFaltouMemoria
* ARV_CondRetNaoEhFolha - caso não seja folha para a
esquerda
*
********************************************************************
***/
ARV_tpCondRet ARV_InserirEsquerda( char ValorParm ) ;
Aula 03Conceitos e Princípios de Modularidade 2
Alessandro Garcia
LES/DI/PUC-Rio
Março 2016
Mar 2009 24 /32Alessandro Garcia © LES/DI/PUC-Rio
Por que investir em modularidade?
– … objetivo: implementar código com melhor facilidade de
entendimento, manutenibilidade, reusabilidade, robustez…
código não-estruturado implica em
complexidade adicional e efeitos negativos
em atributos de qualidade
código estruturado é
Investimento
aumenta o tempo de vida
do software
25 /26Alessandro Garcia © LES - DI/PUC-Rio
RELEMBRANDO: O que é uma interface?
• Interfaces são os elementos (as coisas) através das quais os
módulos (ou funções) interagem
– uma interface define os elementos visíveis necessários para a
comunicação
– outro exemplo de “interface” em software é: janelas para o
usuário
• Para que haja comunicação, o “cliente” e o “servidor”
precisam ter um vocabulário (idioma) comum
– Uma função em um programa C:
• “função cliente” precisa conhecer:
– nome da função
– tipo de dado utilizado pela função
– etc...
Ago 2009 26 /26Alessandro Garcia © LES - DI/PUC-Rio
Interface, sintaxe
• Sintaxe: é o formato de cada item da interface
– Tipos e regras aplicáveis aos itens intercambiados
• Elementos da sintaxe:
– identificador (nome)
– codificação da representação física dos valores, exemplos:
• inteiro, flutuante, string terminado com zero, etc...
– ordem dos elementos intercambiados (parâmetros)
– codificação de valores: determinam como devem ser redigidos
valores de determinado tipo, exemplos:
• sintaxe dos prefixos dos nomes do arquivos: “IBM_[data]_*.txt
• número de matrícula com dígito verificador: 00000-0
• elementos da data separados por hífen: 00-00-0000
Ago 2009 27 /26Alessandro Garcia © LES - DI/PUC-Rio
Interface, semântica
• Semântica: é o significado de cada item da interface
• Exemplos:
– O parâmetro float Veloc representa velocidade em m/s
• não basta saber que é float, é necessário também saber que o
parâmetro é velocidade e que esta é medida em m(etros)/s(egs)
– O string é um nome de pessoa
• não basta saber que é string, é necessário também saber que
denota o nome de uma pessoa...
• ... e que satisfaz determinadas características, ex.: ressalta o nome
ou apelido usual ao se comunicar com a pessoa
Ago 2009 28 /26Alessandro Garcia © LES - DI/PUC-Rio
Quando a semântica não está clara
• Satélite para monitorar o clima em Marte
• Sonda enviada pela NASA em 1999
Sintaxe vs. Semântica da Interface
• int CadastrarNota ( int id, int id2, int id3, float n )
Ago 2009 29 /26Alessandro Garcia © LES - DI/PUC-Rio
Sintaxe[0.00 a 10.00]
Sintaxe vs. Semântica da Interface
• int CadastrarNota ( int id, int id2, int id3, float n )
Ago 2009 30 /26Alessandro Garcia © LES - DI/PUC-Rio
Sintaxe[0.00 a 10.00]
Para garantir a corretude de cada conexão,
basta o programador checar a compatibilidade sintática
da chamada e o protótipo da função?
Sintaxe vs. Semântica da Interface
• int CadastrarNota ( int id, int id2, int id3, float n )
Ago 2009 31 /26Alessandro Garcia © LES - DI/PUC-Rio
Semântica
Condição de retorno
Matricula do Aluno
Ident. Turma Ident. Disciplina
Nota Final
Cadastrar Nota Final de
um Aluno em uma Disciplina/Turma da
Graduação
Exemplo: int i = CadastrarNota ( 0788888, 1301, 2, 9.0);
conexão sintaticamente correta, mas semanticamente errada
Mar 2009 32 /26Alessandro Garcia © LES - DI/PUC-Rio
Corretude de composição via interface
• Infelizmente a maior parte das linguagens não é capaz de
verificar a corretude total da conexão via interface
– verificam somente a corretude sintática (parcialmente )
• Soluções parciais para esse problema
– uso de nomes suficientemente explícitos
NomeAluno = NomeDisciplina ;
VelocidadeMedia = DistanciaPercorrida ;
• podem rapidamente ser identificados como um erro
– comentários
float VelocidadeMedia ;
/* medida em m/s */
Mar 2009 33 /26Alessandro Garcia © LES - DI/PUC-Rio
Verificação da corretude
• Contrato básico
– O cliente deve assegurar a validade sintática e semântica dos
dados transmitidos ao servidor
– O servidor deve assegurar a validade sintática e semântica dos
dados retornados ao cliente
• Desenvolvimento dirigido por contratos: para cada função especificam-se as condições
de entrada e de saída, bem como as condições do estado do módulo (invariante).
Será visto mais adiante: assertivas. Referência complementar: Meyer, B.; “Applying
Design by Contract”; IEEE Computer 25(10); Los Alamitos, CA: IEEE Computer
Society; 1992; pags 40-51
Mar 2009 34 /26Alessandro Garcia © LES - DI/PUC-Rio
Corretude de composição via interface
• Usualmente se requer
– a sintaxe e a semântica da interface do cliente iguais às do
servidor
– uma forma de assegurar isso: ter uma única cópia da
declaração da interface que serve tanto para cliente como para
servidor
• Em diversas ocasiões pode-se usar uma forma mais branda
– a sintaxe e a semântica da interface do cliente implicam a
sintaxe e a semântica da interface do servidor
– observação: para dados de retornados vale o reverso, ou seja,
os dados retornados pelo servidor implicam a sintaxe e
semântica esperadas pelo cliente
Mar 2009 35 /26Alessandro Garcia © LES - DI/PUC-Rio
Pode-se confiar na observância do contrato?
• Não para todos os dados de procedência duvidosa
– dados fornecidos pelo usuário
– dados fornecidos por clientes ou retornados por servidores de
qualidade duvidosa
• Não para dados que ofereçam risco elevado caso estejam
errados
– dados a serem gravados em bases de dados
– . . .
Mar 2009 36 /26Alessandro Garcia © LES - DI/PUC-Rio
Necessidade da validação
• O desenvolvedor não escapa de tratar os casos de dados
não válidos
– ou especifica que não pode receber tais valores
• informa explicitamente que o resultado será indefinido se receber
um dado não válido
• neste caso o programador cliente arcará com as conseqüências da
não observância das restrições
– ou especifica o que acontece se receber tal dado
• neste caso o programador cliente precisa tratar as condições de
retorno indicadoras de anomalia ou outras formas de interceptação
de dados errados (exceções, cancelamento da execução). Exemplo:
• a função malloc( ) pode retornar NULL caso não consiga alocar o
espaço solicitado. O programador cliente de malloc deve sempre
verificar se o retorno foi ou não NULL
– jamais vale assumir que malloc nunca retornará NULL
• o mesmo argumento vale para a função fopen( ) e outras
Mar 2009 37 /26Alessandro Garcia © LES - DI/PUC-Rio
Pode-se confiar na observância do contrato?
• Sempre que não confiar é necessário redigir código de
verificação da corretude dos dados
– pode-se assegurar que os dados estão consistentes com o
estado “do mundo” que simulam? Exemplo:
– Nota válida: 0 <= Nota <= 10,
• se digitar 5 para a nota do João isto estará necessariamente
correto?
– se ele tiver tirado 8? Será corrigido?
– e se ele tiver tirado 3? Será corrigido?
– Exemplos de soluções parciais, reduzem mas não zeram o risco
• dupla digitação por pessoas diferentes
• uso de dígitos verificadores
• uso de controles de soma (“sum-check”)
38 / 30 LES/DI/PUC-Rio
Lembretes
• Monitoria
– 3ª. Feira, 17:00 – 19:00
– 6ª. Feira, 15:00 – 17:00
– Monitor: Alexander
– 9º. Andar predio Pe Leonel Franca
Aula 03Conceitos e Princípios de Modularidade 2
Alessandro Garcia
LES/DI/PUC-Rio
Fevereiro 2014
top related