Algum humor e C++ Design Patterns (parte 2)

Continuamos a discussão a respeito de Singletons, iniciada na primeira parte desse artigo até chegarmos à Injeção de Dependência. As coisas agora se tornam profundamente C++. Transformamos os Singletons em contêineres, para torná-los efetivamente reutilizáveis e discutimos a teoria que existe por trás dos Templates do C++ e de como a metaprogramação é feita nessa linguagem.

[ Hits: 29.920 ]

Por: Paulo Silva Filho em 25/10/2010 | Blog: http://psfdeveloper.blogspot.com


De Typleton para Templeton



O primeiro assunto de que precisamos nos lembrar é que nossa implementação de Singleton, chamada Typleton, não é um Singleton de verdade. Isso acontece porque Typleton é uma classe template e, como todo Template do C++, cada instância sua, para cada tipo usado como parâmetro, é uma nova classe para o compilador.

Então, Typleton é um Singleton para cada tipo que ele instancia. Podemos verificar todas essas coisas lendo o post anterior dessa série. Agora, precisamos resolver esse problema, transformando Typleton em um verdadeiro Singleton, fazendo-o, como Template, instanciável apenas uma única vez.

The solution for Typleton problem is simple, but surpreendently hard. We just must to know if the template class is already instatiated, unregarding its type parameter, and forbid a new instantiation. I've found a bold and neat solution for this problem. And the next section of this post will show it.

A solução para o problema de Typleton é simples, mas surpreendentemente difícil. Nós apenas precisamos saber se a classe template foi instanciada, independentemente do tipo que foi usado como seu parâmetro, e proibir uma nova instanciação. Eu encontrei uma solução inteligente e sucinta para esse problema.

Antes de explicar a solução para o problema de Typleton, precisamos fazer uma racionalização. C++ é uma linguagem na qual a maioria das decisões de design dos programas é feita utilizando-se construções aplicadas em tempo de compilação. Isso está em absurdo contraste com linguagens mais dinâmicas como Java, Python ou Lisp. Templates do C++ são inteligência executada em tempo de compilação, inseridas dentro de um programa feito em C++. Então, para manter consistência de design, todas as soluções para problemas com templates devem ser feitas usando construções e códigos executados em tempo de compilação?

A resposta para a questão acima é imediata: Não. Ponto. Templates C++ são ferramentas muito complexas dessa linguagem e, apesar de serem Turing Completas, a linguagem dos Templates C++ é uma linguagem funcional. Ela não possui variáveis globais, nem estado, nem atribuições. É completamente impossível definir algum comportamento em uma classe template que interfira no comportamento de outra classe template. Talvez alguma solução exótica em tempo de compilação exista para tal problema, mas ela seria complicada, estranha, esotérica e, muito provavelmente, muito difícil de entender e de ler o seu código.

Então eu procurei por uma solução de tempo de execução para o problema de Typleton. A solução de tempo de execução é colocar a função que verifica a instanciação do Singleton fora de qualquer template, então essa função não seria de nenhuma forma instanciável. Então eu enclausurei essa função dentro de uma classe, cujo conteúdo só pode ser lido pelas suas classes filhas, para evitar o uso de funções globais quando elas não são necessárias. Finalmente, eu criei uma nova classe chamada Templeton, exibindo o mesmo comportamento de Typleton, mas cujas instâncias são verificadas pela função fornecida pela sua classe parental.

Complexo? De forma alguma. Difícil de entender? Talvez. Então precisamos ver o código, na próxima página.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Qual é essa dos Templates, no final das contas?
   3. Uma reimplementação muito mais sofisticada do Singleton
   4. Erros na Implementação de Typleton?
   5. De Typleton para Templeton
   6. A implementação de Templeton
   7. Injeções de Dependência em Singletons
Outros artigos deste autor

Algum humor e C++ Design Patterns (parte 1)

Leitura recomendada

A duplicação do buffer de saída na chamada de sistema fork() do Linux

Estudando recursividade direta e indireta

Dynamic libraries com libtool

Compilando o Mono 2.2 no Ubuntu 8.10

Tutorial SFML

  
Comentários
[1] Comentário enviado por julio_hoffimann em 25/10/2010 - 23:36h

Oi Paulo,

Estou impressionado com a sua destreza no assunto! Há tempos que não aprendia coisas tão interessantes assim em POO. O artigo está incrível, conceitos de alto nível explicados de uma forma simples, sem deixar de ser filosófica.

O Templeton foi algo esplendoroso, quase cai da cadeira quando você o manifestou. Com esta série, começo a ver que metaprogramação vale muito a pena e que apesar de ser um investimento árduo, não hesitarei em aprendê-la.

Obrigado por compartilhar tanto conhecimento, desejo sucesso e boa sorte com a Featherns.

Abraço!

P.S.: Quando li no agregador de feeds: Design Patterns (parte 2), parei tudo que estava fazendo para prestigiar o artigo. :-)

[2] Comentário enviado por psfdeveloper em 26/10/2010 - 01:56h

Caro Julio,

eu fico muito feliz com tal manifestação de apreço... Eu vi que eu esqueci algumas partes do texto em inglês, mas o pessoal do Viva o Linux não tirou. Não sei se foi intencionalmente, mas não vou reclamar.

Metaprogramação é um dos tópicos mais importantes e interessantes da programação como um todo. Quase todas as linguagens possuem capacidades de metaprogramação. Algumas surpreendentemente poderosas, ao ponto de você poder quase que alterar a linguagem inteira (como o Lisp, com suas "macros" - vale a pena dar uma olhada, mesmo que seja como uma referência teórica - recomendo o Racket - http://racket-lang.org/ - que no Debian/Ubuntu pode ser obtido através do pacote plt-scheme), alterar comportamento de objetos e de seus derivados em tempo real (como em Javascript - na verdade uma capacidade de Javascript que só vi em Javascript - talvez na sua linguagem mãe, o Self), ou outras fortemente flexíveis por serem totalmente em tempo de execução - como o Python ou o Perl, em maior grau. O Java possui uma abordagem mista para a metaprogramação (com os Generics), que envolve a necessidade de Reflexion, com aspectos estáticos e dinâmicos.

Mas a linguagem que colocou a Metaprogramação na ordem do dia realmente foi C++, que foi duramente criticada por anos a fio justamente por causa do excesso de poder dado a essa capacidade, pelos templates e em momento de compilação. Quando ficou claro o poder da Metaprogramação por templates, diversas linguagens começaram a copiá-la.

Metaprogramação é um assunto árduo, cuja teoria é mais difícil que a codificação em si, mas dou toda força. Vai fundo.

E muitíssimo obrigado por prestigiar meu trabalho. Não tenho o que dizer.

Abraços.

[3] Comentário enviado por edgardiniz em 27/10/2010 - 18:36h

Ainda não li essa segunda parte, apressei o comentário para não esquecer mais tarde.

Com relação aos códigos, você pode utilizar algo como o pastebin.com, que permite fazer o embed dos códigos, e conta com tudo o que você precisa, sem a necessidade de usar imagens com o código e fornece-lo no final.

A não ser que o VOL não permita embedding nos artigos, não sei...

Mas cara, você está de parabéns, estou aprendendo muito com seus artigos.

Continue com o trabalho excelente.

[4] Comentário enviado por psfdeveloper em 27/10/2010 - 20:08h

Caro edgar,

o VOL não permite embedding de tags html no código, só com muitas restrições. E todo código fonte é posto disponível para download na última página do artigo.

Abraços.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts