Programando defensivamente
Muitos são os casos de softwares mal-sucedidos e prontos para o insucesso em sistemas desenvolvidos sem um estudo e planejamento inicial. Até mesmo a forma como ele é desenvolvido durante a duração desse ciclo determina seu fracasso. O que realmente acontece quando estamos frente-a-frente com essa situação todos sabemos. A sensação de insegurança é predominante. Não temos nenhuma confiança em utilizar muitos objetos do projeto. Não temos confiança por não termos um contrato definido. Isso acontece, primeiramente, porque temos um sequência de códigos legados mal-escritos. Onde o profissional que projetou determinado objeto do software não se preocupou em como iremos usar determinado resultado de um método por exemplo. Afinal, em muitos casos, pela falta de conhecimento no domínio do negócio não saberemos lidar com uma informação nula. E como não sabemos se isso realmente poderá acontecer, estabelecemos aquela sequência de testes verificando a nulabilidade de determinada ação. Sem nem realmente sabermos onde queremos chegar com aquilo. Querendo apenas evitar uma exceção de sistema.
Podemos evitar essa situação, criando um projeto de software realmente confiável em termos de codificação, que cá pra nós é a parte mais importante do projeto. Faremos isso programando defensivamente, buscando utilizar práticas de codificação defensiva, já que não temos contratos pré-estabelicidos. Evitando assim, o mal uso deles pelos demais desenvolvedores. Afinal, se alguma coisa pode dar errado, ela indiscutivelmente dará errado. É a lei.
Como não temos um contrato pré-estabelicido em nosso projeto em andamento, utilizamos a programação defensiva para evitarmos mais dor de cabeça. Com ela garantimos que quem utilizará nossos objetos obtenham um resposta segura, não importando o que realmente ele quer que aconteça. Ou seja, sempre procuraremos por todas as coisas que podem dar errado e executaremos uma quantidade excessiva de testes para evitarmos situações embaraçosas no nosso software.
A prática mais utilizada na programação defensiva é a utilização de exceções para casos que precisamos evitar a continuidade do fluxo para determinado valor do objeto. Normalmente utiliza-se exceções checadas. Lembrando que existem casos e casos, e a verdade absoluta é algo que realmente não existe. Então se você pensa que uma exeção não checada é a melhor saída: vá em frente, pois uma exeção checada trará sempre mais código para quem reaproveitará o código. Dependendo do caso, o retorno de um objeto vazio pode significar muito mais que o retorno de um objeto nulo.
Outro prática que podemos adotar em uma programação defensiva é dar a devida importância aos dados de entrada em nossos sistema. Sabemos que apartir de um dado errado, muitos outros se perpetuarão no nosso sistema. Então, seja qual for a fronteira: sistema externo, cadastro básico, rotina de movimentação, não interessa. Todos os dados devem ser válidados. Jamais pense na camada de visão para isso. Toda e qualquer validação de dados nunca deverá ser garantida aí. Afinal cada objeto com sua responsabilidade.
Acredito que a melhor forma de garantirmos segurança e confiabiliade no desenvolvimento de um software são os testes. Use e abuse deles. Crie scripts de testes que testem todos os seus componentes e a saída experada por eles. Qualquer modificação errada no código de seu software devem ser inválidadas nos seus scripts de testes. A grande sacada para isso chama-se desenvolvimento dirigido por testes, o famoso TDD. Vale a pena aprofundarmos nesse assunto.
Um sistema de logs bem construído também nos ajuda a encontrar os principais pontos de falhas do nosso sistema. Nunca ignore esse item na elaboração da arquitetura do seu projeto. Você realmente precisará dele para não perder algumas noites de sono.
Uma coisa que vejo periódicamente é o uso dos famosos “domains”, algo que se originou da programação estrutural. Então vemos aqueles testes absurdos com atributos do tipo String. E os erros são inevitáveis. Por favor, conheça a linguagem de programação que você está utilizando no seu projeto. Para esses casos use e brigue pelo uso de enumeradores. Outra pedida é: documente seu código. É importante. Mas nada de desenhar balões e aquelas coisas bizarras, ok? Seja simples e direto.
Reduzir a complexidade do nosso código e atacarmos o menor ponto de funcionalidade de cada caso de uso separando qualquer algoritmo no menor tamanho possível é outra prática a ser adotada no desenvolvimento. E cada vez que você divide a sua aplicação, você começa a se repetir. Isso gera mais análise e mais projeto pra cada tomada de decisão, aumentando as chances de termos um código coeso e levemente ligado.
Lembre-se que o cliente não liga pra diagramas bem desenhados, uma lista de requisitos em um documento bem elaborado. O que realmente interessa para o cliente é software fazendo alguma coisa concreta. De preferência com a maior qualidade e confiabilidade possível. O desenvolvimento de um software consiste em repetição. Nada de etapas separadas. Na verdade nada de etapas. Quanto mais específico for nosso caso de uso melhor. Iterações curtas até o resultado esperado pelo cliente. E não tenha medo de ser chamado de retranqueiro.
Popularity: 17% [?]
Olá! Eu sou Daniel Tamiosso, um jovem com vinte e um anos, amante da vida e suas várias variáveis.
Comentários