DClick

Aliando Teoria e Prática


Eu acredito mesmo que aliar teoria e prática é a fórmula do sucesso. Os blogs que eu mais admiro (1, 2, 3, 4) pertencem a pessoas que parecem equilibrar bem estes dois fatores.

As pessoas apenas pragmáticas não costumam ter blogs. Já as pessoas teóricas costumam ter, embora com um conteúdo geralmente prolixo e chato. Mas tem um outro tipo de pessoa, nem pragmática nem teórica, que costuma ter blog: o marketeiro. Estes geralmente tem muitas visitas, mas de cada 10 posts 9 são puro marketing pessoal. Confesso que isso me incomoda na medida em que os marketeiros costumam se gabar do número de visitas do seu blog e gostam de se vender como os melhores do mercado. Mas o que me deixa tranqüilo é o fato de saber que eles não constroem sua reputação em cima de algo louvável. Eles se elegem como os políticos do Brasil. Eles ficam famosos como os big Brothers. Eles, eventualmente, conseguem algumas vantagens competitivas como a Micro$oft. E de fato, eles não sabem aliar teoria e prática.

Bem, críticas a parte, analisando novamente um código que surgiu como resposta a um problema na FlexDev, eu senti a oportunidade de aliar teoria e prática. Não julgo que sei fazer isto bem, mas pelo menos é algo que eu busco.

Primeiro, algo útil para você usar caso precise um dia (prática). O exemplo abaixo mostra a utilização de um componente que permite facilmente associar funções a teclas de atalho no Flex.

(Para ver o código fonte: Botão direito - View Source)




O ponto forte deste componente é a sua simplicidade de uso como mostra o exemplo:

CODE:
  1. <local:ShortKey key="{Keyboard.HOME}" ctrlKey="true" handler="{homeHandler}" args="{['arg1', 'arg2']}"/>

Você só precisa o trecho acima para que toda vez que a usuário pressionar CTRL + HOME a função "homeHandler" seja chamada recebendo os argumentos "arg1" e "arg2".

Agora um pouco de teoria que espero que também lhe seja útil de alguma forma. Isto tem a ver com abstração, pesquisa, nomes de variáveis e métodos e Refactoring. Tudo isto usando algo em torno de 10 linhas de código do componente e, prometo, tentarei não ser prolixo (se bem que ao dizer que não serei prolixo eu já estou sendo uma vez que a palavra "prolixo" é prolixa em si).

A primeira versão do componente tem o seguinte trecho de código:

Exemplo 1

CODE:
  1. 1. private function keyDownHandler(event:KeyboardEvent):void
  2. 2. {
  3. 3.  var checkShiftKey:Boolean = !(Number(event.shiftKey) ^ Number(shiftKey));
  4. 4.  var checkCtrlKey:Boolean = !(Number(event.ctrlKey) ^ Number(ctrlKey));
  5. 5.  
  6. 6.  if ((checkShiftKey && checkCtrlKey) && event.keyCode == key)
  7. 7.  {
  8. 7.   button.dispatchEvent(new MouseEvent(MouseEvent.CLICK))
  9. 8.  }
  10. 9. }

Bem, eu posso reescrever o trecho de código acima usando vários "ifs":

Exemplo 2

CODE:
  1. 1. private function keyDownHandler(event:KeyboardEvent):void
  2. 2. {
  3. 3.  if (event.keyCode == key)
  4. 4{
  5. 5.    if ((event.shiftKey && shiftKey) || event.ctrlKey && ctrlKey)
  6. 6.    {
  7. 7.      handler.apply(document, args);
  8. 8.    }
  9. 9.    else if (!event.shiftKey && !shiftKey && !event.ctrlKey && !ctrlKey)
  10. 10.  {
  11. 11.   handler.apply(document, args);
  12. 12.  }
  13. 13}
  14. 14. }

O que tornou possível remover os "ifs" (exemplo 2) foi o uso do Bitwise XOR (o sinal ^ no exemplo 1). E o que tornou possível o uso do XOR foi a abstração. Eu percebi que o que importava para resolver meu problema é que o resultado da comparação entre dois valores booleanos fosse verdadeira caso os valores fossem iguais (verdadeiro e verdadeiro = verdadeiro ou falso e falso = verdadeiro). Então, se houvesse uma maneira de verificar isto eu não precisaria de vários "ifs" para testar diversas situações. Eu lembrava das aulas de lógica da faculdade de Ciência da Computação que tinha uma notação que representava este cenário. Logo, imaginei que deveria haver uma forma de escrever isto numa linguagem de programação como o ActionScript. Isto foi comprovado minutos depois de uma rápida pesquisa no Help. Assim, a linha 3 e a linha 4 do exemplo 1 garantem que o resultado será verdadeiro caso ambos os valores envolvidos no XOR sejam verdadeiros ou ambos sejam falsos.

O "if", assim como as estruturas de repetição, são alguns dos itens que adicionam complexidade num algoritmo e sempre que posso eu tento reduzi-los. Mas neste caso o uso do operador Bitwise XOR conseguiu deixar as coisas mais complexas ainda.

Então pensei em adicionar comentários para deixar as coisas mais claras:

Exemplo 3

CODE:
  1. 1. private function keyDownHandler(event:KeyboardEvent):void
  2. 2. {
  3. 3.  // garante que ambos os valores do shift são falsos ou verdadeiros
  4. 4// os valores do shift são definidos pela propriedade shiftKey desta classe
  5. 5// e pela propriedade shiftKey do objeto event
  6. 6var areShiftValuesFalseOrTrue:Boolean = !(Number(event.shiftKey) ^ Number(shiftKey));
  7. 7
  8. 8// garante que ambos os valores do ctrl são falsos ou verdadeiros
  9. 9// os valores do ctrl são definidos pela propriedade ctrlKey desta classe
  10. 10// e pela propriedade ctrlKey do objeto event
  11. 11var areCtrlValueFalseOrTrue:Boolean = !(Number(event.ctrlKey) ^ Number(ctrlKey));
  12. 12
  13. 13if ((areShiftValuesFalseOrTrue && areCtrlValueFalseOrTrue) && event.keyCode == key)
  14. 14{
  15. 15.  handler.apply(document, args);
  16. 16}
  17. 17. }

Agora eu fiquei na dúvida se vale mesmo a pena ter algo complexo assim com comentários e se a solução com vários "ifs" não era melhor. Foi então que me dei conta que um simples Refatoring com bons nomes de métodos e variáveis poderia substituir os comentários.

Exemplo 4

CODE:
  1. 1. private function keyDownHandler(event:KeyboardEvent):void
  2. 2. {
  3. 3var areShiftValuesEquals:Boolean = areValuesEquals(event.shiftKey, shiftKey);
  4. 4.  var areCtrlValuesEquals:Boolean = areValuesEquals(event.ctrlKey, ctrlKey);
  5. 5
  6. 6if ((areShiftValuesEquals && areCtrlValuesEquals) && event.keyCode == key)
  7. 7{
  8. 8.    handler.apply(document, args);
  9. 9}
  10. 10. }
  11. 11.
  12. 12. private function areValuesEquals(value1:Boolean, value2:Boolean):Boolean
  13. 13. {
  14. 14return !(Number(value1) ^ Number(value2));
  15. 15. }

Observe como este exemplo reflete de forma legível o que tentei mostrar nos comentários do exemplo 3. Aqui vale a ressalva: É impressionante como o pessoal de TI subestima este negócio de dar bons nomes para as coisas. Não falo apenas do código, mas também nomes de funcionalidades, conceitos, etc. Não é incomum eu ouvir as pessoas falando: "o nome é o que menos importa". Mas eu tenho diversos motivos para acreditar que os nomes são realmente importantes. De fato, o nome do método que eu encontrei é fruto do entendimento que tive ao tentar fazer comentários claros. E isto vai de encontro a este excelente artigo onde o autor critica o uso de comentários por programadores inexperientes.

O resumo das teorias e conceitos subjacentes destas poucas linhas de código é o seguinte: Primeiro eu abstraí e entendi que eu não precisava de uma porção de if's para resolver o meu problema. Então pesquisei para ver se a linguagem possuía algum mecanismo que tornasse possível a implementação da minha abstração. Por fim, usei bons nomes de métodos e variáveis para Refatorar e deixar o código mais legível.

Se eu fosse agir como um teórico eu teria escrito um monte de baboseiras sem sair com algo realmente útil. Se eu fosse agir como um simples pragmático eu me daria por satisfeito com a solução dos vários ifs e provavelmente não estaria fazendo este post. Se eu fosse agir como um marketeiro eu "disponibilizaria" este componente para a comunidade com o nome de "Super Ultra ShortKey Framework", o que seria fazer barulho demais para algo tão simples.

Pode ser que o código final com o XOR não agregue mesmo muito valor à solução final. Mas eu acredito que se você quer se tornar bom numa tecnologia você não pode se dar por satisfeito com a primeira solução que lhe aparece. Procure abstrair o problema e pesquise para ver se a tecnologia que você usa provê uma forma melhor para implementar a sua solução. Mas lembre-se de equilibrar a aplicação de soluções pouco convencionais à legibilidade, pois você não é o único desenvolvedor da sua empresa e as outras pessoas não são obrigadas e ter o mesmo conhecimento que o seu. No fim, isto deve lhe ajudar aliar teoria e prática. E a teoria pode lhe ser muito util na solução de problemas mais complexos.

Por Beck Novaes em 31/October/2008 | Comentar | Trackback


No Translations

5 comentários para “Aliando Teoria e Prática”


O bom programador não é aquele q escreve alheio ao problema, mas àquele que codifica sabendo oq faz e COMO faz! Realmente, a abstração do problema faz toda a diferença.

Muito bom artigo, T+


Eu diria: “Nomes não são somente importantes, mas mais importantes”.
Não vou entrar no merito se código está bem feito, otimizado etc, mas nome claro dos variaveis e funções elimina nececidade de comentarios na maioria dos casos.

Alem, gosto aquela frase: “Se algo está complicado demais, provavelmente está errado”.
Deixando código mais simples, quebrando nas funções (claro, não exagerando), com nomes claros que dizem o que função faz, já está avanço grande.


Mto útil esta classe ShortKey. Faz todo o trabalho para nós. Porém ainda tem um problema:

As teclas de atalho só funcionam qndo vc clica sobre um edit ou área editavel ou selecionável do seu projeto. O ideal seria clicar em qualquer lugar da tela e as teclas
de atalho já funcionassem, como ocorre em joguinhos em Flash, que vc somente clica
na tela e já consegue movimentar o personagem pelas teclas do teclado…

Fica ai a dica… flw!


Na realidade a classe funciona quando você clica em qualquer lugar. O problema é inicial é um problema de foco que as aplicações da Flash Platform tem.

Isto foi discutido na FlexDev há algum tempo atrás.
http://groups.google.com/group/flexdev/msg/b57aad7ba3af18e9


Entao, boas praticas de programação sempre é bem vinda quando se pretende exetender em algumas funcionalidades mais tarde porem nem sempre é aplicado na maioria das equipes que ja trabalhei. Entao fica seu recado Beck.

t+

Adicionar comentário

(requerido)
(requerido, não será publicado)