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

Quanto ao uso de reflection. Vale lembrar que reflexão não é OO. É um paradigma à parte. E com reflexão, abrimos mão de segurança.

Se formos contar a reflexão, nenhum padrão é realmente seguro, já que podemos ler atributos ou invocar métodos privados, o que viola um dos princípios básicos da OO em si, o do encapsulamento.

O singleton quebra, o shared object quebra (podemos via reflection trocar o objeto shared por outro objeto), qualquer coisa quebra.

Achei curioso culparem singleton por não se dar bem com testes quando o real problema com testes é a existencia de estado mutavel e acessado por diferentes threads, basicamente a idéia de um objeto que é encapsular estado mutavel. Entretanto não vejo ninguém sugerir OO como prática não-recomendada (quer dizer, Rich Rickey, criador da linguagem clojure sugeriu que this is not about message passing).

Acho que tem muito a ver com o topico ja que dizem que Clojure é segunda edição da linguagem Java.

Oi Mochuara. Nao é culpa só do estado mutavel nao (que voce tem razao, tambem dificulta):

Como voce faz unit test disso aqui sem enfiar a mao no classloader?

void metodo() {
   EnviadorDeEmail.getInstance().envia("x@x.com.br");
}

Como Sergio falou la atras, melhor é receber EnviadorDeEmail pelo construtor, ou melhor ainda, sua interface. Ai sim fica bem testavel.

Há algum tempo, fiz uma pergunta sobre Singleton neste tópico (aliás, o primeiro tópico que abri no fórum). Também gerou uma discussão bastante inflamada mas cheia de informações úteis.

Entre outras conclusões, cheguei a uma regrinha para decidir se o Singleton é a escolha certa para cada situação ou não:

-> O conceito deste objeto dentro do domínio exige que ele seja uma instância única? Ou seja, obrigatoriamente só existe UM no mundo que está sendo modelado? Ex. os já citados Desktop e Runtime.
-> Ou a existência de uma única instância é desejável (por praticidade de programação ou por economia de recursos da máquina), mas não intrínseca ao conceito deste objeto/classe? Ex. fábrica de conexões com BD, cache de objetos usados frequentemente dentro da aplicação.

Só se a resposta à primeira pergunta for sim, então o Singleton será a solução para este caso. Se cair no caso da segunda pergunta (algumas vezes a diferença é sutil) devemos chamar de algum outro nome, como Shared Object.

Curiosamente, não conheço casos em que algum objeto do modelo de negócio possa ser classificado como Singleton. Me parece que o padrão se aplica mais a componentes da API ou de infraestrutura.

Oi Mochuara. Nao é culpa só do estado mutavel nao (que voce tem razao, tambem dificulta):

Como voce faz unit test disso aqui sem enfiar a mao no classloader?

void metodo() {
   EnviadorDeEmail.getInstance().envia("x@x.com.br");
}

Como Sergio falou la atras, melhor é receber EnviadorDeEmail pelo construtor, ou melhor ainda, sua interface. Ai sim fica bem testavel.
[/quote]

Mas isso sempre foi assim. O facto de uma gambiarradores desenharem como no exemplo atesta a incompetencia deles, não de OO, de padrões ou principios. Injeção de Dependência sempre existiu e sempre foi usada. (Esse é outro assunto que daria pano para mangas : DI vs Motor de DI) Injeção de Dependência e inversão de controle são coisas básicas de OO. Se vc as seguir vc vai cair em duas coisas:

  1. Seu codigo será mais facilmente testável.
  2. Seu codigo começará a usar padrões (mesmo que vc não faça isso conscientemente ou sequer saiba o que são)

Testes são um segundo cliente. Eles força a desenhar o sistema para dois clientes. Isso ajuda imenso no design pq vc vê onde as coisas têm que está amarráveis não não amarradas. O verdadeiro anti-pattern aqui seria ServiceLocator não o singleton.
O serviceLocator foi abusado , como muitos outros padrões , ao ponto de criar um anti-padrão.

Agora um novo anti-padrão surge. O abuso de DI e de motores de DI. Já que é tão flexivel então não se fixe nada. Deixa tudo desamarrado. Isto causa o efeito contrário. O caos é tanto que vc identifica cadeias de injeção de 5, 7 niveis. Isso tb é um abuso.

O joshua bloch tinha uma máxima para desenhar frameworks que acho que se aplica muito bem a qq API. Vc precisa ter 3 aplicações para ela. três cenários diferentes. Só assim vc não corre o risco de incluir coisas amarradas e ajuda a ver onde está a parte fixa. O software é um destes cenários. Os testes são outros. O terceiro tem que vir de um cenário hipotético. O principio do Não faça se não precisa, é mal interpretado. Porque mesmo que vc não implemente o terceiro cenário agora, o design compativel com os 3 cenários será mais simples de evoluir. O problema acontece quando vc começa a implmentar o cenário hipotético e esquece dos testes e do software… Enfim, o ponto é que testes naturalmente tornam o codigo melhor por causa deste principio dos 3 cenários.

A mensagem que eu queria deixar clara é que : se vc programar utilizando Patterns, como sendo ferramentas , vc tb terá um codigo mais limpo e menos acoplado. Um codigo padronizado (com patterns) é naturalmente testável porque ele já segue os principios de OO que tornam isso possivel “out-of-the-box”

[quote=sergiotaborda]Testes são um segundo cliente. Eles força a desenhar o sistema para dois clientes. Isso ajuda imenso no design pq vc vê onde as coisas têm que está amarráveis não não amarradas. O verdadeiro anti-pattern aqui seria ServiceLocator não o singleton.
O serviceLocator foi abusado , como muitos outros padrões , ao ponto de criar um anti-padrão.
[/quote]

Mochuara, acho que o Sergio conseguiu excplicar bem melhor. Novamente concordo 100%. Quem usa TDD nunca mais escreve esse tipo de codigo com singleton, pois de cara percebe que nao vai conseguir testar. Esse cheiro de service locator realmente é a parte prejudicial no uso do singleton.

[quote=gomesrod]Há algum tempo, fiz uma pergunta sobre Singleton neste tópico (aliás, o primeiro tópico que abri no fórum). Também gerou uma discussão bastante inflamada mas cheia de informações úteis.

Entre outras conclusões, cheguei a uma regrinha para decidir se o Singleton é a escolha certa para cada situação ou não:

-> O conceito deste objeto dentro do domínio exige que ele seja uma instância única? Ou seja, obrigatoriamente só existe UM no mundo que está sendo modelado? Ex. os já citados Desktop e Runtime.
-> Ou a existência de uma única instância é desejável (por praticidade de programação ou por economia de recursos da máquina), mas não intrínseca ao conceito deste objeto/classe? Ex. fábrica de conexões com BD, cache de objetos usados frequentemente dentro da aplicação.

Só se a resposta à primeira pergunta for sim, então o Singleton será a solução para este caso. Se cair no caso da segunda pergunta (algumas vezes a diferença é sutil) devemos chamar de algum outro nome, como Shared Object.

Curiosamente, não conheço casos em que algum objeto do modelo de negócio possa ser classificado como Singleton. Me parece que o padrão se aplica mais a componentes da API ou de infraestrutura.[/quote]

Parabéns!! É exactamente isso. Palmas!!

[quote=Paulo Silveira][quote=sergiotaborda]Testes são um segundo cliente. Eles força a desenhar o sistema para dois clientes. Isso ajuda imenso no design pq vc vê onde as coisas têm que está amarráveis não não amarradas. O verdadeiro anti-pattern aqui seria ServiceLocator não o singleton.
O serviceLocator foi abusado , como muitos outros padrões , ao ponto de criar um anti-padrão.
[/quote]

Mochuara, acho que o Sergio conseguiu excplicar bem melhor. Novamente concordo 100%. Quem usa TDD nunca mais escreve esse tipo de codigo com singleton, pois de cara percebe que nao vai conseguir testar. Esse cheiro de service locator realmente é a parte prejudicial no uso do singleton.[/quote]

Como havia dito anteriormente, tudo se resume a estado mutavel. O conceito do Singleton em si não traz problema de testabilidade em linguagens funcionais. O problema é quem usa Java não vai conseguir mockar um singleton. E mocks são fundamentais para testabilidade em sistemas OO, ou seja, que mantem estado mutavel.

MAs mesmo em Java Singletons podem ser uteis em partes que vc não precisa testar. A classe Application do Swing por exemplo é um singleton assim como o ServiceLocator poderia ser. O fato deles não serem testaveis não deveria ser um problema ja que não pertencem ao negócio que onde fica o código critico que precisa ser testado.

[quote=sergiotaborda][quote=ccaneta]O Padrão Singleton pode ser modificado para que exista “um número máximo de instâncias de uma classe”, caracterizando assim um pool de objetos,
[/quote]

Não. Isso é conceptualmente errado. Singleton não um master-pattern de onde derivam os outros.

Se vc quer poder escolher quantas instancias ha , isso não é um singleton. nem um shared object, é ,como vc falou , um pool. mais concretamente ObjectPool.

Não existe isso de “modificar padrões”.[/quote]

Em que situação ocorrem quando vários subsistemas utilizam o mesmo arquivo de configuração ?

Em Java o que é lazy instantiation para o uso de Singleton ?, Java suporta clonagem de Objetos ?

[quote=ccaneta][quote=sergiotaborda][quote=ccaneta]O Padrão Singleton pode ser modificado para que exista “um número máximo de instâncias de uma classe”, caracterizando assim um pool de objetos,
[/quote]

Não. Isso é conceptualmente errado. Singleton não um master-pattern de onde derivam os outros.

Se vc quer poder escolher quantas instancias ha , isso não é um singleton. nem um shared object, é ,como vc falou , um pool. mais concretamente ObjectPool.

Não existe isso de “modificar padrões”.[/quote]

Em que situação ocorrem quando vários subsistemas utilizam o mesmo arquivo de configuração ?
[/quote]

Use Registry. Inspire-se em System.getProperties();

É uma inutilidade. A maior parte das vezes singleton não precisa ser lazy.
Até agora não encontrei um exemplo em que precise ser lazy.

sim. Veja Object.clone() e Clonable.
Esta eu não entendi a relação com o assunto.

[quote] Java suporta clonagem de Objetos ?
sim. Veja Object.clone() e Clonable.
Esta eu não entendi a relação com o assunto.
[/quote]
Fala Sergiãooo !!!

Como o Java suporta a clonagem de objetos, devemos declarar a classe como final, para impedir que suas subclasses possam implementar a interface Cloneable, possibilitando a duplicação de objetos pelo método “clone”, o que romperia com as obrigações deste padrão.Caso a classe Singleton seja uma subclasse de outra que suporte a clonagem, então o método “clone” deve ser sobreposto por outro que apenas lance a exceção CloneNotSupportedException, indicando a impossibilidade da realização desta operação.

[size=24]; )[/size]

[quote=Paulo Silveira][quote=sergiotaborda]Testes são um segundo cliente. Eles força a desenhar o sistema para dois clientes. Isso ajuda imenso no design pq vc vê onde as coisas têm que está amarráveis não não amarradas. O verdadeiro anti-pattern aqui seria ServiceLocator não o singleton.
O serviceLocator foi abusado , como muitos outros padrões , ao ponto de criar um anti-padrão.
[/quote]

Mochuara, acho que o Sergio conseguiu excplicar bem melhor. Novamente concordo 100%. Quem usa TDD nunca mais escreve esse tipo de codigo com singleton, pois de cara percebe que nao vai conseguir testar. Esse cheiro de service locator realmente é a parte prejudicial no uso do singleton.[/quote]

Eu particularmente assino embaixo de tudo que o taborda falou, porém qual é o foco do tópico ? É singleton ? DI ? não ! O foco é a revisão dos padrões

Portanto os padrões devem ser revisados? Sim ou não ? Quais devem ? Devem continuar Existindo sim ou não?

Quem falou que TDD é o correto? Desde quando TDD vale pra tudo? Entendo que TDD aqui é o Test Driven Development.

IMO, posso indicar que depois de muitos e muitos projetos de grande porte, você vai perceber que padrões são sim necessários, quais padrões? O arquiteto vai decidir por projeto e por situação junto com os requisitos do sistema.

Nunca existirá uma solução única para um problema, sempre existirão no mínimo duas, a minha solução e a outra solução possível. Por que existem vários tipos de vassoura se todas varrem o chão?

A TI tem e muito que se padronizar, seja em linguagem, em Design Patterns, em processos no que for, tudo hoje em dia é muito manual, artesanal.

Você produziria um carro do zero sempre? Ou vai usar projetos padrões? Claro que vai usar padrões? Por que?

Produzir código pra depois refatorar ? Tá então eu vou criar um motor 1.0 novo e depois de pronto eu faço ele de novo? É isso ?

Temos sim é que repensar a nossa indústria como indústria de serviços e parar de ficar discutindo se acessar um Singleton via reflection vai estourar a segurança !

Quem disse que tudo que tá na VM tá certo? Quem falou que os design patterns estão sempre certos? Alguém foi lá e amarrou a mão do cidadão?

A única coisa que sempre será constante em um projeto seja ele qual for, em qual linguagem for e pra qual cliente for, é que ele deverá ter um inicio um meio e um fim e que faça o que o cliente quer, porém isso não justifica escrever código 'porco" nem impossível de manter, o mínimo de qualidade é pedida.

O que é qualidade em desenvolvimento de software? Como medimos a qualidade de um código ? Medimos se ele usa padrão? Se implantou o padrão certinho ?

Isso sim é a questão, singleton, shared, flyweight, proxy, factory o padrão que for, não importa, o que importa é fazer um código:

- Conciso
- Manutenível
- Inteligível
- Rápido 
- Correto

O resto é tentar traduzir o mundo em padrões.

Ou alguém já ouviu dizer de bilbioteca de modelagem ? Ou padrões de modelo ? O Objeto pessoa tem que ter CPF/CNPJ e nome? Não ! Cada caso é um caso.

Aonde devemos padronizar ? O que devemos padronizar? Quando padronizaremos ?

Quando teremos qualidade em SW ?

Fica ai algumas questões para os ilustres colegas da classe discutirem se desejarem

O cara não aprende java pelos padrões !!! Em linguagem nenhuma, linguagem aprende-se pela linguagem, depois você usa ela da melhor forma.

JEE Design Patterns foi a melhor forma na época encontrada por uns malucos chamados de GOF e agora com Seam e Ruby por ai com JSF 2 , Ajax e Portals e etc ?

Qual é o padrão ? :twisted: :twisted: :evil: :evil: :evil: :evil: :evil:

Fórum de tecnologia não tem foco, em qualquer uma que você vá. É mais interessante pela conversa que vai levando do que pelo foco.
Eu concordo com o Sérgio Taborda com relação a Singletons, que só deveria ser usado quando realmente tal objeto só existe uma única vez no domínio em questão. Tinha até o papo furado de que, com reflection, poderia-se instanciar mais de um objeto. Mas acredito que, com objetos estritamente únicos (daqueles do tipo Modem, Runtime…), uma segunda instanciação acidental postergaria erros de sincronia mais para frente. E o singleton seria uma necessidade.

No Java, existe essa confusão entre injeção de dependências e container de injeção de dependências, como se as duas coisas precisassem andar juntas. É até possível criar uma classe onde seria feita toda a instanciação de objetos, onde todo mundo obteria instâncias, deixando de lado Spring ou Guice. Eu, que estava estudando Scala, encontrei até um artigo que mostra como fazer DI usando recursos dessa linguagem. E um outro artigo que mostra o porquê de Ruby não precisar de IoC.

Deveria ser revisado. Mas acho complicado saber quais deveriam ser eliminados. Gostaria que patterns fosse algo transitório, que fosse de serventia enquanto as linguagens OO não a suportassem nativamente. Alguns patterns já existem soluções pela própria linguagem, exemplo:

  • Flyweight: strings em Java são assim, Integer de valores pequenos também são, Symbol em Ruby também.
  • Template Method: pode ser implementado via Closures em linguagens OO que a suporta
  • State: pode ser substituído por coroutine em Python, ou por Fibers em Ruby 1.9

Mas ainda assim não é universal e plenamente difundido, fazendo com que os patterns atuais sejam ainda a melhor opção.

TDD é bom porque ajuda a raciocinar em cima do problema antes de sair criando código a esmo. Muita gente não faz isso (e não se dá conta), preferindo olhar uma modelagem de banco e sair criando telas e objetos burros; e rezando para que o cliente olhe com bons olhos o produto final.

Qualquer outra disciplina que faça o programador pensar o problema a ser solucionado ajuda. Só não vale descartar o TDD e não ter outro pra substituir.

Minha visão de projeto de grande porte: qualquer projeto mal feito onde não houve uma alma bondosa que mantivesse a complexidade do software ao mínimo. Pra compensar o inchaço do projeto, é empurrado o engodo da disciplina militar, que faz com que nenhum movimento de progresso seja realizado.

Padrões não está na mão do arquiteto, qualquer desenvolvedor deve usar se for necessário, sem pedir benção de ninguém.

Sim, existem várias soluções. Mas discordo do “minha solução e a outra”, pois posso muito bem estar errado e não ter nada nas mãos.

Pattern = padrões que se repetem
Standard = padrões que garantem uniformidade

Brasileiro acha que padrão de projeto é que-nem norma da ABNT. Não é!

Padronização (de “standard”) é engodo. Desenvolvimento de software é artesanal, e nada vai acontecer que vá mudar isso. Cada projeto é único e tem necessidades específicas, não dá pra definir normas onde todo mundo precisa obedecer.

E se eu quisesse fazer um motor que nunca tenha existido? Tipo: um motor que seja movido a eletricidade, tenha independência de uma semana de recarga, e que vá de 0 a 100 em dois segundos. Acredite, não dá pra fazer certo da primeira vez. Precisará da construção de alguns motores antes de chegar ao ideal.

Não! Refatorar não implica processo de desenvolvimento em cascata.

[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 um projeto onde se tem o Abstract Facory, criamos uma classe Singleton para gerenciar a Connection Manager. :smiley:

[quote=ccaneta][quote] Java suporta clonagem de Objetos ?
sim. Veja Object.clone() e Clonable.
Esta eu não entendi a relação com o assunto.
[/quote]
Fala Sergiãooo !!!

Como o Java suporta a clonagem de objetos, devemos declarar a classe como final, para impedir que suas subclasses possam implementar a interface Cloneable, possibilitando a duplicação de objetos pelo método “clone”, o que romperia com as obrigações deste padrão.Caso a classe Singleton seja uma subclasse de outra que suporte a clonagem, então o método “clone” deve ser sobreposto por outro que apenas lance a exceção CloneNotSupportedException, indicando a impossibilidade da realização desta operação.

[/quote]

Um singleton não deve implementar clonable da mesma forma que não deve implementar serializable ou ser extensivel.
No ambito do 'programe para herança ou proiba-a" em singleton não ha muita conversa : proiba-a.

Um singleton já tem construtor privado o que mata a herança sem precisar ser declarado final, mas mesmo assim é uma boa ideia.
Por outro lado singleton não deve herdar de ninguem (só directamente de objet, claro). Porque senão vários paradoxos podem surgir. Um singleton verdadeiro é um cara standalone, um higthlander do universo. Só pode haver um. Além de garantir isso na instanciação, é preciso matar formas artificiais de instancialização como clone , serialização e herança. Tb por essa razão não faz sentido definir um singleton através de uma interface , porque ao definir com interface estamos dizendo que várias implementações são possiveis. Portanto não garantimos que elas forcem instâncias unicas, logo, não estamos seguindo o padrão singleton.

Um singleton deve ser concreto (defindo por uma classe, não uma interface ou classe abstrata), deve ter construtor privado, ser final, não clonável e não serializável.

[quote=sergiotaborda]É uma inutilidade. A maior parte das vezes singleton não precisa ser lazy.
Até agora não encontrei um exemplo em que precise ser lazy.[/quote]

Concordo. Um singleton “não lazy” é mais simples e mais seguro. E na maior parte das vezes, criar uma única instância de uma classe não será problema nem de performance e nem de memória (se for um problema de memória, é melhor nem usar singleton, já que uma vez criado ele ficará lá para todo o sempre).

Depois, é bom lembrar que a VM só irá criar seu Singleton assim que for usado a primeira vez, pois será nesse momento em que a classe será carregada. Ou seja, o lazy loading já existe.

Olá

Engraçado, com tanto pattern por ái sendo abusado, estuprado e mal usado, só o Singleton levou pancada aqui. Gente, estão esquecendo de muitos tais como:

  • Facade - um dos reis do abuso. Conheci um cara que adorava facade e usava para tudo, até para escovar os dentes

  • Service Locator - este é dos bons. Indispensável no uso dos EJBs 1.x e 2.x. A gente usava JNDI até para ler aquele arquivinho que estava ali do lado

E sem falar dos BOLOVOs.

Quando critiquei o mau uso dos patterns juro que não pensei somente no livro motivo deste tópico. Quiz chamar a atenção que tem alguns caras por aí mais preocupados em programar por patterns para imprerssionar os colegas do que em resolver o principal problema. Ainda acho que primeiro se deve tentar resolver o problema e caso se reconheça algum pattern ou algum caso de reuso de código, uma refatoradinha básica não dói nada. A tal revisão de código é uma boa prática para reconhecer isto e ajudar programadores novos. Muito melhor do que arrotar arrogância tentando provar que sabe mais e que está sempre 100% certo.

E aí concordo com quem disse que em Ruby/Rails este mau hábito ainda não pegou.

KISS… para todos, inclusive os 100% certo…

[]s
Luca

Não ha necessidade de uma segunda edicao do livro de patterns. Patterns continuam sendo um sinal que sua linguagem não possui as abstracões necessarias para resolver seu problema. Patterns como alinguagem Java não mudaram nada de la pra ca.

Sinceramente eu nunca liguei para patterns, pois acho que faço um código bem estruturado, e vejo patterns um pouco como dar nome “cientifico” para as boas maneira de como os bons programadores estão resolvendo problemas.

E já aconteceu várias vezes de virem me dizer que há bacano você esta usando o pattern X, Y, Z, e eu nem imagina por completo desconhecimento do pattern, talvez até, nem o estivesse usando da maneira mais correta e nem resolvendo meu problema da maneira mais correta e prática. Penso que esta situação já deve ter acontecido com muitos, de alguém vir e dar um nome a maneira como tens o código. :stuck_out_tongue:

Isto era o que eu pensava ante de ler muita coisa que o Sergio e o Luca disseram. Se bem que nunca pensei muito a fundo nos patterns, vou mais pelo caminho de resolver o problema da maneira mais simples e com melhor performance que consigo.

Com o que li cheguei a uma conclusão pessoal, e que espero não estar em erro.

Patterns são excelentes quando não atrapalham. Eu pelo menos tenho uma enorme pressão com tempo, tempo é dinheiro, e complicar esta fora de questão.

Agora o que resumidamente entendi do que Sergio falou, e nisto apesar do meu pouco conhecimento e tenho que concordar, é que o conhecimento dos patterns só vai ajudar, todo conhecimento é sempre bom.

Por exemplo se eu tenho um problema para resolver, e for pensar como montar as minhas classes, como vou montar a minha solução, e se houver um pattern que é indicado para esta solução e eu o conheço bem, logo se aplica-lo vou poupar imenso tempo pois conheço ele e sei como usa-lo e aplica-lo rápido e de forma eficaz.

Como já programo a muito tempo e várias linguagens, tenho talvez os meus próprios “patterns”, que para o problema X, Y, Z, vou resolver desta maneira ou daquela, que pela experiência já sei a forma prática e eficaz de resolver, e também isto pode ser chamado de vício, pois pode haver uma maneira mais fácil de resolver usando algum pattern que como desconheço vou passar a vida complicando algo que já foi simplificado.

Minha conclusão é que devo aprender mais sobre patterns para ver os meus maus vícios e como posso programar de forma mais eficaz.

Para quem esta começando, acho que isto é muita perfumaria logo de cara. Já não é fácil para muita gente começar, e levar com mais teoria sem compreender bem na prática, é impossível aprender bem.

Na prática é a conclusão que chego até aqui…

[quote=Luca]
Quando critiquei o mau uso dos patterns juro que não pensei somente no livro motivo deste tópico. Quiz chamar a atenção que tem alguns caras por aí mais preocupados em programar por patterns para imprerssionar os colegas do que em resolver o principal problema. Ainda acho que primeiro se deve tentar resolver o problema e caso se reconheça algum pattern ou algum caso de reuso de código, uma refatoradinha básica não dói nada.[/quote]

Vc diz que não doi porque vc talvez nunca teve que lidar com isso. Refactorar para Produtor-Consumidor não é trivial se o cara fez um negocio macarrónico. Outro padrão que não é trivial é UnitOfWork. O problema nem sequer é com as classes ,aqui normalmente o problema é com deficiência de pontos de extensão onde mexer e usar os patterns.

Não ha problema algum em querer programar pattern driven , o problema é se a pessoa não sabe. É o mesmo tipo de problema de programar test driven, domain driven, etc… todos os 'driven" exigem que a pessoa saiba o que está fazendo. Só que pattern driven quando mal feito destroi todo o design do sistema tornando até o refacctoring caro , demorado ou simplesmente impossivel porque não dá nem para entender a gamb.

Resolver o problema ad hoc não é resolver o problema, é colocar um patch e adiar a solução. Ou seja, é gamb!
Se vc tem um problema vc já procura o pattern ou conjunto de patterns que irão ajudar. è por isso que os catálogos de patterns começam por explicar o problema que o padrão resolver. Espera-se que o designer saiba ligar os pontos. Se o cara não é designer a má escolha não é culpa do pattern ou do cara querer seguir patterns. É simples falta de cultura / experiencia.
O unico requisito para usar pattern é ele resolver o problema, portanto, sabendo o problema escolher o pattern é o proximo passo. O próximo passo não é inventar um codigo ad hoc que resolve. Por definição o pattern é melhor solução que algo inventado na hora.

Soluções ad doc são caras porque caem rápidamente na gamb e podem impedir o refactoring posterior.

O “simple” de KISS não significa desleixado, significa “não inventa”. Ao usar padrões vc não estará inventando nada e portanto está mantendo a coisa simples. Especialmente é simples do ponto de vista dos outros programadores que têm que ler e alterar seu codigo anos depois que vc o criou.