Design Patterns em Scala – Parte 2: Decorator

No post anterior dessa série de Design Patterns falamos um pouco sobre maneiras diferentes de se implementar o pattern Observer em Scala.

Agora vejamos como as Traits podem nos ajudar a “decorar” nossas classes em runtime, com o Pattern Decorator.

Decorator

Muitas vezes quando queremos adicionar um comportamento a alguma classe, pensamos logo em herança, só que herança nem sempre é o melhor caminho. Vejamos o famoso exemplo das Janelas (decoração, janelas… acho vou mudar de ramo.).

Suponha uma classe que desenha uma janela simples na tela.

class Janela {
  def renderiza() = {
    print("Desenhando janela") // Use a imaginação cara!
  }
}

Ótimo, só que em um sistema de janelas, podemos ter diversos tipos de janelas, cada uma com uma combinação de funcionalidades:

  • Janela com barra de título
  • Janela com scroll vertical e barra de título
  • Janela com scroll horizontal, barra de título e barra de status
  • etc etc etc

Já de cara podemos ver que é impraticável criar uma subclasse para cada tipo de janela.

Aí vem a sacada do Decorator: ao invés de herança vamos usar composição e compor, a partir de pedaços de funcionalidade, a janela que quisermos. Tudo em runtime.

Vamos ver como implementar em Java da maneira chata usual:

// Interface implementada pela classe e pelos seus decorators
public interface Janela {
  public void renderiza();
}

// Decorator tem que manter controle de quem ele está decorando
abstract class JanelaDecorator implements Janela {
  private Janela janela;

  public Janela getJanela() {
    return this.janela;
  }

  public JanelaDecorator(Janela janela) {
    this.janela = janela;
  }

  public abstract void renderiza();
}

class JanelaSimples implements Janela {
  public void renderiza() {
    System.out.print("Desenhando Janela");
  }
}

class ScrollBarDecorator extends JanelaDecorator {
  public ScrollBarDecorator(Janela janela) {
    super(janela);
  }

  public void renderiza() {
    this.getJanela().renderiza();
    System.out.print(" com ScrollBar");  // Decorator adiciona comportamento
  }
}

Então, quando você tiver um monte de decorators implementados, você pode começar a decorar suas janelinhas:

Janela j = new ScrollBarDecorator(new JanelaSimples());
j.renderiza();
// Desenhando Janela com Scrollbar

// Você pode decorar com quantos decorators quiser.
Janela j = new ScrollBarDecorator(new TitleBarDecorator(new StatusBarDecorator(new JanelaSimples())));

Muito legal, mas eu só mostrei isso para você poder comparar com Scala.

Em Scala podemos fazer isso usando Traits:

// Nossa Janela
class Janela {
  def renderiza = print("Desenhando Janela")
}

// Quando uma Trait estende uma classe, ela só poderá ser misturada a objetos daquela classe. E também, "super" irá se referir à classe a qual ela foi misturada, ou outra Trait que foi misturada na classe.
trait ScrollBar extends Janela {
  override def renderiza = {
    super.renderiza
    print(" com Scrollbar")
  }
}

// Vamos usar
val janela = new Janela with ScrollBar
janela.renderiza 

// Desenhando janela com Scrollbar

Só isso! Meus dedos agradecem a redução de linhas.

E também aqui você pode usar quantos decorators quiser, separando as Traits com a palavra-chave with:

// "super" sempre vai se referir ao elemento da esquerda. 
val janela = new Janela with ScrollBar with StatusBar with TitleBar with Resize with BolinhasVerdes

Nesse exemplo, quando invocamos o método renderiza() no objeto janela, o primeiro
método a ser chamado é o da Trait a extrema direita BolinhasVerdes. A medida em que invocamos o método em
super, estamos referenciando a Trait logo a esquerda, até chegar na classe Janela.

É assim que funciona a composição de Traits.

Por hoje é só pessoal, e no próximo capítulo sobre Design Pattern:

Pimp My Library

Anúncios

Design Patterns em Scala – Parte 1: The Observer

Todo programador moderno, hype, antenado, ligado nas tendências, curte mesmo um Design Pattern.

Aliás tudo que tem Design no nome fica chique né? “Design de Sombrancelhas”, “Hair Designer”. Mas enfim…

Design Patterns é de fato um assunto bastante interessante, e o conhecimento de alguns desses padrões de design pode facilitar bastante o desenho de soluções.

Nesse post não pretendo ficar explicando a fundo os Patterns mais conhecidos no mundo Java, tem muita coisa já escrita por aí.

Como o foco principal desse blog é a linguagem Scala, vamos dar uma olhada em como alguns Patterns manjados em Java ficam ainda mais interessantes em Scala. Em seguida, vamos ver alguns Patterns novos para Scala.

Singleton

object MySingleton {
 // Código vai aqui
}

Singleton foi elevado ao cargo de construção de linguagem! Usando a palavra-chave “object” estamos criando uma instância única de uma classe.

No exemplo acima estamos ao mesmo tempo declarando uma classe e instanciando um singleton para ela.

Um singleton pode naturalmente estender classes e implementar Traits.

// Nem preciso de corpo se eu não quiser
object MySingleton extends MyClass with MyTrait 

O ministério da saúde dos programadores adverte: Singleton faz mal aos testes. Use com consciência.

Observer

Como vocês já sabem, nesse padrão temos dois personagens principais: o Observer, e o Subject.

O Observer é o objeto que está interessado no que o Subject está fazendo, e o Subject é gentil em notificar os Observers quando algo nele muda.

Primeiro, vejamos o jeito mais conhecido, java-like:

trait Subject {
  private var observers: List[Observer] = Nil

  def addObserver(observer: Observer) = observers = observer :: observers

  def notifyObservers() = observers.foreach(_.receiveUpdate(this))
}

trait Observer {
  def receiveUpdate(s:Subject)
}

// Olha mãe, sou um Singleton
object MyObserver extends Observer {
  def receiveUpdate(s:Subject) {
    println("O subject mudou!")
  }
}

// Olha mãe, eu nem preciso de um corpo
object MySubject extends Subject

// Testa tudo isso aí
MySubject.addObserver(MyObserver)
MySubject.notifyObservers

Criamos uma Trait para o Subject e o Observer e um exemplar concreto para cada um apenas para ver funcionando.

Uma Trait é como se fosse uma interface Java que também pode ter campos concretos. Uma classe consegue “estender” múltiplas Traits.

Só que em Scala eu consigo deixar as coisas mais interessantes. Vamos dizer que você não queira uma interface para os Observers. Que tal se qualquer classe que tiver o método receiveUpdate(s:Subject) pudesse ser um Observer?

Podemos usar Structural Typing para isso, e jogar a Trait Observer fora:

// Subject agora aceita qualquer observer que se "encaixa" no type definido
trait Subject {
  // Adicionei esse Type Alias para dar um nome a esse tipo estrutural.
  type Observer = { def receiveUpdate(s:Subject) }

  private var observers: List[Observer] = Nil
  def addObserver(observer: Observer) = observers = observer :: observers
  def notifyObservers() = observers.foreach(_.receiveUpdate(this))
}

// Não estende nada
object MyObserver {
  def receiveUpdate(s:Subject) {
    println("O subject mudou!")
  }
}

// O resto é igual
object MySubject extends Subject

MySubject.addObserver(MyObserver)
MySubject.notifyObservers

Structural Typing é parecido com Duck Typing, se o objeto tiver aquele método, ele é chamado. Por baixo dos panos o compilador resolve tudo usando Reflection, e por isso talvez tenha um impacto na performance do código.

Agora, uma instância de qualquer, QUALQUER classe que possua o método receiveUpdates(s:Subject) pode se adicionado como um Observer.

Legal, mas podemos ir além! E se eu não quiser que meu Observer seja uma instância de uma classe? Que tal se ele fosse apenas uma função?

Sinta o poder:

trait Subject {
  // Type Alias novamente. O tipo Observer é qualquer função que recebe Subject como parâmetro e não devolve nada (Unit é tipo void).
  type Observer = (Subject => Unit)

  private var observers: List[Observer] = Nil

  def addObserver(observer: Observer) = observers = observer :: observers

  // Mudei aqui para executar a função ( .apply aplica uma função )
  def notifyObservers() = observers.foreach(_.apply(this)) 
}

// Olha mãe, sou uma função!
val updateHandler = (s:Subject) => println("O subject mudou!")

object MySubject extends Subject

// Testa
MySubject.addObserver(updateHandler)
MySubject.notifyObservers

Type Alias é uma construção que permite que você defina um tipo. Isso mesmo, você declara um tipo e dá um nome para ele. Por exemplo, você pode dar um nome diferente para o tipo String:
type MinhaString = String.
Isso é bastante útil com Structural Typing.

Eu sei, eu sei, foi uma viagem e tanto. Se você nunca tinha experimentado nada do mundo funcional, esse aqui foi um pequeno exemplo.

Isso aí, vimos como em Scala podemos escrever o Observer de maneiras diferentes, tornando-o mais flexível.

Se o seu Observer não puder por algum motivo implementar uma interface, ou estender uma classe específica, podemos usar Structural Typing!

Se você não quer criar uma classe só para ser um Observer, e quiser só passar uma função de callback para seu Subject, agora você também pode de maneira simples e concisa. (em Java até daria para fazer uma classe anônima, mas convenhamos que assim é 3430943498 vezes mais bonito).

No próximo capítulo!

Arquitetura e Decoração com o Decorator

E não, não estamos falando sobre jardim, sofás, paredes e decoração de interiores…

View-first vs. MVC – Por que Lift é diferente?

Se você, caro leitor, desenvolve ou já desenvolveu aplicativos Web, deve estar cansado de ver essas três famigeradas letras: MVC, acrônimo de Model-View-Controller.

Se você programa em Java com Struts, sabe muito bem o que é uma Action.

Se você programa em Ruby com Rails, domina os ApplicationControllers.

Se você programa em PHP não tem idéia do que eu estou falando. Brincadeira! (perco o leitor mas não perco a piada).
Se você programa em PHP com CodeIgniter está bastante acostumado com os Controllers.

A arquitetura MVC reina absoluta entre os frameworks Web. Mas vamos lembrar porque é interessante fazer as coisas assim.

MVC e a separação de interesses

E o que essa arquitetura tem de tão fantástica? Ela simplesmente busca manter as coisas separadas. Modelo é modelo, apresentação é apresentação, não vamos bagunçar tudo em um grande bolo-fecal.ASP.
(Se você nunca mexeu em um grande arquivo .ASP de 3000 linhas cheio de HTML entremeado de lógica de negócio – e bugs -, e acha que ‘bolo fecal’ é ofensivo, é porque você tem sorte e não teve que ver essa nojeira!).

Apesar da quantidade de lógica que “vaza” para a camada de apresentação depender do framework que implementa o MVC, do engine de template que é usado e da disciplina do programador, o objetivo do MVC até que foi cumprido com sucesso.

Se você pegar uma aplicação razoavelmente bem feita, usando algum framework MVC poderá ver com clareza todas as classes do modelo, todas as classes que são os controller e todos os arquivos das Views.

De vez em quando, o desenvolvedor pode colocar uma lógica ou outra no template da View. Mas além disso, as coisas estão até que bem separadas.

O Lift ganha pontos aqui porque, ao contrário de PHP, ASP, JSP e outros engines de template, não é possível colocar lógica na View. Uma view em Lift é um simples XHTML e nada mais. É um modelo semelhante ao praticado pelo Apache Wicket.

MVC e uma lógica principal

Vamos pensar aqui, em linhas bem gerais, como é a fluxo de uma Request em um framework MVC:

  1. Chega uma Request para uma URL myApp/myController
  2. O framework mapeia essa URL para algum método do Controller MyController
  3. Esse método faz alguma lógica de negócio, e devolve algo que será no fim das contas a View
  4. A View, com base no estado do Model e do Controller mostra o que tem que mostrar na tela.

Perceba que a request no MVC está atrelada a uma lógica principal, que é basicamente o método invocado no Controller. Vamos tentar exemplificar.

Suponha que eu queira fazer uma tela para listagem de produtos e uma tela para edição de um produto específico. Eu teria as seguintes URLs.

/produtos/listar
/produtos/editar?prod=1234

E meu Controller teria dois métodos, um responsável por montar a tela de listar e o outro pela tela de editar.

Isso até que funciona muito bem, é fácil de fazer e de manter. O problema, é que atualmente, as aplicações Web estão ficando cada vez mais complexas, de modo que uma tela contém inúmeras funcionalidades concomitantes:

Uma tela de listagem de produtos, não apenas lista produtos. Na mesma tela temos uma lista de produtos no meio, um carrinho de compras mostrando o total de produtos na direita, uma lista de produtos sugeridos embaixo, e ainda um chat em tempo real no cantinho.

Já começa ficar complicado orientar nossa aplicação pelo Controller. Se pensarmos que o Controller vai se preocupar com a funcionalidade principal, temos que escolher uma para ele. Se escolhermos a listagem de produtos, quem vai cuidar da renderização das outras funcionalidades?

E ainda por cima, queremos manter nossas classes coesas e nossa View livre de lógica de negócio! Aí complicou.

Lift e a arquitetura “View First”

Foi pensando nesses cenários, muito comuns nas aplicações Web de hoje, que o criador do Lift, David Pollak, resolveu não seguir a abordagem MVC. Ao invés disso ele pensou em uma estratégia que é conhecida no meio como “View First”.

Nessa arquitetura o ponto de acesso de nossas páginas não é o Controller, mas a View. Pense assim, é a View que vai definir o que vai ter na tela e onde essas coisas vão aparecer.

Então cada um desses “blocos de funcionalidade” será mapeado para um Snippet. Cada pedacinho da tela será renderizado por um Snippet diferente, de uma maneira bastante componentizada.

Um Snippet é o equivalente Lift de um Controller, só que no caso é a View quem “chama” o Snippet, e não o contrário.

Vamos ver uma View em Lift, que nada mais é que uma página XHTML:

<!-- Topo -->
<div class="lift:Usuario.boasVindas">
 Bem vindo, <span id="usuarioLogado" />
</div>

<!-- Listagem de produtos -->
<div class="lift:Produtos.lista">
  <ul id="produtos">
    <li id="produtoItem">Produto1 - 9,99</li>
  </ul>
</div>

<!-- Chat Real Time em Comet -->
<div class="chatWindow">
  <div id="mensagens">
    <ul class="lift:comet?type=Chat">
      <li>Line 1</li>
      <li class="clearable">Line 2</li>
      <li class="clearable">Line 3</li>
    </ul>
  </div>
  <form class="lift:Form.ajax">
    <input class="lift:ChatIn" id="chat_in">
    <input type="submit" value="Chat">
  </form>
</div>

Observe que nessa View temos três funcionalidades bem distintas:

  • Um topo com uma mensagem personalizada para o usuário logado, que possivelmente pode ser reaproveitado em todas as telas do sistema.
  • Uma listagem de produtos.
  • Uma janelinha de Chat real-time usando Comet.

Essa View, que poderíamos chamar de /produto/lista.html agora é o ponto de entrada da nossa Request. A partir dessa View serão chamados três diferentes Snippets, cada um responsável por renderizar um pedacinho da View!

O interessante dessa abordagem “View First” é que podemos facilmente criar componentes utilizando os Snippets, e reaproveitá-los em diferentes Views.

Não vou focar muito nos Snippets agora, mas para você, curioso leitor, uma amostra do que poderia ser o Snippet de listagem de Produtos. Note como é sucinto, rápido, prático, bonito, elegante, charmoso, funcional etc etc :

object Produtos {
  def lista = {
    "#produtoItem" #> Produto.findAll.map(p => p.nome + " - " + p.preco)  
  }
}

A ligação com o elemento da view é feito por uma espécie de Seletor CSS. Nesse caso estamos pegando o <li id="produtoItem"> e repetindo para cada produto encontrado no modelo.

Moral da História

Nesse post relembramos um pouco da filosofia MVC e os motivos que levaram a sua concepção e aprendemos um pouco sobre a filosofia “View First” que é um dos fundamentos do framework Lift.

Para os iniciantes em Lift, essa mudança de filosofia pode ser meio estranha, podendo causar um pouco de confusão, desconforto, nojo, náuseas, já que a imensa maioria dos desenvolvedores Web esta bastante acostumada com o MVC.

Minha sugestão é: Faça um teste, brinque um pouco com o Lift para sentir um pouco essa arquitetura.

Você pode acabar gostando.

Como usar o SBT (simple-build-tool) com JRebel

Prólogo

Não muito tempo atrás, em um lugar não muito distante, chamado Web, existiam dois tipos de programadores:

  • Aqueles que dominavam a arte da linguagem interpretada, como Ruby, PHP. Acostumados com o tempo de Turnaround zero, em troca de menos performance.
  • E aqueles que dominavam a disciplina da linguagem compilada e tipada, como o Java, Scala e C#, que em troca de mais performance e servidores de aplicações, submeteram-se ao sofrimento do tempo de Turnaround

Um certo dia, um grupo de sábios estonianos uniram seus poderes e inventaram um artefato chamado JRebel que miraculosamente diminuía o tempo de Turnaround para os desenvolvedores Java e Scala.

Nota de rodapé do autor: Tempo de Turnaround é usado para denominar, entre outras coisas, o intervalo de tempo entre o momento em que você salva seu código e vê as alterações na tela. Em PHP esse tempo é zero, você salva o arquivo, faz refresh no browser e as mudanças estão lá. Em Java, caso você esteja desenvolvendo para um servidor de aplicação como o Weblogic, você tem que salvar seu código, compilar, empacotar, baixar e subir o Weblogic, aí sim você vê suas alterações.

Também conhecido como o tempo em que você levanta para pegar um cafézinho enquanto o servidor está subindo.

E assim eles destruíram os programadores de Ruby on Rails e viveram felizes para sempre.

Brincadeira.

Eles só ficaram mais produtivos, e passaram a tomar menos café (ou não).

JRebel, a salvação

Chega de historinha, esse é um post sério.

JRebel é uma ferramenta criada para diminuir o tempo que você espera para ver seu código funcionando.

Como ele faz isso?

Ele é um Java Agent, que altera os Classloaders da sua aplicação quando ela é executada. Esses classloaders modificados ficam monitorando os arquivos .class de sua aplicação. Quando algum desses .class muda, por exemplo quando você faz uma modificação e compila, o classloader percebe a mudança e recarrega a classe, sem que haja necessidade de reiniciar a aplicação ou o servidor.

Enquanto isso, no mundo dos builds

SBT, ou o Simple-Build-Tool

Essa ferramenta, escrita em Scala, não foi feita pelo Silvio Santos não.

Ela é uma alternativa para o famigerado Maven. Enquanto o Maven vem perdendo adeptos, por ser considerada uma ferramenta engessada, lenta, burra, o SBT vem arrasando corações no submundo emergente de Scala.

O foco aqui não é fazer uma apresentação detalhada de SBT, mas posso elencar alguns pontos chave:

  • É rápido.
  • A configuração é feita em Scala.
  • Integra com Maven e Ivy.
  • Dá para abrir um console Scala com todo seu projeto no Classpath para ficar testando coisas.
  • Consegue monitorar seu código fonte, executando o build assim que algum arquivo muda.

Se você programa em Scala e nunca usou o SBT experimente.

SBT e JRebel, a combinação ágil

Essa combinação vem ficando cada vez mais famosa, especialmente entre os programadores Lift. E tenho que confessar, funciona muito bem. Meu tempo de turnaround está praticamente zero.

Como configurar?

Primeiro baixe o JRebel e em seguida peça uma licença gratuita de um ano para desenvolvedores Scala (ao lado direito da página).

Quando receber a licença siga as instruções (colocar o arquivo da licença no diretório do JRebel).

Em seguida baixe o JAR do SBT, coloque em uma pasta qualquer e crie um script que irá chamá-lo:

java -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=516m -Xmx512M -Xss2M -noverify -javaagent:[CAMINHO_DO_JREBEL.JAR] -jar `dirname $0`/[CAMINHO_DO_JAR_DO_SBT] "$@"

Note que estamos informando ao Java que o JRebel é um javaagent. Assim, quando o você executar o SBT usando esse Script, o JRebel vai subir junto.

Coloque esse Script no seu PATH.

Como usar?

Para tirar os proveitos do JRebel você precisa criar uma aplicação em SBT, usar uma aplicação em SBT, ou configurar o SBT em uma aplicação Maven:

Se você usa Maven, saiba que o SBT consegue ler as dependências do arquivo pom.xml caso você não especifique nenhuma dependência na classe de configuração do SBT. Isso é bastante útil se você precisa manter um projeto em Maven e ao mesmo tempo quiser tirar proveito do SBT.

Vejamos um exemplo. Vamos usar um projeto Lift de exemplo que coloquei no Github:


git clone git://github.com/felipekamakura/sbt_jrebel_lift_example.git myApp


> cd myApp
> sbt


#############################################################

JRebel 3.5 (201011151605)
(c) Copyright ZeroTurnaround OU, Estonia, Tartu.

Over the last 23 days JRebel prevented
at least 92 redeploys/restarts saving you about 3.7 hours.

This product is licensed to Personal
until April 3, 2011
for up to developer seats on site.

The following plugins are disabled at the moment:
* JBoss AOP Plugin (set -Drebel.jbossaop_plugin=true to enable)
Integration with jboss aop agent
* Jackson Plugin (set -Drebel.jackson_plugin=true to enable)
Supports reloading Jackson's JsonSerializer caches.
* Lift Plugin (set -Drebel.lift_plugin=true to enable)
Supports reloading singleton objects that extend LiftScreen or Wizard.
* Log4j plugin (set -Drebel.log4j-plugin=true to enable)
Reloads full configuration of log4j
* RESTEasy Plugin (set -Drebel.resteasy_plugin=true to enable)
Supports adding/changing methods with @Path annotation for RESTEasy application.
* Seam Wicket Plugin (set -Drebel.seam_wicket_plugin=true to enable)
Integration with load time weaving seam annotations to wicket classes
(-javaagent:)
* WebObjects Plugin (set -Drebel.webobjects_plugin=true to enable)
WebObjects JRebel Plugin

#############################################################

Getting Scala 2.7.7 ...
:: retrieving :: org.scala-tools.sbt#boot-scala
confs: [default]
2 artifacts copied, 0 already retrieved (9911kB/5097ms)
Getting org.scala-tools.sbt sbt_2.7.7 0.7.4 ...
:: retrieving :: org.scala-tools.sbt#boot-app
confs: [default]
15 artifacts copied, 0 already retrieved (4096kB/13414ms)
[info] Recompiling project definition...
[info] Source analysis: 1 new/modified, 0 indirectly invalidated, 0 removed.
Getting Scala 2.8.1 ...
:: retrieving :: org.scala-tools.sbt#boot-scala
confs: [default]
2 artifacts copied, 0 already retrieved (15118kB/805ms)
[info] Building project Lift SBT Template 0.1 against Scala 2.8.1
[info] using LiftProject with sbt 0.7.4 and Scala 2.7.7
>

Você está agora no console do SBT. Execute o comando update para baixar as dependências do projeto:

>update

Em seguida, compile e suba a aplicação exemplo com o comando jetty-run:

>jetty-run

Legal, se tudo deu certo, a aplicação Lift de exemplo está disponível em http://localhost:8080/. Entre lá para dar uma olhada, deve estar assim:
Aplicação Lift, JRebel e SBT

Vamos agora ver o poder do JRebel alterando uma classe, compilando-a e vendo a mudança na tela:

Execute o seguinte comando no SBT:

>~prepare-webapp

O prepare-webapp é um comando do SBT que compila e empacota a sua aplicação web. O ~ (til) antes do comando fala para o SBT – “rode o seguinte comando sempre que houve uma mudança no código fonte”.

Sempre que você usar o ~ (til) no SBT, ele vai ficar em um “estado de alerta”, e vai construir tudo sempre que houver mudança. Isso é essencial para conseguirmos baixar o tempo de Turnaround. E também o SBT é esperto o suficiente para compilar apenas as classes de seu projeto que foram alteradas.

Agora abra e altere o arquivo src/main/scala/code/snippet/HelloWorld.scala. Troque a frase de saudação para sua frase favorita.

class HelloWorld {
// Altere a linha abaixo para sua frase favorita
def howdy = "#greet *" #> "Cai fora curioso."
}

Então, quando você salvar a classe, o SBT vai começar a compilar tudo e o JRebel vai notar que houve mudança no .class dessa classe.

De um refresh no browser e note que a tela foi atualizada com suas modificações! Rápido, prático, indolor! Veja que a frase mudou:
Aplicação depois da alteração

É só isso pessoal! Nada de intervalo para o cafézinho durante o build, foi mal…