Archive for the ‘domain.driven.design’ Category

Domain-Driven Design é Simples: Basta Chamar DAOs de Repositórios

Thursday, May 22nd, 2008

Um fenômeno notado no Oriente e no Ocidente é a notável incapacidade de se entender o que raios é Domain-Driven Design. Na minha opinião isso é causado elo fato de que para chegar num nível onde DDD te ajuda você já precisa ter uma base formada e essa base não é comum. Eu vejo muitas pessoas tentando entender a solução quando na verdade elas deviam estar tentando chegar ao problema primeiro.

Uma das conseqüências deste comportamento é a síndrome do Padrão-de-Prata. Todo mundo sabe que Não existe bala de prata mas, hei, ninguém falou nada sobre padrões (ou frameworks, ou plataformas…) então, buscando respostas fáceis é comum se associar Domain-Driven Design aos padrões Entity, Repository, Value Object e amigos.

O que parece bem difícil de entender é que o ponto todo não é usar os padrões e sim porque você os usa. As técnicas dos padrões em si é muito antiga e o livro não traz nada de novo exceto sobre como utiliza-los para atingir o Domain-Driven Design. O que qualquer tópico no GUJ sobre o assunto (e mesmo na lista sobre Domain-Driven Design) não parece entender é que os padrões são um meio e não um fim.

Eu já repeti algumas vezes que você pode utilizar todos os padrões do Eric Evans e ainda assim não usar DDD. Nos últimos meses eu vivi um exemplo claro.

O cliente em questão é uma empresa de comunicação. Ela produz algo que você pode simplificar como um jornal de classificados. Os jornais em si são gerenciados e impressos por um sistema antigo e uma equipe de mais de 30 pessoas foi destacada para criar a versão online deste.

Como o sistema é antigo ele não oferece qualquer interface para conexão, logo a solução encontrada foi acessar o banco de dados diretamente. Como os dados continuam sendo inseridos pelo sistema antigo (e este não muda desde 1998) não existe muito problema nisso.

O projeto possui um time excelente, um dos grupos de pessoas mais capacitadas com quem já trabalhei, mas ainda assim não conseguiam andar. A velocidade da entrega das histórias estava bem abaixo do esperado e o nível de retrabalho era ridiculamente grande, mesmo com clientes on-site. Apos verificar que se a deadline não fosse cumprida eles teriam corte no orçamento chamaram consultores para avaliar a situação.

A primeira coisa que um consultor pensa quando chega num lugar desse é que eles não estão seguindo um processo ágil de verdade. É extremamente comum entrar numa empresa “Agile de carteirinha”e ver um processo que na verdade é composto por mini-waterfalls, tão comum que a solução default é mudar o processo. Não era o caso. O processo era legitimamente ágil, da análise de negócios à homologação, e a equipe, como disse, era excelente.

Apos alguns dias fazendo pair programming percebi uma coisa errada com o vocabulário. Era extremamente difícil entender conceitos simples da aplicação e cada reunião que se ia o vocabulário era diferente. Daí vamos analisar o caso melhor.

O banco de dados em questão, como era de se esperar numa aplicação legada, trazia um bando de regras de negocio embutidas em flags absurdos. O time fez um fabuloso trabalho criando um mecanismo que transformava dados do domínio antigo para o novo, formando um excelente Context Map.

Dentro do domínio o código era extremamente enxuto, fazendo uso de JPA e Spring para deixar o Domain Model apenas com regras de negocio. Eles usam Repositories como interfaces para DAOs que implementam a lógica JPA de maneira bem interessante.

Ainda assim a velocidade era ridícula. 5 pares e apenas 4 pontos por iteração(semanal). Após verificar que o problema não era nem o processo nem o código em si só restava continuar pareando para tentar ver o que estava acontecendo.

Um dia, após reescrever a mesma funcionalidade duas ou três vezes, meu par e eu saímos para um café na Starbucks. Enquanto conversávamos eu perguntei:

- Mas quando é que vocês vão começar a outra parte do sistema?
- Outra parte?
- Sim, a parte que substitui o legado…
- Ah. Não, não vamos.
- Não?
- Quer dizer, vamos sim mas ele não vai ficar muito diferente, na verdade para nós do sistema web a única diferença é que eles vão disponibilizar um web service ao invés do banco de dados…
- Mas vocês não vão mudar aqueles conceitos legados para o modelo novo?!?
- Conceitos legados? Aqueles não são conceitos legados, são os conceitos que nossa indústria usa. Se você parar de usar aqueles termos seus clientes não vão entender o que está falando…

E aí eu entendi o problema da comunicação. Na retrospectiva eu levantei um ponto e conversamos sobre o problema.

A coisa era bem simples, em verdade. Os usuários internos do sistema são vendedores. Quando você vende um anuncio você fala em estilos e estes estilos são padronizados nacionalmente. O sistema antigo, por pior que seja, tem os estilos e os outros conceitos editoriais modelados mas nós não tínhamos isso no sistema web. O nosso domínio, por mais bonito e bem-feitinho, foi criado pensando na melhor forma de disponibilizar dados na Internet e por isso o nosso modelo não falava a língua do usuário. Os usuários falavam os conceitos do modelo antigo e para entender o que eles diziam nós tínhamos que fazer todo o mapeamento para o que aquilo representava em código.

Com apenas algumas iterações para um grande release não há a menor possibilidade de mudar todo o domínio. A solução vai ser implementar as mudanças de maneira incremental, toda vez que código novo é escrito ou código antigo refatorado caminha-se para o novo modelo, que é algo parecido com o abaixo.

Este foi um exemplo real do que não é Domain-Driven Design. Todos os desenvolvedores desta empresa possuíam o livro do Evans nas suas baias, não existia BO ou VO no sistema e as Camadas eram bem definidas. Ainda assim a linguagem do código não era a linguagem do usuário e sem isso você pode até ter um modelo Orientado a Objetos de alta qualidade mas não tem Domain-Driven Design.

Entrevista sobre Domain-Specific Languages

Tuesday, January 29th, 2008

O Laércio Queiroz me entrevistou sobre DSLs. O resultado você vê no blog dele.

Expressividade no Código

Friday, December 28th, 2007

Um post no GUJ mais uma vez rende uma resposta maior do que se supunha. A thread em si é bastante útil mas existe muito ruído então vou tentar sumarizar:

Vocês pegam códigos que te faz passar horas e horas tentando entender o que está sendo feito? Valores que você nem imagina de onde estão vindo?

Eu sou muito ruim ou isso é normal?

E logo surge alguém sugerindo que deveria haver documentação. Existem casos onde documentação, seja JavaDoc, especificação funcional ou etc. é fundamental mas neste caso é diferente. JavaDoc, especificação textual e etc. devem ser uma fonte importante quando que está interessado nessa informação não vai lero código, é como reutilizar uma biblioteca ou um framework. Ninguém quer abrir o Spring para entender como utilizá-lo, precisamos de documentação para isso.

Um cenário completamente diferente é quando você recebe de presente um código já existente para dar manutenção. Neste caso o código tem que fazer sentido, tem que dizer algo. Tem que ser expressivo, mostrar suas intenções claramente.

NOTA: O trecho abaixo foi escrito direto no editor de texto, sem ajuda de compilador ou IDE. Por favor me corrijam.

Qualquer programador meia-boca sabe sua linguagem. Sabe o domínio dela. Veja o trecho abaixo:

abstract class A{
 public abstract int d(){
 }
}

class B extends A{

 int z= 0;
 int x=-1;

 public B(int z, int x){
  this.z=z;
  this.x=x;
 }

 public int d(){
   if(z==15) return x + x* 0.15;
   esle return x;
 }

}

Você entendeu muito bem, tenho certeza, que A é uma classe abstrata implementada por B. Que B tem um construtor que recebe dois inteiros, os armazena e usa numa computação simples com uma ramificação abaixo. Ótimo.

Imagine que você recebeu um email do seu usuário dizendo: “Precisamos fazer com que clientes do sexo feminino que comprem mais de R$1000,00 ganhem 10% de desconto.”. Tente implementar isso no código acima enquanto eu vou almoçar.

E aí, terminou? Sim, sim, claro que é impossível sem saber d que se trata. Então depois de procurar bastante você encontra no diretório onde fica a documentação do projeto um arquivo que pode te ajudar a entender. Após umas cinquenta páginas de diagramas de alto nível inúteis explicando tudo que acontece no container web você chega a uma descrição de algo como:

A classe A tem a lógica abstrata de uma venda. As vendas são sempre feitas de acordo com critérios específicos por isso existem classes que implementam vendas específicas. No momento (01/10/2003) só existe uma implementação, na classe B, que é a venda para uma pessoa física.

A primeira coisa que você pensa é: se desde 2003 ninguém precisou de outra implementação para que essa maldita classe abstrata? Mas ants de mexer no código precisamos entendê-lo, então vamos em frente.

O méodo e questão recebe três argumentos: a quantdade em reais vendida, o sexo da pessoa (segundo código vindo do mainframe na tabela ETXS32) e se a compra é casada ou não (um booleano).

De acordo com o caso de uso UC171 o sexo do comprador é utilizado para aplicar descontos.

TABELA ETXS32
15 -> masculino
22 -> feminino

Se a compra for casada o processamento é feito delegando para outra classe, mantendo o padrão Strategy, Composite e Adapter do Decorator. Note que o Chain of Responsibility do Bridge é usado com Visitors para passar as instâncias de Flyweight pelos Interpreters[…]

Após a sequência de buzzwords de padrões é bom parar. Acho que a informação necessária já está aí em cima e olha que não se passaram nem 4 horas de procura! Vamos lá: recebemos o valor, o sexo segundo um código numérico sem lóica que vêm de outro sistema. Também é passado um boolean.. cadê o boolean?

Procurando no histórico deste arquivo no CVS (poxa vida, eles ainda usam CVS!) você vê que no meio de 2005 alguém tirou o boolean de lá com um comentário ‘Removido compra casada. Ninguém usa isso e ninguém entende isso. Ninuém vai sentir falta’. Acho que a pessoa estava correta mas ela esqueceu que existem uns 300 documentos que precisam ser revistos porque todos fazem referência a esta tal venda casada, do caso de uso, diagrama de domínio até diagrama de deployment. Cada mudança simples implica em editar 300 documentos… provavelmente mais tempo atualizando a tal documentação que o código… dá pra culpar o desenvolvedor?

Bom, agora você entende o que o código faz ao menos. Ele está aplicando um desconto de 15% para homens, você não conseguiu achar isso no caso de uso mas se ninguém está reclamando em produção é porque deve ser assim mesmo. Amanhã (afinal, você perdeu o dia inteiro hoje na ‘documentação’ do sistema) você faz a mudança.

Novo dia e você está pronto para alterar este código. Hmm… alterar pode ser muito rápido e sujo ou devagar e bem feito. Como disse o Uncle Bob recentemente sujo nunca é rápido então você opta pelo caminho com mais qualidade (e mais ético).

Como desenvolvedores profissionais escrevem testes (e gerar você deve começar por aí. Você sabe muito pouco sobre este sistema e o teste vai te dar alguma garantia que a menos esta pequena parta que está mexendo vai continuar funcionando após suas modificações. Vamos lá:

class TestVenda extends TestCase{
 public void testDeveAplicarDescontoSeSexoDoCompradorForMasculino(){
  B vendaParaUmHomem = new B(15, 100);
  assertEquals("Valor final sofreu 15% de desconto", 85, vndaParaUmHomem.d());
 }

 public void testDeveNaoAplicarQualquerDescontoSeVendaNaoCaiEmNenhumaPromocao(){
  B vendaParaUmHomem = new B(9999, 1);
  assertEquals("Valor final intacto", 1, vndaParaUmHomem.d());
 }
}

Os testes executam. Agora vamos alterar um pouco esta classe, pensando no pobre coitado que for mexer nela após você. Vamos começar agregando nomes mais expressivos:

abstract class VendaAbstrata{
 public abstract int vender(){
 }
}

class Venda extends VendaAbstrata{
 static final int NAO_INFORMADO = -1;
 static final int MASCULINO = 15;
 static final int FEMININO = 22;

 int sexoDoComprador= NAO_INFORMADO;
 int valorDaCompra=-1;

 public B(int sexoDoComprador, int valorDaCompra){
  this.sexoDoComprador=sexoDoComprador;
  this.valorDaCompra=valorDaCompra;
 }

 public int vender(){
   if(sexoDoComprador==MASCULINO) return valorDaCompra - valorDaCompra* 0.15;
   esle return valorDaCompra;
 }

}

Já está bem melhor, não? Compare com a primeira versão do código Os testes passam? Então é hora de commitar (eu acho esse neologismo horrível mas alguém sugere algo melhor?).

Vamos para o segundo round: pequeno refactoring. Já é possível fazer a alteração neste código mas anda temos tempo para deixá-lo um pouquinho mais legível, mais claro, mais expressivo. Vamos alterar:

abstract class VendaAbstrata{
 public abstract int vender(){
 }
}

class Venda extends VendaAbstrata{
 static final int NAO_INFORMADO = -1;
 static final int MASCULINO = 15;
 static final int FEMININO = 22;

 int sexoDoComprador= NAO_INFORMADO;
 int valorDaCompra=-1;

 public B(int sexoDoComprador, int valorDaCompra){
  this.sexoDoComprador=sexoDoComprador;
  this.valorDaCompra=valorDaCompra;
 }

 public int vender(){
   int valorFinalDaCompra = aplicarDescontosSobreValorDaCompra();

   return valorFinalDaCompra;

 public int aplicarDescontosSobreValorDaCompra(){

  int valorComDesconto= valorDaCompra;

  if(sexoDoComprador==MASCULINO)
   valorComDesconto = descontarPorcentagem(15, valorDaCompra);

  return valorComDesconto;
 }

 public int descontarPorcentagem(int porcentagem, int valorOriginal){
  return valorOriginal * (porcentagem / 100.0);
 }

}

Agora que tal esta versão do código + teste unitário contra a versão antiga + trezentos documentos e especificações? A implementação da regra nova ficou fácil? Acho que sim, tanto que deixo como exercício ao leitor, bem como algumas dezenas de refactorings que vão deixar o código acima decente.

A resposta curta para a thread do GUJ é: geralmente o problema não é seu mas de quem escreveu o código.

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

-Martin Fowler, “Refactoring: Improving the Design of Existing Code “

Arquiteturas Simples Duram Mais

Wednesday, October 24th, 2007

Um amigo outro dia me perguntou que tipo de arquitetura eu usaria num caso bem peculiar. Basicamente ele foi encarregado de definir a arquitetura corporativa de um grande banco, ou seja: definir hoje a forma como aplicações serão construídas pelas próximas décadas. Basicamente ele vai se ro cara que vai ser xingado por algumas centenas de programadores nos próximos tempos, não importa que arquitetura escolha.

Há poucos dias atrás falamos aqui sobre arquiteturas de referência e seu efeito danoso. Geralmente quando alguém tem à frente um desafio desse ele logo pensa em um modelinho que mostra obriga o uso de uma meia dúzia de frameworks e padrões (clássico moderno: Struts/JSF e JPA, clássico vintage: Struts 1.1 e EJB/DAO). Para melhorar ainda é incorporado um conjunto de classes “utilitárias” feitas com práticas que talvez tenham servido para um projetinho piloto mas hoje em dia só atrapalham.

Ainda assim uma arquitetura corporativa é algo interessante. Quando empresas grandes não possuem uma macro-arquitetura acabam crescendo de maneira desordenada e criando dezenas de aplicações redundantes e gambiarras de integração entre sistemas. Note no entanto que uma arquitetura corporativa não é uma arquitetura de referência, a arquitetura corporativa não fala sobre como implementar aplicações mas sim provê guias sobre como integrá-las, define as relações previstas em no ecossistema que é uma grande empresa.

Quais são as melhores macro-arquiteturas que você conhece? Eu consigo pensar em algumas: Apache, UNIX, World Wide Web… Nestes ecossistemas aplicações novas surgem, são alteradas e morrem todos os dias há décadas, um sistema criado com a tecnologia mais recente de 2007 vai rodar tranqüilamente neste ambiente. Por quê?

Porque estas arquiteturas se baseiam em primitivas e contratos, não em especificações rígidas. Criar um módulo para o Apache , um programa para rodar em UNIX ou uma site é basicamente criar um programa de computador em uma das plataformas suportadas que obedeça a um contrato.

Uma boa arquitetura corporativa vai definir algumas políticas e contratos para a aplicação se relacionar com o meio-ambiente e só isso. No caso do banco, poderíamos definir que uma aplicação deve disponibilizar via uma interface POX/REST seus WebServices, que ela deve utilizar a API do Mogile FS para guardar dados em disco, que cache deve ser feito utilizando a API do memcached.

E se o arquiteto quiser sair do padrão? Ótimo, saia, mas ele deve oferecer compatibilidade com o ambiente.

E se eu já tiver comprado um sistema que faz WebServices via SOAP? Eu preciso criar um meio de disponibilizar estes serviços via POX/REST também. Pode ser uma adaptador simples, um ESB, o que quer que seja. É como quando você compra um equipamento eletrônico com tomada americana, você não vai mudar uma tomada na sua casa para o padrão exótico, vai é comprar o adaptador necessário para plugar ele nas tomadas do seu ambiente.

Mas e se não precisarmos de filesystem distribuído? E se já estivermos utilizando uma solução de cache que faz mais sentido nesta aplicação?

Ótimo, use. O uso de filesystem X, cache Y, banco de dados Z deve ser um guia. Toda vez que alguém precisar de uma solução de cache, filesystem, etc. ele olha o guia da empresa, se não servir ele usa algo que sirva. O que importa é que o uso fique encapsulado no sistema. Imagine que ao invés do Oracle 10g eu resolva usar um MySQL na minha aplicação. Está ótimo mas eu devo manter essa peculiaridade interna à minha aplicação. Os outros sistemas que vierem a se comunicar com o meu não devem precisar saber sobre a existência deste banco, eu não posso usar este banco para comunicação entre aplicações (o que já é uma coisa péssima para se fazer de qualquer forma).

O que importa é:

  1. O arquiteto tem liberdade para resolver seu problema da maneira mais adequada
  2. O novo sistema é compatível com o meio-ambiente

Para ser um bom arquiteto não é necessário ter tanta experiência assim, basta saber olhar os casos de sucesso e aproveitar o que funciona. Geralmente as técnicas utilizadas nestas arquiteturas são também catalogadas como Padrões Arquiteturais em livros. Um bom arquiteto tem que ser um ávido leitor de livros e de código.

Conexão Java 2007

Tuesday, October 23rd, 2007

Mais um ano vai, outro ano vem e o Conexão Java está aí. Este é certamente o evento mais descolado da comunidade Java do Brasil.

O CJ é um grande encontro entre as pessoas que participam em fóruns como o GUJ, o PortalJava e o RioJUG. O foco do evento são os mini-cursos que agem na formação de novos profissionais. Bem, formação não exatamente, ninguém sai de um curso de meioa dúzia de horas especialista em nada mas é uma boa oportunidade de ter contato mão-na-massa com algumas tecnologias e técnicas.

Este ano a estrela do evento é ninguém menos que Carlos Villela. Radicado em Londres pela ThoughtWorks há… bem, há alguns anos… o cv vem falar de algo bem atual: o declínio dos arquitetos monoglotas.

Também teremos algo um pouco diferente. Possivelmente deve haver um repeteco da minha palestra sobre arquitetura do JustJava 2007 (infelizmente sem o Paulo que vai estar de férias) mas enquanto isso é confirmado ficamos com mais uma atração: Oficina do Arquiteto.

Essa é uma idéia meio maluca que acabamos de fechar, vai funcionar mais ou menos assim: alguém traz uma arquitetura -seja de um projeto existente, livre ou de uma empresa, ou desenhado na hora- e nós debatemos esta. Na conversa vão sobrar padrões arquiteturais, guidelines e uma boa dose de bate-papo sobre o que nós, arquitetos, estamos fazendo por aí. Se você já tiver alguma idéia me adiante por email para organizar melhor as coisas, eu vou preparar algumas arquiteturas clássicas para usarmos quando não houver nenhuma na roda. A idéia é bem simples: debate, informação e diversão.

Adaptação de Linguagens

Thursday, October 18th, 2007

Mais um texto no fragmental.tw, desta vez algo mais genérico sobre modificações em linguagens. Eu ando lendo bastante sobre linguagens embutidas em outras (DSLs Internas) e outras formas de modificação de linguagem como Fluent Interfaces. É bem complicado chegar à qualquer conclusão em temas tão abstratos mas a experiência no uso destas técncias no dia-a-dia e no laboratório me mostraram que existem diferenças entre as formas de alterar uma linguagem. Em Language-Oriented Programming você cria linguagens, com Fluent Interfaces não.

Bom, mais sobre isso em Language Adaption.

Anotações sobre Language-Oriented Programming (LOP)

Friday, October 12th, 2007

Como alguns sabem eu tenho um blog em inglês onde o foco é na minha linha de pesquisa atual: Domain-Specific Languages e Language-Oriented Programming. Eu venho psotando sobre minhas experiências brincando com este “novo” paradigma e acabo de postar o rascunho de um primeiro artigo sobre o tema. Comentários são mais que bem-vindos.

.Net: Princípios OO e Alt.Net

Wednesday, October 10th, 2007

Duas rapidinhas sobre Microsoft .Net:

  1. Já está nas bancas a nova edição da Mundo .Net (#5) com mais um artigo meu na coluna sobre arquitetura. Desta vez o foco são princípios de Orientação a Objetos. O artigo é bem genérico eu recomendo que mesmo programadores de outras plataforma dêem uma olhada.
  2. Martin Fowler publicou uma ótima análise do que pode ser o movimento mais interessante dentro da plataforma .Net: o movimento alt.net.

JustJava 2007 (Upped)

Monday, October 8th, 2007

Update: Enfim o Paulo publicou.

A palestra com o paulo foi sensacional. Muita gente me perguntou ao final da palestra qual minha relação com a Caelum, se sou instrutor de lá ou coisa do tipo. Bem, não :)

Palestra

Além de ser amigo do pessoal da empresa eu acredito fortemente na proposta de trabalho da Caelum, mas não tenho nenhum vínculo empregatício, comercial ou que quer que seja com eles.

Eu simplesmente acredito que o nível de treinamento que alguém obtém lá é bem superior ao treinamento pasteurizado dado pelos centros de treinamento que eu conheço. A palestra em si foi prova disso, nós falamos sobre tecnologias e técnicas que não são vistas nos ‘cursos de arquitetura’ normais e sobre como as tecnologias que de fato fazem parte do programa destes cursos quase sempre é antiquada e/ou inadequada. É uma empresa que consegue sair do commodity que é treinamento Java hoje em dia e trazer algo de valor, geralmente por um preço muito mais acessível.

Caelum

Os slides devem estar disponíveis no site da Caelum em breve.

Ruby “ou” Rails?

Tuesday, October 2nd, 2007

Esse post no GUJ me fez pensar sobre a melhor maneira de absorver algo como o Rails. Rails é uma plataforma de desenvolvimento altamente produtiva e boa parte da produtividade vem do fato de que não é preciso abstrair um domínio na linguagem.

Desenvolvimento de aplicações web é um domínio que inclui diversos conceitos e abstrações. Vejam por exemplo uma sessão web. Se uma pessoa ler sobre o protocolo HTTP em si vai perceber que não existem sessões, o protocolo não mantém estado entre as requisições. Para burlar este problema nós utilizamos cookies ou URIs especiais para informar ao servidor o ID da sessão do cliente. Este é um conceito.

Em Java (ou outra plataforma parecida) vamos abstrair a sessão em uma classe. É desta forma que trabalhamos em Java: criamos classes para representar os conceitos do domínio.

O problema é que até conhecer o suficiente para utilizar de maneira adequada esta abstração na forma de classe você precisa conhecer o que é uma classe e todos os conceitos derivados desta. Basicamente não se consegue criar algo razoável sem saber um mínimo de programação orientada a objetos.

E como Rails resolve isso? Rails abstrai boa parte destes conceitos na linguagem. Ruby é uma linguagem OO e é possível representar a sessão da mesma maneira que se faz em Java mas este não é o meio utilizado em Rails e esta forma de representar as coisas é seu maior diferencial.

Uma sessão em Rails está embutida implicitamente dentro do controlador. Trabalhar com elas é muito simples, para efeito de comapração é como se seu controlador em Java herdasse uma classe que possuísse o objeto que representa a session (que tem a mesma interface que um Map) como atributo protected. Exceto que o acoplamento gerado para acessar a session da classe-mãe em Ruby é muito fraco enquanto em Java seria enorme (na verdade provavelmente a melhor opção em Java seria um método e não um atributo. Em Ruby estes conceitos são bem mais flexíveis) é mais uma questão de filosofia do framework do que de linguagem utilizada em si.

Apesar da polêmica se é ou não uma Domain-Specific Language, Rails é um exemplo claro de Language-Oriented Programming. Neste paradigma de programação (praticado em Lisp desde…sempre!) a linguagem utilizada é modificada e estendida para acomodar os conceitos do domínio. No caso do Rails a linguagem Ruby ganha características que permitem ser estupidamente simples criar uma aplicação web.

E o que isso representa para quem está aprendendo? Eu diria que existem 2 tipos de pessoas que desenvolvem em Rails: desenvolvedores e desenvolvedores de aplicações web. Qual a diferença?

Desenvolvedores aos quais me refiro são desenvolvedores profissionais de software (analistas, programadores, hackers, o que quer que você queira chamar). São pessoas que se dedicam profissionalmente a entender as milhões de coisas que são importantes no desenvolvimento de projetos de software. Utilizar Rails para eles é apenas se beneficiar de uma boa ferramenta que implementa conceitos de MVC, ActiveRecord, LOP, Domain Model, Meta-Programação, convention over configuration, JavaScript, etc.

Para eles eu recomendo primeiro aprender Ruby. Rails sem Ruby é exotérico demais, você não vai entender como é possível que sua classe ganhe métodos conforme precisa deles e outras coisas estranhas (principalmente se você vem de Java ou C#).

O outro estereótipo, o desenvolvedor de aplicações web, geralmente é umc ara com menos conhecimento técnico, menos interesse em construção de software e habilidades em outras áreas. Pode ser o designer que quer fazer seus projetos com relativa independência de programadores, pode ser o cara que tem um estalo e uma brilhante idéia para uma aplicação Web 2.0 que o fará milionário… O ponto é que desenvolver software para este cara é só uma parte do processo, o meio, e não o fim. Este cara não precisa aprender tantos conceitos, ele pode se basear em receitas prontas e correr para um técnico quando precisar de algo mais heavy-metal. Para este cara eu recomendo aprender diretamente Rails, eventualmente ele pode melhorar Ruby e programação em geral com a evolução do seu projeto.

Interessante notar o conceito que funciona com Rails e com desenvolvimento baseado em Domain-Specific Languages (sendo Rails uma ou não): o usuário não vai desenvolver o software sozinho. Ele se baseia em algo construído para ele por um técnico (seja o framework Rails ou uma DSL) mas não consegue sair muito daquele escopo específico e limitado sem acompanhamento profissional. Este é o objetivo dos pesquisadores de DSLs neste momento.