Evitando Null Pointer Exception em Scala

No meu post anterior foi discutido uma maneira de tentar evitar os famigerados NPE nas aplicações escritas em Java. Atualmente, uma linguagem que tenho gostado bastante é Scala. Uma das idéias da linguagem é a de fornecer soluções prontas para problemas comuns que encontramos quando fazemos código em Java. Um exemplo muito bom disso é a idéia para evitar os NPEs.

Para exemplificar, será usada a mesma agenda que foi escrita no post anterior. Abaixo segue o código da agenda escrito em Scala:

 import scala.collection.mutable.Map
 class Agenda {
   private val contatos = Map[String,Contato]()
  //aqui adicionamos um contato no mapa usando o email como chave
   def adiciona (contato:Contato) {
        contatos += contato.email -> contato
   }
   def  buscaPor(email:String) = {
         if(contatos.contains(email)){
            contatos.get(email).get
         }
         else{
            null
         }
    }
 }

Aqui está sendo retornado o mesmo null que era retornado no post anterior. Vale salientar que dei uma forçada no código para deixar ele parecido com o escrito em Java. E o cliente segue abaixo:

 object TesteAgenda {
      def main(args : Array[String]) : Unit = {
             val agenda = new Agenda
  	     agenda.adiciona Contato("alberto","teste@teste.com.br")
 	     val contato = agenda buscaPor "teste2@teste.com.br"
             if(contato==null){
                  println("Nao foi achado")
             }
             else{
                  println(contato.nome)
             }
      }
 }

Para tentar evitar esse tipo de retorno, a linguagem já vem com uma implementação mais esperta do que a sugerida pelo Null Value Object e muito mais elegante do que a exibida no post anterior. A implementação está abaixo:

 def buscaPor(email:String):Option[Contato] = {
    if(contatos.contains(email)){
        Some(contatos.get(email).get)
    }
    else{
      None
    }
 }

Option é uma trait, que pode ser encarada como uma interface do Java, porém com mais poderes. Ela vem com duas implementações: Some(…), quando você quer indicar que algum objeto vai ser retornado e None para indicar que nada vai ser retornado. Agora no código cliente podemos usá-la da seguinte maneira:

  println(contato.getOrElse(Contato("nao encontrado", "email@email.com.br")).nome)

Dessa maneira é evitado o NPE a um custo bem pequeno. Sem a necessidade de herança ou implementações mais complexas, já está pronto :). E o método getOrElse faz o papel do if else que era feito antes.  O post de Tony Morris cita vários exemplos de uso dos métodos das Options, mostrando o que cada um faz por baixo do pano. O mais interessante é que a própria linguagem faz bastante uso de Options para resolver problemas.

O exemplo de buscar um valor no mapa é um caso típico de retornar uma Option, e o método get já foi implementado dessa forma.  Segue o código:

  def buscaPor(email:String) = contatos.get(email)

Pretendo continuar explorando a linguagem nos próximos posts do blog. Acredito que as possibilidades que ela nos traz durante o desenvolvimento do código valem bastante a pena.  Outros blogs a serem acompanhados, que vem escrevendo sobre Scala são os da Caelum e de Urubatan.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s