Um pouco de metaprogramação

Quem assina a lista django-brasil recebeu essa mensagem do Luciano Ramalho sobre metaprogramação. Achei muito interressante e demonstra perfeitamente o quão poderosa é a linguagem Python.

Estou reproduzindo o texto sem alterações:

Em geral não é tedioso programar com o Django, mas às vezes é, veja só quanta repetição:

# http://pastebin.com/f2fc7b238

class DescriptorInline(admin.TabularInline):
   model = Descriptor

class RecruitmentCountryInline(admin.TabularInline):
   model = RecruitmentCountry

class OutcomeInline(admin.StackedInline):

   model = Outcome

class TrialInterventionCodeInline(admin.TabularInline):

   model = TrialInterventionCode

class SecondaryNumberInline(admin.TabularInline):

   model = TrialNumber

class TrialContactInline(admin.TabularInline):

   model = TrialContact

class TrialInstitutionInline(admin.TabularInline):

   model = TrialInstitution

class ClinicalTrialAdmin(admin.ModelAdmin):

   inlines = [SecondaryNumberInline, RecruitmentCountryInline,

              OutcomeInline, TrialContactInline, TrialInstitutionInline,

              DescriptorInline, TrialInterventionCodeInline]

No código acima, cada nome de modelo aparece três vezes… (uma vez ao
declarar a classe XXXInline, no atributo model do inline, e mais uma
vez no atributo inlines).

Além disso, quase todas as declarações de inlines são idênticas… E o
princípio DRY, como fica?

Felizmente Django é Python. Então aquilo pode ser reescrito de uma
maneira mais legal assim:

# http://pastebin.com/f5af2bd28

tabular_inline_models = [Descriptor, RecruitmentCountry, TrialInterventionCode,

                        TrialNumber, TrialContact, TrialInstitution]

tabular_inlines = []

for model in tabular_inline_models:

   cls_name = model.__name__+'Inline'

   cls = type(cls_name, (admin.TabularInline,), {'model':model})

   tabular_inlines.append(cls)

class OutcomeInline(admin.StackedInline):

   model = Outcome

class ClinicalTrialAdmin(admin.ModelAdmin):

   inlines = tabular_inlines + [OutcomeInline]

O truque aqui foi usar a função type(), que pode ser usada para criar
classes dinamicamente. Para isso a gente passa três argumentos para a
função type():

- uma string que será o __name__ da classe
- uma tupla de super-classes (importante: a vírgula dentro do
parêntesis indica que é uma tupla de um elemento)
- um dicionário com os atributos da classe (métodos e variáveis)

Não tente fazer isso em Java ;-) .

[ ]s
Luciano

Templates em PHP, só se for com PHPTAL

Para os desenvolvedores PHP segue uma dica de uma ferramenta de templates muito legal!

O PHPTAL é um motor de geração de templates para PHP5 que implementa a sintaxe ZPT (Zope Page Templates) ex.:

<div class="item" tal:repeat="item itemsArray">
    <span tal:condition="item/hasDate" tal:replace="item/getDate"/>
    <a href="${item/getUrl}" tal:content="item/getTitle"/>
  <p tal:content="value/getContent"/>
</div>

Enquanto a maioria dos desenvolvedores continua a usar tags ASP/JSP/PHP como principal linguagem para seus templates, a comunidade Zope teve a ótima idéia chamada TAL. A idéia era mover a ações para dentro de atributos XHML ao invés de usar outras tags e elementos.

Essa é grande vantagem da sintaxe do ZPT, sua simplicidade, não existem novas tags para aprender, e sim novos atributos que podem ser adicionados a qualquer tag XHTML e que atribuem comportamentos específicos. Esses novos atributos possibilitam ações como: condição, definição, repetição, inclusão de attributos, substituição de conteúdo, entre outros.

No exemplo disponível no site do projeto podemos ver o equivalente ao código acima:

<?php foreach ($values as $value): ?>
<div class="item">
  <div class="title">
    <?php if ($value->hasDate()): ?><?=$value->getDate()?><?php endif; ?>
    <a href="<?= $value->getUrl() ?>"><?=
		htmlentities($value->getTitle())
	?></a>
  </div>
  <div class="content">
    <?= htmlentities($value->getContent()) ?>
  </div>
</div>
<?php endforeach; ?>

Nota-se a economia de código fonte que o PHPTAL oferece.

Outra grande vantagem so PHPTAL é que, o tamplates são compilados para código fonte PHP5. Funcionando semelhante a idéia de bytecode em python, onde o código fonte em PHPTAL é compilado para PHP na primeira vez em que for executado, sendo o mesmo somente gerado novamente se o código fonte for alterado.

Abaixo a lista funcionalidades do PHPTAL

  • separação da lógica e apresentação,
  • avisa se você esquecer de fechar uma tag ou se tem erros no template
  • templates limpos e legíveis,
  • fácil integração com editores HTML WYSIWYG,
  • abstração de dados usando um sistema similar a XPath,
  • interessante sistema de macros HTML,
  • sistema de internacionalização integrado (usando gettext),
  • habilidade de substituir expressões XPath por expressões PHP,
  • quase nenhuma perda de velocidade (templates são compilados, grandes expressões podem ser substituídas por código PHP,
  • compatível com aceleradores PHP,
  • mais de quatro anos de suporte da comunidade ZPT,
  • código extensível.

Bom, segue ai a dica para quem quiser um motor de templates interessante e fácil de aprender.
Mais detalhes no site do projeto: http://phptal.org

Até a próxima.