January 27, 2009

Refactoring como meio e Design como Fim

Ainda é muito comum discussões sobre refactoring. Mas sinceramente acredito que boa parte delas perderam o ponto a muito tempo. Refactoring como o próprio Fowler disse é uma técnica sistemática para reestruturar código sem mudar o seu comportamento. Sempre que escolhemos uma abordagem de design como por exemplo: DBC, TDD, RDD, DDD, etc.. estamos levando a solução através modelos consolidados. Esses modelos tem prós e contras e dependendo da situação um vai ser melhor do que o outro.

Eu partircularmente gosto muito do modelo do RDD. Mas como chegamos a um modelo solido e eficaz? O design não nasce pronto, deve ser feito de forma incremental utilizando refactoring por exemplo, mas o refactoring não deveria mudar a semantica, logo precisamos de algo mais que refactoring, nesse caso estamos falando de design incremental.

Como fazer um bom Design?

Para fazer um bom design é necessário conhecimento do dominio! Sem conhecimento do dominio é impossível fazer um design robusto e sustentável. Outro fator é fundamental na construção de um bom design é o conhecimento de patterns como do GOF, EAI, EIP, MOM, etc... Outro compomente que ajuda na criação de um bom design é conhecer como boms frameworks foram feitos e segui-los. Um ótimo framework em termos de design é o Spring Framework.



Como eu recomendo que isso aconteça?

Primeiro faça funcionar. Antes de tentar sair aplicando um design mais robusto faça as coisas funcionarem. Ok as coisas estõ funcionando agora faça testes unitários de forma que os testes cubram as coisas que você fez, então agora aplique refactoring e design incremental para melhorar o seu design.

Que ponto se perdeu com refactoring?

Vejo que em muitas discussões sobre refactoring se perdeu o real objetivo que é um método sistemico para que no final das contas nos melhoremos o design. Design não se aplica exclusivamente a métodos e classes.

Onde se Aplica o Design?



Precisamos trabalhar o design em todos esse níveis! Algumas coisas já vem dos requisitos como por exemplo a responsabilidade de cada sistema e outras vão sendo evoluídas ao longo do projeto. Não que essa seja uma tarefa fácil, por que o design vai ficando melhor a medida que você vai conhecendo o domínio mas algumas coisas você pode fazer meio que up to front. Normalmente essas coisas up to front se aplicam a arquitetura e não a regras de negócio.

Duas soluções excelentes para fazer isso são o Spring Framework, claro que você deve utilizar interfaces e classes abstratas e a outras é o Maven, que ajuda a qquebrar e gerenciar diversos jars de dependências em um projeto.


Como reduzir o peso da gerencia de projetos utilizando o Tracker

Mesmo que você não esteja utilizando XP ou até mesmo Agile, você pode reduzir boa parte da carga de trabalho de gerenciamento de projetos! Um gerente de projetos normalmente tem que ficar atualizando uma seria de artefatos que são utilizados para acompanhar tanto o status do projeto como riscos, requisitos e entre outras coisas.

O XP determina uma role que ele chama de Tracker. Essa pessoa normalmente faz a atualização de gráficos, de riscos, do próprio backlog se você utiliza Scrum por exemplo. O XP determina que essa pessoa seria o Tracker de todo o projeto. Eu vejo uma aplicação mais nobre para esse papel, se você desenvolve de maneira iterativa com iterações de 1-4 semanas você pode fazer um roteamento de Tracker.

O Tracker não precisa ser a mesma pessoa sempre, o ideal é que esse papel seja um papel rotativo, assim todos ficam mais ciente do que está acontecendo no projeto e um bom peso é removido do gerente. Sem falar que com a rotatividade todos da equipe irão participar das atividades de cunho gerencial e logo será mais fácil inovar e melhorar o processo como um todo.

Se você usa Scrum pode passar parte das tarefas do Scrum Master para o Tracker por exemplo como atualizar o backlog, isso não elimina o fato de que todos tem de atualizar o quadro nas reuniões diárias.

Muitas vezes o gerente de projetos está muito ocupado ou gerencia mais de um projeto ao mesmo tempo, com essa utilização do Tracker rotativo as coisas ficam mais fáceis para o GP.

January 21, 2009

Swing Fácil com Groovy: Como criar seus próprios componentes

Não tenho dúvidas que o desenvolvimento de aplicações desktop com Java tem seu problemas. Não digo apenas pela estrutura de composite do Swing, ou de classes gigantes com muitas responsabilidades como o JFrame. Mas mesmo com todos esses problemas vejo o desenvolvimento de aplicações Swing para Java ainda com viabilidade.

Hoje é dia é comodismo desenvolver aplicações para Web. O que acontece é que nem todos os sistemas ou nem todas as funcionalidades dos sistemas podem ser feitas na web, por que?
  • Complexidade do desenvolvimento com JavaScript
  • Consumo de memória do cliente(Browser)
  • Complexidade de tecnologias Ajax VS problemas de uso de Arquiteturas Commet.
  • Falta de bons IDEs e Debuggers para JavaScript
  • Pouca performance na execução de JS devido a sua arvore DOM.
  • Tempo de desenvolvimento e custo de manutenção
Quando desenvolvemos com Swing puro por mais nojento que possa ser ainda assim nos livramos de muitos problemas. Vejam que eu não sou contra o desenvolvimento para web, mas sem sempre é viável, e temos que avaliar a possibilidade de sistemas RichClient.

Como deixar o Swing melhor?

A melhor coisa seria um refatoração e re-design da API mas como isso não é simples e mesmo que feito iria dar muito custo e problemas de manutenção/migração. Então qual seria uma possibilidade intermediária? Groovy!

O Groovy tem um recurso muito bom que é o suporte a Builders que são classes que seguem o pattern Builder. Com esse objetos podem criar objetos de maneira muito mais fácil e produtiva, sem falar que o código fica muito mais simples por se parecer com uma DSL.



Por que usar um Builder?

A questão não é só clareza, simplicidade e produtividade, com um Builder vamos alem disso. Um Builder é como um factory só que parametrizavel, logo se você constrói suas interfaces com Builders do Groovy ao invés de Swing direto você ganha a possibilidade mudar o comportamento da interface sem ter que mudar todas as telas!

Como isso é possível?

Isso é possível devido a duas coisas que se usadas em conjunto vão dar a você a flexibilidade e robustez necessárias a suas aplicações desktop. A primeira delas é fazer hold da variável de builder no seu código para uma classe mais superior. Aqui estou me referindo a boa e velha programação para interfaces, isso é bem possível de se fazer com groovy por que existe o BuilderSupport.

A única coisa que para mim deixou a desejar foi no design do SwingBuilder por que esse cara não segue a mesma hierarquia de classes do BuilderSupport. Bom até a versão 1.5.7 é assim vamos ver se agora nas próximas versões os caras da SS resolvem isso :)

Criando os seus próprios Builders

Criar um builder é uma tarefa relativamente fácil a questão é a complexidade que você irá colocar no seu componente. Vou mostrar como criar um builder de gui que extende o SwingBuilder e adiciona um novo widget que gera uma caixa de texto que só permite digitação de números!

Dependências
  • JDK 1.6
  • Groovy 1.5.7 (groovy-all-1.5.7.jar)
Passos necessários
  • Criar o Builder
  • Criar uma factory
  • Registrar essa factory no builder
Como você pode perceber com poucos passos podemos fazer e já colocar o builder em uso. Vamos ao código do builder então.

CustomSwingBuilder.java

package com.blogspot.diegopacheco.groovy.builder;

import groovy.swing.SwingBuilder;

import com.blogspot.diegopacheco.groovy.builder.factories.NumericTextFactory;

/**
* Builder groovy que adiciona funcionalidades ao builder do Swing.
*
* @author Diego Pacheco
* @since 20/01/2009
* @version 1.0
*
*/
public class CustomSwingBuilder extends SwingBuilder{

public CustomSwingBuilder() {
super();
}

/**
* Método que registra as factories que vao processar os widgets adicionados por você.
* Você deve informar a tag do widgets e a factory que processa o mesmo.
*
*/
@Override
protected void registerWidgets() {   
super.registerWidgets();
registerFactory(NumericTextFactory.WIDGET_TAG, new NumericTextFactory());
}

}

Esse é o Builder fato. Ele extende o SwingBuilder e tem a sobre-escrita do método registerWidgets esse método registra as factories que tem os widgets personalizados que você venha a construir!

Neste caso por uma questão de boas práticas estou passando uma constante com a tag do widget que no caso tem o valor "caixaNumeros", que sera a tag que você utilizara no groovy.

Agora vamos ao código da factory NumericTextFactory.java
package com.blogspot.diegopacheco.groovy.builder.factories;

import groovy.util.AbstractFactory;
import groovy.util.FactoryBuilderSupport;

import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JTextField;

/**
* Factory que cria um JLabel com controle de digitação
* que soh deixa digitar numeros.
*
* @author Diego Pacheco
* @since 20/01/2009
* @version 1.0
*
*/
public class NumericTextFactory extends AbstractFactory{

public static String WIDGET_TAG = "caixaNumeros";

@Override
@SuppressWarnings("unchecked")
public Object newInstance(FactoryBuilderSupport builder, Object name,Object value, Map attributes) throws InstantiationException, IllegalAccessException {

JTextField textField = new JTextField((String)attributes.get("text"));
textField.setBackground(Color.YELLOW);       
textField.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
textField.setToolTipText("Digite algum número entre 0 e 9!");

attachEvents(textField);       
return textField;
}

/**
* Metodo que adiciona eventos ao botao
* @param textField
*/
private void attachEvents(JTextField textField){

textField.addKeyListener(new KeyListener(){
public void keyPressed(KeyEvent e){}               
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){
System.out.println(e.getKeyChar());                   
if ( (e.getKeyChar() >=48 && e.getKeyChar()<=57)){                         // numeros validos                     }else{                         e.consume();                     }                                }         });             }     } 
Aqui que as coisas acontecem! Essa classe extende AbstractFactory que é a factory padrão dos builders do Groovy ela já contem os métodos do ciclo de vida do parser do Groovy, assim você tem um conjunto de métodos estilo callback a sua disposição. Nesse caso só foi necessário o uso do método newInstance o qual cria um objeto JTextField e chamo um metodo privado que eu criaei para colocar o tratamento de eventos. O tratamento de evento só deixa que se digite números de 0 a 9. Agora podemos testar o builder em um código Groovy chamei de GroovyUsage.groovy
package com.blogspot.diegopacheco.groovy.builder.usage

import java.awt.*
import javax.swing.*
import groovy.swing.*

import com.blogspot.diegopacheco.groovy.builder.*

/**
* Classe groovy que mostra como usar o builder.
*
* @autor Diego Pacheco
* @since 20/01/2009
* @version 1.0
*
*/
public class GroovyUsage {

def swing = new CustomSwingBuilder()

public void renderMe(){       

def frame = swing.frame(title:'Tela de Teste', size:[300,300]) {
borderLayout()
caixaNumeros(text:"",constraints: BorderLayout.NORTH)
}
frame.show()       
}

public static void main(String []args){
new GroovyUsage().renderMe()       
}

}
Aqui podemos ver que esta sendo usado a tag caixaNumeros(text:"",constraints: BorderLayout.NORTH) e mais nada! Se você rodar esse código ira aparecer uma tela com uma caixa de texto que só permite a digitação de números! Ese exemplo é muito simples! O importante aqui é as possíbilidades que esse recurso do Groovy nos permite dentre as muitas possíbilidades podemos:
  • Criar componentes customizados e usa-los de forma produtiva
  • Colocar controles arquiteturais do tipo segurnça, i18m, etc...
  • Requisitos de usabilidade como cores, posicionamento, fonte, etc...
Dentre outras tantas utilidades, se quizerem os fontes estão disponíveis aqui!

January 17, 2009

Backup fácil no Ubuntu com Groovy e Groosh

Em um projeto de desenvolvimento de software é comum usar boas práticas de gerência de configuração e ambiente. Essas práticas são na maioria traduzidas em processos de ferramentas.

Ferramentas são utilizadas para diversos propósitos como controlar a versão do código ou controlar os buils do projeto ou controlar e gerenciar o bugs e issues do projeto. Normalmente por questões de custo e performance essas ferramentas ficam em um ambiente Linux. Logo não basta apenas ter um bom conjunto de ferramentas que auxiliam no desenvolvimento mas é necessário ter bons scripts de backup também.

Utilizando o Bugzilla por exemplo como ferramenta de BugTracking você possuirá uma base de bugs e ocorrências sobre eles. Você não vai querer perder esses dados pois eles são muito úteis para tratar e controlar a evolução doa software mas também para o trabalho de métricas de um profissional de Qualidade de software.

Bom já que não queremos perder essas informações precisamos fazer backup. Mas qual a melhor maneira de fazer esse backup? Uma maneira fácil e eficiente é usar os scripts bash do próprio linux. Mas e se você precisar fazer algum script de backup mais apurado? Nem todos os desenvolvedores Java são programadores bash! Então que tal fazer os backups com Groovy?

O que é Groovy?

Groovy é uma linguagem de script que roda em cima do Java. Com o Groovy podemos ter toda a robustez do Java mas em forma de script e com isso ganhamos em simplicidade e produtividade acima de tudo.



Groovy + Bash + Shell ?

O Groovy tem um modulo muito legal que é o Groosh. Se trata de um MOP que abstrai as chamadas ao shell ou bash. Com ele podemos invocar os principais comandos linux em um script Groovy com isso podemos criar scripts poderosos de backup sem reinventar a roda.

Vamos então a uma passo a passo para a instalação do Java 6 no linux e também a instalação do Groovy e é claro do Groosh também.

Instalando o JDK 6 no Ubuntu

primeiramente você deve remover todas as versões do Java que por ventura já estejam instaladas na máquina. Você deve remover os pacotes do synaptic, rpm e por ventura se você tiver instalado algum jdk na mão também deve ser removido. Esse procedimento de remoção você pode pular, mas por uma questão de boas práticas de gerência de configuração é muito saudável que você a faça.

Então baixe o JDK 6 no site da sun. Vamos utilizar o JDK 6 Update 11. Logo você deve baixar o arquivo *jdk-6u11-linux-i586.bin*. Uma vez esse arquivo baixado você deve o tornar executável, você pode fazer isso com o comando chmod +x jdk-6u11-linux-i586.bin.

Agora crie a pasta java dentro do diretório /usr. você pode fazer isso com o comando: sudo mkdir /usr/java a sua senha será solicitada. Agora basta executar o arquivo com o comando: sudo ./jdk-6u11-linux-i586.bin você devera segurar ENTER até terminar de ler a licensa e por fim digite yes para finalizar a instalação.

Agora basta criar as váriaveis de ambiente do Java, evite o arquivo /home//.bashrc com o vim, então comando fica assim:
sudo /home//.bashrc

Aqui vamos colocar o export da váriavel de ambiente do Java. Adciione as seguintes linhas no arquivo:
#
# Variaveis de ambiente do Java 6
#
JAVA_HOME=/usr/java/jdk1.6.0_11
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME

Para testar feche o shell e abra de novo o shell e digite: java -version, deve aparecer algo do tipo:
pacheco@cromx:/usr/java$ java -version
java version "1.6.0_11"
Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Server VM (build 11.0-b16, mixed mode)

Instalando o Groovy no Ubuntu

Por uma questão de boas pricas também vamos instalr o Groovy no /usr/java. Então se posicione nesta pasta antes de continuar.

Após você ter instalado o java devidamente agora vamos instalar o Groovy. Vamos utilizar a versão 1.5.7 do Groovy, você deve baixar no site do groovy o arquivo groovy-binary-1.5.7.zip. Uma vez o arquivo baixado você deve o tornar executável para isso use o comando: sudo chmod +x groovy-binary-1.5.7.zip. OK agora vamos extrair o arquivo usando o unzip. O comando fica assim: sudo unzip groovy-binary-1.5.7.zip.

Agora é necessaŕio setar as váriaveis de ambiente do Groovy, edite novamente o arquivo /home//.bashrc com o vim e adicione as seguintes linhas ao final do arquivo:

#
# Variaveis de ambiente do Groovy
#
GROOVY_HOME=/usr/java/groovy-1.5.7
PATH=$GROOVY_HOME/bin:$PATH
export GROOVY_HOME

Para testar a instalação do Groovy feche o shell e o abra de novo e digite: groovyConsole. Deve aparecer uma tela semelhante a essa:



Instalando o Groosh no Groovy do Ubuntu

Para finalizar as instalações agora só falta instalar o Groosh. Ele é instalado dentro do groovy como uma biblioteca do tipo jar. Então vá no site do Groosh e baixe o mesmo. Vamos utilizar a versão 0.3.0 do Groosh.

Baixe o arquivo groovy-groosh-0.3.0-bin.tar.gz. deixe o arquivo executavel com o comando: sudo chmod +x
groovy-groosh-0.3.0-bin.tar.gz. Agora é necessaŕio extrair o arquivo com o comando tar. Faça isso com esse comando: sudo tar -vzxf groovy-groosh-0.3.0-bin.tar.gz. Agora basta copiar o jar do groosh para a pasta de libs do groovy vocÊ faz isso com esse comando a baixo:
cp groovy-groosh-0.3.0.jar /usr/java/groovy-1.5.7/lib

Agora para testar a instalação crie um arquivo chamado test.groovy e digite o seguinte código:
import static groosh.Groosh.groosh
import static org.codehaus.groovy.groosh.stream.DevNull.devnull

def gsh = new groosh.Groosh()
gsh.ls().toStdOut()

Para rodar o arquivo basta digitar no console: groovy test.groovy. Esse script irá listar todos os arquivos do diretório corrente usando o comando do linux ls.

Agora já temos toda a infra-estrutura para realizar backups com Groovy e Groosh de maneira fácil aproveitando o melhor do linux e do Groovy.

Que comandos posso usar com o Groosh?

Todos! basta fazer por exemplo new groosh.Groosh().SeuComandoLinux! Podemos usar o su, o ls, o grep, o tar, emfiem não existe limites. Podemos encadear vários comandos também.

Podemos listar os programas em execução:

import static groosh.Groosh.groosh
import static org.codehaus.groovy.groosh.stream.DevNull.devnull

def gsh = new groosh.Groosh()
gsh.ps().toStdOut()

Podemos fazer pipes e usar o grep do linux por exemplo também:
import static groosh.Groosh.groosh as shell
import static org.codehaus.groovy.groosh.stream.DevNull.devnull
import static org.codehaus.groovy.groosh.stream.StandardStreams.stdout

shell().ls("/usr/java/") | shell()._grep("gz") | stdout()

Veja que aqui o grep foi usado com um _grep isso se deve por que o Groovy já tem um comando grep e para não conflitar com o grep do linux usamos o underline.

Podemos fazer um script mais apurado como esse a baixo:
import static groosh.Groosh.groosh as shell
import static org.codehaus.groovy.groosh.stream.DevNull.devnull
import static org.codehaus.groovy.groosh.stream.StandardStreams.stdout

def g = shell().ls("/usr/java/") | shell()._grep("groovy")
def linhas = shell().each_line { l, w ->
w.write("Resultado: $l \n")
}

g.pipeTo(linhas)
linhas.toStdOut()

Esse scirpt faz um ls no diretório /usr/java e depois uma pesquisa com o grep por diretorios ou arquivos com o nome contendo a palavra groovy. Com o closure each_line do Groosh podemos customizar o processamento de cada linha do resultado de um pipe para outro.

No final o pipe do grep para o closure é executado e o resultado é mostrado no console.

Você pode compactar arquivos usando o tar do linux o script para fazer isso é muito simples:
import static groosh.Groosh.groosh as shell
import static org.codehaus.groovy.groosh.stream.DevNull.devnull
import static org.codehaus.groovy.groosh.stream.StandardStreams.stdout

shell().tar("-zcvf",new File("/home/pacheco/backup.tar.gz"),"/usr/java").toStdOut()

Agora você já possui o ambiente e o miniomo de conhecimento necessário para fazer seus script com shell e Groovy. Espero que tenha ajudo alguém :)

January 16, 2009

O Papel do Arquiteto de Software

Quando falamos de um projeto desenvolvimento de software que se utilize Java como linguagem de programação é comum ouvir de alguém que você precisa de um arquiteto de software. Na verdade esta necessidade não é única de projeto Java, independente da tecnologia de implementação dependendo da magnitudede seu projeto você vai precisar tanto de um arquitetocomo você precisaria de um analista ou gerente de projetos.

Diferente do que muitos pensam arquitetura não significa escolher frameworks, a arquitetura de software vai muito além do que meramente decidir se no projeto vão utilizar Spring ou Hibernate, Struts ou JSF.

Mas qual o papel do Arquiteto de Software?

Em poucas palavras é dar suporte e participar de todas as decisões técnicas significativas em termos de design e implementação. Em outros termos estamos falando de riscos, a arquitetura serve para mitigar os principais riscos técnicos de um projeto, veja que eu disse os principais ao invés de todos.

Se você trabalha com riscos no seu projeto e trabalha com priorizarão de requisitos essa é uma tarefa relativamente simples, pois a arquitetura já sabe com o que deve se preocupar e com o que não deve dar muita atenção e deixar os desenvolvedores resolver.

Agora se você não trabalha com riscos e não possui priorizarão de requisitos isso pode se tornar em um grande problema e a arquitetura pode perder o foco e se preocupar e gastar energia de mais com questões de importância inferior.



Eis que existe a fronteira com requisitos...

Se você estiver utilizando um processo baseado em RUP, você irá fazer uma análise inicial de negocio focando 80% dos requisitos mais importantes do sistema e desses requisitos 20%+- serão os requisitos mais importantes para arquitetura. O arquiteto participa dessa priorizarão de requisitos por que ele sabe o que pode ser critico em termos técnicos e o que deve ser preocupação da arquitetura e o que não deve ser.

Arquiteto não precisa saber das regras de negócio?

Esse é um grande erro! Um arquiteto de verdade deve se preocupar muito com as regras de negócio, isso de que arquitetura é um coisa e requisitos e analise são outras não existe! O arquiteto de software precisa se preocupar com as regras e a cima de tudo entender e conhecer os requisitos do sistema!

A arquitetura também serve para atender os requisitos do sistema! Se a sua arquitetura Java não atende os requisitos do sistema para que ela serve? Usar frameworks por modismo não serve de nada, não podemos nos esquecer que o objetivo não é utilizar frameworks ou desenvolver código de arquitetura. O objetivo é solucionar os problemas do negócio com um sistema!

Sim, existem arquiteturas de referencias!

Por mais que alguns agilistas teimem isso existe. Quando estamos em um contexto corporativo, normalmente existe um domínio mais fechado e os sistemas não fogem muito de uma linha e você pode e deve reaproveitar componentes e acima de tudo reaproveitar sistemas e isso que é SOA!

Nem sempre a solução está somente no Java

Muitas vezes a solução é mais heterogênea! Não conseguimos resolver todos os problemas somente com Java. As vezes é necessário envolver código de banco como PL/SQL por exemplo ou até mesmo outras linguagens como Delphi, VB, C, etc...

Não é necessário conhecimento especifico!

Um bom arquiteto não é aquele que sabe tudo de Spring ou EJB, mas é aquele que conhece os principais componentes de uma solução e conhece outras coisa como banco de dados, requisitos, processos, metodologias, redes, protocolos, web, etc... Como já dizia ou Vitruvius:

"O arquiteto ideal deve ser uma pessoa erudita, um matemático, familiarizado com estudos históricos, um estudioso aplicado de filosofia, conhecedor de música, que não desconheça medicina, detentor de saber jurídico e familiarizado com astronomia e cálculos astronômicos." - Vitruvius, circa 25 BC
Em geral o arquiteto precisa muitos de alguns skills como: Liderança, comunicação, pro-atividade, com relacionamento com a equipe. Sem falar que o mesmo deve entender de Design de sistemas!

A arquitetura fica pronta na fase de elaboração?

Outro erro! A fase de elaboração do RUP serve para mitigar riscos não para concluir a arquitetura. Ninguém quer fazer uma BIG Arquitetura Up to Front! Outro equivoco comun que vejo é a arquitetura de papel, você precisa desenvolver código da fase de elaboração, não precisa ser código em volume, mas é necessário ter desenvolvimento!

A prova de conceito arquitetural deve ser o mais real o quanto for possível. Se possível já utilize requisitos do usuário consolidados(Casos de uso)! Lembrando que se você fizer toda a arquitetura nessa fase você estara cacateando o projeto, e isso é muito ruim. :(

January 11, 2009

Apresentações no SlideShare

Criei uma conta no slideshare e coloquei algumas apresentações lá. A partir de hoje vou começar a colocar as apresentações lá. De facto com o Slideshare é mais fácil para visualizar, baixar e compartilhar apresentações. Uma grande vantagem é que ele disponibiliza um objeto para você colocar em seu website ou blog.

Coloquei algumas postagens como o novo recurso, vocês podem conferir clicando nos links a baixo:

January 6, 2009

Não Existe Separação entre Requisitos e Desenvolvimento

Acho que uma das primeiras coisas que todos aprendemos ou deveríamos ter aprendido na faculdade ou em uma curso técnico (sou do antigo PD) ou até mesmo trabalhando é que o modelo em Cascata é ruim. De facto não é um modelo ruim por natureza, só que para o desenvolvimento de software não funciona!

Muitos sabem disso ou pior pensam que sabem, provavelmente qualquer pessoa que você falhe vai concordar com você sobre isto, porem na prática na hora de executar as coisas, o que eu vejo por ai é muito projeto em Cascata até mesmo projetos que se dizem ágeis.



É o velho desenho do balanço. Mas a grande questão que esse desenho nos trás é a seguinte palavra: Requisitos. Também não é nenhuma novidade que cada real gasto em requisitos pode ser 60% mais caro em produção. Muitos falam que sabem disso mas na prática eu vejo justamente o contrário.



Um sintoma de que as coisas não estão indo bem, sinal de confusão :) é separar as disciplinas em fases ou momentos. Não existe um momento de análise ou um momento de programação. O que existe são momentos em que existe mais desenvolvimento do que análise, bem como o RUP já nos mostra através do gráfico de Baleias.

Quando estamos realizando a análise de requisitos existe um processo inicial chamado de triagem que é nele que vão nascer os requisitos candidatos. Esses requisitos candidatos podem ser desenvolvidos e gerenciados por um lista simples. Uma vez eles devidamente validados eles viram requisitos consolidados e deixam de ser requisitos candidatos.

Os requisitos e o processo de triagem não é de uso exclusivo para requisitos do usuário, devemos utilizar isso para requisitos não funcionais também, leia-se arquitetura de sistemas meus amigos. Muitas vezes o processo de requisitos e análise vai bem mas quando falamos de arquitetura os requisitos são esquecidos. Não podemos deixar de trabalhar com requisitos para o desenvolvimento da Arquitetura assim como de Casos de Uso.

Quando estamos realizando o trabalho de requisitos de alguma forma mesmo que não tão direta como a codificação estamos dando características para a solução essas características são tão fortes que devem ser visíveis de fora do sistema. Assim já estamos de certa forma fazendo a solução, as pessoas se enganam quando acham que a solução vem com projeto e desenvolvimento, na verdade a solução inicia nos requisitos.

Por que ?

O grande objetivo da Arquitetura, Projeto e Codificação é atender os requisitos, sejam eles Use Cases, Features, Stories ou o que forem. Logo você deveria estar sempre se pergunta qual requisito ou quais requisitos esse seu código ai está atendendo. Com isso as coisas se encaixam, as atividades de codificação e de levantamento de requisitos não podem ser coisas separadas.

Você precisa saber o que construir antes de construir(Requisitos) mas você também precisa saber se o que você está construindo é viável (Arquitetura) e também precisará ver como construir (Projeto) e por fim construir e testar. Por isso não ache que é perda de tempo quando os analistas de Requisitos estão conversando muito com os desenvolvedores e arquitetos.

De novo, muitas pessoas dizem que sabem disso, mas no final na hora de fazer o projeto não fazem essas coisas, por fim pecam nas práticas mais básicas.

Estimando com Scrum

É possível ter um certo nível de predicatibilidade utilizando Scrum. Podemos realizar estimativas de valor com o método. Isso pode ser atingido mesmo com uma certa rotatividade de recursos humanos da equipe. O único requisito é que as iterações tenham o tamanho fixo.

Falando de iterações com tamanho fixo isso é variável de projeto a projeto, empresa a empresa. O Recomendável é que isso fique de 1 a 4 semanas, pelo Scrum. Falando de RUP ou EVO por exemplo podemos ter iterações maiores, mas iterações mais curtas já se provaram mais produtivas.

A grande questão a se balancear é o overhead de se fazer a retrospectiva do Scrum e abrir a nova Sprint pois esses processos comem tempo! Mas uma vez você escolhendo o tamanho de sua iteração ou como o Scrum chama: Sprint, você deve utilizar esse padrão sempre.

Agora podemos estimar, o Scrum recomenda que utilizemos a sua medida abstrata que são os pontos, muitas pessoas utilizam isso em conjunto com User Stories ou até mesmo features. Eu particularmente prefiro utilizar Casos de Uso. Independentemente desta questão é a forma de estimar o Scrum por ser utilizando em iterações relativamente curtas utiliza uma medida abstrata como padrão mas você pode utilizar outra como Linhas de Código, Horas, Dias, Número de Telas, UCP, Etc...



Podemos realizar estimativas utilizando a técnica da temperatura do dia passado, no caso a Sprint passada. O processo funciona assim, no dia do planejamento da Sprint você precisa contar quantas pessoas e por quantos dias elas vão trabalhar.

Supondo que você utilize Sprints de 2 semanas e que você tenha 4 colaboradores trabalhando os dias da Sprint então teríamos uma tabela do tipo:



Aqui todos menos o Zelano estão trabalhando todos os dias da Sprint, veja que ele trabalha 4 dias a menos que os outros, isso pode ser por que ele tem que ira ao médico ou qualquer outro compromisso que ausenta ele do projeto. Essa tabela irá variar de Sprint a Sprint ora podem ter mais colaboradores ora menos ora mais dias ora menos e assim por diante.

Somando tudo vamos chegar o ManDays que significa a quantidade de Pessoas que vão trabalhar em tantos dias. Aqui nesse exemplo o total é de 36. Então aplicamos as formulas a baixo:



Sendo que a primeira Sprint é diferente pois você não tem Sprint passada para utilizar como entrada para essa, a sugestão que dou é colocar o fator de foco entre 40% e 60% ai depende da sua confiança quanto a essa sprint.

Então com o fator de foco podemos calcular o SEV(Estimativa de Velocidade da Sprint) que é calculado com a soma de todos os pontos da Sprint * o fator de foco. Lembrando que essa é a primeira estimativa, é difícil de acertar. Bom as coisas variam de projeto a projeto mas entre 3 e 5 Sprints é para as coisas se estabilizarem e o SEV tende a ser muito preciso ou muito próximo da precisão.

Agora da segunda a ultima Sprint do projeto você pode pegar o fator de foco da Sprint passada, lembre-se que a tabela de Mandays foi feita no inicio da sprint, então pode ser que alguém ficou doente ou saiu do projeto logo você deve atualizar essa tabela. Para calcular o Fator de Foco(FF) da Sprint passada você pega o total de pontos entregues e divide pelo Mandays realizado da Sprint passada então esse FF você pode usar na estimativa da próxima Sprint.

O FF é como se fosse a sua produtividade, falando de um modo geral. E esse valor vai se ajustando para mais ou para menos de Sprint a Sprint, a vantagem de utilizar esse mecanismo é saber se os pontos ou a maioria deles vão ser entregues nessa Sprint. Isso pode ser utilizado como dita o Scrum em sua forma pura para estabelecer se tais funcionalidades do sistema vão estar disponíveis ou não e pode ajudar na priorizarão, ou seja, saber se você pode entregar os pontos que o usuário deseja.

January 5, 2009

WebService REST fácil com Groovy e Jersey

Como já disse o Jim Webber o WSDL deve morrer! Não tenho dúvidas de que em termos de produtividade e simplicidade utilizar WS-REST é a melhor solução do que utilizar WS-*. Em 2007 já tinham surgido soluções em Java para implementação de WS-REST como o RESTLet. Hoje após a criação da JSR-311, que dita como criar um WebService REST em Java existem já alguns frameworks que podemos utilizar além do RESTLet como o Jersey.

O Jersey é um framework Java que implementa a JSR-311 além de ser a implementação de referência para essa JSR. Com ele podemos escrever WebServices REST de maneira fácil e rápida utilizando um conjunto de anotações.

Você pode publicar um WS-REST utilizando qualquer container como o Glassfish, JBoss, Oracle IAS, ou até mesmo o Tomcat. Mas existe um pequeno servidor chamado de Grizzly. Esse servidor é escrito em Java e prove acesso via HTTP e de forma parcial a API de servlets, mas isso é mais do que suficiente para a escrite e disponibilização de um WS-REST.

Vou mostrar como é fácil fazer um WebService REST utilizando Groovy, Grizzly e Jersey. O código é muito simples e resumo você expoe um POJO Groovy anotado com as anotações do Jesery através do Grizzly, ai basta consumilo com um client. Esse client pode ser um script Groovy, o seu browser ou quaçquer linguagen como Delphi, PHP, .NET, etc...



GroovyPojo.groovy
package com.blogspot.diegopacheco.groovy.rest.server

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

/**
*
* POJO Groovy que utiliza as anotaçoes do Jersey.
*
* @autor Diego Pacheco
* @since 05/01/2009
* @version 1.0
*
**/
@Path("groovy-pojo")
class GroovyPojo {

@GET
@Produces(["text/html"])
def show() {
"groovy WS-REST Rocks!"
}

@GET
@Produces(["text/html"])
@Path("/diego")
def showPath() {
"http://diego-pacheco.blogspot.com"
}

}

Esse é o POJO que será exposto via Grizly. Reparem que ele possui as anotações do Jersey. Vou explicar anotação por anotação.
  • @GET: Aqui estou dizendo que quando esse recurso for invocado pelo método GET do HTTP o método que possui essa anotação será executado. Você pode usar outras anotações, no caso o Jersey concencionou que as anotações tem o mesmo nome do método no protocolo HTTP. EX: @PUT, @POST, etc...
  • @Produces(["text/html"]) : Aqui estou dizendo que o método que possuir essa anotação gerá como saida HTML poderia ser texto puro mesmo, XML ou outra saida.
  • @Path("/diego"): Por fim essa anotação indica que mesmo o resucros sendo exposto deverá ser acessível ainda pelo caminho /diego. Semelhante a uma página dentro de um context root.
É importante reparar que o POJO tem uma anotação de @Path isso significa que ele só será acessível por esse caminho. Agora vamos ao código do Servidor.

GroovyRESTServer.groovy
package com.blogspot.diegopacheco.groovy.rest.server

import com.sun.grizzly.http.SelectorThread;
import com.sun.grizzly.tcp.Adapter;
import com.sun.jersey.api.container.ContainerFactory;
import com.sun.jersey.api.container.grizzly.GrizzlyServerFactory;
import com.blogspot.diegopacheco.groovy.rest.server.GroovyPojo;

import javax.ws.rs.core.UriBuilder;

import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;

/**
*
* Server Groovy que utiliza o Grizzly para levantar um endpoint WS-REST
* feito em Groovy.
*
* @autor Diego Pacheco
* @since 05/01/2009
* @version 1.0
*   
**/

adapter = ContainerFactory.createContainer(Adapter.class,GroovyPojo.class)
baseUri = UriBuilder.fromUri("http://localhost/").port(10101).build()
server = GrizzlyServerFactory.create(baseUri, adapter)

System.out.println("Jersey WS-REST startado... OK");
System.out.println("Tente digitar: http://127.0.0.1:10101/groovy-pojo no seu browser")
System.in.read()
server.stopEndpoint()

Você deve deixar essa classe rodando para que o server fique no ar. Como você pode ver ele é muito simples, como estou utilizando Groovy as coisas ficam mais simples ainda.

A primeira coisa foi costruir um adpter via ContainerFactory.createContainer, aqui eu digo qual adpter eu vou utilizar e qual POJO eu quero expor. Depois eu monto a URL que o WS-REST vai responder com o UriBuilder. Finalmente o WS-RESt é criado no Grizzly com o GrizzlyServerFactory.

Agora vamos ao código cliente. Após subir o server a qualquer momento você pode digitar no Browser:
  • http://127.0.0.1:10101/groovy-pojo
  • http://127.0.0.1:10101/groovy-pojo/diego
Des de que o server esteja no ar é claro :) O código cliente foi escrito em Groovy também, mais uma vez pela simplicidade e facilidade, você poderia escrever em outra linguagem.

GroovyRESTClient.groovy
package com.blogspot.diegopacheco.groovy.rest.client;

import groovy.util.GroovyTestCase

import com.sun.grizzly.http.SelectorThread;
import com.sun.grizzly.tcp.Adapter;
import com.sun.jersey.api.container.ContainerFactory;
import com.sun.jersey.api.container.grizzly.GrizzlyServerFactory;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;

import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.core.UriBuilder;

import com.blogspot.diegopacheco.groovy.rest.server.*;

/**
*
* Client Groovy que consome o WS-RESt feito em Groovy. 
*
* @autor Diego Pacheco
* @since 05/01/2009
* @version 1.0
*   
**/

ws = Client.create().resource(UriBuilder.fromUri("http://localhost/").port(10101).build());

println "Retorno do WS-REST foi 1: " + ws.path("groovy-pojo").get(String.class)
println "Retorno do WS-REST foi 2: " + ws.path("groovy-pojo/diego").get(String.class)

Através do Client.create() acessei o WS-RESt feito em Groovy e depois para usar os métodos publicados foi utilizado o .path() para dar o path e por fim disse como eu queria pegar o retorno, nesses casos tudo é String.

Se Alguem quizer o código está disponível aqui. Utilizei o plugin do Groovy para o eclipse, se tiverem problemas com plugin do Groovy na versão 3.4.1 do eclipse verifiquem isso.