quinta-feira, novembro 30, 2006

Dependências entre Controles : Parte 1

Este é o primeiro de uma série de três posts, nos quais eu falarei sobre dependência de controles nas telas de cadastro.
Nessa colocação inicial, darei uma visão geral do problema e como ele é resolvido no braço. No segundo, vou mostrar como alguns frameworks encaram essa situação. No terceiro e último, é apresentada a proposta do Merlin. Depois de lerem, não hesitem em dar suas opiniões e sugestões.

NOTA: A dependência de controles envolve muitos tipos de elementos de interface (como caixas de texto, seleção, marcação, textos estáticos, etc.) e por isso, para ser mais objetivo, vou tratar de dependências entre caixas de seleção, ou comboboxes. Escolhi elas por dois motivos: primeiro, porque representam elementos de complexidade intermediária se comparados com outros objetos existentes na interface do usuário e, segundo, porque elas a estão há tempo pipocando na minha cabeça, pedindo para serem armazenados em um meio durável, hehehe.

Dependência entre controles, um exemplo
No projeto de formulários, é dito que existe uma dependência entre controles quando o conteúdo ou o estado de um (ou mais) controle(s) depende do conteúdo ou estado de outro(s) controle(s). Essa é uma definição que eu criei, porque não lembro de ter visto algo melhor nos livros que já li.
Para ficar mais claro, veja essa figura:

Essa tela representa o cadastro de uma pessoa,
a qual mora em uma cidade que, por sua vez, pertence a um estado (ou Unidade Federativa - UF). Aqui, o objetivo é simples: ao selecionar um estado, espera-se que a caixa de seleção das cidades exiba somente as cidades que pertencem ao estado selecionado.
Para implementar esse comportamento, a abordagem tradicional, via código, é a seguinte:
  1. Ao carregar o formulário (evento onShow, por exemplo), é carregada a caixa de seleção estado, colocando como valor padrão nenhum ou aquele mais apropriado para o usuário (tal como o projetista definiu). Esse carregamento nada mais é do que um comando de seleção de registros no banco de dados sobre a tabela de estados. A caixa de seleção da cidade está (1) ou sem nenhum dado carregado e nem selecionado ou (2) está carregada com (2.1) os estados pertencentes ao estado previamente carregado com uma cidade padrão selecionada, ou (2.1) sem nenhuma cidade padrão selecionada, ou (2.3) está carregada somente com uma cidade, que é a cidade padrão e esta está selecionada. Variações nesse modelo podem ocorrer, mas o comportamento essencial é esse.
  2. No evento onChange da caixa de seleção do estado ocorre um processamento que seleciona no banco de dados (ou em um cache local) as cidades que pertencem ao estado que acabou de ser selecionado. Dependendo do que o projetista definiu, quando isso ocorre, a caixa de seleção da cidade pode ficar com (1) um valor padrão para o estado selecionado ou (2) ficar posicionada em nenhum.
  3. Modificações na caixa de seleção da cidade não implicam em nada.
No tocante aos dados exibidos nessas caixas de seleção, observa-se os atributos mais comumente reconhecidos pelo usuário, tais como (1) para cidades, o nome e (2) para estados, a sigla ou o nome. Novamente, depende do projetista :-)

As dificuldades
Quanto à complexidade disso, o tipo de processamento a ser executado (regra de negócio) é bastante simples. Tanto que, em algumas IDEs (como o Delphi) existem controles específicos para essa funcionalidade, os quais entram em funcionamento com alguns ajustes de configuração e/ou pequenos trechos de código adicionais. Quando não existente, esse comportamento geralmente é implementado na íntegra pelo programador e reside (quando muito!) em classes utiltárias e genéricas, de forma que possa ser reutilizado quando necessário. Programadores mais avançados (e com tempo de sobra) criam códigos bastante complexos, performáticos e (duvidosamente) estáveis, os quais são empacotados em componentes da casa e reutilizados (expostos?) como obras de arte em vários sistemas. Não obstante, é comum esses componentes terem suas limitações exarcebadas somente quando muito tempo passou desde seu projeto e as consequências para manutenção acabam revindicando todo o tempo que fora "ganho" antes...
Sem considerar esses aspectos (que seguramente muitos desenvolvedores irão me questionar), existe um problema muito mais impactuante e de uma transparência tamanha que passa despercebida pela quase totalidade dos desenvolvedores: retrabalho.

Retrabalho x reuso
Reuso é o ato de utilizar novamente algo que já foi utilizado. É como aquele programador que diz: Pô, para isso eu já tenho uma classe que resolve. É só instanciar esse objeto, chamar aquele método e configurar esses parâmetros que está pronto! Isso é o reuso. E todos amam essa palavra, principalmente quando ele funciona.
Retrabalho é o que o programador acima acabou de fazer. Ele já tinha a solução pronta, mas teve que aplicá-la novamente no novo problema que surgiu.

De certo, muitos vão perguntar: Mas isso é mais do que óbvio. Toda vez que eu tenho um mesmo problema, eu "pego" a solução que já possuo e aplico ela novamente!

E eu, com minha visão pessimista, vou dizer: Isso tá muito trabalhoso ainda! Eu quero uma solução reutilizável, mas que não implique em retrabalho. Tu não tens uma?

Talvez...vamos dar uma olhada na caixa de ferramentas...
[continua]

0 comentários: