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.921 ]

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


Qual é essa dos Templates, no final das contas?



Na minha opinião, templates são um dos mais importantes, superestimados, subvalorizados e depreciados aspectos da linguagem de programação C++. A Comunidade Java parece odiar os Templates do C++, como pode ser visto na documentação a respeito de Generics do Java. No link apresentado em [1], o autor chama Templates C++ de "um Extravagante Processador de Macros". A prestigiosa revista Dr.Dobbs [2] possui uma opinião diferente.

Precisamos entender que os engenheiros e o quadro de funcionários da Sun (e, agora, da Oracle), no geral, tentam vender Java como uma panacéia; então eles precisam inflar as ferramentas do Java e depreciar qualquer tipo de concorrência. A opinião deles é muito enviesada, mas, para mim, é inaceitável dizer que uma das melhores e mais bem engenheiradas ferramentas de Metaprogramação (os Templates de C++) são apenas um "Processador de Macros Extravagante".

Eu concordo com a opinião de que os Templates de C++ são exatamente como um processador de macros que, sendo um Processador de Macros, é daqueles muitíssimo poderosos. Qualquer pessoa que sabe programar com a linguagem M4 entende do que estou falando. Por outro lado, podemos dizer que Generics do Java são uma ferramenta de metaprogramação que utiliza uma "Extravagante Forma de Remoção da Tipos" para garantir genericidade e capacidade de conteinerização ao Java, dependendo fortemente de reflexão para alcançar padrões complexos. E eu odeio reflexão em linguagens de programação. Mesmo quando elas são completamente disponíveis (como em JavaScript, Python ou Perl), eu raramente uso, e quando uso, o faço com muito cuidado, uma vez que acho que o uso de reflexão pode tornar um programa tão badernado quando o uso de variáveis globais.

Como o Java é uma linguagem com capacidades dinâmicas muito maiores do que C++, Generics podem ser eficientes porque a linguagem pode contar com ferramentas de tempo de execução para garantir o rigor de uso dos tipos - o que é quase impossível com C++, por conta de sua anêmica RTTI (Run-Time Type Information, algo como "informação de tipagem em tempo de execução"). Mas eu sou um programador Java também, e não quero participar da rivalidade que existe entre essas linguagens. Não vou compará-las, mais, mas você precisa entender que alguns dos padrões descritos aqui são praticamente impossíveis de serem reproduzidos usando Generics do Java.

Voltando ao C++, Templates são uma forma de programação que roda em tempo de compilação. Eles são, apenas, uma pequena linguagem de programação inclusas dentro do C++, feita para trabalhar com o código C++ como seus dados. Essa linguagem permite a criação de pequenos subprocedimentos (as próprias classes ou funções "templatezadas") cuja implementação é o seu próprio texto "templatezado" e seus parâmetros de entrada são constantes de tipos inteiros, Classes, Estruturas ou qualquer outra definição de tipo. Templates C++ são completamente conscientes do Sistema de Tipagem de C++, o que é uma capacidade muito grande e crítica.

Templates suportam recursividade, sendo possível programar loops com eles. Outro aspecto presente nos templates é a existência de Guards (guardiães). Um guard apenas é um conjunto de definições de uma mesma expressão (no nosso caso, um Template), com diferentes constantes como valores de entrada, promovendo, para cada valor de entrada específico, um comportamento diferente; ou seja, um guard é um condicional. Com essas características, os Templates C++ se tornam Turing Completos. Veja as referências presentes no Artigo da Wikipédia presente em [4] e vocês vão verificar o que eu estou falando.

Depois dessa explicação a respeito de o que é um Template C++, precisamos entender como eles trabalham, quando compilamos um programa.

Quando definimos um Template, eles são como uma definição de classe: estáticos e inativos. Mas, cada vez que chamamos um template com um dado parâmetro (os valores que ficam circundados por <..>), que pode ser uma constante ou um tipo, nós instanciamos o template. Antes de chamarmos o compilador propriamente dito, o compilador de templates do C++ irá criar uma cópia do código do template, substituindo os parâmetros pelos valores dados àquela instância em particular. Para cada instanciação, uma nova cópia do código será gerada pelo compilador. Então o código seguirá para o compilador C++ propriamente dito e gerará o objeto binário, com diferentes identificadores e símbolos para cada instância do template. Quando revisitarmos o padrão Singleton, isso ficará mais claro.

Os Templates C++ são tão poderosos, que a mais influente e abrangente Biblioteca de C++ (na minha opinião), o Boost [3], depende fortemente do uso de Templates, e mesmo pesquisa de ponta em metaprogramação é feita usando essa biblioteca. Para todo programador C++, o Boost é conhecimento obrigatório.

Depois desse conteúdo profundamente teórico, vamos para os padrões de design. Vamos revisitar o Singleton.

Créditos:

[1] Artigo Oficial de Java Generics da Sun (agora Oracle): http://www.oracle.com/technetwork/articles/javase/generics-136597.html
[2] Revista Dr.Dobbs: http://www.drdobbs.com/184401818
[3] O Boost pode ser encontrado em: http://www.boost.org
[4] A wikipédia possui um arquivo poderoso a respeito de metaprogramação com Templates, que pode ser visto em: http://en.wikipedia.org/wiki/Template_metaprogramming

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

Instalando Facebook Folly através do Conan

Cuidado com números em Ponto Flutuante

Criando aplicativos para o iPhone no Linux (sem Xcode e MacOS X)

Alocação dinâmica de memória em C

GNA: um Coprocessador para Aceleração Neural

  
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