DSLs não são para gerentes

Por Fabio Kung em 30/12/08

Já vi e ouvi de muitas pessoas e em muitos lugares que Domain Specific Languages são uma ótima ferramenta para deixar o código tão simples de escrever, tão legível e tão parecido com uma linguagem natural (português, inglês), que serve para que não programadores possam escrever parte do código.

A idéia é que o próprio gerente, cliente, analista-não-programador, ou alguém com este tipo de perfil não técnico escreva as regras de negócio em uma linguagem muito parecida com a linguagem natural, eliminando a necessidade de programadores e reduzindo os custos.

Este pode até ser um uso possível e interessante para DSLs, mas infelizmente, DSLs não tem a mínima pretenção de serem linguagens naturais. Isso seria muito ambicioso para o escopo de uma línguagem específica para um domínio. DSLs não foram criadas para ensinar inglês ou português aos computadores.

Existe uma outra forma interessante de usar DSLs, pela qual tenho preferência declarada e felizmente, parece haver uma convergência para esse meio de aplicá-las. O objetivo é fazer com que o código fonte do programa fique mais próximo do problema sendo resolvido. DSLs como forma de aumentar a expressividade do código. Dave Thomas e Andy Hunt tratam desse assunto no famoso livro The Pragmatic Programmer, sob o nome de Program Close to the Problem Domain.

Em seu livro Domain Driven Design, Eric Evans fala muito sobre a importância de todos os envolvidos no desenvolvimento do sistema usarem a mesma linguagem, que ele chama de linguagem ubíqua (Ubiquitous Language). Desta forma, conseguimos diminuir o abismo que existe entre programadores e especialistas no negócio, facilitando comunicação e diminuindo os clássicos problemas do “telefone sem fio”.

problemas de comunicação

problemas de comunicação

DSLs são uma ferramenta para o desenvolvedor. Uma das formas de inserir os termos da linguagem ubíqua no código fonte, de fazer o código refletir o problema que está sendo resolvido. Desta forma, programadores podem fazer com que o código fique auto explicativo e auto documentado. O próprio código se explica; é a documentação de si próprio.

Ando tão “viciado” nessa forma de escrever código, perseguindo expressividade, fazendo com que o próprio código se explique, que em muitos casos a DSL surge naturalmente depois de algumas refatorações. Aqui, Behavior Driven Development (e principalmente o ciclo red-green-refactor) tem ajudado muito, mas esse assunto fica para um próximo post.

Uma técnica simples para aumentar a expressividade é evitar escrever comentários no meio do código. O tradicional “comentário é mal cheiro no código” (code smell).

Ao invés de escrever o comentário, simplesmente extraia o código que estaria sendo comentado em um novo método. O nome deste novo método deve ser exatamente o mesmo que iria ser escrito no comentário.

“You’ve written the code, now you have to write about the code. In a perfect world, you’d never have to write comments for this purpose: the code will be expressive enough that someone who reads it will understand it. Two things help achieve this result: expressive, readable languages and the composed method pattern.” — Neal Ford

Neal Ford diz que linguagens expressivas e legíveis ajudam a eliminar a necessidade de explicar o código. Geralmente, linguagens mais modernas são mais expressivas do que as mais antigas como Assembly. Mesmo usando linguagens mais modernas, ainda podemos usar nossa ferramenta de programadores preferida: DSLs para criar a linguagem com a expressividade adequada para resolver o problema!

Essa técnica tem o seu preço, claro. É sempre uma troca, uma questão de vantagens e desvantagens; clássico trade-off. Projetar uma DSL pode dar mais trabalho no início, já que precisamos pensar em como desejamos escrever o código (Language Oriented Programming) e pode exigir alguns ciclos extras de refatoração até o código chegar num nível bom de expressividade.

O que tenho percebido é que esse possível esforço extra no desenvolvimento (nem está comprovado cientificamente que ele existe [1]), costuma compensar mais para a frente, dada a facilidade de ler e entender o código, associado ao fato dos programadores estarem naturalmente o tempo todo usando a linguagem ubíqua.

Além disso, diminui bastante a necessidade da famosa pilha de documentação extra que precisa ser escrita em muitos projetos. Na maior parte deles isso tudo é até escrito quando o software já está pronto! Não estou querendo dizer que manuais não devam ser escritos, mas boa parte desse esforço extra de documentação pode ser reduzido. Principalmente o esforço relacionado a documentação que tem como alvo outros desenvolvedores e pessoas que possivelmente darão manutenção no código.

Assim como os testes durante o desenvolvimento, podemos encarar o uso de DSLs como um investimento, e não tempo extra no desenvolvimento.

Feliz ano novo a todos!


1. eu até acho que fico mais produtivo escrevendo código desse jeito.

Caelum Porto Alegre e Cursos de Verão

Por Paulo Silveira em 15/12/08

Cursos de VerãoNada melhor que aproveitar o verão, as férias na faculdade e/ou na empresa para dar um salto na sua carreira, não? Pensando nisso, a Caelum lançou a campanha dos Cursos de Verão 2009, com condições especiais para pacotes de cursos em Janeiro, apoio total aos alunos de outras cidades e maior disponibilidade de cursos e turmas que nos outros meses.

Entre em contato conosco para saber mais informações e fazer sua reserva. Aproveite o mês de Janeiro e faça os cursos mais respeitados do mercado!


Caelum Porto AlegreA Caelum em Porto Alegre agora não é mais apenas uma parceria, e sim a própria Caelum! A Wansoft, nossa parceira, cresceu e agora com vários funcionários está se dedicando a consultoria e desenvolvimento. E a própria Caelum está administrando e executando os treinamentos na capital gaúcha.

Dada a alta demanda de Janeiro nos cursos integrais, alguns dos nossos instrutores de São Paulo estarão em Porto Alegre ministrando diversos cursos. A Caelum POA está localizada na Av. Cristovão Colombo, 1789, cj. 501. Entre em contato para mais informações ou veja o mapa detalhado.

Falando em Agile 2008 - Scrum na Globo.com: Derrubando Mitos

Por Paulo Silveira em 03/12/08

Boa notícia: já estamos disponibilizando uma palestra do Falando em Agile 2008!

Quem fala é Danilo Bardusco, gerente de desenvolvimento de aplicações Web na Globo.com, com a palestra entitulada “Scrum na Globo.com: Derrubando Mitos“. Aproveitem!

Segurança em aplicações Web: XSS

Por Sérgio Lopes em 25/11/08

Bons tempos aqueles quando os computadores não eram ligados em rede, não existia Internet e as aplicações eram todas Desktop. Em tempos de Web 2.0, Mashups e Aplicativos Web, as dores de cabeça são absurdamente maiores assim como o número de aplicações expostas a ataques. Seu sistema é seguro?

Ultimamente tenho notado como poucas pessoas se preocupam de verdade com segurança na web, ou pior, como os desenvolvedores desconhecem os problemas envolvidos na programação pra web. É preciso entender como o HTTP funciona, como os browsers funcionam, o que o JavaScript é capaz de fazer e até as implicações de segurança dos ingênuos HTML e CSS.

Pensando nisso, resolvi escrever uma série de artigos sobre segurança em aplicações Web e começo falando do famoso Cross-site Scripting, carinhosamente chamado de XSS.

Samy is my hero

Em 2005, Samy Kankar, insatisfeito com sua pequena quantidade de amigos no MySpace, escreveu um worm (depois batizado de JS.Spacehero) para turbinar sua lista de amigos.

O script rodava quando alguém simplesmente visitava o perfil de Samy, adicionava o visitante à sua lista de amigos e colocava no perfil do infectado a frase “samy is my hero“. Além disso, o script se propagava para o perfil do usuário infectado, possibilitando que esse infectasse mais pessoas.

Em menos de 20h, Samy tinha um milhão de amigos e o MySpace foi tirado do ar. A aventura ingênua de Samy (com a falha que ele descobriu, poderia ter feito algo bem pior) foi narrada de forma muito cômica no site dele. E, em 2007, lhe rendeu uma condenação nos tribunais com direito à multa, serviço comunitário e afastamento de computadores.

Mas o que o bravo Samy descobriu?

Não confie nos inputs de seus usuários

O MySpace é conhecido pela papagaiada permitida nos perfis dos usuários. Diferente do Orkut, por exemplo, o dono do perfil do MySpace pode mudar praticamente todas as características visuais do site (fundo, cores, letras, imagens, vídeos etc). Para isso, o MySpace aceita que o usuário digite HTML e CSS para personalizar sua página, mas com limites para a coisa não virar zona.

O que Samy fez? Descobriu uma falha no filtro do MySpace que limita os inputs e conseguiu colocar em seu perfil um código JavaScript que seria executado por cada visitante do seu perfil. Com técnicas de Ajax e um pouco de tempo livre, Samy fez um JavaScript que executava as ações descritas acima.

XSS - Cross-site scripting

Um ataque XSS é aquele que permite a injeção de scripts no site atacado, em geral por meio de algum campo de input do usuário. Note que um ataque XSS é um ataque ao usuário do site e não ao sistema servidor em si. Isso porque o script injetado nunca será executado no servidor, mas sim nos navegadores dos clientes que visitarem a página infectada.

A regra de ouro de qualquer sistema com input de usuários é que não devemos confiar jamais naquilo que o usuário digitou. Além de XSS, podemos ser alvos de muitos outros ataques, como SQL Injection, injeção de parâmetros e outros (quem sabe abordamos num artigo futuro).

Embora pareça simples, a OWASP (Open Web Application Security Project) diz que nada menos que 9 em cada 10 sites estão vulneráveis a esse tipo de ataque. Anualmente, eles fazem um estudo das 10 falhas mais encontradas na Web, e no ano passado, XSS foi o campeão.

Como se proteger

Todo input do usuário deve ser sanitizado antes de qualquer coisa. Isso significa passar algum tipo de filtro que consiga remover tags potencialmente perigosas.

Se o seu site não deve ser customizado pelo usuário de nenhuma forma e o input dele deveria ser texto puro, basta remover toda e qualquer tag encontrada. Mas o caso mais complicado (aqui entra o MySpace) é quando você deseja permitir certas tags (negrito, por exemplo) e qual abordagem seguir para filtrar as tags não desejadas.

É considerado, hoje, total insanidade mental e causa da maioria das vulnerabilidades de XSS, tentar escrever esse filtro de input sozinho. Ele é extremamente complexo. Pense no caso simples, aquele onde não desejamos aceitar nenhuma tag. 99% das pessoas pensariam que o código abaixo faz um excelente trabalho:
String limpo = input.replaceAll("<", "").replaceAll(">“, “”);

É um código Java que transforma:
<script>alert('XSS');</script>

…nisso (claramente inofensivo):
scriptalert('XSS');/script

E o código abaixo então?
+ADw-script+AD4-alert('XSS')+ADw-/script+AD4-

Esse código é executado por qualquer navegador atual usando codificação UTF-7. E obviamente aqueles nossos “replaceAll” não resolvem o problema. Há centenas de outros exemplos que usam encodings estranhos, html entities, carateres especiais no meio etc.

E isso com o objetivo de tirar todas as tags da frente. E quando queremos que algumas sejam aceitas? Quais tags são seguras? E os atributos nessas tags? Até um <img> com atributo src apenas está vulnerável se não tomarmos cuidado.

Moral da história: fazer os replacezinhos na mão é insano. Não fazer nada a respeito é suicídio.

Arrumando o problema

Precisamos sanitizar o input dos usuários e precisamos de algo pronto que faça isso. Há trocentos projetos por aí que fazem esse tipo de serviço. Em especial, o AntiSamy do pessoal da OWASP que tem versões em Java e .Net. A Microsoft tem uma API anti-XSS para .Net. Há ainda o HtmlPurifier para PHP, o sanitize do Ruby on Rails e muitos outros em outras plataformas.

O AntiSamy é bastante customizável, permitindo que definamos níveis diferentes de purificação através de regras em um XML. Ele ainda é capaz de mostrar mensagens de erros amigáveis para os usuários. Usá-lo é bem simples:


AntiSamy as = new AntiSamy();
CleanResults cr = as.scan(suspeito);
String limpo = cr. getCleanHTML()

É considerada boa prática também purificar a saída dessas strings, por precaução. Com JSP, isso é muito fácil:

<c:out value="${suspeito}" escapeXml="true" />

Conclusão

XSS é um problema real e muitas aplicações estão vulneráveis. Samy atacou o MySpace em 2005 e conseguiu 1 milhão de amigos. A busca do Google tinha as falhas do UTF-7 comentadas acima em 2005. Apoiadores do Firefox sequestraram as maiores comunidades do Orkut em 2005 e mudaram os logos para o do Firefox. Eleitores de Hillary Clinton redirecionavam visitantes do site de Barack Obama para o site de sua adversária nas prévias da eleição americana em abril desse ano. E milhares de outros casos públicos.

Proteja sua aplicação!

Referências

Mirror DSL: facilitando o uso da API de reflection

Por Jonas Abreu em 17/11/08

No último domingo foi feito o primeiro release público do projeto Mirror (versão 1.2).

O Mirror é um projeto que tem por objetivo facilitar o uso da Java Reflection API, removendo boa parte da burocracia (como as diversas checked exceptions que são lançadas) e utilizando uma DSL para melhorar a legibilidade do código.

Com essa remoção de burocracia e a DSL, é possível transformar o seguinte código:

Field toSet = null;
for (Field f : target.getClass().getDeclaredFields()) {
    if (f.getName().equals("field")) {
        toSet = f;
    }
}
if (toSet != null && ((toSet.getModifiers() & Modifier.STATIC== 0)
        && ((toSet.getModifiers() & Modifier.FINAL== 0)) {
    toSet.setAccessible(true);
    toSet.set(target, value);
}

em algo mais legível e expressivo:

Mirror.on(target).set().field("fieldName").withValue(value);

Atualmente o Mirror possui suporte para lidar com as operações reflectivas mais comuns (como instanciar objetos, invocar métodos, ler ou escrever atributos, etc). Ele foi desenvolvido por Adriano Almeida, Diego Feitosa e eu, todos consultores/instrutores aqui da Caelum, enquanto enfretavamos problemas comuns no dia a dia.

Esperamos que possa ser útil para vocês também!