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

OO é simples, as pessoas é que tem mania de complicar as coisas :smiley:

[quote=ramilani12][quote=pcalcado]
3) Heranças atrapalham testes da mesma maneira que composição atrapalha: quando se cria acomplamento com classes difíceis de serem testadas. O resto escrito neste tópico é FUD
[/quote]

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 problema de herança com testes é que você não tem como testar sua classe isoladamente, tem que levar de brinde todo comportamento dos parentes.

Herança é uma bomba quando você precisa alterar o comportamento de uma classe com várias filhas.

[quote=urubatan][quote=pinto]
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…
[/quote]
OO é simples, as pessoas é que tem mania de complicar as coisas :smiley:
[/quote]

Excelente !

[quote=louds]
O problema de herança com testes é que você não tem como testar sua classe isoladamente, tem que levar de brinde todo comportamento dos parentes.

Herança é uma bomba quando você precisa alterar o comportamento de uma classe com várias filhas.[/quote]
Louds, o esquema é que quando herança é utilizada corretamente, o comportamento teria que ser replicado de qualquer forma …
Ja se a herança foi utilizada só para “copiar métodos e atributos”, ai sim, uma alteração ferra com tudo …

Se fosse vivo, provavelmente Einstein diria que a física quântica é simples, e certamente eu discordaria…

Não creio que se possa qualificar como simples algo que a maior parte das pessoas leva bastante tempo para entender e usar corretamente.

Eu mesmo não domino completamente OO, o que me faz sofrer por causa da minha mania de fazer as coisas da maneira mais correta possível.

Sergio, usar heranca eh tao ruim quanto blocos de catch vazios, instanceofs em vez de polimorfismo, switches, metodos longos, classes so com getters e setters, etc…

Detesto ser repetitivo, mas vamos la:

A vida seria maravilhosa… como disse o Gosling uma vez quando falou que uma das coisas que mudaria no java era tirar o EXTENDS.

PastorAlemao realmente é um Cachorro. Voce DEVE usar o relacionamento IS A pra isso. Use entao INTERFACES. Cachorro é uma interface. Voce faz composicao com uma classe chamada DadosDeCachorro, nao com Cachorro, nem sei de onde voce tirou isso.

AbstractSet e AbstractCollection sao BEM diferentes… sao template methods, apesar de que os mais xiitas iriam falar pra voce nao usar isso tambem. LinkedHashSet teve de estender HashSet porque ja tinha gente que nao manjava direito de OO recebendo HashSet como argumento em vez de puramente Set.

Ja que voce gosta tanto de citar o Joshua Bloch, aqui vai algumas:

[quote]Rather than subclassing, just use pure interfaces.
It’s not so much that class inheritance is particularly bad. It just
has problems[/quote] - James Gosling, pai do Java

http://www.artima.com/intv/gosling3P.html

[quote]Favor object composition over class inheritance[/quote] - Erich Gamma, Design patterns

[quote]Item 14: Favor composition over inheritance[/quote] - Joshua Bloch, Effective Java

Alias, nesse capitulo, Joshua mostra EXATAMENTE como é pessimo estender… collections!!! Bem o exemplo que voce gosta de dar aqui… mostra como resolver com composicao e explica claramente o porque… vale a pena voce dar uma lida

Bom, talvez o pessoal devesse ler mais Nietzsche. Joshua Bloch pregou que herança é lixo mais usou bastante herança nas collections. O código das bibliotecas Java está cheio de herança por todos os lados, a começar pelo implícito extends Object, mas Deus (Gosling) recita que extends é evil e o rebanho se curva em reverência. As pessoas reclamam de getters e setters, exaltam o attr_accessor do Ruby, mas não se incomodariam de usar composição + interfaces, pois julgam assim serem merecedores da terra.

Vamos abolir o uso de herança e usar interfaces + composição pra tudo:

public interface Object {

   public String toString();

   public int hashCode();

   // outros aqui...

}

public class ObjectImpl implements Object {

    public String toString() {
        // implementação default de todo objeto..
    }

    pubilc int hashCode() {
        // implementação default de todo objeto...
    }

    // outras implementações default aqui...
}

public class MyClass implements Object {

    private final Object obj; // composição

    public MyClass() {

        this.obj = new ObjectImpl();

    }

    public int hashCode() {
         return this.obj.hashCode(); // delegando...
    }

    public String toString() {
        // minha implementação, diferente de ObjectImpl...
        return "MyClass: " + obj.toString();
     }
}

Talvez alguém mais mundano poderia oferecer uma explicação clara de o porquê ser herança um ato ignóbil.

Quem ainda faz isso? Quem ainda declara private HashSet set = new HashSet() ao invés de private Set set = new HashSet(); ? Talvez vc esteja falando de Java 1.1.1, quando não existia interface Set. Aí tudo bem, só que isso tem quase uma década e LinkedHashSet não existia em 1.1.1 (só surgiu em 1.4), então quem estava usando HashSet não queria usar LinkedHashSet, pois simplesmente não existia. Mesmo assim, não dava para ter refatorado as collections para ficar puro e certinho, sem herança? O cara que quer usar o LinkedHashSet pode e deve urgentemente refatorar de HashSet para Set. Isso sim é um erro grotesco de OO: bind to specification not to the implementation.

Talvez não tenha sido esse o motivo dele ter usado herança. Ou foi desatenção (Joshua Bloch erra?) ou foi preguiça de replicar código que nem louco só para se livrar do extends e ir para o reino dos ceús:

public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {

    private static final long serialVersionUID = -2851667679971038690L;

    /**
     * Constructs a new, empty linked hash set with the specified initial
     * capacity and load factor.
     *
     * @param      initialCapacity the initial capacity of the linked hash set
     * @param      loadFactor      the load factor of the linked hash set
     * @throws     IllegalArgumentException  if the initial capacity is less
     *               than zero, or if the load factor is nonpositive
     */
    public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }

    /**
     * Constructs a new, empty linked hash set with the specified initial
     * capacity and the default load factor (0.75).
     *
     * @param   initialCapacity   the initial capacity of the LinkedHashSet
     * @throws  IllegalArgumentException if the initial capacity is less
     *              than zero
     */
    public LinkedHashSet(int initialCapacity) {
        super(initialCapacity, .75f, true);
    }

    /**
     * Constructs a new, empty linked hash set with the default initial
     * capacity (16) and load factor (0.75).
     */
    public LinkedHashSet() {
        super(16, .75f, true);
    }

    /**
     * Constructs a new linked hash set with the same elements as the
     * specified collection.  The linked hash set is created with an initial
     * capacity sufficient to hold the elements in the specified collection
     * and the default load factor (0.75).
     *
     * @param c  the collection whose elements are to be placed into
     *           this set
     * @throws NullPointerException if the specified collection is null
     */
    public LinkedHashSet(Collection<? extends E> c) {
        super(Math.max(2*c.size(), 11), .75f, true);
        addAll(c);
    }
}

Ele podia ter tranquilamente feito assim:

public class LinkedHashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {

    private static final long serialVersionUID = -2851667679971038690L;

    private final Set mySet;

    public LinkedHashSet(int initialCapacity, float loadFactor) {
        mySet = new HashSet(initialCapacity, loadFactor, true);
    }

    public LinkedHashSet(int initialCapacity) {
        mySet = new HashSet(initialCapacity, .75f, true);
    }

    public LinkedHashSet() {
        mySet = new HashSet(16, .75f, true);
    }

    public LinkedHashSet(Collection<? extends E> c) {
        mySet = new HashSet(Math.max(2*c.size(), 11), .75f, true);
        mySet.addAll(c);
    }

    // 500 linhas aqui de métodos reimplementando todos os métodos das interfaces e
    // delegando para mySet
}

Trocaríamos Herança por composição + interfaces + um monte de repetição de código. A vida poderia ser mais pura assim, visto que nós estaríamos de acordo com as nossas entidades superiores. Mas tenho minhas dúvidas se seria mais maravilhosa…

Só em 2008 eu devo ter visto isso umas 10 vezes no mínimo, e não é de desenvolvedor jr não.

Etc., etc., etc…

Tchê Urubatan,

É por essa e outras tantas que considero OO tão complexa e consequentemente de difícil aprendizagem.
Como profissionais tão experientes e bem sucedidos podem divergir tanto?
Afinal OO pode ser considerada uma “ciência” exata, ou é mais subjetiva?
Um humilde pedido:
Vc, que é tambem experiente e bem sucedido, poderia indicar um caminho (livro, cursos, etc…) para que eu possa dominar OO e um dia talvez considera-la simples?
Por favor, me ajude!

Sérgio, composição só é gera toneladas de métodos de delegação para aqueles que usam uma linguagem pobre e não sabem usar os recursos dela.
Com Java já é possível resolver esse problema a anos usando, por exemplo, proxies.

O problema do LinkedHashSet é que as collections do Java nunca foram feitas para serem extendidas. O design delas é um fracasso nesse sentido.
Se elas suportassem eventos e callbacks seria trivial implementar LHS sem toneladas de delegação.

Justificar herança usando um exemplo furado é fácil.

Sérgio, por mais incrível que pareça, na maioria dos casos, as “boas práticas” não foram criadas simplesmente para preencher espaço, para aparecer ou para depois aparecer no fórum com uma listinha de pessoas que usam as “boas práticas” criadas por ela.

As ‘boas práticas’ geralmente são criadas quando se passa por uma situação diversas vezes (experiência) e se estuda elas (conhecimento), analizando qual é a melhor alteranativa que geralmente atende a maior parte dos casos. É claro que vai ter uma situação ou outra que é melhor fazer algo diferente, mas na média, é melhor se ater as boas práticas, geralmente os resultados são melhores. É claro que não se deve seguir cegamente tudo o que se fala, mas se 12319083791280 pessoas que são reconhecidas na comunidade estão falando bem de algo, é melhor pelo fazer uma analize séria, é provável que vá te ajudar em alguma coisa.

Note que o pessoal encheu o GUJ de posts com argumentos técnicos e você mais uma vez esta tapando os ouvidos e gritando que é complexo, é complicado, é error-prone, etc. O mesmo argumento você usa para o Hibernate, por exemplo. É um excelente ORM, facilita muito a vida, é poderoso, é usado por muitos empresas nos mais diferentes ambientes, etc. Dificilmente alguém conseguiria num projeto “normal” criar algum mecanismo de ORM melhor que o Hibernate, na média é melhor você usar ele do que criar o seu próprio ORM caseiro. Só que para usar ele você tem que gastar algumas horas para entende-lo. E por causa disso você diz que é complexo, é complicado, é error-prone, etc.
As “boas práticas” também requerem que você gaste um bom tempo para entende-las. Parece que tudo que leva mais que uma hora para aprender você acha complexo, complicado e error-prone.

OO é simples? Boa parte do povo que aprende essa coisa na faculdade desaprende logo que entra no mercado. Ou pior ainda é quando acha que realmente aprendeu para você acompanhar uma thread no guj que desmente tudo que você outrora acreditara. IMHO, OO não é simples, por isso as coisas se complicam (caso não seja gasto o devido esforço e paciência para aprender aplicar OO na prática!).

mas… é só desabafo :stuck_out_tongue: continuem a discussão!

[quote=urubatan][quote=louds]
O problema de herança com testes é que você não tem como testar sua classe isoladamente, tem que levar de brinde todo comportamento dos parentes.

Herança é uma bomba quando você precisa alterar o comportamento de uma classe com várias filhas.[/quote]
Louds, o esquema é que quando herança é utilizada corretamente, o comportamento teria que ser replicado de qualquer forma …
Ja se a herança foi utilizada só para “copiar métodos e atributos”, ai sim, uma alteração ferra com tudo …[/quote]

Perfeito. Afirmação mais sensata até agora.

Tem razão. Só que proxy não é algo natural dentro de Java. É um tapa-buraco. Requer interfaces (a não ser cglib) e por aí vai. Mas foi uma ótima observação. Antes do Gosling falar que Java não deveria ter extends ele deveria ter falado que Java deveria ter um esquema de proxies um pouco mais descente ou simplesmente um method_missing.

Não acredito em qualquer coisa que me dizem como se fosse uma doutrina religiosa sobrenatural e irracional do além-nada. Um bom debate não faz mal a ninguém e muito menos para quem está equivocado. Boas práticas podem se tornam más práticas, vide singleton. Seus argumentos foram fracos e carregados de emoção, que é a principal inimiga da razão. Creio que sua perfídia colaborou negativamente para o debate, mas mesmo assim parabéns, pois seus anseios foram amansados e nem foi necessário apelar para os deuses ou o sobrenatural! Pense nisso e leia um pouco de Nietzsche e Epicuro, pode te fazer bem. E lembre-se: "Desacreditar o argumentador não desacredita o seu argumento. Não é preciso ser religioso (nem do PT) para ver que atacar um amigo é imoral. Vc fala de flores, mas o seu Jardim tem ervas daninhas…

OO em teoria é extremamente simples. Já na prática não o é, pelo contrário, é bem complicado e requer muita prática para dominar. É um aprendizado constante. Quanto mais se programa, mais se aprende. Qualquer programador sinsério vai admitir que seus primeiros programas OO eram um lixo.

Minha contribuição:
Testes unitarios são muito uteis sim. Ponto. são a solução para os problemas do mundo? Claro que não.
Herança é bom ou ruim? Boa em alguns caso, ruins em outros. Como quase tudo na nossa area.
O problema é que as coisas não são 8 ou 80, bom ou mal, azul ou vermelho.
Sim, é possivel escrever um sistema TODO, que funcione, que seja confiavel, <coloque aqui seu requisito prefereido> sem um unico teste.
A maiora aqui faz isso todos os dias. Eu faço todos os dias.
A questão é que se me perguntassem se eu prefiro fazer com testes ou sem testes, minha resposta seria: Com Testes!!!
Pq? Alem tudo que ja foi dito nessa thread, pq ja participei de projetos com e sem testes, e senti na pele a diferença.
Usado da maneira certa, junto com outras praticas ele ajuda em muito.
Quem nunca escreveu um codigo e pensou depois “coitado de quem for ter que alterar isso!!!”?
Bom, com testes, o “coitado vai ter um ponto de partida”, os testes.
Quem faz codigo são as pesssas, pessoas produzem codigo de maneiras diferentes.
Testes fazem parte de uma cultura, de uma maneira de se fazer software. Sozinho, talvez ele mais atrapalhe do que ajude.
Cultura essa que diz que o codigo não tem dono, não existe o dono daquela “logica maluca” que so ele pode alterar.
Por isso existem testes, para se ter um ponto de partida para o entendimento do sistema, entre outras coisas.

[]´s

Talvez até fosse possível usar-se apenas composição e não herança. O problema é que o java foi arquitetado desta forma e não será refatorado (backward compatibility). Logo, se você for programar em java deverá usar herança. Não gosta disso? Procure outra linguagem ou aprenda a lidar com isso. Não tem jeito.

Interfaces também tem lá seus problemas (que pouca gente cita). Precisa adicionar um método na interface ou mudar a assinatura? VOCÊ VAI QUEBRAR TODAS AS IMPLEMENTAÇÕES AO FAZÊ-LO! E que tal fazer uma outra interface que herde desta primeira acrescentando os métodos novos e colocar um @Deprecated nos que devem ser removidos? VOCÊ ESTARÁ FAZENDO GAMBIARRAS, E NÃO CONSERTANDO O PROBLEMA! Aliás, existem interfaces no java que são gambiarradas desta forma.

Acho que o maior problema em java é a falta de mixins. Se houvesse mixins, delegação seria algo mais simples e mais usado, mas talvez isso pudesse trazer a herança múltipla de classes. E antes que falem, sim herança múltipla de classes também tem algum propósito válido em alguns casos.

Outro problema no java é o backward compatibility. Embora ele seja vital para o sucesso do java, ele é ao mesmo tempo um câncer. As cagadas feitas na API estão lá para sempre!

Hehe, mas o tópico já se desvirtuou totalmente aqui :smiley:

bocejo

Bom,
respondendo a pergunta original do topico, eu acho que os testes unitarios ainda não são tão populares pq ainda não se vende software se utilizando alguma cultura/metodologia que use testes.
A maioria do sistemas desenvolvidos ainda utilizam waterfall(classico ou modificado) aonde não existe a figura dos testes unitarios. Ou quando existe, vão ser feitos em uma “fase de construção de testes”, ou seja, muito codigo ja foi produzido, dificultando a utilização de testes.
Eu pelo menos, so desenvolvi usando testes unitarios em projetos que utilizaram alguma metodologia agil. Pq nesses casos os testes eram vistos como devem, sem ser a bala de prata, mas sendo muito uteis dentro da maneira de desenvolvimento proposta.

[]´s

[quote=jgbt]Bom,
respondendo a pergunta original do topico, eu acho que os testes unitarios ainda não são tão populares pq ainda não se vende software se utilizando alguma cultura/metodologia que use testes.
A maioria do sistemas desenvolvidos ainda utilizam waterfall(classico ou modificado) aonde não existe a figura dos testes unitarios. Ou quando existe, vão ser feitos em uma “fase de construção de testes”, ou seja, muito codigo ja foi produzido, dificultando a utilização de testes.
Eu pelo menos, so desenvolvi usando testes unitarios em projetos que utilizaram alguma metodologia agil. Pq nesses casos os testes eram vistos como devem, sem ser a bala de prata, mas sendo muito uteis dentro da maneira de desenvolvimento proposta.

[]´s
[/quote]

Pois é. Imagine que você já tenha um código grande e peçam para criar o código de teste. É possível fazer isso de forma relativamente fácil? Se a resposta for não, está aí a causa deles não serem muito populares!

Pras consultorias é vantajoso não ter testes antes, porque o software vai dar trocendo milhoões de problemas, eles vão ficar extendendo o prazo de entrega eternamente e a consultoria continua ganhando lá R$ 150/hora por cada desenvolvedor, qual a vantagem pra eles entregam algo de qualidade dentro do prazo?

E infelizmente é esse tipo de empresa que pega a grande maioria (chute uns 90% até) dos projetos de softwares existentes no mercado.