:: NEO Framework... Novo projeto Open Source brasileiro!

Usando um conceito lógico chamado backwards compatibility. Vc vai adicionar novas funcionalidades sem quebrar seja qual for a lógica que já está ali…

Exemplo prático:


public double parseExecutedQty(ByteBuffer buf) {
 
       // 100 linhas de um lógica gigantesca para parsear um inteiro que está num byte buffer...
       
       // isso sempre funcionou só que acabamos de descobrir que tem uma bolsa enviando quantidade executada em notação científica
       // e o seu chefe pediu para vc corrigir isso...
}

Em algum ponto da lógica acima, vc vai poder fazer um IF mais ou menos assim:


if (qtyString.indexOf("E") &gt 0) {

   // estamos falando de notação cientícia (1E4), 
   // logo aqui partimos para um algoritimo alternativo para parsear a coisa...

}

Não é difícil perceber que a alteração acima respeitou TOTALMENTE a questão da backward compatibility. O seu código novo só vai ser aplicado A SITUAÇÃO NOVA, sendo que para as situações antigas, que estão funcionamento perfeitamente, o código ficou praticamente intocado, ou seja, as linhas executadas (algoritmo) serão as mesmas. Isso se consegue com um mínimo de disciplina e lógica, ou seja, basta vc fazer um IF direito.

Essas são as situações práticas da vida real onde vc pode muito bem alterar uma coisa, sem teste unitário e sem quebrar nada…

OBS: Não tenho dúvida que existe profissionais por aí que diante desse problema iriam partir para uma re-implementação do método e/ou que não entendem o que venha a ser backwards compatiblity, etc. Vc não quer ser um profissional desses! E vc não quer ter um profissional desses na sua equipe.

Se ele for o filho do seu chefe, então vc realmente precisa de testes unitários e testes unitários passa a ser a coisa mais importante do seu sistema.

Não sei se conseguir passar minha opinião de que teste unitário, na maioria das vezes passa como um remédio que resolve apenas os sintomas do problema e não o problema em si…

Não seria melhor vocês criarem outro tópico para discutir estas coisas?

De vez de vocês incentivarem o projeto do cara que poderia ser uma coisa que facilitaria nosso dia a dia de trabalho, fição ai na briga de QUEM TEM O EGO MAIS ALTO.

Senhores, por favor mantenha a devida compostura.

O ponto é que não são os testes o grande milagre, mas como o desenvolvimento orientado a testes funciona.

Teste unitário, testam uma classe só, seguindo uma necessidade que você têm para ela.

Por exemplo: Eu tenho que criar um classe que faz soma e não pode aceitar numero negativos.

Eu vou lá, escrevo meu test, que no caso estou usando JUnit, mas poderia ser um main como já citaram aqui. O JUnit é um framework que te ajuda a fazer teste e só.

public void testSomaNaoAceitaNegativo() {
  MeuSomadorMaster somador = new MeuSomadorMaster();
  try {
    somador.soma(3, -1);
    fail("Deveria lançar exception com possitivo, negativo);
  } catch (Exception e) {}

  try {
    somador.soma(-3, 1);
    fail("Deveria lançar exception com negativo, possitivo);
  } catch (Exception e) {}

  try {
    somador.soma(-3, -1);
    fail("Deveria lançar exception com negativo, negativo);
  } catch (Exception e) {}

  assertEquals(4, somador.soma(3, 1));
}

É um exemplo simples, e assim como foi um exemplo simples foi super simples de fazer o teste.

Eu escrevi esse teste antes de implementar, e já tenho na minha cabeça como vou implementar pois fui pensando nisso enquanto escrevi o teste.

O que eu garanto com isso? Que vou fazer certo? Nesse caso nem isso, pois é bem simples e com certeza eu ia fazer correto. Mas eu já pensei na pratica como isso será utilizado e tenho certeza que amanha não vai aparecer um mané, que precisando que essa classe some negativos, mude o comportamento dela. Na qual todo o resto do sistema está baseado.

Testes unitários evitam 100% os Bugs? NÃO! E NINGUÉM ESTA FALANDO ISSO! Mas eles evitam que os bugs que você já pensou em evitar ou que já foram descobertos voltem a acontecer.

E se você escrever os testes antes do desenvolvimento, você vai ter uma baita ajuda para pensar na maneira mais simples de implementar algo. Quando você implementa algo sem nem saber como vai utilizado na real, você acaba complicando demais.

Abram a cabeça, experimentem, no inicio é complicado você demora muito para ter eficiência, mas depois que você aprende, você começa a programar melhor, mais rápido, mais simples e mais seguro.
Isso é um fato, mais do que documentado e vivido no mundo real.

Agora, não é só teste unitário que você tem que ter os outros testes continuam sendo necessário, mas acabam ficando mais simples e mais baratos.

Agora, existe sim o mundo dos sem testes, mas para esse mundo que até funciona. Se você usar testes, o seu design seria mais simples, melhor entendido por todos e mais barato (os problemas não voltariam a acontecer pq uma pessoa mudou uma classe de uma maneira que não deveria).

Fazer testes unitários no inicio, quando ainda não falta experiência e conhecimento, é dificil e trabalhoso. Depois acaba sendo muito mais rapido programar com testes do que sem testes. Vira uma ferramenta que te ajuda a tomar decisões de design, te ajuda a documentar o funcionamento de uma classe, te ajuda a entender o funcionamento de um framework que você achou na internet e tem testes, melhora a colaboração da equipe e a qualidade do software.

Por favor, comprem um livro de alguém reconhecido sobre TDD e desenvolvimento orientado a testes e leiam de cabeça aberta. Façam uma experiência. E parem de justificar a cabeça dura. É um fato que está sendo vivido pelas empresas e pessoas que geram software mais barato e melhor.

Utilizar um framework sem testes unitário, é acreditar muito na competência de uma pessoa, o problema é um bom framework deve ter um ambiente alltamente colaborativo, e ser altamente colaborativo em um ambiente aonde os testes são manuais é muito caro, além de ser chato, e quando se trabalha de graça as pessoas só querem fazer o que é legal.

Então, mesmo o framework sendo bom e tal, o fato de não ter testes unitário é um risco para a continuidade do framework, quando o atual core encher o saco e partir para outra. Além de ser um trabalho ter que testar (você não vai colocar um framework novo em produção sem testar né) o framework na mão.

Com testes unitário, você pode ir lá e ler se os testes do cara são suficiente para você ou não, pq usar só testes também não diz nada, têm que usar e usar bem.

Isso é gambiarra, na minha opinião. Depois de um tempo, o código estaria cheio de IFs que ninguém sabe ao certo pra que serve, colocados lá só para ser uma garantia mandrake de backward compatibility. Parece mais medo de mexer no códigos dos outros.

Interessante, se você procurar sobre programação orientada a gambiarras em sites do Wikipedia ou Desciclopedia, eles falam que isso é técnica de POG. Se você não sabe o porquê daquele código existir, coloca um IF e deixa ele lá. Se funciona, tá ótimo.

O problema é fazer backwards compatiblity sem você saber qual é o comportamento do método. Você têm que documentar isso, ou você documenta em javadoc, ou você documenta em word ou você documenta utilizando testes unitário.

A vantagem de utilizar testes unitário é que você têm certeza que quem implementar vai seguir direitinho tudo que você documentou.

As pessoas cometem erros, e isso não faz delas maus profissionais.

Você parece acreditar muito em profissionais perfeitos, tipo, e só o cara olhar o método é não fazer errado. Não é só, isso é tudo o que o ser humano não é, perfeito.

Quando você fala assim, soa no meu ouvido como se alguem fala-se assim: As montadoras não precisam testar os carros, é só o cara olhar as instruções e montar do jeito que tá lá. Você não vai querer ter um profissional que monta carro errado na sua equipe, vai?

Pois é, é POG e ainda é um code smell -> http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html

Isso é gambiarra, na minha opinião. Depois de um tempo, o código estaria cheio de IFs que ninguém sabe ao certo pra que serve, colocados lá só para ser uma garantia mandrake de backward compatibility. Parece mais medo de mexer no códigos dos outros.
[/quote]

Cara, eu acho que vc está confundindo IF com gambiarra. Um caso novo vai exigir um IF novo para tratar dele. Isso está longe de ser gambiarra, mas fique a vontade para propor uma solução alternativa PRÁTICA e enriquecer o debate…

Como vc faria a alteração no método parseExecutedQty para parsear notação científica?

[quote] O problema é fazer backwards compatiblity sem você saber qual é o comportamento do método. Você têm que documentar isso, ou você documenta em javadoc, ou você documenta em word ou você documenta utilizando testes unitário.
[/quote]

O meu ponto é o OPOSTO desse. Vc não precisa conhecer o código, nem saber o que ele faz para não quebrá-lo. Vc usou um IF e fez um branch, ou seja, partiu para um outro caminho e deixou o caminho anterior intocado.

Até funciona, mas concordo com o ZehOliveira, depois um tempo o código vai tá uma salada.

E a gente tava falando de refactoring, refactoring não é só adicionar um if ou fazer um override.

Realmente, ele trata o sintoma, pra ele não aparecer mais.
Teste unitário não resolve nada, só evita problemas, principalmente que os problemas voltem.

[]'s

Rodrigo Auler

[quote=eduveks][quote=pcalcado]
Das duas uma: ou seu software só tem essa tela ou você tem todo o tempo e recursos do mundo. Mesmo assim, é muito fácil um tester esquecer um passo ou fazer algo errado. Como disse antes um teste não substitui o outro mas teste click-click-click é simplesmente perda de tempo e dinheiro quando pode ser evitado. No seu exemplo acima no mínimo deveria ser utilizado algo como Selenium.
[/quote]

Quando q o teste click-click-click não é preciso? Como vc vai testar se o form esta bem do lado do cliente, e retornando a informação correta? Os testes unitários garantem isto?[/quote]

Leia novamente meu texto.

[quote=eduveks]
E como você vai fazer os testes funcionais, na mão? Quanto tempo demora para você fazer um teste de regressão? Testes unitários não eliminam testes funcionais, eles agem em um nível mais abaixo e quando você acha um bug num teste unitário é mais barato que num funcional. [/quote]

Eu concordo que um código sem testes tem valor, mas também concordo que a qualidade deste processo de desenvolvimento, não necessariamente do código, não é aceitável.

[quote=saoj][quote] O problema é fazer backwards compatiblity sem você saber qual é o comportamento do método. Você têm que documentar isso, ou você documenta em javadoc, ou você documenta em word ou você documenta utilizando testes unitário.
[/quote]

O meu ponto é o OPOSTO desse. Vc não precisa conhecer o código, nem saber o que ele faz para não quebrá-lo. Vc usou um IF e fez um branch, ou seja, partiu para um outro caminho e deixou o caminho anterior intocado.
[/quote]

Isso não é bom Sergio, pode até funcionar, mas com o passar do tempo você vai criando um monstro.

O melhor modelo de desenvolvimento, na minha opinião, é um ambiente colaborativo aonde todos sabem qual é a funcionalidade do software e o conhecimento está distribuido pela equipe.

Vamos supor que a parte de cima do método precise ser alterada, e o carinha que fez morreu atropelado na semana passada, testes unitário seriam uma mão na roda ter testes unitário, não?

E se testes unitários não lhe custa-se nada, além de tornar a sua equipe mais produtiva? Então, essa é a promessa do TDD, que eu e muitos aqui vivemos no dia-a-dia e damos o testemunho de que passada a fase de aprendizado aumenta a sua produtividade e qualidade.

Agora, você pode continuar ler e chamar isso de teórico e socialista (pelo visto, estar nos EUA esta lhe fazendo bem), mas é algo que eu e muitas empresas vivemos no dia-a-dia.

[quote=saoj]E quando vc colocar em produção, um belo dia vc vai descobrir um problema que vc nunca preveu e nunca poderia ter previsto… (Ex: Quantidade fracionada ou em notação científica quando uma ordem é executada). Nenhum teste vai pegar situação que vc não tem como prever, e isso já é uma grande desvantagem de testes, o que o torna meio inútil para muitas situações da vida real.
[/quote]

Vamos supôr que esta situação aconteceu e você recebe uma issue/trouble ticket com este problema. Quais os próximos passos?

Se você não criar um teste automatizado (funcional ou unitário, preferencialmente ambos) como vai ter um mínimo de garantia que ao corrigir este bug você não introduziu outros em funcionalidades que já estavam OK antes da mudança? vai testar tudo de novo manualmente ou com métodos main?

Quanto ao imprevisível, existe toda uma disciplina de engenharia de software dedicada a testes, sobre limites, classes de equivalência e demais características que, se aplicadas, reduzem as incertezas drasticamente. Estão entre nós há décadas, todo mundo estuda e faz prova disso na faculdade mas ninguém nem sonha em pôr em prática.

Não vou entrar na discussão ‘use OO e evite testes’ porque algumas páginas atrás já vimos que isso não é real. Que tal msotrar para seu chefe que você tem segurança de mudar o codebase e não é um code cowboy? E se você adoecer e outra pessoa tiver que fazer este refactoring? Como ele consegue saber que ao mudar aquela vírgula o comportamento básico da classe foi mantido?

Em OO nós utilizamos polimorfismo para comportamento que varia e não ifs, inviabilizando o argumento acima, mas esta não é a discussão.

Se você garante que seu código não tem erro parabéns, eu não sou tão bom assim e ninguém que tenha conhecido até hoje é, por isso me precavejo com testes que vão garantir que eu ou um dos meus 100+ colaboradores não quebrem contratos.

Colocar OO como panacéia quando os nomes mais importantes do paradigma (Fowler, Beck, Evans, Page-Jones, tres amigos, Gamma, Uncle Bob só os que lembro de cabeça) usam e escrevem livros sobre o uso de testes unitários é beeeeeeeeeem estranho. Eu não sei não mas acho que estes nomes entendem um pouquinho mais sobre o paradgima que eles ajudaram a criar, especificar e catalogar.

De novo quero deixar claro que não sou o dono da verdade, estou apenas colocando a minha opinião baseado na minha experiencia. Experiencias diferentes geram opiniões diferentes igualmente válidas.

Concordo com que vc falou mas quando vc diz Vamos supor que a parte de cima do método precise ser alterada a minha dúvida passa a ser outra.

Por que a parte a cima precisa ser alterada? Ela não estava funcionando? Se ela precisa ser alterada, ela tem um bug sério, que com certeza não tem como ter passado nos primeiros testes funcionais da coisa.

O meu ponto no debate é que existe código que funciona, que vc não fez e que vc respeita. Esse código só deve ser alterado nos últimos dos casos, quando vc pegou um erro muito grotesco, ou algo desse nível. Isso (erros grotescos) geralmente vai acontecer na fase inicial de desenvolvimento, onde vc está esperando e pode pagar o preço de um erro grotesco. Num sistema (ou framework) estável e que já está rodando algum tempo, é natural não esperar um tipo de erro desses e é prudente (na minha opinião) respeitar os códigos que já estão lá e que já estão funcionando.

[quote=eduveks]
Testes não é obrigatório… não é por q estes caras dizem q é, quem diz se é e não é é o cliente, e até hoje nenhum disse q era, por q até eles confiam mais no teste q eles fazem do q em testes unitários.[/quote]

E seus clientes falam pra você cirar a classe X, a interface Y e o método Z? Não né? E por quê?

Porque quando eles contratam um profissional eles acreditam que estão comprando os serviços de alguém que sabe o que está fazendo.

Leia de novo o meu exemplo prático (o código mesmo) para constatar que é praticamente impossível para minha alteração quebrar alguma coisa. E não foi porque foi eu que fiz, foi uma questão de filosofia e lógica.

Acho que essa pergunta encerra qqer discussão sobre testes.

O estilo deste exemplo é conhecido como codigo spaghetti:

http://yost.com/computers/java/java-spaghetti/

E é algo que OO veio solucionar, mas soluções já existem desde programação estruturada (coesão, acoplamento, módulos…) nos anos 80.

[quote=pcalcado][quote=saoj]
Exemplo prático:

[/quote]

O estilo deste exemplo é conhecido como codigo spaghetti:

http://yost.com/computers/java/java-spaghetti/

E é algo que OO veio solucionar, mas soluções já existem desde programação estruturada (coesão, acoplamento, módulos…) nos anos 80.[/quote]

De novo peço que se minha solução é errada ou spagetti que vc ensine para a gente como deveria ter sido o procedimento correto para alterar o método e resolver o problema. É muito fácil e deselegante falar que o código do outro é spagetti e não ter a humildade de propor uma solução alternativa e melhor…

Ñão sei se concluindo, mas tentando, o ponto aqui me parece claro. Vocês (Sérgio e etc.) não usam testes unitários e ficaram ofendidos quando alguém falou que código sem estes não presta e começaram a atacar testes unitários. O problema é que os argumentos acabaram há várias páginas, estamos apenas repetindo a mesma coisa novamente e novamente.

Como falei antes eu acho que desenvolvimento sem testes não presta, mas o código gerado pode (apesar de tender fortemente a não) ser de qualidade. O problema é que se eu compro software que não tem testes eu não confio no fornecedor (seja software livre ou não).

[quote=pcalcado]Ñão sei se concluindo, mas tentando, o ponto aqui me parece claro. Vocês (Sérgio e etc.) não usam testes unitários e ficaram ofendidos quando alguém falou que código sem estes não presta e começaram a atacar testes unitários. O problema é que os argumentos acabaram há várias páginas, estamos apenas repetindo a mesma coisa novamente e novamente.

Como falei antes eu acho que desenvolvimento sem testes não presta, mas o código gerado pode (apesar de tender fortemente a não) ser de qualidade. O problema é que se eu compro software que não tem testes eu não confio no fornecedor (seja software livre ou não).[/quote]