Design Patterns em formulários Windows complexos – Parte I

 

Introdução

A seis anos eu trabalhava com Delphi em projetos de outsourcing. Gostava do trabalho, pois tinha oportunidade de, a cada projeto, conhecer pessoas novas em ramos de atividade quase sempre diferentes. Por outro lado, algo que me incomodava muito era a falta de tempo dedicado a pensar no que era feito. Hoje, quando penso nisso, vejo que o foco era fazer funcionar para cumprir o prazo.

 

Um dos projetos que mais me recordo desta época é o de um software que seria utilizado para controlar transações financeiras de uma corretora. Esta corretora controlava os investimentos de centenas de clientes. Regras de negócios à parte, o mais interessante deste projeto era o fato de que ele deveria possuir um dashboard que serviria como uma espécie de painel de alertas. Reza a lenda que na especificação original deste painel havia palavras como mediúnico e sagrado. Mas esta especificação eu não vi...

 

Em última análise este dashboard era um formulário que deveria funcionar como uma espécie de painel de carro, emitindo avisos conforme a situação atual. Eis algumas características que constavam na especificação final:

·         O usuário deve ter a liberdade de ‘montar’ o painel da forma como bem desejar;

·         Adicionar um novo indicador deve ser o mais simples possível (do ponto de vista de programação e do ponto de vista de usabilidade);

·         Ao alterar um parâmetro do painel, os indicadores que forem afetados devem ser atualizados.

 

Hoje vejo que o mais próximo do ideal seria que nós fizéssemos as partes deste formulário com o mínimo de acoplamento possível umas com as outras. Um indicador não deveria conhecer todas as partes afetadas por uma modificação realizada nele, por exemplo.

 

Pois bem, isto seria o ideal, mas não foi o que fizemos. Para tornar curta uma história que é longa vou dizer o seguinte: Nós fizemos o programa, levamos cerca de nove meses para construí-lo, ele roda até hoje e atualmente é um exemplo para mim. Um exemplo do que não deve ser feito! O tal formulário do dashboard hoje está com cerca de 30 mil linhas e é um bloco monolítico (eu já vi programas Clipper melhores estruturados). Veja bem, eu estou falando de uma classe com milhares de linhas, centenas de métodos e com centenas de agregações que conhece todos (eu disse todos) os detalhes imagináveis da operação do dashboard.

 

A situação era tão grave que manter aquele programa era quase como isto:

·         Cliente paciente: Doutor, meu braço dói;

·         Desenvolvedor residente: Deite aqui, por favor. Vou aplicar uma anestesia geral;Cliente paciente: O que?! Eu só estou com dor no braço! Tire a mão de cima de mim...;

·         Desenvolvedor cirurgião: Bisturi, por favor...

 

Brincadeiras à parte, o que aconteceu naquela ocasião foi que pensamos na interface como algo feito em camadas, não como uma classe. Minha teoria é que com o advento da programação “orientada a eventos” sugerida pelo modelo de desenvolvimento RAD, alguns programadores (como nós na época) “esqueceram” que formulários são classes. Para piorar, neste caso específico o formulário tinha de suportar alterações de uma maneira melhor do que simplesmente sair colocando “if” (e bota if nisto) nas rotinas existentes.  Bem, o “jeito” encontrado para fazer aquilo pode ser resumido da seguinte forma:

 

1-Colocávamos um monte de painéis no formulário.

 

2-Conforme a ação que usuário escolhesse, controlávamos as propriedades Visible destes painéis e, às vezes, até de controles dentro deles.

 

3-Todo mundo conhecia todo mundo. Um indicador sabia quem ele teria de afetar.

 

4-Voltar ao item 1.

 

Para tentar mostrar alguns dos problemas que nós enfrentamos com esta abordagem, criei um programa com o objetivo de simular as mesmas situações de interface proporcionadas por um software da Microsoft chamado MS-SQL 2000 BPA. Este software é bem útil para quem utiliza SQL Server e pode ser baixado no seguinte endereço:

http://www.microsoft.com/downloads/details.aspx?FamilyID=b352eb1f-d3ca-44ee-893e-9e07339c1f22

&displaylang=en

 

mpdpfwcp1fig01.jpg   mpdpfwcp1fig02.jpg 

MS-SQL BPA: Versão original versus versão cover.

 

No que tange a interface com o usuário, o software é baseado em páginas que vão sendo apresentadas à medida que o usuário escolhe as opções no painel contido na parte esquerda do formulário. O programa também limita as opções disponíveis conforme o contexto atual.

 

O código é o mais simples possível:

 

private void SetActualEnvironment(BpaCoverEnvironment environment)

{

        if (environment == BpaCoverEnvironment.WelcomePage)

        {

               this.panWelcome.Visible = true;

               this.panLogin.Visible = false;

               this.panInstances.Visible = false;

               this.panGroups.Visible = false;

               this.panReports.Visible = false;

 

               this.llInstances.Enabled = false;

               this.llGroups.Enabled = false;

               this.llReports.Enabled = false;

               this.llLogout.Enabled = false;

        }

        else if (environment == BpaCoverEnvironment.LoginPage)

        {

               this.panWelcome.Visible = false;

               this.panLogin.Visible = true;

               this.panInstances.Visible = false;

               this.panGroups.Visible = false;

               this.panReports.Visible = false;

 

… (continua)

 

Do ponto de vista do designer temos a seguinte situação:

 

mpdpfwcp1fig03.jpg 

 

mpdpfwcp1fig04.jpg 

 

Em minha opinião, levando em consideração o que a prática me mostrou, usar uma estratégia destas em algo mais complexo, nos deixa com os seguintes problemas:

  • Devido ao forte acoplamento entre as ‘partes’ do formulário, o código fica muito rígido. Imagine que o programa possa apresentar páginas conforme o ramo de atividade do seu cliente. Fazer isto nesta estrutura só é possível tornando a classe maior e mais difícil de manter;
  • A estrutura favorece códigos monolíticos e altamente baseados em controles condicionais. Códigos assim são muito difíceis de reutilizar e manter;
  • Como não há um conceito de responsabilidade (o formulário é responsável por tudo), os remetentes de uma solicitação acabam tendo de conhecer seus destinatários. Isto só colabora para aumentar ainda mais o acoplamento. Além do mais pode acontecer do remetente A ter de conhecer o destinatário B que por sua vez também deve conhecer o remetente A. O que significa que mesmo criando ‘controles’ para as partes, elas ainda teriam que se conhecer;
  • Caso seu programa adicione partes dinamicamente segundo algum critério, (algo que suporte plugins, por exemplo) um código como este colabora muito para tornar tudo um pouco mais complexo. Não há a possibilidade de conhecer a priori o que será carregado e como aquilo que será carregado interage com o restante do formulário (e com outros plugins, porque não?);
  • Dependendo da complexidade do que for feito, o formulário pode ficar com um tamanho muito grande para proporcionar o gerenciamento adequado da complexidade;
  • Se o formulário for baseado em partes invisíveis, fazer uma alteração de designer pode ser tão bacana quanto uma corrida de cavalos de tróia cuja chegada é a sua casa.

Leia também: Design Patterns em formulários Windows complexos – Parte II