Livro Design Patterns: e se houvesse uma segunda edição?

Recentemente, numa entrevista ao Gang of Four, foi revelada a intenção de uma nova edição do mais que conhecido livro Design Patterns:
http://www.informit.com/articles/article.aspx?p=1404056

Em uma excelente e curta entrevista, os autores falam de diversos tópicos, como a necessidade de design patterns em linguagens funcionais e dinâmicas, alguns patterns que viraram smells em grande parte dos casos (anti patterns) como o singleton, injeção de dependências como pattern e muito mais. Leitura recomendada!

abraços!

Olá

Tenho para mim que o livro da gang dos 4 é um bom livro mas a pressão pelo uso de design patterns foi ruim para os programadores em geral.

Explico:

Padrões deveriam ser uma segunda ou terceira preocupação do programador. Ele deveria se concentrar em resolver o problema da forma que conseguisse. No futuro ao refatorar, caso reconhecesse algum padrão aí sim alterava o código.

Mas não foi isto que vi muitas vezes. Os caras achavam bonitinho programar por padrões.

Ora, foi neste mundo fértil de beócios que surgiu aquele terrível livro da Sun dos Core Design Patterns. Os programadores eram então incentivados a fazer do modo complexo coisas que poderiam ser mais simples.

Por algumas discussões aqui no GUJ, temo que esteja acontecendo algo semelhante com DDD. As vezes leio alguns posts tão complexos que fico com saudades do tempo em que a gente se concentrava no problema a resolver sem precisar satisfazer o colega que acha mais bonitinho assim ou assado.

Fiquem tranquilos, não estou tendo ataques de duct-tape programmer by Joel Spolsky. Apenas acho que design patterns deve ser usado por programadores experientes que reconhecem um padrão ao olhar a solução codificada ao invés de ser usado só para o programador falar difícil para o colega que usou XPTO ou KYMZ.

Seria interessante uma segunda edição baseada em outras linguagens. Mas deveria vir com um alerta: A gang dos 4 adverte, usar design patterns em excesso pode causar embruculhamento (*) do seu código.

(*) Substitua embruculhamento por uma palavra mais feia se conseguir

[]s
Luca

Muito interessante a entrevista.

Será que alguém poderia indicar alguma situação onde Singleton ainda seria útil nos dias de hoje?

[quote=tnaires]Muito interessante a entrevista.

Será que alguém poderia indicar alguma situação onde Singleton ainda seria útil nos dias de hoje?[/quote]

Em várias situações. Mas normalmente nas que se vivem no mundo EE (liás a especificação meio que proibe isso)

Singleton é util e está em vários lugares da API padrão.

Dizer que ha um problema com o singleton é não entender o que um padrão é. O problema não é com o sigleton, é com a educação OO das pessoas. A maior parte usa um singleton (porque é o padrão que aprendeu) para resolver coisas que seriam corretamente resolvidas com um outro padrão. O erro é do programador e do ensino, não do padrão ou de quem o identificou.

Padrões são para OO o que receitas são para a culinária, mas ao contrário. Quando vc começa na culinária começa seguindo receitas e só depois vc evolui para o estado em que pode simplesmente fazer. Vc entendeu as regras inerentes às receitas e vc as aplica abstractamente. Os padrões é ao contrário. VC começa por não os usar, mas vc segue os principios de OO (os que não os seguem têm problemas mais graves ). Ao usar os principios abstratamente durante um tempo vc identifica padrões.
O pulo do gato é que os padrões se podem ensinar mesmo a quem não segues os principios abstratamente e a pessoa pode programar bem usando padrões mesmo sem conhecer muito OO.

O problema não são os padrões. O problema é a fraca cultura dos programadores que não os entendem. Confundem tudo, é um caos. Coisas como dizer que pode haver mais do que uma instancia de um singleton ou que MVC é separação em camadas são exemplos da pouca e fraca cultura de padrões.

Usar padrões e programar padrões sim é uma vantagem. Quem não entende isto é porque não os usa direito ou nunca viu alguem usar direito. … ou simplesmente é preguiçoso.

Já tenho ouvido absurdos de fazer qualquer codigoa ad hoc e depois refactorar. Isso gera um custo imenso, porque a primeira coisa que o cara faz é gamb. Refactorar gamb é impossivel.

Existe até um livro “refactorando para patterns”. Se eu vou refactorar para patterns isso significa que o programa escrito com patterns é que é o melhor. portanto, se eu programar com patterns desde o inicio não preciso refactorar.

Refactorar virou pipula mágica para desculpar a asnceira, a falta de conhecimento e a gamb. Senhores, refactorar é caro! e quanto mais gamb é, mais caro fica.

Aprender a programar usando patterns é aprender a programar usando meta-OO. um nivel acima. claro, se quase ninguem sabe OO não se pode esperar que saiba patterns , mas dizer que patterns é ruim é simplesmente absurdo e um desfavor à comunidade OO (seja em que linguagem for)

Até nesses casos que porventura existam, singleton não se justifica, IMHO.

Até não vejo problema em usar uma instância só pra fazer alguma coisa, a parte ruim é obrigar, como o pattern faz.

Paulo, muito bom, obrigado por compartilhar.

tnaires, o singleton foi muito usado no passado, porém houve uma onde de “não usar” singleton… coitado dele, de um dia para o outro foi escurraçado. Ele era muito bom pelo fato de criar uma instancia unica, mas hoje em dias com os processadores mais inteligentes somados a evolução da própria vm instanciar objetos e coleta-los nem é mais tão preocupante. Vejo assim não haver uma necessidade de singleton. Lembrando que há uma proposta pro EJB 3.1 de haver uma anotação @Singleton.

Uma discução que acompanhei há algum tempo foi sobre logging… em ambientes j2ee se você usar sua classe de logger como static você não consegue trabalhar bem com os repository selectors, onde criando como instancia normal você consegue usá-los.

Luca, concordo mesmo contigo sem adicionar ou remover alguma palavra do seu post. Excelente.

Abraços

Como foi mencionado, concordo totalmente com o Luca!!!. E a Kathy Sierra deveria escrever o novo livro, aí seria um catalogo bom de ler!! :slight_smile:

Sobre o singleton especificamente: o problema não é o fato de ter ou não uma instância única da minha classe. O problema é que as demais classes que usam esse meu objeto único são obrigadas a saber que aquilo é um singleton (normalmente através do famigerado getInstance estático).

A evolução do singleton hoje, na linha da separação de responsabilidades, é usar inversão de controle e injeção de dependencias. Minha classe que precisa daquela outra de instancia unica, ao inves de chamar o getInstance, recebe uma dependencias. E o container resolve se a instancia a ser injetada deve ser unica ou não.

Compare qual código deixa as duas classes mais desacopladas:

class PrecisoDeUmCaraSingleton {
  PrecisoDeUmCaraSingleton() {
      SouUmSingleton s = SouUmSingleton.getInstance();
  }
}

ou:

class PrecisoDeUmCaraQueNãoSeiSeÉSingleton {
  PrecisoDeUmCaraQueNãoSeiSeÉSingleton(NãoSeiSeÉSingletonENãoMeInteressa n) {
      // injecao de dependencia
  }
}

No fim, singleton hoje deixou de ser Design Pattern de código e passou a ser configuração de escopo em containers IoC.

Seu exemplo mostra com toda a clareza porque é difícil escrever testes para singletons.

De uma coisa tenho que concordar com o Luca, quando chegamos e conhecemos outras linguagens e comunidades, percebemos o quanto o Java se torna mais complexo com a tal caracteristica de adicionar Isso e Mais aquilo e Aquilo outro só para ficar, digamos, “bonitinho”. Nisso vejo que, por fora, Ruby, Python e outras vem ganhando terreno e matando o Java e sua extrema complexidade. Lamentável.

Olá

Você captou justamente o que eu quiz dizer. A complexidade inibe o iniciante. Vamos programar, resolver problemas, aprender o negócio, saber usar TDD. Deixem o código bonitinho para lá enquanto aprende. Com tempo a gente melhora. E aí então naturalmente usará alguns padrões.

Muito melhor do que se preocupar em escrever código baseado em padrões é se habituar a fazer revisão de código. Se você não costuma fazer as partes mais dificeis usando programação em par, pelo menos reserve alguns momentos do seu dia para sentar com outros programadores para rever os códigos deles e principalmente para que outros revejam seu código. Convença seu chefe de que isto não é perda de tempo. Vai aprender bem mais rápido e evitar levar adiante código que nem você que fez consegue explicar para o colega.

E nunca esquecer que a gente programa para resolver negócio.

[]s
Luca

Concordo com o Sergio sobre usar DI invés de codificar seu Singleton,. diminuindo o acoplamento entre dependencias. Mas notem que a MOTIVAÇÃO que é algo fundamental na execução de qualquer pattern ainda existe no caso do Singleton, a diferença é que não é você que o codifica, é algum framework ou biblioteca.

Logo o Singleton, ainda hoje, pode e deve ser utilizado, a diferença é que não tem que codifica-lo em seu projeto já que o fizeram por você… apenas anote ou configure seu framework favorito :wink:

Importante no singleton é nao ficar chamando um metodo estatico getInstance como o Sergio mostrou: voce fica super acoplado e é dificilimo de testar (passar mocks). Assim como factory methods, é importante isolar esses patterns criacionais dependente de metodos estaticos, fazendo com que voce recebe a referencia no construtor: facilita bastante qualquer tipo de teste e diminui drasticamente o acoplamento.

Acho que devo ter acessado o guj de um universo paralelo … o que se passa com vcs ?

Desktop é uma classe singleton no JSE. Onde é que está escrito que ele é um singleton ? Cadê a assinatura souumsingleto.getsingleton ? Compare com Calendar.getInstance e Locale.getInstance que não são singleton.

Tente injetar Desktop numa classe. É muito simples com Guice, não tanto com Spring, mas e dai ? é possivel. é o que interessa.

confundir singleton dom DI ? mas que raios vcs estão pensando ? Singleton é um padrão criacional !
Vc se esquecem que DI usa factories. Alguem tem que criar os objetos para eles serem injetados !! em todos os motores de DI vc pode configurar essas factories. O ponto não é injetar, mas sim criar. Se a classe ñ é singleton várias instancias podem ser criadas mesmo com um motor de DI.

Singleton como acesso global é subsittuido por Registry.

@Singleton é a perpetuação da asneira. Não satisfeitos com a confusão do VO o povo da jcp adora meter lenha na fogueira. A culpa é do Spring que chama - erradamente - de singleton objetos que são na realidade shared object. E como o povo do Spring está na jcp… bom, já se viu.

Singletons reais são raros. Mas isso não invalida o padrão. O problema é o mau entendimento que as pessoas têm de padrões. Não só design patterns, mas de outros como Produtor-Consumir que é essencial em mensageria e concorrencia.

Castigar o singleton pelo mau uso que os programadores fazem dele é como castigar a tinta pelas palavras groseiras que se escrevem com ela. Ainda mais absurdo é culpar todos os padrões como um todo. É como se castigássemos o próprio alfabeto por permitir escrever palavras.

Vcs não estão dizendo coisa com coisa. Quem ler isso vai achar que padrões é uma porcaria. A mensagem a ser transmitida não é essa. É exatamente ao contrário. Foi depois que padrões foram introduzidos na API do java que ele ficou mais limpo. A API de collections é um otimo exemplo assim como a nova NIO2 usando Visitor para iterar arquivos. E já a NIO tinha melhorado usando uma versão de observer. E a JDBC que todo o mundo usa toda a hora é um excelente exemplo de Bridge.
O melhor e mais edgy de java é feito com aplicação de padrões!

Agora, o problema é: estudar padrões , aprender padrões, e usar padrões é dificil e complexo! Não é para qualquer um. Portanto:

  1. padrões é otimo.
  2. aprenda-os
  3. aprenda-os direito!

Ha certas ocasiões em que dá tristeza ver o que se escreve de padrões … frases do tipo “Fiz um façade para encapsular a chamada”

É como ver as pessoas falarem mal ou escreverem errado. Fere os ouvidos e corta o coração quando é um profissional dizendo.
O pior não as pessoas não saberem, é alguem dizer que aprender é inutil.

Bom falar que padrões são necessários por causa da austeridade da linguagem é ainda pior asneira. São padrões de OO , de design, de arquitetura , de segurança, etc… não são padrões de linguagem !! afinal o GOF era smalltalk e C++ e ainda é válido em java, C# , qq outra linguagem OO.

Que raios deu em vocês ?

Palavras bonitas mas como de um político. Você fala para poucos e logo poucos lhe escutam. Conheceu Rails? Viu Ruby? Quando colocamos a mão em situações como Ruby, Rails, questionamos o porque o Java ou outra louca linguagem que deseja seguir este método obscuro de desenvolvimento existe. Desde que comecei a aprender Java vi tantas palavras que posso colocar em um dicionário facilmente. Também vi quando comecei a trabalhar com isso que os projetos pequenos se tornam demorados. Seria falta de conhecimento decoreba dos padrões? Sei não, pra mim é coçar a orelha esquerda com a mão direita.
Ai vem um Rails da vida, mostra que, tudo que fiz poderia ser prático, divertido e nada confuso. Que A que programou, B entende, C entende e qualquer outras letras que colocar aqui, entende. Agora, tem projetos em Java que, graças a Deus, inventaram as IDE’s, porque é a coisa mais louca que já vi, é um padrão X que passou a ser chamado de Y, porque antes era VO, depois virou “PÓ”, rs. Ai fazem as maravilhosas packages com nomes de sei lá o que e dizem: há, isso é DDD. Putz, quantos anos levam para um iniciante aprender tudo isso? Quanto tempo terei que machucar minhas mãos para escrever “belamente”?
Eu digo uma coisa, levei nem 1 mês para entender Rails, em 2 meses estava em um projeto e até hoje já passei por 4 projetos em Rails, sendo um de porte médio. Mudei de equipe várias e várias vezes e cada linha escrita e reescrita eu compreendo. Se entrar no meio de um projeto Rails já sou produtivo. Se for em Java, só se der sorte. Sorte com a complexidade ou com metidos arrogantes que arrotam letras e padrões que nunca ouvi falar, mas que existem talvez para tornar o programador mais valioso.
Desculpe o desabafo gente, mas é que já vi tantas discussões de padrões e cada dia mais penso que sei menos. Já até falei em outro post que to quase mudando meu nick para rubymaniaco.

Tirando as frases mais exaltadas, eu acho que no fim estamos todos falando a mesma coisa. Patterns são difíceis mas resolvem bem alguns problemas, e ótimos exemplos estão na própria API do Java SE.

E sobre o singleton em particular, é o que eu falei: o problema em geral não está em ter uma única instância (isso às vezes é útil, mas raramente como você disse). O problema é o acesso global vinculado ao Singleton (e aliás a alguns outros patterns creacionais, como a própria Factory).

Você sugeriu usar Registry para evitar o acesso global. Ok, é um jeito (embora eu não goste). Mas DI é outro jeito (que aliás substitui boa parte da necessidade do Registry). Hoje singleton acabou virando configuração dentro de container IoC, bem como boa parte das Factories, que fabricam para um container depois injetar (não chamamos mais factories em nossos códigos).

Aliás, também achei @Singleton uma má ideia :slight_smile:

[quote=javamaniaco][quote=sergiotaborda]

Castigar o singleton pelo mau uso que os programadores fazem dele é como castigar a tinta pelas palavras groseiras que se escrevem com ela. Ainda mais absurdo é culpar todos os padrões como um todo. É como se castigássemos o próprio alfabeto por permitir escrever palavras.

Que raios deu em vocês ?
[/quote]
Palavras bonitas mas como de um político. Você fala para poucos e logo poucos lhe escutam.
Conheceu Rails? Viu Ruby? Quando colocamos a mão em situações como Ruby, Rails, questionamos o porque o Java ou outra louca linguagem que deseja seguir este método obscuro de desenvolvimento existe.
[/quote]

Isso porque vc tem pouca bagagem para entender. Qual é a base do modelo de objetos do ruby ? Em java é classe, em javascript é
prototype ( os dois são padrões ) e em ruby ? vc sabe ? eu lhe digo : meta-class.
O que é um meta-class ? é o uso do padrão MetaObject. Um MetaObject é um objeto que descreve outro. Este padrão é muito usado em XML onde um esquema define o xml, em banco de dados onde um conjunto de informações define os “metadados” (passo a expressão) do banco. Em java o tipo Class é um MetaObject porque define como um object será. Uma meta-class do ruby é um objeto que define como a class será. É um nivel acima. E é isso, apenas isso, que permite que o ruby seja mais flexivel que java. É facil entender porquê essa flexibilidade pois vc está usando um nivel de abstração mais elevado. O mesmo acontece com groovy e outras linguagens com meta-class.

Vc não viu o suficiente. tinha visto o padrão MetaObject ?

Obviamente.

Ha pessoas que dizem que furam, ha pessoa que obliteram. Cada um usa a palavra mais explicativa que conhece.

E veja só que interessante. Ele faz tudo isso apenas com um design pattern: MetaObject. Genial, não ?

Na boa, que culpa tenho eu disso ? Que culpa tenho eu ou o java ou quem quer que seja, dos seus talentos e defeitos ?

Mais uma vez : que culpa temos nós que vc não ouvi falar ? a culpa é toda sua que não estudou o suficiente!
Veja só que a ironia : vc está dizendo que ruby é uma maravilha, mas ele é feito a partir de um padrão chamado MetaObject que vc nunca ouviu falar. O cara que inventou o ruby, deve ser, portanto, pela sua logica um “metido arrogante”.

Alguns fazem, alguns ensinam e o resto lê nos livros.
E algums nem livros leêm…

Culpar padrões ou o java ou a sun ou o jcp ou seja quem for pela própria ignorância é desonesto e irresponsável.

Eu não tenho culpa de saber padrões. Ou vão me queimar na fogueira por isso ? :lol: :lol: :lol: :lol: :lol: :evil:

[editado por mim mesmo - estava redundante com o que o Sergio escreveu ]

… menos a parte de @Singleton. Qual mal vc vê nesta anotação Sergio Lopes? E você Taborda, que mal você vê em uma anotação que realmente provê a criação única de um objeto em memória? Somente o nome? Se for isso o que vc sugeriria, apenas por curiosidade.

[quote=Sergio Lopes]

Você sugeriu usar Registry para evitar o acesso global. Ok, é um jeito (embora eu não goste). Mas DI é outro jeito (que aliás substitui boa parte da necessidade do Registry).[/quote]

Pois é… então vc acha que o Spring não tem um Registry… o que vc acha que é o ApplicationContext com o seu getBean(id) ?
Pense melhor.

No guice é mais obvio o uso de regestry no objeto de bind onde vc configura o bind da interface/classe com a classe.
Não é possivel trabalhar com metadados em um Registry. A razão é simples : metadados, são, por definição, globais.

Releia o conceito de Registry e compare com o ApplicationContext. Já agora compare tb o Factory com o Provider do Guice.

Motores de injeção precisa criar objetos : logo, precisão de saber como criá-los ( registry de metadados) , criá-los (factory) e depois injetá-los (Registry de metadados de injeção lidos de annotações, xml, etc… ) se o objeto tem mecanismos especiais de criação como singleton, prototype, etc… então é preciso um factory especial, mas um factory, non the less…

[quote=Alessandro Lazarotti]Olã Sergio,
Não olhei o ponto onde alguém confundiu Singleton com DI. Como você mencionou Singleton é padrão criacional e de nada tem haver com DI. O que muitos disseram aqui (e não só aqui), é que em muitos casos você pode delegar a criação do objeto fora da classe que a tem como composta ou do método que a utiliza, diminuindo a amarração da classe, o que não ocorre na maioria das vezes que é utilizado Singleton.[/quote]

O que estou dizendo é muito simples : não ha como delegar a criação de um singleton a uma outra classe. Essa é a essencia do padrão. Se vc delega, é porque, obviamente não era um singleton. Singletons verdadeiros não podem ser criados sem ser pela sua propria classe.

Veja bem o conceito de singleton nasce da proibição explicita de injeção de dependencia que é um principio da OO. Portanto, não faz sentido que um motor de injeção possa criar um singleton. É como ter uma fabrica de singleton, simplesmente impossivel.

O ponto que abordei é a confusão de que um singleton possa ser criado via motor de DI. Não pode. O exemplo é a classe Desktop.
Contudo, isso não signfiica que eu não o possa injetar. Posso sim. É só configurar o motor de DI corretamente. Isto rebate o que foi dito que não usar singleton aumenta a testabilidade e a injeção. Isso é falso. Vc nunca usa singleton porque quer. VC usa porque precisa. Se ha outro jeito então aquilo não era um singleton para começo de conversa.

Pense realmente a fundo num outro jeito de implementar Runtime ou Desktop sem ser usando singleton. Não é possivel. Venham quantos DI existirem…