Como eu Desenvolvo Software – Parte 4

Oi pessoal, espero que todos tenham tido um ótimo natal! Eu consegui descansar um pouco, aproveitando para passar um fim de semana agradabilíssimo com a família em Bonito – MS. Para quem não conhece, recomendo muito, a região é fantástica, com locais maravilhosos.

Retomando o post anterior, eu estava falando sobre a minha maneira de desenvolver software, com o objetivo de fornecer uma perspectiva possível para os que estão começando, ou uma outra visão para os que estejam tentando definir uma forma prática para trabalhar com desenvolvimento. No post anterior, eu apresentei um problema fictício e a decisão de construir um sistema web para resolvê-lo. Iniciei com a análise sobre as condições de contorno do sistema e toda a parte de infra-estrutura envolvida. Estávamos no ponto onde tínhamos o esqueleto definido, com a parte de segurança já estabelecida. Até este momento, estávamos vendo questões de caráter não-funcional do sistema. Num cenário real, estas questões podem ser muito mais complexas do que o meu exemplo, pois pode já haver algum tipo de restrição de desempenho ou de segurança, por exemplo, que exija uma infra-estrutura muito mais complexa, fazendo com que esta etapa se torne um projeto em si.

Mas assumindo que seja algo padrão, a próxima fase seria começar a trabalhar na parte funcional do sistema. Neste momento, o que eu faço é começar por uma tarefa que seja algo que possa dar valor imediato para o cliente. Se o objetivo do sistema é controlar despesas de viagem de funcionários, algo que poderia ter valor imediato seria disponibilizar a lista das últimas viagens realizadas, com a consulta de viagens individuais e o cadastro de nova viagem. Claro que fazer algo de grande valor pode fazer com que seja necessário existir previamente toda uma gama de telas de apoio. Por exemplo, se estamos controlando viagens, teríamos que ter o cadastro de funcionários, de destinos, de tipos de despesa contabilizadas etc. Neste ponto começa a surgir o conceito de “Domínio” do problema (ver DDD), onde os termos já passam a ter um significado específico (ubiquitous language) e são utilizados para uma melhor comunicação com o cliente. Esta comunicação é fundamental para o sucesso e a evolução posterior do sistema, portanto é de grande importância tentar definir os termos corretos e já empregá-los toda vez que houver alguma comunicação.

Cada entidade de apoio deve ter seu mecanismo de persistência definido. No meu caso, diferentemente do DDD, eu não utilizo agreggates para centralizar a persistência. Para mim, cada entidade de domínio vai ser traduzida diretamente em uma tabela do banco de dados – a única exceção são as entidades que são classificadas como enumerations (enums), estas ficam só em código. O que diferencia enums de entidades de apoio, para mim, é o significado para o sistema da inclusão de novos registros. Se um usuário puder incluir uma instância da entidade e o sistema não tiver que ter sua parte de negócio alterada por causa disto, ela é uma tabela; caso contrário, é uma enum. Por exemplo, um cliente pode cadastrar uma cidade de destino a qualquer momento e nenhuma regra de negócio precisa ser alterada. Agora, imaginemos que existam categorias de faturamento pré-definidas que vão definir graus de reembolso. Se cadastrar um novo tipo de categoria ou uma categoria inteira implicar na necessidade de alteração do sistema, ela é um enum. Claro que sempre pode-se tentar modelar um sistema onde haja pouca necessidade de modificações, com quase tudo parametrizado em entidades e praticamente nenhuma enum. Mas pode ser que isto não valha a pena em determinados cenários.

Uma vez que as entidades de apoio estejam definidas, vão ser criados os objetos de domínio que as irão representar. No meu caso, esta tarefa é feita na seguinte ordem: 1) Primeiro a entidade tem seu principais atributos identificados (mentalmente); 2) É criada a tabela no banco de dados que vai armazenar a entidade – eu tento manter a tabela com os nomes de colunas o mais próximo possível dos atributos do objeto; 2) Usamos o framework, para gerar a entidade no diagrama do ActiveWriter; 3) Usamos os geradores de código .TT do framework para efetivamente construir a entidade e o respectivo repositório (sim, cada entidade tem o seu) e factory. Este processo é muito rápido, é questão de segundos fazer uma entidade usando esta sequência. Como tudo é feito no framework, a partir da geração tudo está 100% funcionando, já que não há nenhuma intervenção manual; assim nem é necessário utilizar testes unitários para entidades. Alguns até argumentam que eles seriam úteis para facilitar na evolução no caso de modificações de entidades; porém na minha experiência, este tipo de coisa é tão rapidamente detectado e corrigido que não justifica o esforço de testes (nem mesmo o esforço de tentar automatizar a construção dos mesmos via framework, pelo menos não até o momento).

Sempre com o objetivo de gerar a tela de melhor valor, deve-se então identificar, das entidades de apoio, quais são as necessárias para cadastrar dados que irão ser utilizadas na tela. É importante detectar dados de apoio que são tão importantes que merecem ser tratados como uma tarefa própria. Neste nosso exemplo, existe uma grande chance de o cadastro de funcionário ser um caso destes, seja pelo volume de informações, seja pela necessidade de um maior número de regras de negócio que devem ser seguidas durante o cadastro. Para cada um destes casos identificados é criada uma nova tarefa, de prioridade maior e da qual a tela de melhor valor será dependente.

Para os outros casos, é criada uma tela de CRUD. Telas deste tipo são também feitas com suporte do framework; construí-las é simplesmente definir colunas de visualização e busca na lista de entidades, definir os campos que serão utilizados no formulário de inclusão/alteração e escrever eventuais regras de validação de inclusão/modificação. Um CRUD simples pode ser feito no framework em poucos minutos (o meu record é 8 minutos para uma entidade simples, considerando a criação da tabela, da entidade e das telas). E como todas as telas de CRUD também são construídas de forma padronizada, também não utilizamos testes unitários para este tipo de tela. A criação de CRUDs é um processo tão rápido que há uma tentação de se tentar fazer um sistema inteiro usando telas deste tipo. Isto dificilmente é viável. Primeiro porque telas que possuem formulários muito grandes podem ser confusas para o usuário. Segundo porque para fazer uma atividade simples, um usuário teria que navegar em muitas telas, o que também atrapalharia a usabilidade. Assim, eu prefiro somente utilizar CRUDs para as entidades de apoio mesmo.

Neste ínterim o cliente está sempre sendo atualizado. Ele é notificado e participa cada vez que uma nova tarefa é gerada. A cada CRUD liberado ele também é notificado. Em novos sistemas, os primeiros releases já podem conter várias telas de CRUD 100% operacionais. Isto contribui para que o cliente perceba o andamento do projeto e já possa atuar em eventuais falhas de comunicação ou entendimento.

Novamente este post já está muito grande. Vou parar por aqui, continuo na semana que vem. Acho que em mais 1 ou 2 posts eu consiga finalizar esta série. O assunto é muito extenso, cada um dos tópicos que eu mencionei poderia se tornar um post completo. Espero que esteja conseguindo ao menos dar uma visão geral do processo. Por favor, fiquem à vontade para perguntar ou sugerir.

Desejo a todos um feliz 2011, repleto de realizações e com muita saúde e sucesso!

, , , , ,

  1. Deixe um comentário

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: