<?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>Diego Fleury, front-end architect</title>
	<atom:link href="http://www.diegofleury.com.br/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.diegofleury.com.br</link>
	<description>Working to make the web a better place</description>
	<lastBuildDate>Sat, 19 Jun 2010 19:07:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>jQuery Namespace Design Pattern</title>
		<link>http://www.diegofleury.com.br/2010/06/jquery-namespace-design-pattern/</link>
		<comments>http://www.diegofleury.com.br/2010/06/jquery-namespace-design-pattern/#comments</comments>
		<pubDate>Sun, 13 Jun 2010 12:06:40 +0000</pubDate>
		<dc:creator>Fleury</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Plugins]]></category>

		<guid isPermaLink="false">http://diegofleury.com.br/?p=1</guid>
		<description><![CDATA[Apresenta o padrão de projeto que melhora a organização de plugins e ajuda a reduzir as chances de conflito de nomes <a href="http://www.diegofleury.com.br/2010/06/jquery-namespace-design-pattern/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Em 2008, quando eu trabalhava na Compos, houve uma demanda para construir algo que simplificasse a validação de formulários no lado cliente. No meio do benchmark que fiz para saber o que deveria projetar, percebi que seria um plugin extenso e que os outros plugins com a mesma finalidade, optaram por dividir suas partes no formato de plugins. Ou seja, o plugin virou um conceito e suas funções concretas se tornaram plugins, muitos plugins. O maior problema com certeza, foi que a maioria desses plugins tinham nomes bem genéricos. Isto me causou preocupação, que me levou enviar um email para John Resig sobre alternativas que minimizassem as chances de conflitos de nomes. Ele me respondeu que a equipe do jQuery estava avaliando algumas possibilidades, mas nada tinha sido definido.</p>
<p>Eu ainda precisava encontrar uma solução para isto, e o resultado desse estudo vocês podem ver na apresentação abaixo que apresentei para a equipe de front-end da Globo.com.</p>
<p><strong>Update:</strong><br />
Meu amigo Francisco Rodrigues me deu um feedback pedindo pra eu detalhar mais o assunto e é isso que farei agora.</p>
<p>Antes de mais nada, temos que considerar que o padrão conhecido para construção de plugins do jQuery, resolve o problema de maneira formidável somente quando o plugin é bem atômico. Entretanto, quando precisamos dividi-lo, encontramos algumas soluções que trazem consigo uma série de problemas. Vejamos como funciona este formato padrão:</p>
<p><code>
<pre>jQuery.fn.invert = function() {
  return this.each(function() {
    var
      $this = $(this),
      inverted = $this.text().split("").reverse().join("");
    $this.text(inverted);
  });
}

$("div#foo").invert();</pre>
<p></code></p>
<p>Como podemos ver, em casos assim, este padrão resolve nosso problema perfeitamente. Entretanto, e quando nosso plugin abrange uma série de outras funcionalidades ou precisa ter uma interface de métodos para ser manipulado por outras partes da sua aplicação?</p>
<p>O melhor caso que conheço para exemplificar este problema, é o <a href="http://docs.jquery.com/Plugins/Validation">jQuery Validation Plugin</a>. Vejam que este plugin na verdade não é um plugin, ele é uma coleção de plugins que podem ou não ter relação um com o outro.</p>
<p>Várias pessoas perceberam este problema e tentaram contorná-lo de várias formas. Dentre as mais utilizadas há a invocação de métodos selecionado por parâmetro. Vejamos:</p>
<p><code>
<pre>(function() {
  var methods = {
    myAction: function() { /* ... */ },
    myOtherAction: function() { /* ... */ }
  };

  jQuery.fn.bar = function() {
    var args = $.makeArray(arguments), method = args.shift();
    methods[method].apply(this, args);
  };
})();

$("div#foo").bar("myAction", "myArgument");</pre>
<p></code></p>
<p>Outra opção é fazer o que muitos conhecem como programação orientada a eventos ou, buzz de eventos, onde basicamente, os métodos serão manipuladores de eventos e quando queremos invocá-los, disparamos o gatilho destes eventos. Seria algo assim:</p>
<p><code>
<pre>
jQuery.fn.bar = function() {
  this
    .bind("bar.myAction", function(args) { /* ... */ })
    .bind("bar.myOtherAction", function(args) { /* ... */ })
};

$("div#foo").trigger("bar.myAction", "myArgument");</pre>
<p></code></p>
<p>Outro problema comum são as informações que temos que compartilhar entre estes métodos do nosso plugin. A forma como desenvolvemos plugins hoje, pode confundir principalmente quem está iniciando, e isso pode originar problemas sérios como variáveis globais ou quase isso. Estes contexto extremamente permissivos podem causar problemas quando que por um agente externo, valores de controle do plugin forem alterados na força bruta.<br />
Essa exposição vai contrário às boas práticas e pode causar problemas inesperados no código.</p>
<p>Por último, já vi casos onde de um método para o outro, a referência do objeto que está sendo manipulado é passado. Isso é feio, muito feio, além de não ser viável quando temos métodos demais pois trará uma grande poluição no código.</p>
<p>Sendo assim, se você precisar dar uma melhora na organização, temos estas opções que mostrei, algumas outras menos populares e ainda, plugins de namespace.</p>
<p>Eu não gosto de plugins de namespace. Internamente, eles fazem um processo muito caro para resolver nomes tipo Java e depois retornar o plugin requisitado. Além do mais, são soluções experimentais que não tiveram adesão. Acredito que o motivo para essa falta de popularidade se deve ao fato de que eles fogem bastante da natureza de como o jQuery atua.</p>
<p>Mas bem, a solução encontrada foi fazer com que o objeto do jQuery recebesse novas funcionalidades durante a execução. Utilizei uma técnica descrita por <a href="http://www.crockford.com/">Douglas Crockford</a> como <a href="http://www.crockford.com/javascript/inheritance.html">Object Augmentation</a>. Não é nada de outro mundo. Veja um exemplo simples:</p>
<p><code>
<pre>var nome = new String("Diego");
nome.sobrenome = "Fleury";</pre>
<p></code></p>
<p>Então o que eu faço neste pattern, tornar o nome do plugin, seu namespace. E sendo assim, eu retorno o objeto do jQuery com os novos métodos que eu adicionei.</p>
<p><code>
<pre>$.fn.MyPlugin = function() {

  this.firstMethod = function() {
    return this.each(function() {
      // Faz algo útil
    });
  };

  return this;

};

// Retorna o objeto do jQuery com a nova função, firstMethod
$("div#foo").MyPlugin();

// Executa o que firstMethod se propõe a fazer e
// retorna o mesmo objeto jQuery modificado
$("div#foo").MyPlugin().firstMethod();</pre>
<p></code></p>
<p>Não sei se perceberam, mas para identificar o namespace, eu convencionei que a primeira letra é maiúscula. Agora todas as partes menores só poderão ser invocadas se anteriormente MyPlugin() for executado. Simples não?</p>
<p>Bom esse pattern ainda tem um problema de performance. Por uma característica da linguagem, quando o código do plugin é carregado, somente a function de MyPlugin é construída pelo interpretador JavaScript. Ou seja, o que está dentro ainda não foi avaliado. O resultado desta construção é referenciado em jQuery.fn.MyPlugin e executado a cada invocação. Entretanto, toda vez que MyPlugin é executado, seu contexto interno será interpretado e avaliado. Neste momento a função firstMethod será construída também. Isso não seria um problema de fosse somente uma função, mas imagine 30 métodos sendo construídos toda vezes que MyPlugin é executado. Pesado não? A solução pra isso é simples. Vamos mover qualquer função para fora de MyPlugin e dentro dele, só faremos referência a algo que já foi construído antes.</p>
<p><code>
<pre>(function($) {

  $.fn.MyPlugin = function() {

    this.firstMethod = parts.firstMethod;

    return this;

  };

  var parts = {
    firstMethod: function() {
      return this.each(function() {
        // Faz algo útil
      });
    }
  };

})(jQuery);
</pre>
<p></code></p>
<p>Pronto! Até me sinto mais leve. Este pattern ainda nós dá o benefício de fazer opções globais, que podem ser valores genéricos que sere para a maioria dos casos mas se precisar de algo mais específico, pode ser sobrescrito. Vejam na apresentação maiores detalhes de como isto é feito.</p>
<p>No pior dos casos (por favor, evite fazer isso ao máximo), quando você tiver métodos demais, você poderá utilizar a função de extensão do próprio jQuery para não ter de declarar dentro do namespace cada método que quiser referenciar.</p>
<p>Por último, nada impede de você ter namespace dentro de namespace caso seja algo extremamente extenso. Mas se chegar a esse nível, considere a possibilidade de que seu plugin pode ou precisa ser quebrado em mais de um.</p>
<p>As vantagens são notáveis. Dentro em breve mostrarei para vocês o meu plugin de validação e espero que ele sirva como um bom case.</p>
<p>Dúvidas? Sugestões? Erros? Deixe um comentário!</p>
<p><em><strong>English:</strong><br />
In 2008, when I worked in Compos, there was a demand to build something that simplified form validation on the client-side. In the middle of the benchmark that I ought to know what design I should do, I realized that it would be an extensive plugin and other plugins with the same purpose, chose to divide their parts in plugin format. That is, the plugin became a concept and its precise functions have become plugins, many plugins. The biggest problem of course, was that most of these plugins have names very generics. This caused me concern, which led me to send an email to John Resig about alternatives that might minimize the chances of name conflicts. He replied that the jQuery team was evaluating some possibilities, but nothing had been set.</p>
<p>I still needed to find a solution to it and the results of this study you can see in <a href="http://www.slideshare.net/dfleury/jquery-namespace-pattern">this presentation</a> which I show to front-end team of Globo.com.</em></p>
<div style="width:425px" id="__ss_4490665"><object id="__sse4490665" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=jquery-namespace-pattern-100613210115-phpapp02&#038;stripped_title=jquery-namespace-design-pattern-ptbr" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse4490665" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=jquery-namespace-pattern-100613210115-phpapp02&#038;stripped_title=jquery-namespace-design-pattern-ptbr" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
       ]]></content:encoded>
			<wfw:commentRss>http://www.diegofleury.com.br/2010/06/jquery-namespace-design-pattern/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.270 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-05 05:50:00 -->
<!-- Compression = gzip -->