terça-feira, 5 de maio de 2009

Princípios de projeto - Parte I

Falaremos agora de correção e robustez.

Aqui, a palavra correção, é utilizada para traduzir correctness, representando a qualidade do que é correto.

Sintetizando em uma frase, correção é o atendimento dos requisitos pela sua aplicação; robustez é a capacidade do seu sistema em lidar, de forma correta, com as exceções.

Estes princípios são obrigatórios. Sem eles não existe aplicação. Na teoria, isso é simples de ver, enquanto, na prática, não é tão simples assim. Existem alguns motivos para o projeto falhar na correção, e serão mostrados no próximo post.

Quanto mais simples e direta a pergunta, mais simples e direta será a resposta. Entretanto, é com requisitos complexos e confusos que, normalmente, trabalhamos. O cliente, não nos chama para resolver dois mais dois.

Normalmente, para implementar um determinado requisito, dispomos de
n formas. Assim, para sabermos qual a forma correta, precisamos recorrer aos outros princípios de projeto de software. Por hora, isso não nos interessa.

Podemos usar invariantes para garantir os valores de entrada. Essa é, inclusive, a razão de viver dos métodos de atribuição: setters.

Mas o que são invariantes? Segundo Page-Jones:
É uma condição que todo objeto de uma determinada classe deve satisfazer, por todo seu ciclo de vida (quando o objeto estiver em equilibrio).
Objeto em equilíbrio é o objeto que não está em transição de estado.
Também temos as pré e pós-condições, que atuam a nível das operações. Ex: MENOR_DATA <= nascimento <= MAIOR_DATA. Lembrando que eliminamos números mágicos, portanto não interessa, para quem estiver implementando, os valores das constantes MENOR_DATA e MAIOR_DATA. Em termos gerais, esses valores, fazem parte das regras de negócio do cliente. Mas e a correção no comportamento? Este tipo é bem coberto pelos Testes Unitários. Com eles, descobrimos se a lógica está fazendo o que deveria fazer. Existe um excelente artigo sobre o JUnit aqui. Outro excelente artigo, este sobre mock objects. Montando uma suíte de testes, teremos muito mais segurança ao executar refatorações e atender as Change Requests.

O tratamento de exceções é outra forma de garantia de robustez. E o primeiro aspecto que deve ser observado é: nunca lance uma Exception. Se você está tratanto de alguma exceção, saiba o que está sendo tratado. O tempo é curto, mas isso é ponto chave na aplicação. Saiba, ao certo, que tipo de exceção aquele trecho de código pode lançar e trate-a. Todos nós, desenvolvedores, seremos um pouco mais felizes.

É válido notar que, os testes podem passar e mesmo assim a robustez não estará totalmente garantida. A suíte não é responsável por testar determinadas situações, como queda do banco. Enquanto o banco está no ar, os testes rodam. E quando cair? Vai despejar um stack trace na tela do cliente? Claro que não.

A robustez é uma das variáveis que fornecerá os dados para medir a confiabilidade do seu sistema. Outras variáveis são a arquitetura de hardware, S.O. e a rede. A confiabilidade é obtida através de qtd de falhas / unidade de tempo.

Uma falha na rede pode, facilmente, ser tratada na sua aplicação, mostrando uma mensagem de erro agradável (se é que podemos unir erro e agradável na mesma frase) para o usuário. Falhas e/ou baxa perfomance de hardware ou S.O. é mais complicado de resolver no código.

Podemos prever problemas de perfomance, pensando na eficácia do código. Entretanto, estaremos sempre limitados ao(s) hardware(s), ao S.O. e à rede. Se uma base de dados
tunada, estiver em um Pentium 100 MMX, com 64mb de memória, em uma rede de 10Mbits, sua aplicação CRUD pode estar em um supercomputador, com código eficaz e, mesmo assim, deixará a desejar na perfomance.

É necessário buscar o equilíbrio correto entre essas quatro variáveis principais, equilibrando, também, com uma variável importante para o cliente: o custo.


No próximo post, discutiremos alguns dos fatores que levam a falha do princípio da correção no processo de software.


Parte II - Correção
Parte III - Design por contrato
Parte IV - Flexibilidade
Parte V - A Lei de Demeter
Parte VI - Eficiência
Parte VII - Coesão
Parte VIII - Usabilidade
Parte IX - Relacionamento entre classes

Nenhum comentário:

Postar um comentário