29
Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso Frederico Silva Guimarães 04/11/2005 [email protected]

Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

  • Upload
    bardia

  • View
    31

  • Download
    2

Embed Size (px)

DESCRIPTION

Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso. Frederico Silva Guimarães 04/11/2005. [email protected]. Agenda. Motivação e Objetivo Design by Contract Assertivas e Tratamento de Erros Java C/C++ Estudo de Caso Conclusões. - PowerPoint PPT Presentation

Citation preview

Page 1: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Impacto do uso de design by contract no desenvolvimento de

sistemas: um estudo de caso

Frederico Silva Guimarães

04/11/2005

[email protected]

Page 2: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Agenda

• Motivação e Objetivo

• Design by Contract

• Assertivas e Tratamento de Erros– Java

– C/C++

• Estudo de Caso

• Conclusões

Page 3: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Motivação e Objetivo

• Mostrar a experiência que tivemos com o uso de assertivas no desenvolvimento de aplicações comerciais

– Por que Java e C++?

• Pois são largamente utilizadas hoje em dia (e são as linguagem que usamos normalmente)

– Por que essa experiência é importante?

• Mostrar que assertivas têm grande utilidade, mesmo sendo pouco utilizadas

• Mostrar que o uso de assertivas pode fazer a diferença entre o sucesso e o fracasso de um sistema

• Mostrar um caso real de uso de assertivas (o assunto é bastante explorado no meio acadêmico, entretanto no meio comercial o mesmo não acontece)

Page 4: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Design By Contract (DBC)

• Contrato estabelecido entre um construto e seus clientes

– Cliente: garantir condições ou propriedades antes de invocar métodos do construto

– Construto: depois da execução, garantir que condições ou propriedades serão verdadeiras

• Contratos são formado por um conjunto de assertivas que definem o comportamento de um construto e de seus métodos

• No DBC os contratos são executáveis, escritos na própria linguagem de programação, ou em alguma meta-linguagem

• Conjunto de assertivas executáveis

Page 5: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Design by Contract (DBC)

• Um contrato tem três elementos essenciais

– Pré-condições

– Pós-condições

– Invariantes

Page 6: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Assertivas - Java

• Possui uma estrutura própria para o uso de assertivas– assert <expressão booleana> [: <mensagem de erro> ]

• assert value != null;

• assert value instanceof List : values.getClass().getName();

– Quando a expressão booleana é falsa, levanta um AssertionError com a mensagem de erro

– Os asserts normalmente estão desligados, deve-se executar o programa passando um parâmetro extra (-ea) para ligar as assertivas

• java –ea –cp <CLASSPATH> <MAIN CLASS> <ARGS>

– Só disponível a partir da J2SE1.4

• Códigos usando J2SE 1.3 ou menor– Usamos “ifs” e levantamos exceções em caso de falha

• Normalmente IllegalArgumentException e IllegalStateException

Page 7: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Assertivas – C/C++

• Não possui nenhuma estrutura própria para o uso de assertivas

• Usamos “ifs” e chamamos uma função em caso de falha

– Normalmente essa função loga/mostra o erro e aborta o programa

Page 8: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Tratamento de erros - Java

• Padronizado: todos os erros levantam um Throwable

– Exception

• RuntimeException

– Error

• Estrutura try..catch..finally permite pegar um Throwable (um qualquer ou um especifico), e tratar o erro

• O Throwable traz informações sobre o erro:

– Possui um stacktrace mostrando a execução (inclui linhas e métodos) até o momento que o erro ocorreu

– O próprio nome da classe diz, de modo geral, qual foi o erro

• IOException, ArrayIndexOutOfBounds, NullPointerException, OutOfMemoryError

– Possui uma mensagem sobre o erro

• por exemplo o índice inválido no ArrayIndexOutOfBounds

Page 9: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Tratamento de Erros – C/C++

• Os erros fazem:

– O programa “voar”

• Ex: acessar uma variável nula

– ou funcionar de maneira errada

• Ex: acessar um índice inválido de um array, mas ainda assim acessar um espaço válido de memória

– Em ambos os caso, não se tem nenhuma informação sobre o que aconteceu ou onde aconteceu

• Executando em modo debug em algumas IDEs é possível ter uma idéia de onde ocorreu o erro (caso ele não ocorra em uma biblioteca externa), mas ainda é impossível saber que erro ocorreu

Page 10: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Tratamento de Erros – C/C++

• Em C++ existe a estrutura try..catch, que não costuma ser usada

– Sua utilização pode gerar problemas como vazamentos de memória

– A maior parte das bibliotecas (incluindo a std) não fazem uso do throws

• A bibliotecas XercesC faz uso dela

– Erros, como acesso inválido de memória, fazem o programa “voar” ao invés de levantar uma exceção

– Não há padronização:

• Qualquer coisa, até mesmo um int ou string pode ser levantado

• Métodos não são requeridos a declarar os tipos que podem levantar como exceção

Page 11: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Tratamento de Erros – C/C++

• Em C/C++, as funções/métodos costumam ter código de retorno para informar se houve algum erro durante a execução (ao invés de levantar exceções)

Page 12: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Exemplo - Java

public static void copyFile( File sourceFile, File targetFile )throws IOException

{assert sourceFile != null;assert sourceFile.exists() : “File doesn’t exists:

”+sourceFile. getAbsolutePath();assert sourceFile.isFile() : “File is a directory: ”+sourceFile.

getAbsolutePath();assert targetFile != null;...

}

• Caso não utilizássemos assertivas, se algum dos argumentos fosse inválido, o código levantaria uma exceção (NullPointerException, FileNotFoundException, etc..)– Essa exceção nos daria quase as mesmas informações que o

AssertionError

Page 13: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Exemplo - C++

int32 UtiltitesIO::copyFile( QFile* sourceFile, QFile* targetFile ){

if(sourceFile == NULL){

return RET_CODE_SOURCE_FILE_IS_NULL; //1}else if(targetFile == NULL){

return RET_CODE_TARGET_FILE_IS_NULL; //-1}else if(!sourceFile->exists()){

return RET_CODE_SOURCE_FILE_DOES_NOT_EXIST; //3}...return RET_CODE_OK; //0

}

• Caso não houvesse assertivas, se algum dos argumentos fosse inválido, o programa “voaria”

Page 14: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Estudos de casos

• XmlParser

• Gip-View

Page 15: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

XmlParser

• Projeto consistiu em traduzir, de Java para C++, um código que lê e escreve certas classes em xml (cerca de 170 classes)

– Usando bibliotecas Log4cxx e XercesC

• O projeto teve uma equipe de 4 pessoas, e o tempo era escasso

– Houve uma preocupação em traduzir o código rapidamente, para depois testá-lo

• O código foi traduzido sem qualquer código extra em relação a versão Java

• Em especial, não foi colocada nenhuma assertiva ou tratamento de erro além do que existia no código Java (que eram poucos)

Page 16: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

XmlParser

• A tradução foi rápida

– Parte foi automatizada por um programa (em Java) que gerava um esboço do .cpp e do .h a partir dos .java

• Quando começaram os testes, começaram os problemas. Muitos erros, mas que em Java:

– Não aconteciam

• EX: variáveis não inicializadas

– Em C++, elas recebem um valor aleatório

– Em Java, recebem null, 0 ou false;

– Geravam erro de compilação

• Ex: funções que devem retornar valores, mas não retornam valores em todos os caminho possíveis

Page 17: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

XmlParser

double getVal(int code){

switch (code){

case 0:return ...;

case 1:return ...;

case 2:return ...;

case 3:return ...;

}//Cadê o return para code != {0, 1, 2, 3}

}

Page 18: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

XmlParser

• Quando começaram os testes, começaram os problemas. Muitos erros mas que em Java:

– Lançam exceções específicas:

• Acessar uma variável nula

– Em C/C++ o programa “voa”

• Typecast errado

– Em C/C++ o programa vai “voar” (ou não!!!!) quando algum método ou atributo for acessado

• Acesso inválido de memória (índice inválido de um array)

– Em C/C++, o comportamento do programa é indeterminado

Page 19: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

XmlParser

• Gastou-se uma boa parte do projeto (2 meses), apenas na descoberta e tratamento dos erros

• Como normalmente o programa “voava” em funções das bibliotecas externas, era necessário depurar o programa passo a passo, não só para tentar descobrir o que houve, mas também para descobrir aonde ocorreu o erro

– E, normalmente, a real causa era um dos erros citados anteriormente

• Muitos desses erros poderiam ter sido evitados (ou mais facilmente descobertos) se tivessemos inserido assertivas pelo menos em alguns pontos chave do código durante a tradução

Page 20: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Gip-View

• Sistema para inspeção de dutos

– Para comparação:

• O sistema possui cerca de 210 classes

– Dessas, 80-90 foram parcialmente reutilizadas de outro projeto que também foi desenvolvido utilizando assertivas

• O sistema foi desenvolvido por 3 possoas

– 2 delas comuns aos dois projetos

• Foi desenvolvido desde o início com o uso de assertivas

• Em 2 meses, já havia uma versão beta do sistema

• Desses dois messes foram gastos 2-3 semanas em testes e integração com a ferramenta de inspeção

Page 21: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Gip-View

• Em todo o desenvolvimento o programa “voou” apenas 5 vezes (mas caiu várias vezes em assertivas ), apenas 1 vez na mão do cliente (ainda durante a fase de testes)

• Em cada uma dessas vezes que o programa “voou”, o tempo gasto com a descoberta e o conserto do erro foi drasticamente maior do que quando alguma assertiva falhava

• E, normalmente, quando a causa do erro era descoberta, via-se que ele poderia ter sido evitado (ou encontrado mais facilmente) com o uso de assertivas

Page 22: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Gip-View

• O sistema continua em desenvolvimento

– Novas funcionalidades estão sendo adicionadas

• Ele já se encontra em uso a alguns meses e tem se mostrado bastante estável

– Já foi inclusive usado em inspeções reais

Page 23: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Gip-View – Ligando/Desligando Assertivas

• Maneira mais comum: Usando DEFINES

#ifdef GIP_USE_ASSERTS

if ( value == NULL )

{

ClErrorManager::abortProgram(“mensagem“);

} // if

#endif

• Problemas– 8 ou 80: Ou todas as assertivas ou nenhuma

• Seria possível usar vários defines para níveis de assertivas e para classes ou grupos de classes, mas isso dificultaria muito a manutenção e configuração

– Necessidade de re-compilação do código para ligar/desligar assertivas

Page 24: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Gip-View – Ligando/Desligando Assertivas

• Solução: Usar a configuração do log da aplicação como configuração das assertivas

• O log é feito através da biblioteca log4cxx que é uma implementação em C do log4j da Apache

– É configurado em arquivo de configuração (log4j.properties)

– Mensagens logadas podem ser de 5 níveis

• FATAL > ERROR > WARN > INFO > DEBUG

• É possivel desligar todas as mensagens, ou desligar apenas mensagens abaixo de um determinado nível

Page 25: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Gip-View – Ligando/Desligando Assertivas

– Configuração hierarquica dos Loggers

• Cada Logger recebe um nome na criação

– Logger * LOG = Logger::getLogger(<nome>);

• Logger com o nome br.com.gip.Utilities herda configurações de:

– br.com.gip, br.com, br, e do Logger raiz (root)

• Permite facilmente ligar ou desligar um grupo de Loggers ao alterar o nível permitido para as mensagens

Page 26: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Gip-View – Ligando/Desligando Assertivas

• Definimos um nível para cada assertiva

• Se as mensagens daquele nível não estiverem habilitadas no Logger daquela classe, aquela assertiva não é testada

Page 27: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Exemplo

int32 UtiltitesIO::copyFile( QFile* sourceFile, QFile* targetFile ){

if(LOG->isInfoEnabled()){

if(sourceFile == NULL){

return RET_CODE_SOURCE_FILE_IS_NULL; //1}else if(targetFile == NULL){

return RET_CODE_TARGET_FILE_IS_NULL; //-1}else if(LOG->isDebugEnabled()){

if(!sourceFile->exists()){

return RET_CODE_SOURCE_FILE_DOES_NOT_EXIST; //3

}}

}...return COPY_FILE_OK; //0

}

Page 28: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Conclusões

• Em Java é possível ter boas informações sobre os erros ocorridos sem o uso de assertivas (principalmente assertivas simples), no entanto o uso de assertivas pode ajudar ainda mais na descoberta da causa e localização dos erros

• Já em C/C++ o uso de assertivas é uma necessidade, sem elas fica muito difícil/trabalhoso a descoberta da causa e a localização de erros

Page 29: Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso

Frederico Silva Guimarães <[email protected]>

Referências

• DBC: Bertrand Meyer. Applying Design by Contract. In Computer IEEE 25 (10), October 1992, pag 40-51.

• DBC: B. Venners, Contract-Driven Development - A Conversation with Bertrand Meyer, Part III, Artima Software site, March 2004.

• QT: http://www.trolltech.com/products/qt/index.html

• XercesC: http://xml.apache.org/xerces-c/

• Log4j: http://logging.apache.org/log4j/docs/

• Log4cxx: http://logging.apache.org/log4cxx/