[Parcialmente Resolvido] Eliminando um IF complicado

Boa noite.

Depois de muito tempo, cá estou com uma dúvida nas melhores práticas.

O caso é o seguinte:

Tenho uma classe, chamada ARS. A classificação de uma ARS é definida por 3 atributos:

[list]Ocorrencia: Intervenção Manual, Investigação e Correção[/list]
[list]Complexidade: Complexa, Média, Simples e Muito Simples.[/list]
[list]detstatus: Procedente ou Improcedente[/list]

Existe uma funcionalidade na aplicação que é a pontuação de cada ARS baseada nesses 3 atributos. Isso gerou o IF abaixo (com valores fictícios) que estou “doido” para eliminar, pois, até para mim, que foi quem desenvolveu a aplicação, é difícil de dar manutenção:

	/**
	 * Business logic for ARS's score
	 * @return the score of ARS
	 */
	public double getScore() {
		if (this.detStatus == null) {
			detStatus = "";
		}
		if ((isInvestigacaoProcedente()) && (isComplexa())) {
			return 150.0;
			
		}else if ((isInvestigacaoProcedente() || isIntervencaoManualProcedente()) && (isMedia())){
			return 35.0;
			
		}else if (((isInvestigacaoProcedente() || isIntervencaoManualProcedente()) && (isSimples())) ||
				((isInvestigacaoImprocedente()) && (isMedia())) || 
				((isIntervencaoManualImprocedente()) && (isComplexa()))){
			return 15.0;
			
		}else if (((isInvestigacaoProcedente()) && (isMuitoSimples())) ||
				((isInvestigacaoImprocedente()) && (isSimples()) ||
						(isIntervencaoManualImprocedente()) && (isMedia()))){
			return 7.5;
			
		}else if ((isInvestigacaoImprocedente()) && (isComplexa())) {
			return 12.5;
			
		}else if (((isIntervencaoManualProcedente()) && (isMuitoSimples())) ||
				((isIntervencaoManualImprocedente()) && (isSimples()))){
			return 11.0;
		}else {
			return 0.0;
		}
	}

Com o Design Patterns da GoF e o Padrões de Projeto em Java do Steven John Metsker debaixo do braço, fui a luta e achei que os os padrões State ou Strategy pudessem resolver meu problema.

Mas antes de definir entre os dois padrões, preciso definir a modelagem.

Pensei em criar uma hierarquia que começasse de ARSStatus descesse para ocorrencia, depois para complexidade e depois para procedencia (detstatus). Acontece que desta forma, eu teria uma quantidade absurda de classes na hierarquia (40).

Tendo isso em vista, pensei em criar classes que combinassem os valores desses 3 atributos e fazer um override do método pontuar() em cada uma delas. Dessa forma, eu teria 24 classes. Entretanto, o que me preocupou foi o tamanho dos nomes das classes =).

Um ex: IntervencaoManualMuitoSimplesImprocedente :shock:

Estou inclinado a usar essa segunda abordagem, pois, apesar do nome grande, me parece que IntervencaoManualMuitoSimplesImprocedente é uma classe do sistema.

Qual a melhor abordagem para esse caso, a primeira? a segunda? ou nenhuma delas?

Obrigado.
Abraços!

Oi,
Os valores de retorno do getScore representam alguma coisa ou são simplesmente “os valores de getScore”?
Por exemplo: num jogo existem 3 tipos de ponto, cada ponto tem um nome e valor especial (ponto de falta, ponto de tiro livre e ponto total), cada um desses pontos possui uma regra especial.

class Score {

    isFalta(); // e tome umas regras aqui esse retorna 1
    isPontoDeTiro(); // idem esse retorna 2
    isPontoTotal(); // e aqui mais complexo ainda esse retorna 3
    isPontoNulo();

    getScore(); // retorna ou isFalta ou isPontoDeTiro ou isPontoTotal ..., alguma coisa tem que retonar, nem que seja isPontoNulo
}

Eu tentaria essa abordagem. Fica claro pro sujeito ler isso?

public Boolean isInvestigacaoProcedenteComplexa() {
   return isInvestigacaoProcedente() && isComplexa()
}

public Boolean isInvestigacaoManualProcedenteMedia() {
    return ((isInvestigacaoProcedente() || isIntervencaoManualProcedente()) && (isMedia()))
}

public Integer getScore() {
  //switch aqui dentro
  if (isInvestigacaoProcedenteComplexa)
     return ARS.VALOR_X
  if (isInvestigacaoManualProcedenteMedia)
     return ARS.VALOR_Y
}

No final das contas serão n métodos onde n == número de valores (150.0, 0.0) que você precisa.
Acho legal também avaliar se isInvestigacaoProcedente é tão diferente de isInvestigacaoImprocedente é tudo Investigacao?

No mais, futuramente, posta aqui qual foi a solução!

Inté.

Esqueci de dizer: boa sorte, vai com calma, pede opnião pro resto da equipe, e testa (na boa, precisa MESMO).

Amigo, obrigado por ter utilizado seu tempo com o meu problema.

Gostei da sua solução, já melhoraria o entendimento. Entretanto, a princípio, estou procurando uma solução mais OO, com herança e overriding do método pontuar().

Se eu não conseguir implementar dessa forma (e vou começar a caminhar hoje), com certeza usarei a sua sugestão, muito obrigado.

Agora, respondendo as suas perguntas:

Representa sim. Esta pontuação é importante para o negócio.

Para efeito de pontuação, uma reclamação improcedente do usuário é diferente de uma reclamação procedente.

Então… estou inclinado a usar a minha segunda hipótese.

Conseguindo a modelagem, o late-binding, devo partir pelo caminho das 24 classes com os nomes grandes (mas claros). Entretanto, nessas 24 classes, haverá replicação de código no pontuar(), já que a lógica é implementada da mesma forma para alguns grupos.

Talvez eu divida os grupos de pontuação e reduza a quantidade de classes e ainda mate a duplicação.

Pensei nisso a pouco tempo, tenho que amadurecer a idéia. A princípio, me pareceu a melhor saída.

Mais uma vez obrigado.

Abraços.

Acho que já melhorou um pouco, mas ainda não estou plenamente satisfeito, pois ainda quero ver se coloco as filhas de Score num Map e faço pegar a instância correta, sem if’s. Ainda não vi como. :x
Nessa nova versão, ainda existem 3 níveis de IF, só que encapsulados na nova classe Classification.
Também ainda não estou satisfeito com o local do método getScore(). Não sei se pegar a instância correta de Score seja responsabilidade de Classification.
Segue a nova estrutura, partindo do método que starta toda a coisa.

Classe ARS

	/**
	 * Business logic for ARS's score
	 * @return the score of ARS
	 */
	public double getScoreValue() {
		if (classification == null) {
			// Necessary, because the Hibernate, for reasons that I ignore
			// makes this component null if the data on table is null
			classification = new Classification();
		}
		Score score = classification.getScore();
		return score.getValue();
	}

Classe Classification onde a subdivisão em grupos de pontuação pode ser vista.

	public Score getScore() {
		if (isVeryHigh()) {
			return new VeryHigh();
			
		}else if (isHigh()){
			return new High();
			
		}else if (isAbove()) {
			return new Above(); 
		
		}else if (isMedium()){
			return new Medium(); 
			
		}else if (isLow()){
			return new Low(); 
			
		}else if (isVeryLow()){
			return new VeryLow();
			
		}else {
			return new Score();
		}
	}

Classe Score com o método getValue() default

/**
 * Superclass for Score definition
 * @author Celso Martins
 * @since 03/04/2009
 */
public class Score {
	
	public Score() {
		super();
	}
	
	public double getValue() {
		return 0.0;
	}
}

Não creio que as filhas sejam necessárias, pois só possuem uma implementação diferente de getValue().

Os testes rodaram na boa.

Claro que aceito (e peço) opniões para melhorar essa joça.

Continuarei pensando essa arquitetura.

Obrigado a todos que, pelo menos, olharam e analisaram o problema. E obrigado ao faq por ter olhado, analisado e sugerido. Sugestão essa que aproveitei nessa nova arquitetura.

Abraços.

Oi,
Acho que não fui claro na mina pergunta / resposta:
Essas 24 classes servem apenas para se obter o valor do score?
Se as combinações de ocorrência, status, etc são importantes para -além- de obter o score, pode ser o caso de se criar todas as 24 classes, mas se elas servem apenas para formar o score, eu acho overkill.

Terminando o serviço mostra aqui no fórum!

Inté!

[quote=faq]Oi,
Acho que não fui claro na mina pergunta / resposta:
Essas 24 classes servem apenas para se obter o valor do score?
Se as combinações de ocorrência, status, etc são importantes para -além- de obter o score, pode ser o caso de se criar todas as 24 classes, mas se elas servem apenas para formar o score, eu acho overkill.

Terminando o serviço mostra aqui no fórum!

Inté![/quote]

Pois é… separadamente, esses atributos servem para alguma coisa. E, como está nesse meu ultimo post, abandonei a idéia das 24 classes, pois haveria redundância de lógica. Assim, preferi criar esses 6 grupos de pontuação.

Estou ainda pensando na solução para esses trocentos IFs, como utilizar um MAP, por exemplo. Mas ainda não vi como.

Abraços.

[quote=celso.martins]Acho que já melhorou um pouco, mas ainda não estou plenamente satisfeito, pois ainda quero ver se coloco as filhas de Score num Map e faço pegar a instância correta, sem if’s. Ainda não vi como. :x
Nessa nova versão, ainda existem 3 níveis de IF, só que encapsulados na nova classe Classification.
Também ainda não estou satisfeito com o local do método getScore(). Não sei se pegar a instância correta de Score seja responsabilidade de Classification.
Segue a nova estrutura, partindo do método que starta toda a coisa.

Classe ARS

	/**
	 * Business logic for ARS's score
	 * @return the score of ARS
	 */
	public double getScoreValue() {
		if (classification == null) {
			// Necessary, because the Hibernate, for reasons that I ignore
			// makes this component null if the data on table is null
			classification = new Classification();
		}
		Score score = classification.getScore();
		return score.getValue();
	}

Classe Classification onde a subdivisão em grupos de pontuação pode ser vista.

	public Score getScore() {
		if (isVeryHigh()) {
			return new VeryHigh();
			
		}else if (isHigh()){
			return new High();
			
		}else if (isAbove()) {
			return new Above(); 
		
		}else if (isMedium()){
			return new Medium(); 
			
		}else if (isLow()){
			return new Low(); 
			
		}else if (isVeryLow()){
			return new VeryLow();
			
		}else {
			return new Score();
		}
	}

Classe Score com o método getValue() default

/**
 * Superclass for Score definition
 * @author Celso Martins
 * @since 03/04/2009
 */
public class Score {
	
	public Score() {
		super();
	}
	
	public double getValue() {
		return 0.0;
	}
}

Não creio que as filhas sejam necessárias, pois só possuem uma implementação diferente de getValue().

Os testes rodaram na boa.

Claro que aceito (e peço) opniões para melhorar essa joça.

Continuarei pensando essa arquitetura.

Obrigado a todos que, pelo menos, olharam e analisaram o problema. E obrigado ao faq por ter olhado, analisado e sugerido. Sugestão essa que aproveitei nessa nova arquitetura.

Abraços.[/quote]

Que tal assim:

[code]public class Score {
private final pontos;
public Score(double pontos) {
super();
this.pontos = pontos;
}

public double getValue() {
	return pontos;
}

}
[/code]
Daí você elimina a necessidade de ter um monte de classes Score.

Outra possibilidade:

[code]public enum Score() {
VERY_HIGH(7.0), HIGH(6.0), ABOVE(5.0), MEDIUM(4.0), BELOW(3.0), LOW(2.0), VERY_LOW(1.0), ZERO(0.0);

private final double pontos;

private Score(double pontos) {
    this.pontos = pontos;
}

public double getValue() {
    return pontos;
}

}
[/code]Edit: O que há nestes métodos isVeryHigh(), isHigh(), isAbove(), etc.?

Em primeiro lugar, obrigado Victor!

Dessa forma, quando eu criar a classe Score, eu já deveria saber o valor da pontuação, não é?
O que eu estou querendo é que isso seja definido em runtime, instanciando uma filha correta de Score. No momento, a definição desse score é simples, mas, como diz um colega por aqui, vai que muda?.

Tive sérios problemas para dar manutenção nessa BL, apenas duas horas após implementada (eu já sabia disso na implementação), quando tive que descobrir porque um determinado caso estava retornando 0. Com a nova estrutura de IF sugerida pelo faq já ajudou bastante, mas além disso, eu queria ver se conseguia alguma coisa mais OO.

Acho que dessa forma, facilita a manutenção. Pelo menos já me senti melhor ao dar manutenção depois da refatoração.

Eu também não sei se “estou procurando chifre em cabeça de cavalo”. Se estou viajando demais nessa situação. Mas é viajando que se aprende. =)

Talvez essa inquietação me ajude a melhorar, ou não. =)

Interessante essa implementação com ENUM, mas pelo que entendi, eu também teria que saber a pontuação no momento da instanciação, o que estou querendo evitar (não sei se corretamente).

[quote=victorwss]
Edit: O que há nestes métodos isVeryHigh(), isHigh(), isAbove(), etc.?[/quote]

Uma implementação parecida com o que foi colocada no meu primeiro post nessa thread. Lembrando que os valores e a lógica são fictícias, mas servem para demonstrar onde eu queria chegar. Creio. =)

Abraços.

Tenta algo assim:

public interface Regra { public boolean aplicar(SeuObjeto obj); public double pontos(); }[code]public class RegraVeryHigh implements Regra {// Nome tosco, eu sei. Não pensei em um melhor
public boolean aplicar(SeuObjeto obj) {

}

public double pontos() {
    return 150.0;
}

}[/code]public class SeuObjeto { ... public double getScore() { for (Regra r : regras) { if (r.aplicar()) return r.pontos(); } return regraDefault.pontos(); } }

Oi celso.martins, blz?

Então…lendo sobre a sua questão o que me veio a cuca foi o seguinte:

O pattern Decorator; esse, se não me engano, é aquele que utilizaram para formar o preço de um cafezinho baseado nos valores de insumos no livro Padrão de Projetos.

Achei o seu problema semelhante ao exemplo do livro, lá eles queriam formar o preço aqui vc quer formar o score da sua ARS o problema é que pra resolver a sua questão desta maneira acredito que teria que distribuir o valor dos scores entre as classificações de suas ARS (Intervenção Manual, Investigação e Correção, Complexa, Média, Simples, Muito Simples, Procedente, Improcedente) de forma que teriamos “pesos” diferenciados para cada uma destas “classificações”. Como resultado final teriamos a seguinte situação: Ao pedir o score de uma ARS a operação iria SOMAR os pesos das classificações que lhe foram atribuidas e formariam o score, sem precisar de fazer nenhum IF e só iria haver manutenção quando fosse criado uma nova classificação.

Problema nesta “solução”:

  1. Nem sempre é possível dividir este tipo de valor de forma coerente e justa.
  2. Se vc criar uma nova classificação, vc correrá o risco de modificar o perfil do score a partir deste momento porque ela entrará na somatória fazendo com que os totais que representam os scores se modifiquem.

Espero ter apresentado um novo caminho para este seu problema.

flws

Acho que uma leitura nesses links te ajudará a resolver seu problema:

http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html
http://www.refactoring.com/catalog/replaceConditionalWithVisitor.pdf
http://sourcemaking.com/refactoring/replace-conditional-with-polymorphism
http://c2.com/cgi/wiki?ReplaceConditionalWithPolymorphism

Meus amigos… agradeço as respostas. Estou acompanhando vivamente o que estão sugerindo. Estou sem tempo de analisar e testar as propostas pois acabei de mudar de equipe e estou em semana de provas.

Neste fim de semana, vou tentar implementar estas sugestões.

Mas vou colocar as impressões que tive.

[quote=victorwss]Tenta algo assim:

public interface Regra { public boolean aplicar(SeuObjeto obj); public double pontos(); }[code]public class RegraVeryHigh implements Regra {// Nome tosco, eu sei. Não pensei em um melhor
public boolean aplicar(SeuObjeto obj) {

}

public double pontos() {
    return 150.0;
}

}[/code]public class SeuObjeto { ... public double getScore() { for (Regra r : regras) { if (r.aplicar()) return r.pontos(); } return regraDefault.pontos(); } }[/quote]

Victor, gostei dessa sugestão. Me parece simples e eficiente. Parece deixar o codigo mais claro também.

[quote=fantomas]Oi celso.martins, blz?

Então…lendo sobre a sua questão o que me veio a cuca foi o seguinte:

O pattern Decorator; esse, se não me engano, é aquele que utilizaram para formar o preço de um cafezinho baseado nos valores de insumos no livro Padrão de Projetos.

Achei o seu problema semelhante ao exemplo do livro, lá eles queriam formar o preço aqui vc quer formar o score da sua ARS o problema é que pra resolver a sua questão desta maneira acredito que teria que distribuir o valor dos scores entre as classificações de suas ARS (Intervenção Manual, Investigação e Correção, Complexa, Média, Simples, Muito Simples, Procedente, Improcedente) de forma que teriamos “pesos” diferenciados para cada uma destas “classificações”. Como resultado final teriamos a seguinte situação: Ao pedir o score de uma ARS a operação iria SOMAR os pesos das classificações que lhe foram atribuidas e formariam o score, sem precisar de fazer nenhum IF e só iria haver manutenção quando fosse criado uma nova classificação.

Problema nesta “solução”:

  1. Nem sempre é possível dividir este tipo de valor de forma coerente e justa.
  2. Se vc criar uma nova classificação, vc correrá o risco de modificar o perfil do score a partir deste momento porque ela entrará na somatória fazendo com que os totais que representam os scores se modifiquem.
    [/quote]

Também entendi as suas considerações e a partir desta sua mensagem, minha mochila ganhou uns 8Kg com os dois livros de Pattern que citei no primeiro post. Estou tentando decifrar o Decorator. O Strategy, devido a outra sugestão que recebi há algum tempo aqui no fórum, eu já vinha mastigando.

Ainda não tenho nada de concreto para definir.

[quote=Emerson Macedo]Acho que uma leitura nesses links te ajudará a resolver seu problema:

http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html
http://www.refactoring.com/catalog/replaceConditionalWithVisitor.pdf
http://sourcemaking.com/refactoring/replace-conditional-with-polymorphism
http://c2.com/cgi/wiki?ReplaceConditionalWithPolymorphism[/quote]

Bem Emerson. Em primeiro lugar, obrigado por você ter entrado na discussão. Seu post me deu um certo trabalho de pesquisa também (o que é muito bom). Principalmente com a questão do Visitor que até então eu só tinha lido rapidamente. Acho que o “replace conditional with polymorphism” é o que estou tentando fazer, não?

Não estou conseguindo acessar o link do Visitor por aqui. Mas já deu uma rota para uma outra linha de raciocínio.

Mas agora, outra dúvida surgiu: O Strategy seria realmente a pior abordagem para esse caso? O motivo seria a possibilidade de aumento significativo no número de classes, caso aumente a quantidade de estratégias que definem uma pontuação?

Mais uma vez obrigado a todos.

Abraços.

Cara, eu acho que você está indo no caminho certo sim. No caso do Visitor você pode esquecer por enquanto e se concentrar apenas no polimorfismo. Depois que você conseguir melhorar bem a organização desse código, dá uma olhada no Visitor pra ver se vai fazer sentido aplica-lo.

A solução correta para seu problema eu não tenho muito como pensar pois você não postou o que faz os métodos isInvestigacaoProcedente(), isComplexa(), isXXX(), etc. Acho que talvez nem precise mas o importante é você pensar que precisa ter objetos para representar os conceitos do teu sistema. Pode ser que faça sentido ter objetos como Ocorrência ou Complexidade talvez. Isso você vai ter que analisar pois eu não sei do que se trata o domínio desse teu problema.

[]s

Assim que eu conseguir implementar alguma coisa com a solução do Victor, o Decorator (fantomas) e com o Visitor (Emerson), ressuscitarei este tópico, postando os códigos.

Por enquanto, obrigado a todos pelas respostas.

Abraços!

Olá Celso, acho excelente você se interessar em melhorar a qualidade do seu trabalho, se metade do pessoal com quem eu trabalho pensasse como você eu seria mais feliz :slight_smile:

mas, contudo, eu vou ser um cara chato e discordar da idéia de fazer 24 classes para substituir esse unico método.

meu argumento é o seguinte:

o objetivo da melhoria no código é torna-lo mais entendível certo? eu não acho que fazendo 24 arquivos diferentes e espalhar a logica por um monte de lugar vai ajudar nesse caso. até porque você está tento muito trabalho para entender esse pattern, o próximo que terá de fazer manutenção nesse código vai ter que fazer o mesmo esforço, isso se ele souber de antemão que isso é um pattern, senão ele vai ficar muito perdido antes de entender o que acontece (em termos de lógica de negócio, que é o que importa no final das contas).

eu sugiro o seguinte: estude os patterns, mas implemente eles em coisas mais simples primeiro, pra você avaliar melhor em que casos eles são mais útil.

faça uma refatoração simples no teu código, ela pode ajudar muito na visualização da lógica, inclusive com uns comentários para ajudar.

como o código abaixo por exemplo, acrescentando alguns comentários vai ficar muito melhor

  /**
   * Business logic for ARS's score
   * @return the score of ARS
   */
  public double getScore() {

    if (this.detStatus == null) {
      detStatus = "";
    }

    boolean intervencaoNaoManualProcedente = isInvestigacaoProcedente();
    boolean intervencaoManualProcedente = isIntervencaoManualProcedente();
    boolean intervencaoProcedente = intervencaoNaoManualProcedente || intervencaoManualProcedente;

    boolean intervencaoProcedenteSimples = intervencaoProcedente && isSimples();
    boolean intervencaoProcedenteMedia = intervencaoProcedente && isMedia();

    boolean intervencaoManualProcedenteMuitoSimples = intervencaoManualProcedente && isMuitoSimples();

    boolean intervencaoNaoManualProcedenteMuitoSimples = intervencaoNaoManualProcedente && isMuitoSimples();
    boolean intervencaoNaoManualProcedenteComplexa = intervencaoNaoManualProcedente && isComplexa();

    boolean intervencaoManualImprocedenteSimples = isIntervencaoManualImprocedente() && isSimples();
    boolean intervencaoManualImprocedenteMedia = isIntervencaoManualImprocedente() && isMedia();
    boolean intervencaoManualImprocedenteComplexa = isIntervencaoManualImprocedente() && isComplexa();

    boolean investigacaoImprocedenteSimples = isInvestigacaoImprocedente() && isSimples();
    boolean investigacaoImprocedenteMedia = isInvestigacaoImprocedente() && isMedia();
    boolean investigacaoImprocedenteComplexa = isInvestigacaoImprocedente() && isComplexa();

    if (intervencaoNaoManualProcedenteComplexa) {
      return 150.0;
    }
    else if (intervencaoProcedenteMedia) {
      return 35.0;
    }
    else if (intervencaoProcedenteSimples || investigacaoImprocedenteMedia || intervencaoManualImprocedenteComplexa) {
      return 15.0;
    }
    else if (intervencaoNaoManualProcedenteMuitoSimples || investigacaoImprocedenteSimples || intervencaoManualImprocedenteMedia) {
      return 7.5;
    }
    else if (investigacaoImprocedenteComplexa) {
      return 12.5;
    }
    else if (intervencaoManualProcedenteMuitoSimples || intervencaoManualImprocedenteSimples) {
      return 11.0;
    }
    else {
      return 0.0;
    }
  }

ps: já vi muita gente se afundar em pattern e acabar fazendo coisas incompreensíveis, muitos colegas que se afundavam em livros fizeram códigos difíceis de alterar que acabaram afundando o projeto. o segredo é ir com calma, não se empolgar demais com essa de pattern e achar que tudo é pattern, afinal no trabalho temos que mostrar mais resultado que fazer experiencias.

maschiojv, em primeiro lugar, obrigado por se interessar pelo problema.

Acho que se a maioria dos desenvolvedores dessem a devida importância à qualidade, as nossas vidas seriam mais interessantes. :wink:

Bem, voltando aos IFs, esse assunto ainda está em aberto, pois mudei de equipe recentemente e não estou podendo dar a devida atenção.

Esse assunto continuou sendo desenvolvido aqui. Inclusive estou devendo uma postagem de código por lá. Confesso que esqueci. =)

Por enquanto, a solução está como na minha última postagem. Como o ViniGodoy não gritou, acho que estou mais ou menos no caminho. A solução mostrada pelo luBS eu já havia tentado. Algo não me agradou nessa abordagem. Achei estranho usar “alguma coisa” a partir de algo que parece uma constante. =)

Além disso, me parece ferir a Lei de Demeter.

Mais uma vez obrigado… e sinta-se a vontade para mais sugestões.

EDIT:

[quote=maschiojv]
ps: já vi muita gente se afundar em pattern e acabar fazendo coisas incompreensíveis, muitos colegas que se afundavam em livros fizeram códigos difíceis de alterar que acabaram afundando o projeto. o segredo é ir com calma, não se empolgar demais com essa de pattern e achar que tudo é pattern, afinal no trabalho temos que mostrar mais resultado que fazer experiencias.[/quote]

Eu sou da lei do mais simples possível. Ficou fácil de manter (geralmente chamo um estagiário amigo meu para dar uma olhada)? Então vamos que vamos. Claro que estou sempre buscando a melhor forma, mas sempre respeitando a facilidade de manutenção.

Quanto ao trabalho, meu líder vive me pedindo para esquecer o Java. Sabendo que vou no Falando em Java 2009, já me avisou que vai começar a me “entubar” por conta da minha teimosia. Estou trabalhando em uma das áreas de integração e uso uma ferramenta que não tem nem o cheiro do Java: Informática PowerCenter.

Qualquer envolvimento meu com desenvolvimento, no meu atual momento, é por amor. Então, estou no campo das experiências mesmo, forçando o desenvolvimento de algumas ferramentas para a empresa e pesquisando. Assim, não deixo enferrujar.

Meu blog também foi uma ótima idéia para não deixar a peteca cair.

Enfim, vamos que vamos.