<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Log4Dev &#187; Design</title>
	<atom:link href="http://log4dev.com/category/design/feed/" rel="self" type="application/rss+xml" />
	<link>http://log4dev.com</link>
	<description></description>
	<lastBuildDate>Mon, 03 Oct 2011 22:20:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
	<div id='fb-root'></div>
					<script type='text/javascript'>
						window.fbAsyncInit = function()
						{
							FB.init({appId: null, status: true, cookie: true, xfbml: true});
						};
						(function()
						{
							var e = document.createElement('script'); e.async = true;
							e.src = document.location.protocol + '//connect.facebook.net/pt_BR/all.js';
							document.getElementById('fb-root').appendChild(e);
						}());
					</script>	
						<item>
		<title>Curso de HTML5 em São Paulo</title>
		<link>http://log4dev.com/2010/08/31/curso-de-html5-em-sao-paulo/</link>
		<comments>http://log4dev.com/2010/08/31/curso-de-html5-em-sao-paulo/#comments</comments>
		<pubDate>Tue, 31 Aug 2010 12:57:02 +0000</pubDate>
		<dc:creator>Miguel Galves</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Formação]]></category>
		<category><![CDATA[Notícias]]></category>

		<guid isPermaLink="false">http://log4dev.com/?p=823</guid>
		<description><![CDATA[A W3C Brasil irá oferecer um curso de HTML 5 em São Paulo, entre os dias 21 e 23 de setembro. Segundo um email que eu recebi ontem, O programa do curso abrange as principais novidades da versão 5 da linguagem HTML até o momento e priorizará a apresentação dos novos elementos com o debate [...]]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2010/08/31/curso-de-html5-em-sao-paulo/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div>A <a href="http://www.w3c.br/">W3C Brasil</a> irá oferecer um curso de <strong>HTML 5</strong> em São Paulo, entre os dias 21 e 23 de setembro.</p>

<p><a href="http://www.w3c.br/cursos/html5/"><img class="aligncenter" title="Curso de HTML 5" src="http://www.w3c.br/cursos/html5/images/nome-evento.gif" alt="" width="486" height="185" /></a></p>

<p>Segundo um email que eu recebi ontem,
<blockquote>O programa do curso abrange as principais novidades da versão 5 da linguagem HTML até o momento e priorizará a apresentação dos novos elementos com o debate em classe da nova semântica. Alguns exercícios serão aplicados com o intuito de demonstrar as novas implementações. Nossa estrutura infelizmente não comporta a formação de diversas turmas do curso de HTML5 que nos permita atender o grande número de solicitações de interessados, inclusive para outras cidades. Por isso faremos uma seleção dos participantes segundo os critérios de compromissos:</p>

<ul>
<li>com a replicação do conteúdo do curso;</li>
<li>com a publicação livre das aplicações geradas;</li>
<li>com um projeto real de uso do HTML5;</li>
<li>e com a participação efetiva em uma comunidade dedicada à melhoria da linguagem.</li>
</ul>

<p>O propósito do W3C Brasil, mais do que treinar no uso da nova versão, é o de organizar uma rede de interlocutores, formadores e multiplicadores preparados para os debates em torno dos padrões web, gerando massa crítica na formulação das novas recomendações.</blockquote>
Para saber mais sobre o curso, acesse <a href="http://www.w3c.br/cursos/html5/">http://www.w3c.br/cursos/html5/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2010/08/31/curso-de-html5-em-sao-paulo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OAuth</title>
		<link>http://log4dev.com/2010/06/23/oauth/</link>
		<comments>http://log4dev.com/2010/06/23/oauth/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 11:59:03 +0000</pubDate>
		<dc:creator>Miguel Galves</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[OAuth]]></category>
		<category><![CDATA[Segurança]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://log4dev.com/?p=756</guid>
		<description><![CDATA[No dia 31 de Maio do ano do Senhor de 2010, por volta das 15h, o meu caro amigo Lullis me mandou uma singela mensagem no GTalk dizendo algo como &#8220;Você viu que o sistema de Basic Auth do Twitter para de funcionar hoje né? E que daqui pra frente só com OAuth né?&#8221;. A [...]]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2010/06/23/oauth/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div>No dia 31 de Maio do ano do Senhor de 2010, por volta das 15h, o meu caro amigo Lullis me mandou uma singela mensagem no GTalk dizendo algo como &#8220;Você viu que o sistema de Basic Auth do <a href="http://twitter.com">Twitter</a> para de funcionar hoje né? E que daqui pra frente só com OAuth né?&#8221;. A frase, descontextualizada, pode parecer apenas mais uma curiosidade geek. O Twitter já vinha anunciando esta migração de modelo de autenticação há um certo tempo.</p>

<p>Mas no mundo de Miguel, isso caiu como uma bomba atômica.</p>

<p><a href="http://delamagente.files.wordpress.com/2009/08/network_security.jpg"><img class="aligncenter" src="http://delamagente.files.wordpress.com/2009/08/network_security.jpg" alt="" width="306" height="228" /></a></p>

<p>Resumindo: o mecanismo de autenticação usado pelo <a href="http://job4dev.com">Job4Dev</a> e pelo <a href="http://www.sigaseutime.com.br">SigaSeuTime</a> simplesmente deixaria de funcionar em algumas horas. No caso do SigaSeuTime, isto era uma catástrofe de proporções enormes, já que boa parte do nosso público vem do Twtter. Uma longa noite me aguardava&#8230;até que percebemos que Lullis havia falado besteira, e que na verdade o prazo máximo era 31 de junho. Ufa.</p>

<p>Tive então tempo de estudar um pouco o protocolo, e fazer uma implementação usando algumas libs. Por sorte a documentação do próprio <a href="http://apiwiki.twitter.com/">Wiki do Twitter</a> é bem interessante. Gostaria de compartilhar alguns pontos aqui.
<h2>Basic Auth</h2>
É o maior lixo já inventado para autenticação. Basicamente, você adiciona no header da sua requisição um campo cujo valor é o seu username e a sua senha simplesmente codificados em <a href="http://en.wikipedia.org/wiki/Base64">Base 64</a>. Resumindo, senha em claro. Mais básico e inseguro que isso, impossível.
<h2>OAuth &#8211; Idéia básica</h2>
A idéia do <a href="http://oauth.net/">OAuth</a> é permitir que o provedor de um serviço permita o acesso a certos recursos a usuários sem precisar dar a senha principal. No caso do Twitter, isto é bem útil, já que a grande maioria dos usuários interagem com o sistema usando aplicativos externos.</p>

<p>Com este protocolo, seria possível permitir que por exemplo o Job4Dev atualizasse a sua timeline, de forma segura e autenticada, sem que eu precisasse guardar a sua senha na minha base de dados. Conveniente!
<h2>OAuth &#8211; O protocolo</h2>
<a href="http://oauth.net"><img class="alignnone" src="http://oauth.net/images/oauth-logo.png" alt="Logo OAuth" width="200" height="60" /></a></p>

<p>Vou tentar tornar esta descrição a mais simples possível.</p>

<p>OAuth usa um mecanismo de pares de chaves públicas e privadas para gerar assinaturas, permitindo uma identificação inequivoca da origem de cada requisição. Simples demais?</p>

<p>Ok</p>

<p>Vamos supor que o usuário @mgalves queria que o Job4Dev publique vagas na sua timeline, usando um app que algum dia será criado. Este app possui duas chaves, geradas pelo @job4dev: um consumer key e um consumer secret (que como seu nome diz, deve ser guardada de forma secreta). O passo a passo seria mais ou menos o seguinte:
<ul>
    <li>O app gera uma requisição especial HTTP, usando as duas chaves citadas acima, para obter um token de request temporário.</li>
    <li>Com este token em mãos, o app gera uma requisição HTTP de autorização de acesso para o Twitter. Esta requisição passa como parâmetros o token, o consumer key e uma assinatura gerada a partir de um hash (SHA) de uma string composta pelo token, pelo consumer key e pelo consumer secret key. Portanto, é única, e apenas o app do Job4Dev é capaz de gerar (comprovando assim a procedência da chamada).</li>
    <li>O Twitter já sabe, a partir da assinatura, que quem está pedindo permissão de acesso é o Job4Dev. Falta saber qual usuário irá autorizar o acesso: para isso o site pede que eu, @mgalves, efetue o login e explicitamente autorize o acesso.</li>
    <li>Autorizado o acesso, o Twitter envia para o app um novo par de chaves que serão utilizados para assinar as demais requisições, e que mapeiam de forma única a permissão de acesso do app job4dev aos recursos da conta de @mgalves. Caso eu resolva REVOGAR o acesso, basta invalidar estas novas chaves.</li>
</ul>
Melhorou? Espero que sim.</p>

<p>Um ponto importante deve ser ressaltado quanto ao último passo. O retorno do novo par de chaves pode ser feito de duas formas: callback e PIN code. Callback é a forma padrão descrita no protocolo do OAuth, e simplemente consiste em definir um callback HTTP no app que está pedindo acesso, que será chamado pelo provedor (no caso o Twitter) ao final do processo passando as chaves por parâmero POST.</p>

<p>Mas isso apenas funciona se o app em questão for web, e puder responder a uma requisição HTTP. Caso isto não aconteça (como no Tweetdeck por exemplo), o Twitter exibe na tela um código numérico único chamado PIN CODE: o app deve receber este PIN code (copy &amp; paste) e gerar uma nova requisição passando o token, o pin code e a assinatura, cujo retorno é o par de chaves.
<h2>E o TweetDeck?</h2>
Depois de ter lido e entendido o tema, a seguinte dúvida me veio a cabeça: e o TweetDeck, como faz? E nenhum momento eu autorizei o acesso aos meus recursos, e ainda assim, as coisas funcionam. Será que no final de junho ele para de funcionar?</p>

<p>Fucei a documentação do Twitter e achei uma extensão ao protocolo chamada de XAuth, uma pequena variação que permite que as chaves de acesso sejam obtidas através de uma requisição especial contendo username e senha do usuário. Isso evita a necessidade do protocolo definido acima, e funciona bem em casos onde quem vai acessar os recursos é o dono da conta.</p>

<p>Mas segundo o Twitter, para que um app que queira usar este protocolo deve entrar em contato diretamente com eles, explicando a real necessidade.</p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2010/06/23/oauth/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Passagem de Parâmetros em Python</title>
		<link>http://log4dev.com/2009/05/26/passagem-de-parametros-em-python/</link>
		<comments>http://log4dev.com/2009/05/26/passagem-de-parametros-em-python/#comments</comments>
		<pubDate>Tue, 26 May 2009 11:00:54 +0000</pubDate>
		<dc:creator>Miguel Galves</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Linguagens de Programação]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://log4dev.com/?p=570</guid>
		<description><![CDATA[Dentre os temas que geram discussões intermináveis, apaixonadas, e na maioria das vezes, completamente inúteis, a questão de tipagem de dados em linguagens de programação ocupa um espaço não desprezível. Tipagem forte, tipagem fraca, tipagem estática, tipagem dinâmica. Existem prós e contras para cada lado, e os defensores de cada campo passam horas e horas [...]]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2009/05/26/passagem-de-parametros-em-python/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div>Dentre os temas que geram discussões intermináveis, apaixonadas, e na maioria das vezes, completamente inúteis, a questão de <strong>tipagem de dados em linguagens de programação</strong> ocupa um espaço não desprezível.</p>

<p>Tipagem forte, tipagem fraca, tipagem estática, tipagem dinâmica. Existem prós e contras para cada lado, e os defensores de cada campo passam horas e horas tentando provar que o esquema alheio é péssimo. Tendo trabalhado com todos, programando em Java, Python, Javascript e C, chego à conclusão de que é possível ser feliz e produtivo com qualquer uma delas.</p>

<p>Mas nem tudo é perfeito, e em algumas situações, o jardim do vizinho é mais verde&#8230;</p>

<p>Sinto falta em alguns momentos de poder tipificar parâmetros de funções em <strong>Python</strong>, por dois motivos. O primeiro é para evitar que parâmetros de tipos errados sejam passados inadvertidamente: fazer verificação de tipo no início de um método ou função é simples, mas as vezes consome tempo de programação inútil.</p>

<p>O outro que mais me incomoda é que a falta desta tipagem impede que se utilize um recurso muito útil e elegante que é a <strong>sobrecarga de método</strong>. Basicamente, em Python não é possível criar vários métodos com o mesmo nome e com assinaturas diferentes. O jeito Python de resolver isso é verificando o tipo dentro do método, ou então criando um mecanismo de dispatch, usando os famosos dicionários (que são extremamente eficientes. Ousam dizer por aí que é a implementação mais eficiente que existe&#8230;.).</p>

<p>Ambas funcionam, mas não são tão elegantes como a solução oferecida pela sobrecarga. Aproveito, pergunto: existe alguma forma mais elegante de se fazer isso em Python?</p>

<p>Fica aqui a minha sugestão. HEY, GUIDO, TIPIFICA OPCIONALMENTE PARÂMETRO DE MÉTODO AÍ!</p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2009/05/26/passagem-de-parametros-em-python/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Identificação de charsets</title>
		<link>http://log4dev.com/2009/05/18/identificacao-de-charsets/</link>
		<comments>http://log4dev.com/2009/05/18/identificacao-de-charsets/#comments</comments>
		<pubDate>Mon, 18 May 2009 21:39:57 +0000</pubDate>
		<dc:creator>Leonardo Garcia</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Ferramentas]]></category>
		<category><![CDATA[Teoria]]></category>
		<category><![CDATA[charset]]></category>

		<guid isPermaLink="false">http://log4dev.com/?p=561</guid>
		<description><![CDATA[Hoje, para variar, vou falar sobre outra coisa que me incomoda. Aliás, que me incomodava. Sempre fiquei muito intrigado com um fato que recorrentemente eu presenciava: precisava ler um arquivo de &#8220;texto puro&#8221; mas, quando abria o arquivo, lá estavam vários caracteres esquisitos ou pontos de interrogação ou qualquer coisa que não deveria estar lá. [...]]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2009/05/18/identificacao-de-charsets/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div>Hoje, para variar, vou falar sobre outra coisa que me incomoda. Aliás, que me incomodava.</p>

<p>Sempre fiquei muito intrigado com um fato que recorrentemente eu presenciava: precisava ler um arquivo de &#8220;texto puro&#8221; mas, quando abria o arquivo, lá estavam vários caracteres esquisitos ou pontos de interrogação ou qualquer coisa que não deveria estar lá. Ou seja, o programa que eu estava usando não conseguia reconhecer adequadamente o <em>charset</em> do arquivo e, quando tentava mostrar os caracteres usando o <em>charset</em> padrão do programa, um punhado de coisa ficava zuada.</p>

<p>Ficava sempre pensando que alguma coisa idiota devia estar acontecendo, afinal de contas, como um programa não conseguia reconhecer um <em>charset</em>? Tantos anos de evolução na computação e uma coisa simples como esta ainda não funcionava direito? Tentava de várias formas bolar uma solução para isso mas, qualquer coisa que eu pensava, não era uma solução que eu achasse viável. Afinal, a maneira mais fácil de identificar um <em>charset</em> seria colocar uma espécia de meta-dado no arquivo, como é (deveria ser) feito com páginas web (mas nem sempre funciona também por falhas nos programas!). E aí o arquivo deixaria de ser um arquivo de &#8220;texto puro&#8221;.</p>

<p>Enfim, não tinha uma solução para este &#8220;problema&#8221; e, pelo jeito, via que ninguém mais tinha, afinal o problema continuava existindo. Mas ele continuava me incomodando de tempos em tempos.</p>

<p>Até que li <a href="http://www.joelonsoftware.com/articles/Unicode.html">este texto</a> do Joel. E aquietei meu espírito em relação a este problema. O texto inteiro é bom, especialmente a parte final <em>The Single Most Important Fact About Encodings</em>. E o que resume tudo é esta frase: <em>There Ain&#8217;t No Such Thing As Plain Text</em>. Ou, numa tradução livre: &#8220;Não existe algo como texto puro&#8221;.</p>

<p>Ou seja, tudo aquilo que é mostrado pelo programa que abre arquivos de &#8220;texto puro&#8221; é simplesmente uma abstração. Esqueça os caracteres. Eles são apenas interpretação dos dados reais binários. Qualquer representação dada a eles é apenas resultado de algum processamento por trás que tenta ou não identificar qual foi o <em>charset</em> usado para criar o arquivo.</p>

<p>Por mais óbvio que isso seja e por mais que eu soubesse disso, é engraçado como eu não ligava este simples fato à minha inquietudade em relação ao processamento de arquivos textos pelos programas.</p>

<p>Feito isso, com a ajuda do Joel, problema resolvido!</p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2009/05/18/identificacao-de-charsets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Design OO, Design E-R, e o tal do ORM.</title>
		<link>http://log4dev.com/2009/04/06/design-oo-design-e-r-e-o-tal-do-orm/</link>
		<comments>http://log4dev.com/2009/04/06/design-oo-design-e-r-e-o-tal-do-orm/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 18:01:29 +0000</pubDate>
		<dc:creator>Raphael Lullis</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Teoria]]></category>
		<category><![CDATA[Análise OO]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[ER]]></category>
		<category><![CDATA[ORM]]></category>

		<guid isPermaLink="false">http://log4dev.com/?p=514</guid>
		<description><![CDATA[Vira e mexe aparece algum problema que pode ser um exercício interessante, um Kata para programador que eu gostaria de colocar aqui para ser analisado, discutido e implementado pelo pessoal que visita o blog. Além disso, tem algum tempo também que eu quero escrever sobre os conflitos entre o design Orientado a Objeto e o [...]]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2009/04/06/design-oo-design-e-r-e-o-tal-do-orm/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div>Vira e mexe aparece algum problema que pode ser um exercício interessante, um <a href="http://log4dev.com/2007/09/04/kata-para-programadores/">Kata para programador</a> que eu gostaria de colocar aqui para ser analisado, discutido e implementado pelo pessoal que visita o blog. Além disso, tem algum tempo também que eu quero escrever sobre os conflitos entre o design Orientado a Objeto e o desenvolvimento de aplicações usando banco de dados relacionais, e sobre como as ferramentas que fazem ORM tentam, mas não conseguem resolver esse conflito de uma forma definitiva.</p>

<p>Como não estou com tempo para fazer tudo isso, vou fazer um mix e ver o que acontece. Resumidamente, vou explicar um pequeno problema que eu tenho envolvendo a implementação de um sistema usando o ORM do Django, e gostaria de saber se alguém vê uma solução correta e elegante. </p>

<p>Usando exemplos reais: estou trabalhando em um projeto que visa analisar registros médicos eletrônicos e identificar se certos casos registrados devem ser notificados ao <abbr="Center for Disease Control">CDC</abbr>. Mais especificamente, o que eu quero é analisar o registro de vacinas que a pessoa recebeu e verificar se houve alguma reação adversa. Uma reação adversa pode ser identificada por algo comum como febre, ou algo mais complexo como uma hemorragia ou por um exame de laboratório mostrando uma variação em valores de seus componentes (Hemoglobina, Creatina, Sódio, Potássio, etc). </p>

<p>&#8220;Falando&#8221; OO, o que eu tenho é a classe AdverseEvent, da qual derivam FeverEvent, DiagnosticsEvent e LabResultEvent. Na hora de construir os relatórios, é necessário obter a lista dos eventos e obter também os atributos específicos de cada subclasse. Até aí OO funciona. E antes que the-one-who-can&#8217;t-be-named grite &#8220;Design Patterns&#8221;, eu vou falar que estamos lidando com a implementação de uma Factory: dada uma lista de chaves que identifique uma lista de AdverseEvents, a Factory instancia o objeto adequado a partir da id fornecida.</p>

<p>O &#8220;problema&#8221;: esses objetos ficam em um banco de dados, e como mapear isso para um banco de dados relacional e fazer uma factory que construa o objeto adequado com uma única consulta?</p>

<p>Vamos ao código. A primeira solução seria uma implementação que tenta ser puramente OO. O código abaixo é parte de um típico módulo de definição dos seus modelos quando usando Django.</p>

<p>&nbsp;</p>

<pre><code>class AdverseEventManager(models.Manager):

    def by_id(self, key):
        for klass in [FeverEvent, DiagnosticsEvent, LabResultEvent]
            try:
                obj = klass.objects.get(id=key)
                return obj
            except: pass
        return None

class AdverseEvent(models.Model):
    # Managers
    objects = models.ModelManager()
    manager = AdverseEventManager()

    # Atributos que realmente são de interesse e vão para o BD.
    patient = models.ForeignKey(Demog)
    immunization = models.ForeignKey(Immunization)
    matching_rule_explain = models.CharField(max_length=200)
    category = models.CharField(max_length=20, choices=ADVERSE_EVENT_CATEGORIES)
    created_on = models.DateTimeField(auto_now_add=True)
    last_updated = models.DateTimeField(auto_now=True)



# Classes filhas. NO BD, são mapeadas para tabelas que contém os campos 
# específicos da classe, e referencia a tabela da classe-pai
class FeverEvent(AdverseEvent):
    temperature = models.FloatField('Temperature')
    encounter = models.ForeignKey(Enc)

class DiagnosticsEvent(AdverseEvent):
    encounter = models.ForeignKey(Enc)
    icd9 = models.ForeignKey(Icd9)


class LabResultEvent(AdverseEvent):
    lab_result = models.ForeignKey(Lx)
</code></pre>

<p><p>&nbsp;</p><p>&nbsp;</p></p>

<p>O Factory method é by_id. Para os que não conhecem Django, ModelManager.get() faz a consulta no banco de dados e retorna um único objeto da classe que o contém, ou a exceção DoesNotExist se não existir objetos com os parâmetros indicados. Como a chave pertence a classe-pai, podemos ter certeza que não há haverá objetos das classes filhos com o mesmo id. Isso permite que encontremos o objeto desejado. O problema com essa solução é que o número de consultas é proporcional ao número de sub-classes</p>

<p>O segundo esquema é &#8220;menos OO&#8221;. Para desespero de alguns puristas, nós podemos criar um dicionário no módulo que mapeia as sub classes possíveis e a factory faz sempre duas consultas para obter o objeto apropriado.
<p>&nbsp;</p></p>

<pre><code>ADVERSE_EVENT_CLASSES = {'fever':FeverEvent,
                         'diagnostics':DiagnosticsEvent,
                         'lab_result': LabResultEvent
                         }

class AdverseEventManager(models.Manager):  
    def by_id(self, key):
        try:
           ev = AdverseEvent.objects.get(id=key)
           return ADVERSE_EVENT_CLASSES[ev.event_type].objects.get(id=key)
        except:
            return None

class AdverseEvent(models.Model):
    # Managers
    objects = models.ModelManager()
    manager = AdverseEventManager()

    # Atributos que realmente são de interesse e vão para o BD.
    patient = models.ForeignKey(Demog)
    immunization = models.ForeignKey(Immunization)
    matching_rule_explain = models.CharField(max_length=200)
    category = models.CharField(max_length=20, choices=ADVERSE_EVENT_CATEGORIES)
    created_on = models.DateTimeField(auto_now_add=True)
    last_updated = models.DateTimeField(auto_now=True)

    # Adicionamos esse campo para identificar para saber qual é a subclasse 
    event_type = models.CharField(max_length=20, choices=tuple(ADVERSE_EVENT_CLASSES.items()))
</code></pre>

<p><p>&nbsp;</p><p>&nbsp;</p></p>

<p>Enfim, só estou expondo as duas soluções que eu conheço para lidar com algo trivial. Se alguém tiver alguma idéia diferente, por favor deixe registrado nos comentários.</p>

<p>Com relação a crítica ao ORM: parte da minha bronca são essas incongruências que existem, o ORM não conseguindo fazer uma boa ponte entre o modelo OO e o modelo E-R. É por detalhes assim que estamos começando a ver uma série de projetos de banco de dados não-relacionais, do qual espero falar mais adiante.</p>

<p>Outra coisa interessante: se você perceber, um banco de dados XML não teria esse problema, entretanto parece que ninguém nunca pensou em implementar o <a href="http://www.oracle.com/database/berkeley-db/xml/index.html">BDB-XML</a> como backend para uma datastore.</p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2009/04/06/design-oo-design-e-r-e-o-tal-do-orm/feed/</wfw:commentRss>
		<slash:comments>48</slash:comments>
		</item>
		<item>
		<title>Doc. Job4Dev: Integração com Twitter</title>
		<link>http://log4dev.com/2009/04/02/doc-job4dev-integracao-com-twitter/</link>
		<comments>http://log4dev.com/2009/04/02/doc-job4dev-integracao-com-twitter/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 01:29:02 +0000</pubDate>
		<dc:creator>Miguel Galves</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Engenharia de Software]]></category>
		<category><![CDATA[Ferramentas]]></category>
		<category><![CDATA[job4dev]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://log4dev.com/?p=507</guid>
		<description><![CDATA[Job4Dev deu nascimento ao projeto Open Source Jobboard, hospedado no GitHub e que está sendo levado adiante pelo Raphael. É um ótimo momento portanto para destrinchar e documentar alguns aspectos da arquitetura do sistema. Vou começar pela integração com o Twitter. Por que integrar com o Twitter? Sendo rápido e objetivo, decidi usar o Twitter [...]]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2009/04/02/doc-job4dev-integracao-com-twitter/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div><a title="Job4Dev" href="http://job4dev.com.br" target="_blank">Job4Dev</a> deu nascimento ao projeto <a href="https://github.com/lullis/jobboard">Open Source Jobboard</a>, hospedado no <a title="GitHub" href="http://www.github.com/">GitHub</a> e que está sendo levado adiante pelo Raphael. É um ótimo momento portanto para destrinchar e documentar alguns aspectos da arquitetura do sistema. Vou começar pela integração com o <a href="http://twitter.com/job4dev">Twitter</a>.</p>

<p><strong>Por que integrar com o Twitter?</strong></p>

<p>Sendo rápido e objetivo, decidi usar o Twitter por achar que seu design e seu modo de funcionamento se adequavam perfeitamente àquilo que eu estava buscando: a diversificação dos canais de divulgação das vagas. Esta integração foi possível graças ao fato do microblog oferecer uma API bastante bem feita e bem documentada. Junte a isso a minha vontade de brincar com a plataforma, e temos um cenário perfeito!</p>

<p><strong>E a API do Twitter, como funciona?</strong></p>

<p>Ela é baseada em REST, e permite fazer boa parte (se não tudo) do que um usuário humano poderia fazer. Eu explico sucintamente o seu funcionamento no artigo <a href="http://log4dev.com/2008/05/15/conversando-com-o-twitter/">Conversando com o Twitter</a>. A documentação da API pode ser encontrada em <a href="http://apiwiki.twitter.com/">http://apiwiki.twitter.com/</a>.</p>

<p><strong>Mas chega de papo, vamos ao design da coisa&#8230;</strong></p>

<p>A integração do Job4Dev com o Twitter começou com as seguintes premissas
<ul>
    <li>Baixo impacto sobre o tempo de resposta do site no momento do cadastro de uma nova vaga</li>
    <li>Garantia de que TODAS as vagas seriam publicadas no Twitter</li>
    <li>Simplicidade da arquitetura</li>
</ul>
Resumindo, e usando as palavras da moda, a nova funcionalidade deveria ser ROBUSTA, ESCALÁVEL e CONFIÁVEL.</p>

<p>A chave para se conseguir os dois primeiros ítens é o uso de um sistema assíncrono. Ou seja: a ação de gravação de uma nova vaga na base de dados deve notificar o sistema de que uma nova mensagem deve ser enviada ao Twitter, e o envio deve ser executado em background. Isso evita que problemas na rede ou no próprio microblog (bastante comuns na época do desenvolvimento da funcionalidade) afetem o tempo de resposta.</p>

<p>Para garantir que todas os anúncios fossem enviados, deveria existir um mecanismo que persistisse os tweets em caso de problemas de rede, permitindo envio posterior. Finalmente, para garantir a confiabilidade e a simplicidade, decidi usar o máximo de recursos do sistema operacional. Afinal o Linux para mim é o melhor servidor de aplicações que existe!</p>

<p><strong>E como tudo isso foi implementado?</strong></p>

<p>Eu cogitei gerar a mensagem diretamente a partir da base de dados, uma vez que as informações são gravadas em uma tabela. Mas para garantir que uma vaga fosse enviada apenas uma vez, e permitir que uma mensagem fosse reenviada em caso de problemas de comunição, o esquema das tabelas teria que ser modificado para guardar o estado de processamento do canal Twitter.</p>

<p>Para evitar esta modificação, ao meu ver intrusiva, e aplicando a fundo o <a href="http://en.wikipedia.org/wiki/KISS_principle">conceito K.I.S.S</a>, resolvi utilizar o sistema de arquivos: ao submeter uma vaga, o sistema gera um arquivo texto em um diretório específico, contendo a mensagem a ser enviada. Para garantir que não haja conflito, o nome do arquivo é a URL da vaga.</p>

<p>O envio das mensagens é efetuado por uma tarefa em Python lançada pelo <a href="http://en.wikipedia.org/wiki/Cron">CRON</a>, de 15 em 15 minutos. O algoritmo é simples: verifica no diretório apropriado se existem arquivos de mensagens. Caso existam, abre cada um, lê o conteúdo, formata uma mensagem e efetua a requisição de envio para o Twitter. Caso a mensagem seja enviada com sucesso, remove o arquivo. Caso contrário, registra o erro em um arquivo de log e deixa o arquivo no diretório para uma execução futura.</p>

<p>Os mais curiosos poderão ver o código do módulo Twitter <a href="http://github.com/lullis/jobboard/blob/master/jobs/twitter.py">aqui</a>. Este módulo pode ser livremente utilizado para implementação de uma funcionalidade semelhante. Basta passar por parâmetro o nome do diretório, o nome de usuário no microblog e a senha.</p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2009/04/02/doc-job4dev-integracao-com-twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A nova ortografia e o redesenho de software</title>
		<link>http://log4dev.com/2009/02/13/a-nova-ortografia-e-o-redesenho-de-software/</link>
		<comments>http://log4dev.com/2009/02/13/a-nova-ortografia-e-o-redesenho-de-software/#comments</comments>
		<pubDate>Sat, 14 Feb 2009 01:05:40 +0000</pubDate>
		<dc:creator>Leonardo Garcia</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Opinião]]></category>
		<category><![CDATA[Engenharia de Software]]></category>
		<category><![CDATA[web 2.0]]></category>

		<guid isPermaLink="false">http://log4dev.com/?p=422</guid>
		<description><![CDATA[Faz tempo que eu não escrevo por aqui&#8230; não é que minhas ideias andem sem acento. Ideias não faltam. Falta o algo extra que as coloca no papel. Ou, no caso, no blog. Para mim, uma das coisas que mais marcarm a virada do ano no Brasil foi a entrada em vigência da nova ortografia [...]]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2009/02/13/a-nova-ortografia-e-o-redesenho-de-software/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div>Faz tempo que eu não escrevo por aqui&#8230; não é que minhas ideias andem sem acento. Ideias não faltam. Falta o algo extra que as coloca no papel. Ou, no caso, no blog.</p>

<p>Para mim, uma das coisas que mais marcarm a virada do ano no Brasil foi a entrada em vigência da nova ortografia da língua portuguesa falada por aqui. Dizem que isso foi para unificar melhor a língua portuguesa falada em diversos países. Sinceramente, sempre tive dúvida em relação a argumentos como este. Sempre escutei na escola que a língua é um &#8220;ser&#8221; em constante mutação e evolução causada pelo seu uso pelo povo. Se isso é verdade, até quando a ortografia vai ser comum em todos os países de língua portuguesa? Até os políticos aprovarem outra lei para unificarem novamente as línguas que se mudaram com o tempo? Enfim&#8230; não sou especialista neste assunto e este não é um blog sobre línguas. Então vou deixar este assunto de lado um pouco.</p>

<p>Por outro lado, no final do ano, durante as minhas férias, quando em geral eu me afasto consideravelmente dos computadores, uma pessoa próxima e com mais que o dobro da minha idade veio até mim reclamar que o UOL tinha mudado a interface do seu webmail e agora ela estava perdida. A questão é que apesar da idade, esta pessoa que eu conheço é bem interessada em relação à tecnologia de uma forma geral e mexe no computador com certo traquejo. Aliás, a reclamação em relação ao webmail era justamente porque ela usa esta aplicação como ferramenta de trabalho diária. Como eu estava por perto acabei indo ajudá-la com as dúvidas em relação ao novo webmail do UOL. Como eu tenho conta no BOL (que usa o mesmo engine de webmail que o UOL) eu sabia como era a antiga ferramenta. Já era um bom começo, imaginei eu. Mas confesso que, após ver o novo webmail, fiquei frustrado. Eu ainda conseguia utilizá-lo, mas ele tinha ficado mais difícil. Isso tudo para que ele fosse, &#8220;finalmente&#8221;, Web 2.0! Grande coisa! Mas, vá lá&#8230; eu conseguia usá-lo. Mas a pessoa que estava ali do meu lado estava com sérias dificuldades. E com razão! Para se ter uma idéia a lista de contatos era mostrada por ordem alfabética de&#8230; e-mail. Ou seja, se eu tivesse cadastrado nos meus contatos alguém com nome Miguel mas que tivesse o e-mail frances@algumlugar.com o nome Miguel aparceria na letra F!!!</p>

<p>Depois de ver isso e outras coisas toscas (tudo em nome da famigerada Web 2.0!) fiquei  pensando na frustração da pessoa que veio me pedir ajuda. Fiquei tentando imaginar como era esta frustração porque, como eu disse, apesar de eu achar difícil, vá lá, eu ainda conseguia usar o webmail.</p>

<p>Depois de refletir durante um tempo eu acabei achando algo que, para mim, parecia ser equivalente àquela sensação de frustração: a tal mudança ortográfica do português.</p>

<p>Talvez o que realmente me incomode e fruste com esta nova ortografia seja a mudança em si. Eu fui alfabetizado e escrevo há mais de 10 anos segundo as normas da velha ortografia (que, diga-se de passagem, valerá até 2012; não misturá-las até lá é que vai ser difícil). Mudanças sempre incomodam e ter que reaprender a escrever vai ser um pouco chato. Mas, sinceramente, nada muito complicado neste caso, eu acho. Mais cedo ou mais tarde vou me acostumar (ainda mais com os corretores ortográficos de hoje em dia <img src='http://log4dev.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ). Mas fico imaginando: se eu já estou achando chato ter que reaprender o português, imagina a geração dos meus pais que está passando por isso pela segunda vez depois que foram alfabetizados. E a dos meus avôs que já passaram por isso três ou quatro vezes? Não sei como isso funciona em outros países, mas acho que estas mudanças políticas no Brasil não fazem muito sentido&#8230; ainda mais nesta quantidade. Como será que as pessoas mais velhas se sentem? Talvez já nem estejam se importando mais em aprender direito a nova ortografia se isso não impactar diretamente a vida delas.</p>

<p>Imagino que o sentimento de algumas pessoas em relação aos sistemas computacionais seja parecido. Apesar de as pessoas se acostumarem com eles e aprenderem a utilizá-los, de uma hora para outra, alguém decide que é necessário pegar um sistema que funciona razoavelmente bem e alterá-lo apenas para seguir as tendências da moda Web 2.0, prejudicando imediatamente um incontável número de pessoas que não estavam assim tão interessadas no modismo. Depois de algum tempo não seria de se estranhar que algumas dessas pessoas &#8220;desistissem&#8221; de tentar reaprender a utilizar o sistema.</p>

<p>Vejam que não sou contra mudanças! Desde que elas sejam necessárias, bem pensadas, planejadas, e de que venham para melhorar efetivamente a vida das pessoas, facilitando as tarefas. Sou contra mudanças políticas: como me parece ser a mudança ortográfica e como me pareceu ser a alteração do webmail do UOL (para citar só um exemplo na computação).</p>

<p>Por isso caros leitores, a mensagem que eu gostaria de deixar nesta primeira mensagem que escrevo este ano é uma que já foi tratada aqui neste blog outras vezes: quando você estiver desenhando um sistema ou redesenhando uma funcionalidade já existente, pergunte-se sempre se você está tomando decisões que realmente agregam valor e funcionalidade às suas alterações. Fujam das alterações políticas e burocráticas e, se necessário, fuja dos modismos também. Saiba utilizar as ferramentas e as tecnologias com aquilo que elas melhor tem a lhe oferecer e não vire escravo das novas siglas que aparecem o tempo todo.</p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2009/02/13/a-nova-ortografia-e-o-redesenho-de-software/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Micro introdução sobre orientação a aspectos (AspectJ)</title>
		<link>http://log4dev.com/2008/11/04/micro-introducao-sobre-orientacao-a-aspectos-aspectj/</link>
		<comments>http://log4dev.com/2008/11/04/micro-introducao-sobre-orientacao-a-aspectos-aspectj/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 00:28:55 +0000</pubDate>
		<dc:creator>Thiago Bartolomei</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Ferramentas]]></category>
		<category><![CDATA[Pesquisa]]></category>

		<guid isPermaLink="false">http://log4dev.com/2008/11/04/micro-introducao-sobre-orientacao-a-aspectos-aspectj/</guid>
		<description><![CDATA[Eu estava pensando em escrever sobre algumas coisas que têm me interessado ultimamente e que têm alguma relação com o post sobre vazamento de memoria em Java, mas eu percebi que não teria como, sem fazer uma pequena introdução sobre programação orientada a aspectos (aspect oriented programming, AOP). A gente já discutiu um pouco sobre [...]]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2008/11/04/micro-introducao-sobre-orientacao-a-aspectos-aspectj/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div>Eu estava pensando em escrever sobre algumas coisas que têm me interessado ultimamente e que têm alguma relação com o <a href="http://log4dev.com/2008/10/25/vazamento-de-memoria-em-java/">post sobre vazamento de memoria em Java</a>, mas eu percebi que não teria como, sem fazer uma pequena introdução sobre programação orientada a aspectos (aspect oriented programming, AOP). A gente já discutiu um pouco sobre isso no post sobre <a href="http://log4dev.com/2008/04/24/poor-mans-profiler-decorators-em-python/">decorators em python</a>, mas não fizemos nada mais introdutório (se você já tem uma noção do assunto, provavelmente não vai achar esse artigo muito útil). Então nesse post eu vou falar sobre alguns conceitos de <a href="http://aosd.net">desenvolvimento orientado a aspectos</a>(AOSD), mas com ênfase descarada em AOP na forma como implementada em <a href="http://www.eclipse.org/aspectj/">AspectJ</a>. Eu não pretendo cobrir em profundidade o assunto, pretendo somente dar uma idéia da motivação e discutir alguns pontos sobre o paradigma. Além disso, eu vou usar na maioria a terminologia em inglês, pois eu acho estranho traduzir termos tecnológicos. Se alguem tiver interessado em termos em português, o pessoal do workshop em AOP (WASP&#8217;04) fez um <a href="http://twiki.dcc.ufba.br/bin/view/WASP04/Termos">catálogo de termos</a>.</p>

<p><strong>Motivação e Exemplo</strong></p>

<p>No meu ponto de vista, AOSD não é algo que veio revolucionar o desenvolvimento de software, mas sim um avanço incremental do paradigma de orientação a objetos (OO). Todo bom programador sabe que se deve tentar distribuir as responsabilidades (<em>concerns</em>) do programa em módulos, de forma que cada módulo seja fácil de implementar, entender e reusar. Em C, por exemplo, funções podem ser consideradas módulos. Pra qualquer programa não trivial, você não vai criar somente uma função <code>main()</code>, vai separar a funcionalidade em muitas funções que se chamam pra realizar o objetivo do software. Já OO prega a modularização do software em uma hierarquia de classes e conta com polimorfismo, herança, etc. A motivação de AOSD é que existem algum concerns que entrecortam a hierarquia, ou seja, que mesmo criando essa hierarquia de classes, você não tem como separar dois concerns que deveriam ser separados (para serem melhor implementados, entendidos e reusados).</p>

<p>Pra não ficar somente no abstrato, vamos à um exemplo bem simples, que é utilizado constantemente pra apresentar AOP. Imagine que você tem uma classe que faz o controle do acesso ao banco de dados. O código abaixo é um esboço de como uma classe dessas seria implementada em Java. Você tem um gerente de transações e, em todos os métodos de acesso ao banco de dados, você chama o gerente pra iniciar uma transação e fazer commit se tudo deu certo, ou rollback se deu algum problema. Note que hoje em dia ninguém faria um código assim, já que existem soluções melhores do que ficar escrevendo SQL no seu código (como <a href="http://www.hibernate.org">Hibernate</a>), mas é bem ilustrativo do problema.
<pre></p>

<p>public class DB {
    TransactionManager manager = ...;</p>

<pre><code>public void storeUser(User u) {
    manager.start();
    try {
        // write some sql code storing u into the DB
        manager.commit();
    } catch (DBException e) {
        manager.rollback();
    }
}
public void storeAccount(Account a) {
    manager.start();
    try {
        // write some sql code storing a into the DB
        manager.commit();
    } catch (DBException e) {
        manager.rollback();
    }
}
...
</code></pre>

<p>}</pre>
Claramente dá pra perceber que eu tô misturando dois concerns na mesma classe. Um é persistência (salvar o User e a Account no banco de dados) e outro é controle de transações. Em OO, não tem um jeito elegante de separar esses concerns. Você pode até tentar fazer uma interface com uma callback pra tentar minimizar a repetição de código, como no código abaixo, mas não fica ideal.
<pre></p>

<p>public interface TransactionalTask {
    public void execute();
}
public class TransactionManager {
    TransactionManager manager = ...;</p>

<pre><code>public void executeInTransaction(TransactionalTask task) {
    manager.start();
    try {
        task.execute();
        manager.commit();
    } catch (DBException e) {
        manager.rollback();
    }
}
...
</code></pre>

<p>}
public class DB {
    public void storeUser(User u) {
        manager.executeInTransaction(new TransactionalTask() {
            public void execute() {
                // write some sql code storing u into the DB
            }
        });
    }
    ...
}</pre>
A idéia de AOSD é criar um novo módulo (chamado aspecto) em que você possa encapsular esses concerns que não tem como você modularizar com classes. AspectJ é a implementação mais conhecida de AOP, tanto por ser a primeira, quanto por ser bem robusta e contar com apoio de diversas empresas. Em AspectJ, que é uma extensão de Java (todo código Java é código AspectJ válido), nós criaríamos um aspecto pra encapsular controle de transações. O pseudo código abaixo mostra a idéia (eu não testei o código, então não garanto copy-and-paste funcionando).
<pre></p>

<p>public aspect TransactionManagerAspect {
    TransactionManager manager = ...;</p>

<pre><code>around(Object o) : execution(public void DB.*(..)) &amp;amp;&amp;amp; args(o) {
    manager.start();
    try {
        proceed(o);
        manager.commit();
    } catch (DBException e) {
        manager.rollback();
    }
}
</code></pre>

<p>}</p>

<p>public class DB {</p>

<pre><code>public void storeUser(User u) {
    // write some sql code storing u into the DB
}
public void storeAccount(Account a) {
    // write some sql code storing a into the DB
}
...
</code></pre>

<p>}</pre>
A classe DB agora contém somente código relativo à persistência e o aspecto é responsável pelo controle de transações. Em terminologia de AOSD, <code>around</code> é um tipo de <em>advice</em> e <code>execution</code> um tipo de <em>pointcut</em>. O que esse código tá dizendo é que sempre que a execução do programa for iniciar um método publico, que retorna void, na classe DB, o método deve ser substituído (por isso &#8220;around&#8221;) por esse advice aqui. O código do advice vai fazer o controle da transação e vai chamar <code>proceed</code> pra executar o código original. Note que o código do advice é muito parecido com a nossa solução usando callbacks. A grande novidade aqui é que usando pointcuts a gente consegue especificar quando que a &#8220;callback&#8221; deve ser usada, deixando o código da classe DB bem mais limpo.</p>

<p>Esse exemplo mostra a parte dinâmica da história, isto é, como usar aspectos pra &#8220;interceptar&#8221; alguns pontos da execução de um programa e inserir (ou remover) funcionalidade (código) nesses pontos. Mas AOSD também trata da parte estática ou &#8220;estrutural&#8221; da coisa. Por exemplo, imagine que no nosso exemplo nós quiséssemos inserir um controle de concorrência bem primitivo, pra garantir que ninguém modificou o <code>User</code> no tempo entre eu buscar no banco e salvar. Pra isso, eu poderia adicionar um campo na classe <code>User</code> com um contador que é incrementado sempre que ele for salvo no banco. Desta forma, na hora de salvar, eu confiro se o valor do contador no objeto que recebi é o mesmo do banco de dados. Se não for, significa que alguém alterou o objeto e eu recebi um objeto inconsistente. Novamente, o problema é que esse campo não faz parte do concern persistência ou modelo de dados. Portanto, não faria sentido eu declarar o contador na classe <code>User</code>. Pra resolver esse problema, AspectJ usa <em>intertype declarations</em>, que permitem a declaracão de campos e métodos em outras classes. Por exemplo, o código abaixo declara e inicializa um campo <code>counter</code> na classe <code>User</code>, removendo dela o concern tratamento de concorrência.
<pre></p>

<p>public aspect ConcurrencyManagerAspect {
    long User.counter = 0;
    ...
}</pre>
<strong>Conceitos</strong></p>

<p>Quando eu estava descrevendo o exemplo eu me referi à alguns conceitos de AOSD. Mas acho importante deixar um pouco mais explícito, então seguem algumas definições.</p>

<p>Existem alguns eventos que acontecem durante a execução de um programa que são interessantes de serem interceptados. Esses pontos são chamados <em>join points</em>. Nós vimos que a execução de um método é um ponto interessante quando o objetivo é substituir o método ou introduzir funcionalidade antes ou depois do método. Outros join points, por exemplo, são a chamada de um método (não confundir com a execução), a leitura ou escrita de um campo, ou a inicialização estática de uma classe. Mas esses join points são eventos concretos que acontecem em tempo de execução. <em>Pointcuts</em> são um jeito de especificar de forma abstrata (por exemplo, com regular expressions) quais join points você quer interceptar. AspectJ oferece pointcuts primitivos pros join points mais importantes (como <code>execution</code>, <code>call</code>, <code>get</code>, etc) e outros pointcuts usados pra identificar os objetos envolvidos nos eventos e ligá-los a variáveis. No nosso exemplo, <code>args</code> foi usado pra pegar uma referência ao objeto passado como parâmetro ao método. Outros pointcuts importantes são <code>target</code> (e.g., o objeto que é o destino de uma chamada de método) e <code>this</code> (e.g., o objeto que faz a chamada).</p>

<p>Quando um join point acontece em runtime e ele faz match com um pointcut, então se executa o <em>advice</em> relativo ao pointcut (se tiver algum). Nós vimos como um advice do tipo <code>around</code> funciona. AspectJ também tem advices <code>before</code> e <code>after</code> (que pode ser <code>after throwing</code> ou <code>after returning</code>), que servem pra introduzir código antes ou depois do join point. <em>Intertype declarations</em> também são disponibilizadas por AspectJ pra introduzir novos campos métodos em outras classes, como vimos no exemplo.</p>

<p>Um aspecto é então um módulo usado pra encapsular todas essas construções, do mesmo jeito que uma classe encapsula métodos e campos. O objetivo principal de um aspecto é de modularizar um interesse (concern) que não faz parte da decomposição normal da hierarquia de classes. Esses concerns são chamados de <em>crosscutting concerns</em>, porque eles entrecortam a hierarquia. A implementação de um concern é dita espalhada (scattered) quando ela não está localizada, e entrelaçada (tangled) quando ela está misturada com outros concerns.</p>

<p>Pra quem tiver interesse, o <a href="http://www.eclipse.org/aspectj/doc/released/progguide/index.html">AspectJ Programming Guide</a> é um excelente tutorial com bons exemplos e referências pros diversos tipos de pointcuts, além de explicar alguns problemas que você pode encontrar quando não tiver muita experiência com aspectos.</p>

<p><strong>Discussão</strong></p>

<p>No texto acima eu tratei AOSD e AOP quase como sinônimos, mas eu quero enfatizar que são distintos. Orientação a aspectos surgiu como AOP, pois trazia soluções pra problemas diretamente ligados ao código, como no exemplo sobre controle de transações. Contudo, percebeu-se que seria interessante elevar o nível de abstração e que crosscutting concerns podiam também ser encontrados em design, arquitetura, análise de requisitos, etc. Então AOSD trata não só da programação, mas também de todo o conjunto de metodologias, processos, etc, ligados ao desenvolvimento de software usando a idéia de que crosscutting concerns devem ser tratados como &#8220;first class citizens&#8221;.</p>

<p>Na minha experiência, AOP como encontrada em AspectJ é utilizada quase que exclusivamente em círculos acadêmicos. Existem algumas empresas que adotam AspectJ para alguns projetos, mas a linguagem está longe de ser adotada em larga escala. Porém, alguns conceitos de AOP são muito usados em alguns frameworks e application servers como <a href="http://www.springframework.org">Spring</a> e <a href="http://jboss.org">JBoss</a>. Spring, por exemplo, tem o conceito de interceptors, que nada mais são do que pointcuts e advice, mas menos poderosos (não permitem interceptar join points de pouca granularidade, como getters, se não me engano).</p>

<p>Eu acredito que existem atualmente dois grandes impedimentos pra se usar AOP em larga escala. Primeiro é a tecnologia do compilador. Hoje em dia ninguém aceita trabalhar com um compilador que não seja incremental. Quando você usa Eclipse e faz uma alteração no código, o JDT só compila o necessário. O similar para AspectJ, AJDT, tenta fazer o mesmo. Porém, a tarefa é muito mais difícil, pois uma pequena mudança tem que ser verificada perante todos os pointcuts do seu sistema, pois de repente o que você mudou pode agora ser interceptado pelo pointcut. Assim, apesar de ter uma performance relativamente boa, trabalhar com AspectJ usando AJDT não é tao agradável quanto trabalhar com Java usando JDT.</p>

<p>Segundo, AOSD não vai acabar com todos os seus problemas. É difícil pros programadores entenderem os conceitos e leva tempo pra comunidade desenvolver design patterns e entender o que tirar de melhor do paradigma. Pointcuts são atualmente regular expressions, então eles são frágeis e qualquer mudança de nome de um método pode fazer um pointcut não mais interceptar aquele método, e você não tem como perceber que isso aconteceu. Suporte de boas ferramentas é então essencial. Além disso, eu tenho dúvidas de que aspectos sejam bons pra modularizar concerns heterogêneos como &#8220;logging&#8221;, que foi sempre um dos principais exemplos. O problema é que cada instância de logging é muito específica pro contexto, então não faz sentido você remover todas as chamadas de log e encapsular em um advice, pois o advice teria que ser diferente pra cada ponto que ele interceptasse. Controle de transações é homogêneo, pois o advice sempre faz a mesma coisa, então é um exemplo mais apropriado. Existem estudos que apontam que Mixin Layers são melhores pra concerns heterogêneos como logging, mas isso seria assunto para um outro post.</p>

<p>==========================
Nota no dia 5/11</p>

<p>Conversando com o Miguel eu acabei percebendo algo que talvez não tenha ficado muito claro. AspectJ é uma extensão de Java e precisa de um compilador especial que compila as classes como se fossem Java e depois analisa os aspectos do sistema e faz diretamente as modificações no código (ou introduz testes de tempo de execução quando não tem como verificar estaticamente o resultado). Esse último passo, &#8220;introduzir os aspectos&#8221;, é chamado <em>weaving</em>.</p>

<p>Existem duas alternativas principais de compiladores pra AspectJ. O ajc é parte do <a href="http://www.eclipse.org/ajdt/">AJDT</a>, que é uma extensão do JDT do Eclipse. Como o JDT, o AJDT contém editor, compilador, debugger, e tudo o mais, implementados em plugins pro Eclipse. O principal objetivo do projeto é que a compilação seja rápida pra que você tenha a mesma experiencia que programando em Java, ou seja, ele tenta ser incremental e o código do compilador em si é otimizado (leia-se, não-facilmente extensível).</p>

<p>A outra alternativa é o abc (<a href="http://aspectbench.org">Aspect Bench Compiler</a>), que é um compilador acadêmico cujo objetivo principal é ser extensível pra que se possa fazer pesquisa com linguagens de programação, otimização de código, análise estática, etc. Dessa forma, compilar um sistema grande com abc, principalmente usando as otimizações disponíveis, é bem demorado. O ideal é programar usando o AJDT e usar o abc pra gerar o bytecode de produção, já que ele é bem mais otimizado que o gerado pelo ajc.</p>

<p>Além disso, AspectJ não é a única linguagem orientada à aspectos derivada de Java. No site da aosd.net, por exemplo, tem uma lista com alguns <a href="http://aosd.net/wiki/index.php?title=Supported_Systems">sistemas</a> (derivados ou não de Java) e algumas <a href="http://aosd.net/wiki/index.php?title=Tools_for_Developers">ferramentas</a> orientadas a aspectos.</p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2008/11/04/micro-introducao-sobre-orientacao-a-aspectos-aspectj/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Qual a fonte?</title>
		<link>http://log4dev.com/2008/08/03/qual-a-fonte/</link>
		<comments>http://log4dev.com/2008/08/03/qual-a-fonte/#comments</comments>
		<pubDate>Sun, 03 Aug 2008 20:18:26 +0000</pubDate>
		<dc:creator>Miguel Galves</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Ferramentas]]></category>
		<category><![CDATA[tipografia]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://log4dev.com/2008/08/03/qual-a-fonte/</guid>
		<description><![CDATA[Essa dica é para amantes de design em geral, e fontes e tipografia em particular. Descobri hoje, lendo a revista Mac+, o site What the Font que oferece uma ferramenta que tenta descobrir a fonte utilizada para escrever texto em um arquivo de imagem. O processo é simples: faça upload ou passe a URL da [...]]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2008/08/03/qual-a-fonte/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div>Essa dica é para amantes de design em geral, e fontes e tipografia em particular. Descobri hoje, lendo a revista Mac+, o site <a href="http://www.myfonts.com/WhatTheFont">What the Font</a> que oferece uma ferramenta que tenta descobrir a fonte utilizada para escrever texto em um arquivo de imagem.</p>

<p>O processo é simples: faça upload ou passe a URL da imagem que deseja analisar, verifique se os caracteres que ele detectou estão corretos e pronto. O resultado é exibido na forma de uma lista de textos em diversas fontes, e o sistema permite a comparação das fontes obtidas com a sua fonte original mostrando a sua imagem sempre no centro da tela.</p>

<p>Utilizei a ferramenta para tentar descobrir as fontes utilizadas pelo Raphael para fazer o logo do job4dev (ele perdeu o arquivo PSD original&#8230;), e o resultado obtido está abaixo:</p>

<p><a href="http://beta.log4dev.com/wp-content/uploads/2008/08/whatthefont.png" title="whatthefont.png"><img src="http://beta.log4dev.com/wp-content/uploads/2008/08/whatthefont.png" alt="whatthefont.png" width="519" height="300" /></a></p>

<p>A fonte ATCapone-Light parece a correta!</p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2008/08/03/qual-a-fonte/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Frase do Dia</title>
		<link>http://log4dev.com/2008/05/08/frase-do-dia-5/</link>
		<comments>http://log4dev.com/2008/05/08/frase-do-dia-5/#comments</comments>
		<pubDate>Thu, 08 May 2008 13:18:49 +0000</pubDate>
		<dc:creator>Miguel Galves</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Design]]></category>

		<guid isPermaLink="false">http://log4dev.com/2008/05/08/frase-do-dia-5/</guid>
		<description><![CDATA[&#8220;Customers don&#8217;t know what they want, much less what they need, until they see it.&#8221;]]></description>
			<content:encoded><![CDATA[<p><div class='wpfblike' style='height: 40px;'><fb:like href='http://log4dev.com/2008/05/08/frase-do-dia-5/' layout='button_count' show_faces='true' width='400' action='like' colorscheme='light' send='true' /></div><em>&#8220;Customers don&#8217;t know what they want, much less what they need, until they see it.&#8221;</em></p>
]]></content:encoded>
			<wfw:commentRss>http://log4dev.com/2008/05/08/frase-do-dia-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

