Dicas para o desenvolvimento de um software funcional - Parte VIII
24 de outubro de 2013 André Luis Celestino Desenvolvimento de Software, Metodologias, Qualidade
A qualidade de software sempre foi um tema imensamente discutido na área profissional e acadêmica, além de ser um dos maiores focos das empresas de desenvolvimento. Convido-os para conferir o oitavo artigo da série sobre dicas para desenvolvimento de um software (leia também: Parte 1, Parte 2, Parte 3, Parte 4, Parte 5, Parte 6, Parte 7), no qual destaco mais quatro tópicos relevantes sobre o assunto. Aproveitando, gostaria também de agradecer os feedbacks.
Embora o software seja importante para armazenar informações, é interessante que ele também possua boas rotinas de mineração de dados (Data Mining) para compor estatísticas e apresentar dados históricos. Essas funcionalidades são bastante apreciadas pelos clientes principalmente por contribuir para a definição de estratégias de negócio da empresa. Entre essas informações, o software pode apresentar os clientes potenciais, produtos emergentes, cálculo de variações e faturamento por período, além de gráficos e relatórios bem elaborados. Bons profissionais ressaltam que um software deve trazer valor agregado ao negócio do cliente, e não apenas servir como um contêiner de informações. Portanto, programe o seu software para ser capaz de transformar os dados armazenados em informações estratégicas para o negócio.
Mas vale ressaltar: para que isso seja possível, o banco de dados deve estar bem modelado e com relacionamentos corretamente definidos. Caso contrário, os dados levarão uma eternidade para serem compostos e exibidos, ou, no pior dos casos, não será possível interligar as tabelas de modo a trazer dados relacionados à consulta solicitada.
Apenas para efeito de conhecimento, este conjunto de procedimentos em um software está intimamente ligado a conceitos na área de negócios, como Business Intelligence, OLAP, ETL e Data Warehouse. Vale a pena conhecer estes conceitos e a sua importância no apoio à tomada de decisão do cliente.
Vamos supor que, após aplicar a normalização de dados, você criou um cadastro de cidades no software com o objetivo de registrar as cidades utilizadas em outras tabelas, como clientes, fornecedores e funcionários. Assim sendo, no cadastro de clientes, por exemplo, haverá uma lista de opções (combobox) para que o usuário selecione a cidade do cliente, correto?
Pois bem, imagine que o usuário está preenchendo os dados de um novo cliente e ao selecionar a cidade… ops, a cidade não está cadastrada!
Como são telas diferentes, o usuário terá que:
Fechar a tela de cadastro de clientes;
Abrir a tela de cadastro de cidades;
Cadastrar a cidade;
Voltar na tela de clientes;
Preencher os dados novamente.
Para simplificar este procedimento, procure "integrar" os cadastros, adicionando um botão próximo ao campo para abrir a tela quando necessário. No exemplo acima, adicionaríamos um "atalho" ao lado do campo "Cidade", permitindo o cadastro de uma nova cidade sem necessariamente sair do cadastro de clientes.
Opcionalmente, para manter o visual mais enxuto, muitos desenvolvedores adicionam essa opção na própria combobox, conforme a imagem abaixo:
Porém, atente-se que se houver muitas cidades cadastradas pode não ser viável exibi-las em uma lista de opções, já que, além da demora para carregar todas as cidades na lista, levaria um tempo para o usuário encontrar a cidade desejada. Uma alternativa é exibir uma tela de pesquisa ao invés de utilizar uma lista, para que o usuário possa procurar a cidade diretamente pelo nome. Essa opção fica ainda mais interessante quando há uma tecla de atalho para abrir a tela de pesquisa, como uma das teclas de função (F1 a F12).
É claro, essa dica vale para qualquer situação que envolva relacionamento entre tabelas.
Uma validação é a função de evitar que um dado inválido, inconsistente ou incorreto seja processado ou gravado no banco de dados. Considere a validação como um firewall que analisa os dados digitados pelo usuário: se alguma informação não estiver condizente com os padrões ou regras do sistema, então não é processada. Quanto mais validações você programar no software, maior será o nível de confiabilidade.
Para exemplificar, imagine uma regra de negócio que envolva períodos de vigência sobre um determinado requisito funcional. O período de vigência exige que a data de início de um registro deve ser imediatamente a sequência da data de término do registro anterior. Por exemplo, se a data de término for 23/10/2013, a data de início do registro seguinte deve ser 24/10/2013. Além disso, não é permitida a sobreposição de datas, ou seja, dois registros diferentes não podem compreender o mesmo período. Para controlar a complexidade dessa regra de negócio, é imprescindível que haja uma validação de datas a cada novo registro inserido, evitando que períodos incorretos sejam armazenados no banco de dados. A validação terá que comparar as datas para encontrar possíveis sobreposições e identificar "furos" entre vigências de dois registros consecutivos. Tradicionalmente, a implementação pode ser uma função que retorne um valor booleano como resultado dessas verificações.
Validações geralmente são realizadas antes da inserção do registro de modo que, se os dados não estiverem corretos, a aplicação cancele a operação em transação e permita que o usuário corrija os dados. Porém, existem ainda outras validações que dizem respeito ao comportamento dos controles na tela, como a quantidade de caracteres permitida em um componente ou campos que obrigatoriamente devem aceitar somente números. E volto a repetir: quanto mais você cobrir o sistema com validações, menos haverá "brechas" para falhas, garantindo confiabilidade e integridade dos dados armazenados.
Testes, testes a mais testes!
E por falar em validações, é necessário testá-las, concorda?
Talvez essa seja uma das fases mais importantes no desenvolvimento de um software: testar as funcionalidades, validações e operações de forma intensa, desafiando o seu próprio software a manipular corretamente cada caminho de execução. Teste de software pode ser definido como o acompanhamento da execução de um software em um ambiente controlado para verificar se as saídas e o desempenho correspondem ao esperado.
Acredito que você já tenha recebido algum erro reportado pelo usuário e logo pensou: "Caramba, eu testei essa tela várias vezes, como esse erro aconteceu?". Isso é natural. A causa deste problema é que nós, desenvolvedores, temos um problema conhecido como "vício de programação". Esse vício faz com que nossos testes sejam óbvios, uma vez que, como nós mesmos fizemos a programação, já conhecemos o comportamento do software e não testamos todas as condições que podem ocorrer. Em outras palavras, o desenvolvedor não consegue pensar com a cabeça do usuário, ao menos que ele já tenha experiência com testes ou realmente saiba interpretar o papel de quem está utilizando o software.
Para contornar esse tipo de "vício", desenvolvedores autônomos colocam uma pessoa não relacionada à área desenvolvimento para testar o software. Além de identificar os erros, o desenvolvedor pode ainda observar as dúvidas que surgem quando um novo usuário começa a utilizar o sistema pelas primeiras vezes.
Já no âmbito de empresas de desenvolvimento, há outras soluções mais sólidas:
Contratar analistas de testes para elaborar roteiros que descrevem as possíveis condições que podem ocorrer na tela ou no módulo desenvolvido. Dessa forma, estes analistas podem cobrir as possibilidades de falhas a partir do conhecimento que já têm do sistema e das técnicas de elaboração de testes;
Orientar os desenvolvedores a implementar testes automatizados para cobrir o código-fonte. Os testes automatizados são bastante úteis para executar uma bateria de testes pré-definidos de modo rápido e sequencial, sem a intervenção de um usuário para a entrada de dados. Uma vez implementados os testes, a vantagem é a possibilidade de executá-los sempre quando a unidade de código for modificada.
Há vários frameworks funcionais para apoiar desenvolvedores na criação de testes automatizados, como o DUnit para Delphi e o JUnit para Java, assim como outras ferramentas especializadas, como o TestComplete, TestLink e o Mantis.
Agradeço mais uma vez pela atenção, leitores!
Leia também: Parte 1, Parte 2, Parte 3, Parte 4, Parte 5, Parte 6, Parte 7, Parte 9, Parte 10, Parte 11