Retrabalho e prejuízo

{ January 8th, 2009 }


cmilfont

Autor: cmilfont

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<ItemDevolucao> itensDevolucao = 
		new ArrayList<ItemDevolucao>();
 
}
 
@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<ItemApreensao> itensDevolvidos = 
				new ArrayList<ItemApreensao>();
 
}

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.

Categories: Certifica√ß√Ķes, Design Patterns, Engenharia de Software, Java, Melhores pr√°ticas, Metodologia, M√©todos √Āgeis, Scrum, Test Driven, XP ~ ~ Trackback


Assine os coment√°rios deste artigo.


16 Responses to “Retrabalho e preju√≠zo”

  1. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 12
    Rafael Carneiro

    @Ponte

    O meu pensamento foi por essa linha.

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

    […] do post anterior? Aquele sobre retrabalho e […]

  14. 14
    Trabalho Energizado e a Teoria das 2 horas produtivas - Milfont Consulting

    […] Duas horas produtivas para mim √© uma licen√ßa po√©tica para “c√≥digos test√°veis de forma automatizada, bem escritos, entregues por dia independente de tempo e que n√£o trar√£o retrabalho”. Um par evita muito retrabalho, lembrando que retrabalho n√£o √© refactoring, √© preju√≠zo. […]

  15. 15
    Palestra Agilidade no Mundo Real - Milfont Consulting

    […] Retrabalho e Preju√≠zo http://www.milfont.org/tech/2009/01/08/retrabalho-e-prejuizo/ […]

  16. 16
    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…

Leave a Reply