quarta-feira, 16 de setembro de 2009

Decorando objetos em Scala

No desenvolvimento de software sempre existem características que são ortogonais ao sistema.

Para remover a duplicação de código que tais características causam podemos utilizar interceptors, aspectos, proxies, etc para com isso decorarmos o nosso objeto com a funcionalidade que queremos.

A solução fica legal, mas a quantidade de código que precisa ser gerada às vezes poderia desencorajar a implementação pois a duplicação de código seria trocada em alguns casos por muito código.

Entretanto se você resolver desenvolver seu sistema em Scala uma solução muito mais simples poderá ser implementada.

Com a utilização de traits, você pode adicionar novas características a objetos com muita facilidade e pouco código.

Por exemplo, suponhamos que você queira realizar um profile de alguns objetos no seu sistema.

O seguinte código resolveria tal problema:

  //classe que já possuo
  class T{
    def f = print("Ola enfermeira!")
  }
  //trait que adiciona comportamento a interface de T
  trait Profile extends T{
    abstract override def f = {
      val time = System.nanoTime()
      super.f
      println("Tempo total em nanos: " + (System.nanoTime() - time))
    }
  } 

Ao rodar o seguinte código:

  val t = new T with Profile
  t.f

Obtemos o seguinte resultado: Ola enfermeira!Tempo total em nanos: 214972

O que acontece é que utilizando a palava with na declaração da variável eu estou dizendo ao compilador do scala que ele deve adicionar as caracteristicas na minha Trait Profile ao objeto.

Sim, isso é um tipo de herança

Logo quando eu chamo o método f, a implementação que é chamada é a da Trait e não do objeto T.

Nesse ponto um detalhe que precisamos notar é como o scala trata o super.

Quando chamamos o super dentro da implementação de f em T o método f chamado será o da implementação que está imediatamente a esquerda da definição da trait.

Ou seja, o seguinte código pode ser feito:

  trait Smile extends T{
    abstract override def f = {
      print("=)")
      super.f
    }
  }

  val t = new T with Profile with Smile
  t.f

Tendo como output: =)Ola enfermeira!Tempo total em nanos: 27238

A implementação que está mais a direita (no caso Smile) foi invocada.

Ao chamar super a implementação exatamente a esquerda foi chamada (Profile).

No próximo super a implementação de T foi chamada.

Com tal forma de encadeamento seus objetos podem ser decorados de inúmeras formas.

Tem alguma idéia melhor de como criar tais características?

Coloque nas revisões desse post =)

quinta-feira, 10 de setembro de 2009

Eliminando ifs encadeados com scala.

Estava lendo o seguinte post do meu amigo eliezer sobre eliminar if encadeados e pensei: Como seria um código para resolver esse problema em Scala.

Utilizando firstClass functions e placehoder syntax criei o seguinte código:

object StringUtils {                                                   
  def format( action: String => String, value: String ) = action(value)
  def removeBlanks = { (_:String).replaceAll( " ", "") }                       
  def onlyNumbers = { (_:String).replaceAll( "\\D", "" ) }             
}

Dá pra ver que o código fica bem mais enxuto e a responsabilidade fica toda dentro do objeto singleton StringUtils. O código cliente fica bem interessante também:

StringUtils.format( StringUtils.removeBlanks, "Ola enfermeira" )

O código retorna Olaenfermeira

Legal né =)

Se você tem alguma idéia melhor por favor compartilhe ela aí embaixo.

quinta-feira, 3 de setembro de 2009

Scala e o jeito funcional de programar

Ao programar por muitos anos com linguagens como C e Java nós nos acostumamos demais com o modo imperativo de programação. Fazendo isso esquecemos algumas vantagens que o paradigma funcional pode nos trazer.

Ultimamente estou estudando Scala, e apesar da linguagem permitir que você construa código imperativo, a mesma traz interessantes construções que nos incentivam a usar o paradigma funcional.

Um exemplo simples mas que mostra esse conceito seria um código para varrer os parâmetros de entrada de um programa e simplesmente imprimi-los na tela.

Um código imperativo em Scala seria assim:

var i=0
while(i < args.length){
  println(args(i))
  i += 1
}

Como podemos ver, nada muito complexo, simplesmente um laço que varre a lista imprimindo seus elementos.

Utilizando um pouco do paradigma funcional presente em Scala o mesmo código poderia ser feito da seguinte maneira:

args.foreach(arg => println(arg))

O seguinte código define um function literal. Esta função recebe como parâmetro um item da lista de argumentos e imprime o mesmo, o processo é repetido para cada argumento da lista.

Da mesma maneira que foi chamado um println, qualquer função poderia ter sido chamada sobre a iteração.

É importante notar que o código acima é facilmente implementado em Java, basta pensarmos de maneira mais funcional.

Entretanto, como o valor extraído da lista é o único parâmetro para a função que será executada, é possível fazer com que esse código seja ainda mais simples:

args.foreach(println)

E você achando que o laço no início do post que era simples ein =)