Pq os teste unitários não são tão populares!

Qual o problema de arquivos de 10mil linhas? Não vejo problema nisso. Minhas teclas preferidas são page-up e page-down. Muito mais rápido e produtivo que ficar trocando de arquivo o tempo todo.

Por que testes não são populares?

1º - Não se usa por quê não se sabe usar. Onde aprender? Nunca vi cursos sobre o assunto, documentação do JUnit, por exemplo, é palpérrima. E cadê os livros que ensinam passo-a-passo? Ou melhor, cadê os livros sobre o assunto?

2º - Não se usa por quê não se sabe aplicar testes unitários na fase de manutenção de projetos. Perguntam-se “Para quê a esta altura?”, ou melhor, “como quebrar um monolito em partes manejáveis”. O princípio de um teste unitário é que há unidades a se testar. A maioria dos projeots simplesmente não tem unidades, é um spaguetti code.

Refatoração depende de testes unitário, mas como se não temos eles em primeiro lugar?

3º - Preguiça. Falta de tempo. A empresa não tem experiência, muito menos cultura. Três letrinhas e tudo mais.

Ola

JUnit in Action de 2004 - excelente livro

Test Driven Development: By Example de 2002

Test Driven Development: A J2EE Example de 2005

Test-Driven Development: A Practical Guide de 2003

Pragmatic Unit Testing in Java with JUnit de 2003

TDD and Acceptance TDD for Java Developers de 2007

Java Testing and Design livro grátis disponivel em PDF desde 2004

Além destes livros, há muitos tutoriais que podem ser baixados livremente como este por exemplo: http://hotwork.sourceforge.net/hotwork/manual/junit/junit-user-guide.html

Outra fonte de aprendizado podem ser as centenas de projetos open source que usam testes unitários

E a documentação do JUnit não é “palpérrima” e muito menos paupérrima

Não é por falta de documentação que não se usa.

[]s
Luca

Não ter testes do início não é desculpa. Como qualquer um com alguns anos no mercado 90% do que eu fiz foi dar manutenção em alo já pronto e que não tinha testes. Testes funcionam muito bem nestes cenários, inclusive facilitando a nenharia reversa de módulos cujo “dono” foi demitido.

Já viu quantos métodos as classes do swing tem? O problema principal é que você nunca vai desenvolver nada puro e do zero que não use algum outro código já existente. Sempre vai usar alguma coisa já existente (Swing, EJB, ou até mesmo java.lang.*). Há partes do sistema que não foi você que fez, você não pode mudar e são engessadas. E um bom programador/arquiteto deve saber como conviver com isso e lidar com limitações. Imagine implementar JPasswordField extends Object via composição com JTextField, seria loucura. Além de que isso não funcionaria porque existem muitos lugares que iriam testar se o seu JPasswordField extends Component, JComponent ou qualquer coisa assim.

Ok, você pode falar que o swing não tem uma boa arquitetura, e eu concordo contigo. Mas aí está a diferença entre o bom arquiteto e o excelente arquiteto. O bom arquiteto sabe criar um design lindo. O excelente arquiteto sabe criar um design lindo mesmo usando componentes mal-projetados.

Considerando que Swing é só interface gráfica -que deve ser testada mas não necessariamente com unit tests- eu não entendi o problema. De qualquer modo, criar ‘um design lindo’ vai envolver refactoring logo a aplicação mal-projetada vai ser consertada eventualmente.

Os argumentos usados em discussões como esta me levam a repetir o que sempre digo: independentemente da linguagem ser estruturada ou OO ou outra porra qualquer, “POG” não é “Programação Orientada a Gambiarras”, mas sim “Programador Orientado a Gambiarras”.

Concordo plenamente !

Inclusive seria bom que os amantes da OO evitassem argumentos que possam sugerir que o que apreciam mesmo é a POPE (Programação Orientada a Preguiça de Escrever).

Swing foi só um exemplo. Utilize no lugar dele qualquer outro framework mal-projetado que você seja forçado a usar sem poder alterar uma única vírgula no código-fonte deste.

[quote=victorwss]
Swing foi só um exemplo. Utilize no lugar dele qualquer outro framework mal-projetado que você seja forçado a usar sem poder alterar uma única vírgula no código-fonte deste.[/quote]

Eu ainda não entendi o problema. Se você não pode testar o componente em si basta isolá-lo. Ao invés de fazer sua classe estender isso faça uma classe que estende e apenas delega para a sua, que contêm a lógica de fato e é bem testada. Existem dezenas de padrões e técnicas para fazer isso.

[quote=pcalcado][quote=victorwss]
Swing foi só um exemplo. Utilize no lugar dele qualquer outro framework mal-projetado que você seja forçado a usar sem poder alterar uma única vírgula no código-fonte deste.[/quote]

Eu ainda não entendi o problema. Se você não pode testar o componente em si basta isolá-lo. Ao invés de fazer sua classe estender isso faça uma classe que estende e apenas delega para a sua, que contêm a lógica de fato e é bem testada. Existem dezenas de padrões e técnicas para fazer isso.[/quote]

Então, é aí que está a difereneça entre o bom e o excelente arquiteto:
Criar classes com alta coesão, baixo acoplamento, POGless mesmo estando em cima de um framework ruim e limitado, e não apenas criar classes com alta coesão, baixo acoplamento e POGless. :smiley:

O Leonardo falou que uma classe com 100 métodos é um design ruim é deve ser evitado em primeiro lugar quando comentava sobre algum argumento de que isso prejudicaria testabilidade. Você respondeu dizendo que sistemas legados podem ter 100 métodos. Eu respondi dizendo que istemas legados devem ser refatorados e/ou isolados.

Podemos dizer então que você concorda com o Leonardo?

Teria que haver uma interface Component. É o mesmo caso da interface Object que eu ilustrei num post anterior, mas o seu exemplo é mais um que diz como seria ingrata a vida do programador Java sem herança. Acho que a questão se herança é importante ou não já foi esclarecida. Herança é muito importante na linguagem Java e se vc não acredita em mim pelo menos acredite na implementação do Joshua Bloch de collections, que utilizou herança quando poderia ter utilizado interfaces + composição + delegação.

Acho que vc deve preferir composição ao invés de herança quando não há hierarquia, quando vc não vai precisar passar o filho como pai para sistemas legados ou outros métodos do seu sistema que esperam o pai e podem fazer uso de polimorfismo recebendo o filho.

Um PastorAlemão conter Cachorro ao invés de herdar Cachorro me parece totalmente errado. PastorAlemão é um Cachorro e muito provavelmente vc vai querer passá-lo para métodos que recebem Cachorro e usam polimorfismo. Isso em Java, onde o tipo é fundamental. Em Ruby seria outra história…

Agora se existe uma interface Cachorro, como existe uma interface java.util.Set, vc pode partir para composição + interface + delegação, que vc irá obter o mesmo resultado de herança. A única diferença, ao meu ver, é que vc vai ficar com muitas linhas a mais e repetitivas na sua classe, implementando novamente todos os métodos da interface e fazendo a delegação para o objeto possuído. Não entendo se há alguma vantagem de eliminar herança dessa maneira a não ser pela retórica de que herança não vai bem com testes unitários. Se houvesse o Joshua Bloch teria feito isso aqui http://java.sun.com/javase/6/docs/api/java/util/LinkedHashSet.html, mas ele preferiu herdar de HashSet, sem falar de AbstractSet e AbstractCollection.

Acho que se Object é uma classe concreta e não uma interface, onde todos os outros objetos obrigatoriamente herdam de Object, então ficar evitando herança quando há claramente uma relação de hierarquia é non-sense.

Mas isso não tem muito haver com o tema original que é por que testes unitários não são populares. Eu sinceramente não sei a resposta para isso, nem se a afirmação é 100% correta. Pelo menos aqui no GUJ vejo que é bastante popular.

O link tá errado, arruma aí.

Ponto para as 10 mil linhas !

[quote=pinto][quote=não importa quem]
Acho que vc deve preferir composição ao invés de herança quando não há hierarquia, quando vc não vai precisar passar o filho como pai para sistemas legados ou outros métodos do seu sistema que esperam o pai e podem fazer uso de polimorfismo recebendo o filho.
[/quote]

Ponto para as 10 mil linhas !
[/quote]

Nesse caso vc não está obrigado a implementar todos os métodos do objeto possuído, pois vc não está implementando uma interface, apenas usando composição porque não há uma relação de hierarquia.

Qualidade não tem nada haver com quantitidade. Se vc tem uma classe com mil linhas e o código está bem feito, who cares? Pra isso que existe IDE e os shortcuts do teclado.

Agora se vc tem uma classe com 10 mil linhas repetitivas, fazendo delegação para os métodos de uma interface, então é tedioso, error-prone e feio. As pessoas reclamam de getters e setters, o que dirá disso. Código tb deve ser bonito, uma forma de arte e não uma ciência exata. Se não usemos o Maker (na versão 54.3)… :stuck_out_tongue:

o problema não é herança, herança não é ruim, ruim é herança má utilizada …
Herança apenas para reutilização de campos/métodos causa mais problemas do que resolve.

Exemplo:
Um cliente a algum tempo atraz tinha uma classe “Usuario” e uma classe “UsuarioDependente”, a classe “UsuarioDependente” tinha apenas um campo a mais que “Usuario” que era o relacionamento com o pai.

Pensamento lógico (e errado deles), “UsuarioDependente” vai herdar de “Usuario”, isto foi uma péssima utilização de herança, e é este tipo de utilização que faz com que as pessoas assumam por regra que “herança é má”.

Por que foi errado fazer isto? Por que nem todos os métodos que esperavam um “Usuario” podiam receber um “UsuarioDependente” …
Por exemplo, considerando que houvesse um método:
public void gerarFatura(Usuario usuario)
Este não podia receber um “UsuarioDependente” pois o dependente não recebia fatura, tudo era cobrado do “Usuario”.
A solução para corrigir este problema se não me engano foi criar um “UsuarioBase” e extender as duas classes deste.
Por que um “UsuarioDependente” não é um “Usuario”, pois usuário tem comportamentos que os dependentes não possuem, como por exemplo, pagar a conta :smiley:

Herança quando usada nos casos “é um”, não tem problema algum, mas estes são poucos casos na grande maior parte dos sistemas que eu ja vi até hoje.
Em qualquer situação diferente de “é um”, usar herança é errado e vai te trazer problemas, então em todas estas situações, não use herança, use composição.
E se você perceber que não usou herança nenhuma vez (no seu modelo, herdar de Object ou outras classes padrão do java não conta para o que eu estou descrevendo), não esquenta a cabeça, é provavel que não existisse mesmo nenhum tipo de relacionamento “é um” no seu sistema, a maior parte deles não tem mesmo.
Mas se existir um “é um”, use herança sem pensar duas vezes :smiley:

PS.: este port não é resposta a um post especifico desta thread, mas a quase todos, tanto os que dizem use herança para tudo quanto os que dizem nunca use herança, ambas as posições estão erradas, orientação a objetos bem utilizada ajuda muito, o problema é que a maior parte dos programadores que conheci nas empresa que trabalhei até hoje ( a maior parte não quer dizer todos) não conseguiu entender direito a OO ainda, então usa errado e tem problemas por causa disto.

[quote=pcalcado]O Leonardo falou que uma classe com 100 métodos é um design ruim é deve ser evitado em primeiro lugar quando comentava sobre algum argumento de que isso prejudicaria testabilidade. Você respondeu dizendo que sistemas legados podem ter 100 métodos. Eu respondi dizendo que istemas legados devem ser refatorados e/ou isolados.

Podemos dizer então que você concorda com o Leonardo?[/quote]

Parcialmente. Eu estava questionando justamente um trecho do que ele escreveu.

E eu respondi basicamente que pode acontecer em sistemas onde é obrigatório o uso de algum tipo de framework mal projetado (seja legado ou não). E mesmo assim JPasswordField extends JTextField extends JTextComponent extends JComponent extends Container extends Component extends Object. Ou seja, há um uso grande de herança. Obviamente, há falhas de projeto nestas classes intermediárias (em especial Component, Container e JComponent, que são as principais culpadas por existir centenas de métodos). Essas três pode ser o caso onde não há nem herança, nem composição e nem OO (daí eu concordaria com ele), MAS quanto a JPasswordField, JTextField e JTextComponent, sem dúvida há um uso propício de herança. Basicamente, o problema é que você é obrigado a herdar esses métodos (mesmo se não os quiser), e EU não posso refatorar o swing para eliminar isso, ou seja, o framework ruim me forçou a herdar um caminhão de métodos.

No final crio a minha classe que herda de JPasswordField. EU estou usando a herança de forma propícia, MAS a minha classe tem centenas de métodos (porque estes foram herdados). E isto não é um design ruim que é minha culpa, e sim culpa do framework (no caso, neste exemplo, o swing e o AWT).

Quanto ao resto do post dele, não comentei nada.

Concordo quase completamente. O único ponto que discordo é em relação a “(no seu modelo, herdar de Object ou outras classes padrão do java não conta para o que eu estou descrevendo)”. Já vi gente criando heranças absurdas como MinhaData extends java.util.Date.

O caso clássico de mal uso de herança é o infame java.sql.Date extends java.util.Date.

Shoes nao entendi muito bem prq herança atrapalharia em testes por qual motivo?
No livro design Patterns (Head First) eles recomendam que de prioridade a composição em relação a heranca depois que li o captiulo abriu a minha mente em utilizar Herança


[/quote]
O objetivo (admito que não ficou claro…) do meu comentário foi comparar a grande complexidade da OO com a “extensa” simplicidade da programação estruturada (que foi a minha escola na TI). Por isso a comparação entre o seu parágrafo e as 10 mil linhas.
Aplicar corretamente a OO é tão difícil quanto formar um consenso sobre o que é correto se fazer em OO.
Realmente OO não é pra qualquer um…

Seria bom se mais gente pensasse assim.

Boa… :lol: :lol: :lol: