

<?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>Rodrigo Kumpera Weblog &#187; Scalability</title>
	<atom:link href="http://www.kumpera.net/blog/index.php/category/scalability/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kumpera.net/blog</link>
	<description>Meus achados sobre tecnologia</description>
	<lastBuildDate>Thu, 10 Jun 2010 04:33:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>O trânsito paulistano admite uma solução tecnológica?</title>
		<link>http://www.kumpera.net/blog/index.php/2008/06/19/o-transito-paulistano-admite-uma-solucao-tecnologica/</link>
		<comments>http://www.kumpera.net/blog/index.php/2008/06/19/o-transito-paulistano-admite-uma-solucao-tecnologica/#comments</comments>
		<pubDate>Thu, 19 Jun 2008 06:17:55 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Scalability]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[anger management]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2008/06/19/o-transito-paulistano-admite-uma-solucao-tecnologica/</guid>
		<description><![CDATA[Essa foi uma pergunta que eu me fiz outro dia. Ela surgiu durante uma discussão sobre possíveis soluções para o inferno diário de milhões de pessoas. O argumento da maioria dos presentes era que a única real solução era construir metro. Vim a acreditar que essa é, de longe, aquilo que nossa cidade precisa.
Basta um [...]]]></description>
			<content:encoded><![CDATA[<p>Essa foi uma pergunta que eu me fiz outro dia. Ela surgiu durante uma discussão sobre possíveis soluções para o inferno diário de milhões de pessoas. O argumento da maioria dos presentes era que a única real solução era construir metro. Vim a acreditar que essa é, de longe, aquilo que nossa cidade precisa.</p>
<p>Basta um pouco de matemática para provar que não é cavando túneis que vamos reduzir o caos do transporte. Vamos pegar o caso de uma cidade com um transporte considerado referencia global. Londres possui 408km de metro para 7,5 milhões de habitantes, ou um quilômetro para cada 18,3mil pessoas. Enquanto isso na região metropolitana de São Paulo sobrevivem 19,2 milhões de pessoa com 68km de metro e 257km de trem, ou seja, 282,3mil se debatendo por quilômetro de metro ou 59mil se espremendo no transporte metroviário da cidade.</p>
<p>Fazendo uma simples regra de três, a cidade precisa de mais 720km de trilhos para ter o mesmo nível de conforto de Londres. Pronto, resolvido, só construir agora. Porém as pessoas esquecem que dois detalhes, custo e prazos. Primeiro aos custos, a linha 4 foi orçada originalmente em 1,25 bilhões de dólares e tem uma extensão de quase 13km, o que significa 155 milhões de reais por quilômetro. Por esse parâmetro, São Paulo precisa de aproximadamente 112 bilhões em investimentos, ou sete vezes mais que os 15,8 destinados a todos programas do PAC para o ano de 2008. Mas vamos esquecer isso, pois dinheiro não é o problema. Sério.</p>
<p>O ponto importante é o tempo de construção. No atual ritmo de quatro quilômetros ao ano as obras ficariam prontas somente em 2188. Mas as coisas vão melhorar e vamos andar na mesma velocidade frenética da construção do metrô chines em Pequim, que é cinco vezes mais rápida. Ainda assim, as obras seriam entregues em 2044, daqui 36 anos.</p>
<p>Ouviram bem, serão trinta e seis anos de espera se, por milagre, passarmos a construir na velocidade maluca dos chineses. Vejamos, daqui todo esse tempo eu vou ter 62 anos e a todos dos leitores desse blog terão bem mais de cinqüenta. Ou seja, vamos estar na terceira idade, próximo de nos aposentarmos. Porém se o ritmo das obras se mantiver, talvez nossos bisnetos assistam a conclusão perto do final de suas vidas.</p>
<p>Eu não quero esperar até minha aposentadoria para ter um transporte urbano que preste na minha cidade. Não podemos esperar mais de três décadas, precisamos disso o mais rápido possível. Precisamos para ontem, não podemos que cada um jogo fora centenas de horas parado em engarrafamentos todo ano.</p>
<p>Dito isso, o quanto a tecnologia mudou nossas vidas nos últimos dez anos? Em especial, vamos refletir na questão organizacional das nossas vidas. Hoje é muito fácil via celular e internet organizar reuniões e grupos &#8211; basta um tweet &#8220;vamos beber&#8221; que em uma horas estão todos no bar certo. Hoje é muito fácil centralizar, catalogar, manipular e consultar informação pertinente a milhões de pessoas em tempo real &#8211; basta pensar em coisas como redes sociais, rss e sites de busca. Por fim, hoje a informação possui uma tremenda mobilidade, um celular moderno tem localização via GPS e até 1mb de largura de banda com a internet.</p>
<p>Agora vamos pensar em como opera o transporte público hoje. Temos linhas de ônibus fixas e definidas por engenheiros de tráfego baseados em pesquisar de origem e destino. Nós temos rotas estáticas de transporte, você conseguiria imaginar a internet sem roteamento dinâmico de pacotes? Nós temos rotas otimizadas segundo critérios antigos &#8211; o que seria do Google se a busca fosse baseada no conteúdo de um anos atrás apenas? Nós temos itinerários e linhas que não são adaptadas as necessidades dos usuários no momento que usam &#8211; imagine usar um navegador com 30 minutos de atraso.</p>
<p>Nosso sistema de transporte não deve ser modernizado, precisa ser recriado, repensado e quebrar todas barreiras convencionais. Porque você precisa pegar um ônibus que passa em lugares e horários pré-definidos? Imagine se bastasse do seu celular informar seu destino que um sistema ajustaria a rota de um veículo para melhor servir você e otimizar o uso das nossas vias? Algo quase como um taxi coletivo a custos de um convencional. Hoje temos todas as peças do quebra cabeça tecnológico para viabilizar isso.</p>
<p>Basta começar a pensar no assunto para centenas de idéias surgirem, a maioria delas muito melhor que as minhas. Basta pensar em um modelo de transporte que seja tão ágil quanto nossa vida moderna é, ou deveria ser.</p>
<p>Minha contribuição, entretanto, não é a sugestão tecnológica. O transporte de São Paulo é um mercado de 8 bilhões de reais ao ano, pelo menos. Muita grana não? Porém existe uma reserva de mercado para novas empresas entrarem e na forma de atuação delas, além de um cartel de empresas controlando o serviço hoje. Todos sabemos dos prejuízos que tais reservas causam ao interesse público, por isso a única solução é abrir o setor ao mercado como um todo e permitir que as empresas decidam como operar modal que irão oferecer. O resto deixem por conta da iniciativa privada, que é mister sua capacidade de inovação em face a livre concorrência.</p>
<p>Todo paulistano tem a obrigação de aproveitar que estamos em ano eleitoral, discutir o assunto, questionar seu candidato e tomar uma decisão informada em novembro. Não vamos mais uma vez deixar políticos nos enganarem com suas promessas vazias. Vamos dessa vez mostrar que não temos sangue de barata e mostrar exatamente aquilo que queremos. Eu estou aqui fazendo a minha, agora você Paulistano vá fazer a sua!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2008/06/19/o-transito-paulistano-admite-uma-solucao-tecnologica/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Lugar errado, problema errado</title>
		<link>http://www.kumpera.net/blog/index.php/2007/05/11/lugar-errado-problema-errado/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/05/11/lugar-errado-problema-errado/#comments</comments>
		<pubDate>Sat, 12 May 2007 02:19:05 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Arquitetural Design]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/05/11/lugar-errado-problema-errado/</guid>
		<description><![CDATA[
Os comentários do Phillip no blog do Vitor só me fazem rir de alguém considerar o prevayler para nada que brinquedos. Digo isso por duas razões, pela experiência dos projetos que passei e pelo fato de Java ser uma das piores linguagens possíveis para se implementar prevalencia. Pelos projetos eu eu passei, sempre existiram requisitos [...]]]></description>
			<content:encoded><![CDATA[<p>
Os <a href="http://www.jroller.com/page/vfpamp?entry=schema_evolution_e_retrocompatibilidade_com">comentários do Phillip no blog do Vitor</a> só me fazem rir de alguém considerar o prevayler para nada que brinquedos. Digo isso por duas razões, pela experiência dos projetos que passei e pelo fato de Java ser uma das piores linguagens possíveis para se implementar prevalencia. Pelos projetos eu eu passei, sempre existiram requisitos que inviabilizam seu uso e quanto a Java, bom, basta olhar para o lado para entender.
</p>
<p>
Curiosamente volume de dados nunca foi a razão pelo qual o prevayler não tinha razão. Uma delas foi <strong>latência</strong> e tempo médio de resposta, mas como pode isso ocorrer se o prevayler é tão super mais rápido nas consultas? Simples, o enorme uso de heap tornava o tempo de garbage collection proibitivo, um SGBD usa memória de maneira muito mas eficiente sob o viés do tempo para dar manutenção nela, esse sistema terminou com uma JVM usando 64Mb e a base toda dentro do cache do banco de dados. Outro problema foi <strong>confiabilidade</strong>, o log do prevayler não é protegido de <em>partial writes</em> e usa <em>statement based logging</em>, que não permite recuperação parcial, então se tua controladora corromper o meio do teu log, você se lascou. Porém o maior problema do prevayler é o desenvolvimento com equipes distribuídas ou de médio porte em uma estrutura matricial de projetos, isto é, o esforço de coordenar schema evolution é massacrante, não existe como compartilhar facilmente uma base de dados e a integração entre projetos é infernal.
</p>
<p>
Quanto ao fato de Java ser uma péssima escolha, primeiro pelo fato de não ser uma linguagem baseada em imagem, como smalltalk ou factor, na qual salvar a imagem da heap toda é tão difícil quanto chamar um único método, você não tem que se preocupar com criar toneladas de Commands e transações com rollback são possíveis de ser criadas usando STM(<em>Software Transactional Memory</em>) ou simplesmente alguns <em>become()</em>. Outro problema é que criar buscas complexas com Java é um desastre, muito difícil de bater álgebra relacional ou simplesmente SQL nisso, nesse ponto linguagens funcionais dão um show no Java que beira a humilhação, aplicar predicados e transformações sobre coleções, criando e processando tuplas é super simples, é arroz-com-feijão.
</p>
<p>
No geral, eu vejo o prevayler com um brinquedo educacional para se aprender sobre serialização e só, usar profissionalmente não é interessante do aspecto que vai significar muito provavelmente trabalhar em projetos desintessantes ou mentalmente castrantes. Klaus e companhia que me desculpem, mas esse tipo de problema eu passo adiante, prefiro ficar com os mais divertidos e interessantes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/05/11/lugar-errado-problema-errado/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Utilidade da configuração programática</title>
		<link>http://www.kumpera.net/blog/index.php/2007/04/16/utilidade-da-configuracao-programatica/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/04/16/utilidade-da-configuracao-programatica/#comments</comments>
		<pubDate>Mon, 16 Apr 2007 14:23:02 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Arquitetural Design]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/04/16/utilidade-da-configuracao-programatica/</guid>
		<description><![CDATA[
Parece que configuração programática ficou em voga esses tempos na comunidade Java. A razão não me é muito clara, afinal, todo bom framework deve permitir ser usado de tal forma, porém não de maneira restritiva. Posso ter a opinião viciada nesse caso, mas acredito que configuração deve possuir sua DSL própria e a parte programática [...]]]></description>
			<content:encoded><![CDATA[<p>
Parece que configuração programática ficou em voga esses tempos na comunidade Java. A razão não me é muito clara, afinal, todo bom framework deve permitir ser usado de tal forma, porém não de maneira restritiva. Posso ter a opinião viciada nesse caso, mas acredito que configuração deve possuir sua DSL própria e a parte programática tem sentido apenas quando seu uso automatiza novas tarefas ou, de alguma forma, melhora sua usabilidade pelos desenvolvedores.
</p>
<p>
O maior argumento contra utilizar arquivos de configuração nunca foi muito o formato, seja xml ou qualquer outro, mas sim a quantidade abusiva de informação necessária para satisfazer o framework. Convenhamos, boa parte do tempo vamos usar apenas um conjunto pequeno dos recursos oferecidos e de uma maneira comum. Essas funcionalidades e interações recorrentes, devem possuir uma notação mais sucinta &#8211; o configuração deve ser ser otimizada para o uso comum. Para esse comportamento temos por uso de valores padrão inteligentes.
</p>
<p>
Porem, pode ser feito ainda mais. Neste caso, o framework assume que uma série de interações e padrões de uso serão utilizados e o usuário apenas configura aquilo que for diferente. Por esta maneira de trabalho, temos aquilo que chamamos por configuração por convenção. Juntando com valores padrão inteligentes, configuração deixa de ser uma preocupação, um martírio, para ser apenas um detalhe do projeto &#8211; que é seu devido lugar.
</p>
<p>
Em um cenário como esse, existe valor em expor uma extensa camada programática de acesso à configuração? Pelo resultado encontrado em vários projetos, sim, definitivamente existe, mas longe de ser uma boa ferramenta para substituir os arquivos. Primeiro, acho importante definir quais tipos de configuração existe em um framework e como isso afeta o valor ao abrir as portas para demais programadores.
</p>
<p>
Temos a Configuração de Inicialização, que pode ser vista como uma receita de bolo, que depois de utilizada, é descartada. O Hibernate é um bom exemplo, a configuração informada é utilizada para construir a SessionFactory e depois jogada fora. Outra forma de configuração é o Repositório de Parâmetros, onde toda configuração é armazenada de maneira que possa ser consultada em tempo de execução, o exemplo aqui fica por conta do Struts2, que transforma toda sua configuração em um modelo de objetos que representam os elementos envolvidos no processamento de uma requisição.
</p>
<p>
Das utilidades para configuração programática, destaco transformação, pois é aplicável no caso de Configuração de Inicialização. Transformação, como o nome sugere, altera a configuração já existente em algo mais útil, como colocar todas collections com lazy-loading; ou a partir de dados externos cria novos elementos, por exemplo, mapeando automaticamente todo um pacote de classes.
</p>
<p>
Quando existe um repositório, as possibilidades são maiores, o mecanismo de transformação pode ser aplicado na inicialização ou durante a execução. Para estender o comportamento do repositório utilizasse normalmente o padrão de projeto Plugin, para a descoberta do interessado, caso sejam muito, utiliza-se Chain-of-Responsibility para coordenar as transformações. O Struts2 funciona desta forma, é possível contribuir plugins que são responsáveis por instanciar as actions ou recuperar o mapeamento de um path. É possivel, por exemplo, descobrir quais actions existem no sistema e criar o mapeamento automaticamente.
</p>
<p>
Configuração programática é muito útil, porém não deixa de ser apenas uma ferramenta e, como tal, não deve ser o principal valor que um framework tem a oferecer, pois, a rigor, não trata do problema proposto a ser resolvido. Um framework MVC, por exemplo, deve ter como valores auxiliar no desenvolvimento de sites, dos quais configuração não é uma benéfice, mas sim um ardor maior ou menor para seu usuário.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/04/16/utilidade-da-configuracao-programatica/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Green threads &#8211; idéia ruim ou implementações péssimas?</title>
		<link>http://www.kumpera.net/blog/index.php/2007/04/12/green-threads-ideia-ruim-ou-implementacoes-pessimas/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/04/12/green-threads-ideia-ruim-ou-implementacoes-pessimas/#comments</comments>
		<pubDate>Thu, 12 Apr 2007 15:10:20 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[erlang]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/04/12/green-threads-ideia-ruim-ou-implementacoes-pessimas/</guid>
		<description><![CDATA[ Todo lugar que se prese a falar sobre modelos de threading, native x green, fala que não existe razão para ter threads implementadas em user-space, chamadas de green-threads, se o SO possuir uma boa implementação nativa. Bom, se olharmos em volta, como  neste blog, nas listas de discussão do JikesRVM, do Ruby ou [...]]]></description>
			<content:encoded><![CDATA[<p> Todo lugar que se prese a falar sobre modelos de threading, native x green, fala que não existe razão para ter threads implementadas em user-space, chamadas de green-threads, se o SO possuir uma boa implementação nativa. Bom, se olharmos em volta, como <a href=" http://ciaranm.org/show_post/110"> neste blog</a>, nas listas de discussão do JikesRVM, do Ruby ou do JRockit da época de 2004, vamos notar que todos reclamam muito das limitações e problemas impostos pelo uso de green-threads. As falhas apontadas são tantas que cria uma duvida se existe alguma justa razão em usá-las.
</p>
<p> Para entender melhor a situação, vejamos o modelo de execução que todo sistema operacional espera de seus processos. Um processo possui uma ou mais threads, cada thread possui apenas uma linha de execução* e faz chamadas bloqueantes ao kernel. Ou seja, cada uma deve seguir executando por apenas um caminho e deve parar enquanto uma chamada ao sistema não completa. Contrastemos agora com modelo de green-threads, que pode ser visto da seguinte forma: um processo possui uma ou mais threads, cada uma administra varias linhas de execução e uma chamada ao kernel não impede prosseguir com as demais.
</p>
<p> Essa diferença de funcionamento gera dois problemas. Primeiro de identidade, já que cada thread não possui somente uma linha de execução associada, então primitivas de locking não funcionam pois duas green-thread vão aparecer para o kernel como uma só. O segundo está relacionado ao comportamento do kernel, uma chamada bloqueante partindo de uma linha de execução vai causar várias outras pararem junto.</p>
<p> Ambos problemas dificultam muito a integração com bibliotecas externas, que podem usar o mecanismo de locking do sistema operacional, ou então bloquear indevidamente demais threads. Por exemplo, no Gtk+, o acesso aos widgets é protegido por locks nativos, que em um ambiente com green-threads vai por água abaixo e acaba corrompendo o estado, também tem o fato que executar processamento pesado fora da thread de eventos não ajuda, pois se uma bloqueia, todas bloqueiam. Por fim, tem a questão da escalabilidade, já que várias threads são bloqueadas sem precisar.</p>
<p> Existem alguns sistemas que conseguiram transpor essas barreiras, mas não sem um alto custo associado. Passam, primeiro, a adotar uma primitiva de mais alto nível que uma thread, como um ator, que é muito mais simples de utilizar. Depois fazem o trabalho pesado, criam um mecanismo de execução assíncrona das tarefas bloqueantes, seja fazendo offload para threads nativas auxiliares, ou usando aio e/ou multiplexação. Por fim, partem para as medidas radicais, definindo uma interface para código estrangeiro que garante a semântica e o comportamento das green-threads.
</p>
<p> A interface de integração com código estrangeiro, também conhecida por FFI (Foreign Function Interface), é o elemento mais crítico e problemático, pois precisa impor uma forma diferente de trabalho aos integradores, normalmente via troca assíncrona de mensagens entre uma thread com o código &#8216;perigoso&#8217; e as demais gerenciadas. Uma versão muito mais cabeluda do JNI, para quem conhece.</p>
<p> Das linguagens que implementam efetivamente userland threading, que eu conheço são<br />
Erlang, Scheme e Factor. Elas permitem o uso de milhares de thread leves que consomem poucos recursos e não fazem o escalonador do SO entrar em parafuso. A JVM da BEA, JRockit, uma época suportou green-threads, mas devido a dificuldade de implementar a parte GUI do Java e não criar caos durante chamadas nativas, desistiram do projeto quando o linux passou a ter suporte nativo descente.</p>
</p>
<p>* Por linha de execução entenda o conjunto de registradores e a pilha de funções.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/04/12/green-threads-ideia-ruim-ou-implementacoes-pessimas/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>DSLs vão ter o mesmo fim que AOP?</title>
		<link>http://www.kumpera.net/blog/index.php/2007/01/06/dsls-vao-ter-o-mesmo-fim-que-aop/</link>
		<comments>http://www.kumpera.net/blog/index.php/2007/01/06/dsls-vao-ter-o-mesmo-fim-que-aop/#comments</comments>
		<pubDate>Sat, 06 Jan 2007 04:02:38 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Arquitetural Design]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2007/01/06/dsls-vao-ter-o-mesmo-fim-que-aop/</guid>
		<description><![CDATA[
 Me dei conta hoje que DSLs sofrem do mesmo mal que AOP. Todas palestras e artigos cometem o pecado de sempre surrar um único exemplo. No caso de Aspect Oriented Programming, abusam dos exemplos envolvendo logging. Sem mencionar que de fato sempre estão a falar de tracing! Com DSLs vejo a mesma tendencia acontecer [...]]]></description>
			<content:encoded><![CDATA[<p>
 Me dei conta hoje que DSLs sofrem do mesmo mal que AOP. Todas palestras e artigos cometem o pecado de sempre surrar um único exemplo. No caso de Aspect Oriented Programming, abusam dos exemplos envolvendo logging. Sem mencionar que de fato sempre estão a falar de tracing! Com DSLs vejo a mesma tendencia acontecer em torno de configuração e fico preocupado. Diferente da outra tecnologia, acredito que Domain Specific Languages são uma ferramenta muito importante em um futuro não muito distante</p>
<p>
 Antes de tudo, tenho que concordar com <a href="http://fragmental.com.br/blog/?p=292">este post do Phillip </a> que DSLs são a bola da vez, e todos tem seus olhos virados para ver se rende alguma coisa. Mas o problema hoje não é a falta de ferramentas e sim a um bom playground para experimentarmos com o assunto. Construir, customizar e transformar linguagens não é nada facil e essa é a grande barreira para começarmos a ver avanços.
</p>
<p>
 Mas voltando ao embrólio de como se apresenta o assunto ao grande público. Todos estão falando  o tempo todo sobre como configuração é um problema a ser resolvido por linguagens de domínio. Até o Martin Fowler comete essa gafe em sua <a href="http://www.infoq.com/presentations/domain-specific-languages">palestra na JAOO 2006</a>! O problema é o mesmo que logging, eu diria, representa nenhum risco a complexidade de um projeto. Quantos realmente já tiveram problemas relacionados a dificuldade de colocar logging em uma aplicação? Configuração idem.
</p>
<p>
 Além disso, acho que corremos na mesma direção do fiasco que foram as linguagens de quarta geração, as malditas 4GLs que tanto odiamos. Não vamos criar mini linguagens para o cliente poder sair customizando seu sistema, principalmente porque ele não saberia fazer isso de qualquer maneira. Criaremos atalhos para os desenvolvedores na forma de linguagens simples, limitadas e focadas em tarefas muito específicas; ou via customização da linguagem carro chefe do projeto.
</p>
<p>
 DSLs como customizações é uma coisa que já vemos acontecer, via linguagens com suporte à macros (scheme, lisp, erlang*), ou com abuso do mecanismo de metaclasses &#8211; um exemplo, um pouco pobre, é RoR e ActiveRecord, que customiza Ruby para facilitar manipulação de banco, pobre pois poderia melhorar em muito a sintaxe em favor da manipulação de dados.
</p>
<p>
 Enfim, acredito que veremos muito ainda sobre esse assunto, principalmente confusão e palestras que falam de configuração. Logo deveremos ter acesso a linguagens faceis de serem customizadas e que permitam muita experimentação no assunto. Foi essa experimentação que permitiu AOP ganhar momento com Java e ser assunto de piada entre C++.
</p>
<p> *erlang não ter macros propriamente ditas, mas suporte parser transformers que são capazes de fazer o mesmo trabalho.</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2007/01/06/dsls-vao-ter-o-mesmo-fim-que-aop/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Java cada dia que passa fica com mais cheiro de naftalina</title>
		<link>http://www.kumpera.net/blog/index.php/2006/12/28/java-cada-dia-que-passa-fica-com-mais-cheiro-de-naftalina/</link>
		<comments>http://www.kumpera.net/blog/index.php/2006/12/28/java-cada-dia-que-passa-fica-com-mais-cheiro-de-naftalina/#comments</comments>
		<pubDate>Fri, 29 Dec 2006 00:55:56 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2006/12/28/java-cada-dia-que-passa-fica-com-mais-cheiro-de-naftalina/</guid>
		<description><![CDATA[
 Cada dia que passa eu fico mais convencido que Java precisa rumar para a aposentadoria. Diferente das pessoas que apostam no futuro da plataforma, também acredito que ela já mostra sinais de idade. Java é uma linguagem que já cumpriu seu papel, educou a grande massa sobre bom desenvolvimento OO e aumentou a exigência [...]]]></description>
			<content:encoded><![CDATA[<p>
 Cada dia que passa eu fico mais convencido que Java precisa rumar para a aposentadoria. Diferente das pessoas que apostam no futuro da plataforma, também acredito que ela já mostra sinais de idade. Java é uma linguagem que já cumpriu seu papel, educou a grande massa sobre bom desenvolvimento OO e aumentou a exigência que temos sobre o ambiênte de execução. Só que hoje estamos voltando a enfrentar grandes limitações por conta da linguagem.
</p>
<p>
 Vou primeiro falar da linguagem. Ela foi concebida para ser apenas um C++ melhor, mais simples e usavel; e C++ é uma gambiarra desde seu início.  Hoje os softwares são maiores e exigem melhores abstrações, que Java simplesmente não tem como oferecer. Está na hora de termos uma linguagem com suporte a recursos avançados, e já existe uma massa grande o suficiente de desenvolvedores capacitados para usá-las. Acredito que já podemos introduzir no mainstream suporte a closures, type classes e macros.
</p>
<p>
 Type classes permitem uma maior expressividade na hora de estabelecer contratos e os evoluir, isso é fundamental para tornar a linguagem escalavel, melhorar suas chances no &#8216;programming in the large&#8217;. Essa é, inclusive, a opinião de alguns pesquisadores, que criaram um <a href="http://homepages.cwi.nl/~ralf/JavaGI/">protótipo de linguagem</a> que funde Java 5 com type classes do Haskell. O resultado é um pouco confuso, mas é um ótimo exemplo de como avançar as capacidades da linguagem.
</p>
<p>
 Macros permitem modelar a linguagem da forma que melhor te servir. Seja criando atalhos para idiomas comuns, ou criando DSLs. São duas as técnicas usuais para se implementar macros: a primeira é como scheme implementa, via syntax case e quotations, que podem ser entendidos por um regexp e replace feitos em cima da estrutura da linguagem; a outra é via parser transformers, como Erlang implementa e, de certa forma, o Eclipse usa para fazer refactoring, nele você edita via um programa normal o AST de cada unidade de compilação durante as várias etapas do processo. Parser transformations permitem <a href="http://yarivsblog.com/articles/2006/10/11/recless-a-type-inferring-parse-transform-for-erlang-experimental/">experimentar com sintaxe da linguagem</a> facilmente. Porém hygienic macros ala scheme são mais faceis de usar e podemos ver isso no <a href="http://jse.sourceforge.net/">Java Syntactic Extender</a> que era uma pesquisa de como implementá-las no Java.
</p>
<p>
 Quanto a closures, acredito que não preciso argumentar a respeito, pois qualquer pessoa que brincou com Ruby, por exemplo, sabe do poder e versatilidade delas. Vários idiomas funcionais são impraticáveis de usar em linguagens orientadas a objeto sem closures. O <a href="http://gafter.blogspot.com/">Neal Gafter</a> discute isso a fundo em seu blog.
</p>
<p>
 Java tornou obrigatório um runtime que tivesse gerenciamento automático de memória e tipagem forte garantida em runtime. Hoje vejo que temos novos problemas que deveriam ser resolvidos pelo ambiente de execução, entre eles resiliência, melhor gerênciamento de recursos e maior suporte para programação paralela.
</p>
<p>
 Um programa Java que gera um OutOfMemoryError tem que ser reiniciado porque não tem como continuar e se recuperar de forma controlada &#8211; me digam o nome de um AS que lide bem com OOM. Em um sistema OLTP não temos como gerênciar o consumo individual de recursos de cada transação e isso é um elemento fundamental para garantir um bom SLA. Imaginem se pudessemos limitar o tempo de processamos e memória utilizada por cada requisição feita a um servlet container.
</p>
<p>
 Por fim, temos programação paralela, que é um belo inferno em Java: lidar com sincronização, deadlocks, livelocks, race conditions e o trabalho todo que é paralelisar o programa. Temos que gastar um enorme tempo fazendo tunning do tamanho dos thread-pools, das filas de eventos/mensagens e escolher bem as estruturas de dados. Agora se tivessemos, por exemplo, corrotinas com fork/join suportadas nativamente, ou ainda o modelo leve de processos de Erlang, programação paralela seria mais intuitiva, simples e seria mais facil extrair maior performance.
</p>
<p>
 Resumindo, acho que estamos no ponto que passa a ser realmente importante avançarmos a tecnologia utilizada. Java ainda resolve muito bem, mas eu vejo no meu dia-a-dia vários projetos que apanham por não ter mais expressividade na linguagem ou um runtime mais robusto, mais preparado para os novos desafios de hoje.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2006/12/28/java-cada-dia-que-passa-fica-com-mais-cheiro-de-naftalina/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>A relação entre I/O não bloqueante e continuations</title>
		<link>http://www.kumpera.net/blog/index.php/2006/11/07/a-relacao-entre-io-nao-bloqueante-e-continuations/</link>
		<comments>http://www.kumpera.net/blog/index.php/2006/11/07/a-relacao-entre-io-nao-bloqueante-e-continuations/#comments</comments>
		<pubDate>Wed, 08 Nov 2006 02:27:36 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2006/11/07/a-relacao-entre-io-nao-bloqueante-e-continuations/</guid>
		<description><![CDATA[
No meu artigo anterior sobre NIO e continuations em java
o Willian Mitsuda e o Felipe ficaram em dúvida da utilidade de utilizar continuations. A principal vantagem dessa técnica é poder programar utilizando multiplexação e programação seqüêncial juntas.


Vou dar dois exemplos de como ler linhas usando i/o bloqueante e não bloqueante, deles vou discutir quais os [...]]]></description>
			<content:encoded><![CDATA[<p>
No meu artigo anterior sobre <a href="http://www.kumpera.net/blog/index.php/2006/10/12/29">NIO e continuations em java</a><br />
o Willian Mitsuda e o Felipe ficaram em dúvida da utilidade de utilizar continuations. A principal vantagem dessa técnica é poder programar utilizando multiplexação e programação seqüêncial juntas.
</p>
<p>
Vou dar dois exemplos de como ler linhas usando i/o bloqueante e não bloqueante, deles vou discutir quais os pontos fracos e fortes, por fim vou mostrar como é possivel ter um modelo superior a ambos utilizando Continuations.
</p>
<p><code><br />
//1 I/O bloqueante:<br />
void readLines(Socket sock) throws IOException {<br />
    BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));<br />
    String str;<br />
    while ((str = br.readLine()) != null) {<br />
        System.out.println(str);<br />
    }<br />
}</p>
<p>//2 I/O não bloqueante:<br />
//faz o setup do channel, registra ele para leitura<br />
//quando o selector retornar o channel em questão, invocamos o método read de ChannelState.<br />
void readLinesSetup(SocketChannel channel, Selector sel) throws IOException {<br />
    channel.configureBlocking(false);<br />
    channel.register(sel, SelectionKey.OP_READ, new ChannelState());<br />
}</p>
<p>class ChannelState {<br />
    static final byte CR = 13;<br />
    static final byte LF = 10;</p>
<p>    boolean skipLF;<br />
    StringBuffer builder = new StringBuffer();<br />
    CharsetDecoder decoder = Charset.defaultCharset().newDecoder();<br />
    ByteBuffer buffer = ByteBuffer.allocate(1000);<br />
    CharBuffer cbuff = CharBuffer.allocate(1000);</p>
<p>    //retorna true se deve continuar lendo<br />
    boolean read(SocketChannel channel) throws IOException {<br />
        CoderResult cr = null;<br />
        int res;<br />
        do {<br />
            res = channel.read(buffer);<br />
            buffer.flip();<br />
            do {<br />
                cbuff.clear();<br />
                cr = decoder.decode(buffer, cbuff, res == -1);<br />
                cbuff.flip();<br />
                while (cbuff.remaining() > 0) {<br />
                    char current = cbuff.get();<br />
                    switch (current) {<br />
                    case CR:<br />
                        dumpLine();<br />
                        skipLF = true;<br />
                        break;<br />
                    case LF:<br />
                        if (!skipLF)<br />
                            dumpLine();<br />
                        skipLF = false;<br />
                        break;<br />
                    default:<br />
                        builder.append(current);<br />
                    }<br />
                }<br />
            } while (cr != CoderResult.UNDERFLOW);<br />
            //prepara o buffer para mais leituras<br />
            buffer.compact().position(buffer.limit()).limit(buffer.capacity());<br />
        } while (res > 0);<br />
        if(res == -1 &#038;&#038; builder.length() > 0)<br />
            System.out.println(builder.toString());<br />
        return res != -1;<br />
    }</p>
<p>    private void dumpLine() {<br />
        System.out.println(builder.toString());<br />
        builder = new StringBuffer();<br />
    }<br />
}<br />
</code></p>
<p>
Bom, como vocês podem notar, usando I/O não bloqueante da <b>muito</b> mais trabalho, já que precisamos lidar com a situação de apenas uma parte dos dados estar disponível. Vejam ainda que eu coloquei um exemplo super simples, usei StringBuffer em vez que acumular as instâncias de CharBuffer e não coloquei a lógica de reciclar buffer.
</p>
<p>
Vamos analisar o primeiro exemplo, ele exige que uma thread seja alocada para cada conexão, então acaba por limitar a escalabilidade do sistema, pois dificilmente vai aguentar mais que 500 sockets simultâneos antes do sistema operacional começar a entrar em parafuso. A vantagem fica por conta do código ser super simples e facil de testar.
</p>
<p>
Quanto ao segundo, podemos ver a lógica convoluta para lidar com a conversão para texto e como ter de suportar leituras parciais é dificil. No geral, todo sistema que utiliza NIO para ler dados acaba implementando uma máquina de estados para isso, esforço enorme, que é muito mais dificil de testar. Eu precisei de uma máquina de pilha e 19 estados para implementar o parsing apenas do header de requests HTTP. A complexidade se paga quando vemos a escalabilidade possivel quando usamos multiplexação, é perfeitamente possivel suportar dezenas de milhares de sockets desta forma.
</p>
<p>
Comparando as duas soluções vemos que I/O bloqueante é facil de desenvolver, mas não escala; enquanto I/O não bloqueante com multiplexação é extremamente escalavel, porém muito dificil de programar. O ideal seria conseguir combinar as duas de forma a ter um pouco das vantagens de cada modelo. Para nossa sorte, é possivel, basta usar continuations.
</p>
<p>
Usando continuations não deixamos de utilizar I/O não bloqueante, porêm nos é permitido esconder de uma maneira clara os problemas relacionados a leituras parciais: suspendemos a continuation até que os dados estejam disponíveis, de forma que o usuário possa programar assim como no exemplo 1, mas garantido uma maior escalabilidade. </p>
<p>
Alguém pode me questionar se o custo de dar suspend/resume de uma continuation não é semelhante ao de um thread-switch e se o consumo de memória não é alto. O custo do resume é pequeno, pois não precisamos fazer toda parafernália que um SO deve, depende apenas do suporte da linguagem; quanto ao consumo de memória, uma continuation não exige que sejam criadas várias estruturas com memória do kernel (recurso super limitado) e nem alocada uma pilha enorme &#8211; por padrão a JVM aloca 256k de memória para a pilha de cada thread.
</p>
<p>
Espero conseguir com esse artigo expor uma das muitas possibilidades que continuations nos permitem. Servidores muito mais escalaveis são um exemplo, outro muito interessante é o SeaSide, um framework web escrito em SmallTalk que as usa para gerenciar o estado do usuário.
</p>
<p>Update: O Felipe apontou um erro no texto, está corrigido. Valeu Felipe!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2006/11/07/a-relacao-entre-io-nao-bloqueante-e-continuations/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Java continuations e NIO, o casamento perfeito</title>
		<link>http://www.kumpera.net/blog/index.php/2006/10/12/29/</link>
		<comments>http://www.kumpera.net/blog/index.php/2006/10/12/29/#comments</comments>
		<pubDate>Thu, 12 Oct 2006 04:04:20 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[concurrency]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2006/10/12/29/</guid>
		<description><![CDATA[Eu estava quase perdendo as esperanças de conseguir utilizar NIO para um servidor. Sempre achei muito dificil programar utilizando um socket não-bloqueante, o parsing de qualquer protocolo um mais dificil é um inferno. Eu resolvi então experimentar escrever um servidor usando continuation-passing-style e o resultado foi supreendemente facil, intuitivo e escalavel.
Minha vontade de usar CPS [...]]]></description>
			<content:encoded><![CDATA[<p>Eu estava quase perdendo as esperanças de conseguir utilizar NIO para um servidor. Sempre achei muito dificil programar utilizando um socket não-bloqueante, o parsing de qualquer protocolo um mais dificil é um inferno. Eu resolvi então experimentar escrever um servidor usando continuation-passing-style e o resultado foi supreendemente facil, intuitivo e escalavel.</p>
<p>Minha vontade de usar CPS veio das minhas brincadeiras com Erlang, processos são tão leves nessa linguagem que me leva a acreditar que threads em user-land com scheduling (pseudo)cooperativo são a melhor receita para escalabilidade e facilidade de programação. Quem lembra do windows 3.1, vai me afirmar que cooperative threading é uma enorme roubada e eu concordo, que para aplicações desktop, não funciona bem. Agora pensando em web-application, que basicamente se resume a fazer pequenas tarefas e esperar um tempão pelas operações de I/O completarem, cada thread decidir quando pausar não soa ruim.</p>
<p>Bom, vou descrever um pouco a solução que eu adotei. Utilizei o commons-javaflow para suportar continuations em Java. A biblioteca ainda é experimental, mas já estavel e usavel o suficiente para brincar. O ruim é que você precisa brincar com classloading ou pos-processamento dos arquivos .class. Fora isso uso o feijão com arroz de io multiplexado. Que é manter um Selector para verificar a disponibilidade de todos os sockets e I/O não bloqueante para transmissão de dados.</p>
<p>A grande sacada de usar i/o não bloqueante e continuations é até que simples, sempre que uma operação falhar por não ter dados disponiveis (leitura), ou falta de buffer (escrita), você registra o socket junto ao selector e da yield na continuation (suspende a execução dela). Depois disso, quando a operação ficar disponível, você simplesmente retoma a continuation. Eu implementei um servidor de echo, o código que implementa isso no servidor se resume a:</p>
<p><code><br />
public void run() {<br />
    try {<br />
        String line;<br />
        while ((line = reader.readLine()) != null) {<br />
            writer.write(line);<br />
            writer.write("\n");<br />
            writer.flush();<br />
        }<br />
        socket.close();<br />
    } catch (Exception e) {<br />
        e.printStackTrace();<br />
    }<br />
}<br />
</code></p>
<p>O código parece o mesmo que se usarmos um socket normal e i/o bloqueante, de fato é, com a diferença que as classe de streams são customizadas. O código que se utiliza de continuations não é muito complicado, bem diferente de vários frameworks como mina ou seda, como mostro a seguir o método que faz a escrita usando NIO. O método current() retorna uma referencia a uma classe que controla a interface com o selector e o escalonador.</p>
<p><code><br />
public void write(byte[] b, int off, int len) throws IOException {<br />
    ByteBuffer buff = ByteBuffer.wrap(b, off, len);<br />
    while (buff.remaining() > 0) {<br />
        channel.write(buff);<br />
        if (buff.remaining() == 0)<br />
            break;<br />
        current().register(channel, SelectionKey.OP_WRITE);<br />
        current().ioSuspend();<br />
    }<br />
}<br />
</code></p>
<p>Eu ainda estou começando a bricandeira, ainda pretendo colocar um bom parser de HTTP para funcionar nesse esquema, algum driver opensource para banco de dados e, finalmente, file I/O assíncrono. A partir deste ponto já fica possivel realmente contribuir um sistema com essa tecnologia. Para quem ficou curioso, os links são: <a title="commons-javaflow" href="http://www.kumpera.net/uploads/javaflow.jar">commons-javaflow</a>   e meu <a title="exemplo" href="http://www.kumpera.net/uploads/continuations.zip">exemplo</a>. Para quem gostou, pode ter certeza que vem muito mais por ai.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2006/10/12/29/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Continuations, Java e NIO &#8211; fórmula explosiva</title>
		<link>http://www.kumpera.net/blog/index.php/2006/10/09/continuations-java-e-nio-formula-explosiva/</link>
		<comments>http://www.kumpera.net/blog/index.php/2006/10/09/continuations-java-e-nio-formula-explosiva/#comments</comments>
		<pubDate>Tue, 10 Oct 2006 02:34:44 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scalability]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2006/10/09/continuations-java-e-nio-formula-explosiva/</guid>
		<description><![CDATA[Resolvi esses dias experimentar a possibilidade de usar continuations em Java para implementar um servidor utilizando programação CPS (Continuation Passing Style). Posso dizer que o resultado foi supreendedor, não só foi simples escrever o código de suporte, mas como o commons-javaflow está em um estado bem usavel.
Eu implementei um servidor de echo, e o objetivo [...]]]></description>
			<content:encoded><![CDATA[<p>Resolvi esses dias experimentar a possibilidade de usar continuations em Java para implementar um servidor utilizando programação CPS (Continuation Passing Style). Posso dizer que o resultado foi supreendedor, não só foi simples escrever o código de suporte, mas como o commons-javaflow está em um estado bem usavel.</p>
<p>Eu implementei um servidor de echo, e o objetivo era que ele fosse muito escalavel, então queria que com uma thread apenas fosse possivel lidar com milhares de clientes. A saída era usar NIO, que leva a um estilo de programação muito complexo. Nesse ponto entram continuations, que me permite escrever uma casca sobre a api do java.nio de forma a fica super simples. Estou terminando de refatorar o código, mas ai vai como ficou o código que implementa o servidor de echo:</p>
<p><code>  public void run() {<br />
try {<br />
String line;<br />
while ((line = reader.readLine()) != null) {<br />
writer.write(line);<br />
writer.write("\n");<br />
writer.flush();<br />
}<br />
socket.close();<br />
} catch (Exception e) {<br />
e.printStackTrace();<br />
}<br />
} </code></p>
<p>Ném parece que estou usando Channels, Buffers e toda aquela parafernália. Assim que terminar de fazer uma limpesa no código, mostro o truque e, se der tempo, um benchmark usando threads e continuations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2006/10/09/continuations-java-e-nio-formula-explosiva/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Código fonte do meu artigo sobre escalabilidade e alguns comentários</title>
		<link>http://www.kumpera.net/blog/index.php/2006/09/19/codigo-fonte-do-meu-artigo-sobre-escalabilidade-e-alguns-comentarios/</link>
		<comments>http://www.kumpera.net/blog/index.php/2006/09/19/codigo-fonte-do-meu-artigo-sobre-escalabilidade-e-alguns-comentarios/#comments</comments>
		<pubDate>Tue, 19 Sep 2006 03:37:16 +0000</pubDate>
		<dc:creator>kumpera</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scalability]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.kumpera.net/blog/index.php/2006/09/19/codigo-fonte-do-meu-artigo-sobre-escalabilidade-e-alguns-comentarios/</guid>
		<description><![CDATA[Primeiro gostaria de agradecer todo feedback positivo que tenho recebido em relação ao artigo. Estou aqui disponibilizando o código fonte dele, ou explicar como ele está disposto e por fim vou fazer alguns comentários sobre o artigo.
O arquivo zip contem 5 diretórios: deps, versao-inicial, versao-replicacao, versao-particionamento e versao-caching. Em deps, você encontrará os jar que [...]]]></description>
			<content:encoded><![CDATA[<p>Primeiro gostaria de agradecer todo feedback positivo que tenho recebido em relação ao artigo. Estou aqui disponibilizando o <a title="Fontes do Artigos" href="http://www.kumpera.net/blog/wp-content/uploads/2006/09/artigo.zip">código fonte dele</a>, ou explicar como ele está disposto e por fim vou fazer alguns comentários sobre o artigo.</p>
<p>O arquivo zip contem 5 diretórios: deps, versao-inicial, versao-replicacao, versao-particionamento e versao-caching. Em deps, você encontrará os jar que são as dependências do projeto, eles contém tudo, inclusive a API de servlets. Os demais diretórios são quatro versões do mesmo site, cada um com recursos de escalabilidade distintos, eu recomendo ler na seguinte ordem, pois cada um constroi em cima do anterior:</p>
<ol>
<li>versao-inicial, sem nenhum dos recursos descritos no artigo, apenas o básico do sistema;</li>
<li>versao-replicacao, adicionei aqui o suporte a replicação master-slave;</li>
<li>versao-particionamento, particionei a tabela posts nessa versão; e</li>
<li>versão-caching, contempla suporte a caching local para o DAO Blog.</li>
</ol>
<p>Esses fontes estão disponíveis sob a licensa do MIT, que significa que você pode fazer qualquer coisa, menos me culpar se algo der errado.</p>
<p>Quanto ao artigo, acho que ficou faltando falar sobre tolerância a falhas, em um ambiente distribuido as chances de um servidor falhar é muito maior, por exemplo, o Mean Time Between Failure dos HDs SATA modernos gira em torno de 300mil horas, em um parque com 200 máquinas usando espelhamento (dois discos por servidor), vamos ter pelo menos um disco falhando por mês, com sorte. Esse assunto, porém, não foi abordado porque merece por sí só um artigo inteiro.</p>
<p>Eu gostaria de ter também discutido sobre o uso de caches distribuidos, como memcached, mas também é um assunto bem delicado, do qual não seria simples para incluir nos exemplos, já que a questão de resiliência e adaptabilidade seriam mais gritantes.<br />
Apesar desses dois pontos que gostaria de ter discutido melhor, acho que o artigo conseguiu seu objetivo (meu objetivo), que era abrir os olhos de quem o lê que escalabilidade não é responsabilidade exclusiva do servidor de aplicação e que não se trata de um assunto intangível.</p>
<p>Update: O Lucas me lembrou que esqueci de colocar um link para o arquivo, <a href="http://www.kumpera.net/blog/wp-content/uploads/2006/09/artigo.zip">use este aqui</a>, valeu Lucas!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kumpera.net/blog/index.php/2006/09/19/codigo-fonte-do-meu-artigo-sobre-escalabilidade-e-alguns-comentarios/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
