Por que Collections.sort(lista) e não lista.sort()?

Bom dia,

A pergunta é mais generalista do que a descrita no título, pois pode ser feita pra vários dos métodos da classe Collections.

Alguém sabe o motivo para que alguns dos métodos da classe Collections não sejam métodos das interfaces List, Set, etc? Pois na minha visão, a versão alternativa seria mais OO, ou estou enganado?

Abs.

IMO, pra ser DRY.
Como List é uma interface, ela não possue implementação. Neste caso, se tivessemos sort na interface, cada implementação de List deveria repetir o mesmo código. Neste caso é melhor criar um método estático comum pra todo mundo que implemente List. Além disso, pra poder ser ordenada, uma lista deve conter objetos que implementem Comparable.

[quote=tveronezi]IMO, pra ser DRY.
Como List é uma interface, ela não possue implementação. Neste caso, se tivessemos sort na interface, cada implementação de List deveria repetir o mesmo código. Neste caso é melhor criar um método estático comum pra todo mundo que implemente List.
[/quote]

Mas a AbstractList não está lá pra resolver esse problema?

[quote=tveronezi]IMO, pra ser DRY.
Além disso, pra poder ser ordenada, uma lista deve conter objetos que implementem Comparable.
[/quote]

Talvez, isso sirva pra justificar o sort(), mas não outros métodos, como o shuffle(), por exemplo.

Acho que a duplicidade de implementação não é o principal motivo, porque (1) como foi observado, seria simples colocar a implementação em uma classe mãe comum, como a AbstractList; e (2) A implementação do sort não precisa ser necessariamente a mesma para diferentes listas, pois cada uma poderia fazer da maneira mais otimizada para aquela estrutura em particular.

O que eu considero que motivou essa decisão foi a ideia de que a estrutura de dados e os algoritmos que fazem determinadas operações (sort, shuffle, search, troca-troca, etc) conceitualmente não fazem parte do mesmo objeto. Poderiam funcionar independente um do outro, trocando-se à vontade tanto a estrutura como o algoritmo.
Enfim… talvez nem todo mundo concorde com essa ideia (será que existe uma resposta absoluta nesse caso :?: ), mas acho que era o que pensavam os designers do frameworks de coleções. Inclusive pode ser influência do C++ , onde os algoritmos não são membros das coleções (containers) e sim funções globais.

[quote=gomesrod]Acho que a duplicidade de implementação não é o principal motivo, porque (1) como foi observado, seria simples colocar a implementação em uma classe mãe comum, como a AbstractList; e (2) A implementação do sort não precisa ser necessariamente a mesma para diferentes listas, pois cada uma poderia fazer da maneira mais otimizada para aquela estrutura em particular.

O que eu considero que motivou essa decisão foi a ideia de que a estrutura de dados e os algoritmos que fazem determinadas operações (sort, shuffle, search, troca-troca, etc) conceitualmente não fazem parte do mesmo objeto. Poderiam funcionar independente um do outro, trocando-se à vontade tanto a estrutura como o algoritmo.
Enfim… talvez nem todo mundo concorde com essa ideia (será que existe uma resposta absoluta nesse caso :?: ), mas acho que era o que pensavam os designers do frameworks de coleções. Inclusive pode ser influência do C++ , onde os algoritmos não são membros das coleções (containers) e sim funções globais.[/quote]

Pode ser isso mesmo… estou achando que grande parte é questão de gosto.

A questão, é que list.sort() dá impressão de ser algo mais OO (a ordenação poderia ser vista como um comportamento) e tem a vantagem de não precisar passar parâmetro. Por outro lado, como você bem disse, algumas pessoas podem achar que a list está fazendo mais do que deveria, deixando-a com baixa coesão.

Engraçado é ver que Python (se não me engano) é o contrário do Java: a ordenação é feita com list.sort() mas, para pegar o tamanho, é preciso fazer len(list)…

Outro ponto que acho interessante:

len(list) em Python retorna o tamanho da lista.

já Collections.sort(list) de Java não retora uma list, mas modifica a que é passada como parâmetro. Só eu acho esse comportamento um pouco estranho? Parece que algo como:

List<QualquerCoisa> qc = Collections.getSorted(list);

sem modificar a list original seria menos pior…

Aliás, da maneira como está, é como se estivéssemos passando um ponteiro de retorno em C, que é feio pra caramba. Se não me engano, o Clean Code desencoraja a alteração de estado de objetos passados por parâmetro.

quantas pessoas aprendendo Java já não tentaram fazer isso?

System.out.println(Collections.sort(list));

Se tivesse que escolher só um dos dois para ser parte intrínseca do objeto list eu ficaria do lado do Java e escolheria o size :slight_smile:

IMO, acho que nenhuma das formas estaria correta.
Organizar não é uma função de uma lista, mas de um Organizador.
Pensando dessa forma, acho que, deveria ter uma classe do tipo Sorter e esta sim teria a inteligência para realizar a organização da classe.
Poderia ter uma fábrica (Factory ou Builder) onde forneceria a classe-base e retornaria uma implementação específica e formas de fornecer implementações para casos não abordados (onde o desenvolvedor criaria pontos que mapeariam a lógica adequada, como é feito quando fornece-se um Comparator).