1 / 29

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. kid@teccomm.les.inf.puc-rio.br. Agenda. Motivação e Objetivo Design by Contract Assertivas e Tratamento de Erros Java C/C++ Estudo de Caso Conclusões.

bardia
Download Presentation

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

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Impacto do uso de design by contract no desenvolvimento de sistemas: um estudo de caso Frederico Silva Guimarães 04/11/2005 kid@teccomm.les.inf.puc-rio.br

  2. Agenda • Motivação e Objetivo • Design by Contract • Assertivas e Tratamento de Erros • Java • C/C++ • Estudo de Caso • Conclusões Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  3. 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) Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  4. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  5. Design by Contract (DBC) • Um contrato tem três elementos essenciais • Pré-condições • Pós-condições • Invariantes Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  6. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  7. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  8. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  9. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  10. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  11. 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) Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  12. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  13. 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” Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  14. Estudos de casos • XmlParser • Gip-View Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  15. 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) Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  16. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  17. 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} } Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  18. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  19. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  20. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  21. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  22. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  23. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  24. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  25. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  26. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  27. 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 } Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  28. 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 Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

  29. 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/ Frederico Silva Guimarães <kid@teccomm.les.inf.puc-rio.br>

More Related