Retrabalho e prejuízo

Em todos os projetos que trabalhei até hoje no mercado local [Ceará] existem profissionais mais ou menos qualificados a partir de uma base mínima de qualidade que um profissional tem que possuir dentro do modelo “Enterprisey” – que estamos acostumados e que responde pela quase totalidade dos projetos de software.

Essa base mínima eu proponho que seja – dentro do modelo exposto –  raciocínio lógico. O resto ele pode aprender.

Raciocínio lógico está ligado diretamente a noção de avaliar a situação, encontrar um padrão, investigar soluções existentes e implementar a solução, além claro de bom senso.

Não adianta pregarmos que os profissionais deveriam ser melhor escolhidos assim ou assado porque a realidade é que as empresas não tem como medir satisfatoriamente quem é ou não competente e mais cedo ou mais tarde você se deparará com indivíduos em sua equipe vindos por diversas nuances administrativas, seja aquele superqualificado cheio de títulos ou o primo do diretor da empresa.

Aonde quero chegar com essa história?

Precisamos avaliar os riscos necessários com bastante antecedência para que toda a equipe e consequentemente o projeto não sejam lesados e paguem o preço da incompetência às vezes de um único elemento. Parece óbvio? Acredite, não é!

Temos um projeto em um cliente – uma Alfândega – que precisamos refatorar todo o código criado por um determinado profissional com apenas dois ou três meses pronto. O projeto ainda está no início e já temos que refazer código.

Convenhamos, tudo bem que o código de meia hora atrás já é legado, mas código tão recente não deveria já ser refatorado sem mudança na lógica de negócio ou arquitetural. Algo muito errado aconteceu.

Mudanças não funcionais acontecem, surge um novo paradigma ou framework que reduz o tempo de desenvolvimento e convenientemente é adequado sua mudança, isso é comum durante a manutenção de um software já em produção com um meio século de uso – que em informática dura cerca de 4 ou 5 anos.

O nosso em questão não há motivos. Projeto novo, sem restrição ou adequação à “Arquitetura de Referência”, Frameworks de última milha na plataforma Java como JSF, Spring e Hibernate. Testes unitários – mas não TDD.

Como dito, separei um exemplo em código para demonstrar aonde quero chegar. Tem uma lógica bastante simples, existe um processo de apreensão de mercadorias na alfândega e liberação dessa mercadoria.

Há 3 tabelas que representam isso no modelo E/R: TB_DEVOLUCAO, TB_ITEM_APREENSAO, TB_ITEM_DEVOLUCAO. Segundo a lógica relacional, a TB_ITEM_DEVOLUCAO é uma tabela de junção entre a devolução e os itens apreendidos para indicar que item será devolvido.

Seguindo minha definição, um profissional com raciocínio lógico encontraria fácil a solução do mapeamento entre essas entidades apenas lendo a documentação, ele saberia que o Hibernate tem um mapeamento de OneToMany com Join Table Uni ou Bidirecional.

Mas não, ele criou essa bizarrice:

@Entity
@Table(name="TB_DEVOLUCAO")
public class Devolucao {

	@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
	@JoinColumn(name="SEQ_ITEM_DEVOLUCAO")
	@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
	private List itensDevolucao = 
		new ArrayList();
	
}

@Entity
@Table(name="TB_ITEM_DEVOLUCAO")
public class ItemDevolucao { //Para que essa entidade?

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name="SEQ_ITEM_DEVOLUCAO", columnDefinition="NUMERIC")
	private Integer codigo;

	@OneToOne
	@JoinColumn(name="SEQ_ITEM_APREENSAO")
	private ItemApreensao itemApreensao;
	
}

Esse profissional em questão é graduado em computação, tem mestrado em uma federal, certificação como arquiteto Java e diversas outras certificações e pasme, anos de experiência em projetos. Mas não tem o básico, raciocínio lógico. Não investiga e não sabe desenvolver software de qualidade.

O código em questão pode parecer bobagem até mas isso se repete em todo o código criado por esse profissional.

Um profissional responsável em refatorar o código com apenas curso técnico e uma mísera certificação de programador java refatorou assim [como deve ser]:

@Entity
@Table(name="TB_DEVOLUCAO")
public class Devolucao {
	
	@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
	@JoinTable(name="TB_ITEM_DEVOLUCAO",
		joinColumns = @JoinColumn(name="SEQ_ITEM_DEVOLUCAO"),
		inverseJoinColumns = 
				@JoinColumn(name="SEQ_ITEM_APREENSAO")
	)
	@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
	private List itensDevolvidos = 
				new ArrayList();
	
}

Ad Hominem da minha parte? Tomar uma exceção pela regra? nada disso, eles são legião! Isso é meu cotidiano.

O prejuízo que esse profissional acarreta a todos os envolvidos é enorme e até difícil de ser mensurado porque envolve custos e humor da equipe que impacta em outros custos imperceptíveis na conta final que é a “fodisse” dos caras que tiveram que refatorar, ou seja, fizeram o seu e o trabalho alheio.

Ah, mas XP não prega o código coletivo? ir lá e consertar? Mas quebra o principal valor que é “Respeito”. Além do mais o projeto em questão seque o velho Cascata – mas culpa do cliente que exigiu ser assim, exigiu não, obriga.

Pela minha experiência de nada adianta você jogar um Clean Code nas mãos dele e pedir para estudar, ele vai continuar escrevendo nmDesc em uma propriedade ou IRepository em uma Interface. Ele foi treinado assim e sem raciocínio lógico no máximo que voce vão conseguir é retreiná-lo para conseguir comer a banana por outro túnel.

Um projeto sem um líder técnico responsável com aptidão e experiência necessária aliado a método baseado em BDUF sem um processo restritivo [como TDD] com modelagem ultrapassada com papéis de analista de sistemas “UMLizados” deixa esse tipo de profissional cometer esses pecados e prejudicar a todos os envolvidos retrabalho desnecessário.

É fácil resolver isso? É! O problema maior é que não podemos simplesmente aceitar que “o cliente quer assim”, temos um dever ético com nossa profissão de não permitir que o paciente escolha como ele quer ser operado e ceder médicos que não tenham capacidade de operá-lo.

16 thoughts on “Retrabalho e prejuízo

  1. Fabrício Lemos

    Infelizmente coisas assim não são raras. O melhor remédio para isso é programação em par, levando em conta outro valor do XP que é feedback. Quando o carinha começar a escrever umas coisas dessas, ter um par dividindo o trabalho ajuda a impedir a bizarrice.

  2. Rafael Ponte

    Fabricio,

    Programação em par, feedback e principalmente código coletivo com certeza poderiam solucionar este problema no código, mas para o cenário explanado pelo Milfont eu não vejo outra solução se não “puxar a orelha” desse bendito desenvolvedor-com-anos-de-experiência, ou na pior das hipoteses, infelizmente, coloca-lo no seu devido lugar.

    Uma coisa é errar, isso qualquer um pode, outra coisa é errar muito -e sempre- por falta de conceitos e fundamentos básicos sobre desenvolvimento de software.

    Infelizmente nossa realidade é essa, estamos rodeados de code-monkeys e “profissionais” com bons títulos/cargos/papeis nas empresas, mas que no final não possuem sequer o conhecimento necessário para serem apenas mais um code-monkey entre tantos outros.

    Enfim, excelente post Milfont, como sempre.
    Abraços.

  3. Rodrigo Galba

    esse caso pode levar a questão de que títulos não resolvem problemas, mas pessoas resolvem problemas. Até o mais experiente pode errar, e feio…

    ótimo post, Milfont!!
    massa!

  4. Anderson

    O primeiro erro foi usar Hibernate.

    O segundo foi colocar um programador ruim para fazer o serviço.

    O terceiro foi usar Hibernate.

    O quarto foi usar Hibernate.

    O quinto foi usar Hibernate.

    O sexto foi usar anotações (a.k.a. configuração hard coded).

    O sétimo foi não usar iBatis ao invés de Hibernate.

    Milfont, BTW você deveria postar mais, seus posts sempre são matadores. =)

    Abraços,
    – Anderson

  5. Diego Plentz

    Anderson, com todo respeito, você comeu bosta 🙂

    Annotations do Hibernate ajudam e muito a você seguir o conceito DRY. Deixar a configuração num xml – além de ser um pé no saco de manter – é um pé no saco de escrever.

    E o iBatis é uma piada de mal gosto 😉

  6. Marcos Eliziario Santos

    Cara, pense que poderia ser muito pior.
    Ele poderia ter feito medicina, ser até um neurocirurgião e um dia acabar fazendo uma cirurgia em você.
    Ele faz merda, mas logo, logo, se ele continuar sendo tão idiota, ele vira gerente, e aí para de atrapalhar.

  7. Anderson

    Oi Diego,

    As configurações em XML são muito úteis na minha opinião (e tão boas para DRY quanto anotações).

    Eu considero uma idéia terrível tirar as configurações de um local amplamente conhecido e escondê-las dentro de classes. Veja só alguns dos efeitos colaterais imediatos:

    * Mudou um parâmetro? Recompile o código e reempacote seu jar.
    * Programador novo no projeto? Leia essas 37 classes para entender como as coisas funcionam.
    * Hibernate specific: ter uma entidade *e* um TO me parece um overkill. Sem anotações bastaria um TO, pois o hibernate o trataria como entidade sem poluir o TO original.

    Quanto o iBatis ser uma piada de mau gosto, não concordo. É um *TIRO* para aprender e executar. Hibernate é leeeeeeeeeeento (apesar dos relatos em contrário do Gavin King) e muito mais difícil de configurar e usar. Ele te poupa do SQL mas em compensação te obriga a aprender um monte de outros conceitos. Sessões são uma dor em especial. É ridículo ter que ficar colcando lógica no controlador/qqr outra classe para passar os objetos “do jeito que o Hibernate espera” (WTF??) para a camada de serviço.

    É isso… =)

    Se você conseguir me convencer do contrário eu volto a usar o Hibernate =)

    Abraços,
    – Anderson

  8. Rafael Carneiro

    Não gosto de fazer comparativos entre tecnologias ou frameworks, mas o Plentz e o Anderson poderiam fazer alguns testes e análises sobre o Hibernate e iBatis, respectivamente.

    Apesar dos dois frameworks possuirem paradigmas diferentes, essa “comparação” seria uma boa, me lembra um artigo na última MundoJava. 🙂

  9. Rafael Ponte

    @Anderson
    ” Eu considero uma idéia terrível tirar as configurações de um local amplamente conhecido e escondê-las dentro de classes.”

    E classes que representam o modelo do domínio não são lugares amplamentes conhecidos pela equipe? Se não for, então há grandes problemas!

    * Mudou um parâmetro? Recompile o código e reempacote seu jar.”

    Hoje em dia preocupação com compilação, geração de código, empacotamento, testes, deploy etc você deixa para uma ferramenta de integração contínua, existem várias no mercado, e se ainda assim você não quiser uma, um simples Ant resolve o teu problema.

    “* Programador novo no projeto? Leia essas 37 classes para entender como as coisas funcionam.”

    Acredite, ler 37 xml’s, ou até menos, é centenas de vezes MENOS legível e manutenível do que ler um domain model, mesmo em um modelo capenga.

    “* Hibernate specific: ter uma entidade *e* um TO me parece um overkill. Sem anotações bastaria um TO, pois o hibernate o trataria como entidade sem poluir o TO original.”

    DTO? Você realmente precisa disso? Andas trabalhando com aplicações distribuídas? Além do mais, mesmo em uma aplicação distribuída, você não precisa de um DTO para cada entidade do seu modelo.

    “Ele te poupa do SQL mas em compensação te obriga a aprender um monte de outros conceitos.”

    A maioria dos frameworks/tecnologias te impulsionam a aprender novos conceitos ou até mesmo a abandonar velhos maus hábitos, isso é normal. E não deveria ser um problema para desenvolvedores.

    “Sessões são uma dor em especial. É ridículo ter que ficar colcando lógica no controlador/qqr outra classe para passar os objetos “do jeito que o Hibernate espera” (WTF??) para a camada de serviço.”

    Hoje temos vários frameworks (Spring, Guice etc) que cuidam disso para você, e o melhor, evitam o “glue code” na tua aplicação. Sem falar que estes mesmos frameworks tem uma excelente integração do iBatis, principalmente em relação a controle transacional.

    Anderson, eu conheço muito bem o iBatis pois já trabalhei muito tempo com ele, e sei bem suas diferenças em relaçao ao Hibernate/JPA, mas eu discordo de todos os teus argumentos em relação do Hibernate e os possíveis problemas que ele causa.

    Na verdade vejo que você está um poquinho desatualizado em relação ao framework.

    Enfim, discussões como estas são sempre bem vindas e agregam muito valor a todos.

  10. Rafael Ponte

    @Carneiro
    “[…] Apesar dos dois frameworks possuirem paradigmas diferentes, essa […]”

    iBatis e Hibernate não possuem paradigmas diferentes, ambos são frameworks ORM, contudo o iBatis é um ORM com um filosofia baseada em DAOs, apenas isso.

  11. Anderson

    haha =)

    quase comecei uma flamewar (how cool is that?) =)

    rafael, tréplicas abaixo.
    ——————————————-
    “E classes que representam o modelo do domínio não são lugares amplamentes conhecidos pela equipe? Se não for, então há grandes problemas!”

    isso mesmo: pela *equipe*. mas se colocar em XML qualquer novato/cara de fora da equipe já saca logo como as coisas funcionam. é um mapa da sua aplicação (e pelo amor de deus, pessoal, que fobia é essa de xml? não tá escrito em japonês não.).
    ——————————————-
    “Hoje em dia preocupação com compilação, geração de código, empacotamento, testes, deploy etc você deixa para uma ferramenta de integração contínua, existem várias no mercado, e se ainda assim você não quiser uma, um simples Ant resolve o teu problema.”

    concordo parcialmente. nem sempre vc tem o script ali fácil na mão. em muitos casos ser capaz de só salvar um xml e restartar o servidor (se tanto) é muito prático. mas é um bom ponto.
    ——————————————-
    “Acredite, ler 37 xml’s, ou até menos, é centenas de vezes MENOS legível e manutenível do que ler um domain model, mesmo em um modelo capenga.”

    aqui deu deadlock =)
    acho xml espetacular em termos e legibilidade… como eu disse antes, é um mapa da aplicação.
    ——————————————-
    “DTO? Você realmente precisa disso? Andas trabalhando com aplicações distribuídas? Além do mais, mesmo em uma aplicação distribuída, você não precisa de um DTO para cada entidade do seu modelo.”

    trabalho com rest diariamente, portanto preciso de TOs. mas rest é só um exemplo… não vejo como uma entidade substituiria um TO (a não ser como um wrapper inteligente em algo que deveria ser burro).
    ——————————————-
    “A maioria dos frameworks/tecnologias te impulsionam a aprender novos conceitos ou até mesmo a abandonar velhos maus hábitos, isso é normal. E não deveria ser um problema para desenvolvedores.”

    concordo. só esclarecendo que eu nunca insinuei que aprender coisas novas deveria ser um problema para desenvolvedores.
    ——————————————-
    “Hoje temos vários frameworks (Spring, Guice etc) que cuidam disso para você, e o melhor, evitam o “glue code” na tua aplicação. Sem falar que estes mesmos frameworks tem uma excelente integração do iBatis, principalmente em relação a controle transacional.”

    o spring é meu pão e minha manteiga =), e realmente ajuda *muito* na eliminação do boilerplate code (HibernateDAOTemplate é mão na roda).
    ——————————————-
    “Anderson, eu conheço muito bem o iBatis pois já trabalhei muito tempo com ele, e sei bem suas diferenças em relaçao ao Hibernate/JPA, mas eu discordo de todos os teus argumentos em relação do Hibernate e os possíveis problemas que ele causa.

    Na verdade vejo que você está um poquinho desatualizado em relação ao framework.”

    Nem tanto… parei no Hibernate Core 3.2.x / Hibernate Tools 3.2b9, ou seja, menos de um ano de defasagem (tudo bem, isso é muito tempo em TI).

    No fundo, acho que a melhor ferramenta é aquela à que você se adapta melhor. No meu caso, passei 4 anos +- felizes com o Hibernate, mas nosso relacionamente se desgastou =)

    Estou namorando com o iBatis há pouco menos de 1 ano e tem sido fantástico. Não é só rápido. É ridiculamente rápido. E ridiculamente fácil.
    ——————————————-

    Alfinetada final: anotações são o começo do fim. Vamos virar um exército de preguiçosos se isso pegar.

    Abraços,
    – Anderson

  12. Pingback: Retrabalho e prejuízo: Quod erat demonstrandum - CMilfont Tech

  13. Pingback: Trabalho Energizado e a Teoria das 2 horas produtivas - Milfont Consulting

  14. Pingback: Palestra Agilidade no Mundo Real - Milfont Consulting

  15. Hudson Leite

    Principalmente quando se trabalha para o “Governo”, o cliente sempre quer aquela nova feature pra ontem (mesmo o cré…dor levando algo em torno de 2 meses para homologar).

    Minha proposta nesse cenário (Lazy “Homologation” Customer) é enviar para “homologação” e nesse período/gap de tempo, alguém que por ventura se interessar, já que o código é coletivo, fazer uma mágica chamada “Refatoração”, justificando assim o salário que se recebe religiosamente do contribuinte com algo que gere valor ao invés de ficar coçando…

Comments are closed.