[Refatorando Tudo!] Representando nada com o Padrão de Projeto Null OBject

No post anterior nos falamos sobre a importância de não retornar nulos nas funções. Uma maneira de evitar esse problema é utilizando um objeto válido, mas que não possui nenhuma informação. Nesse post vamos entrar mais em detalhes sobre o Padrão Null Object.

Nada é alguma coisa

No post anterior já dei essa dica, mas pra quem perdeu, essa apresentação da Sandi Metz Nothing is Something é muito boa e explica as implicações de design de retornar nulo.

A ideia básica do padrão é criar um objeto que é válido, ou seja não vai lançar nenhuma exceção ou causar problemas, mas que não possui nenhuma informação.

class Pedido
  attr_reader :total, :imposto, :numero
  def initialize(total, imposto, numero)
    @total, @imposto, @numero = total, imposto, numero
  end
end

class PedidoInvalido < Pedido
  def initialize
    super(0, 0, 0)
  end
end

Mas qual a vantagem de retornar um novo objeto ao invés de retornar nulo, que já existe?

Se você programa em uma linguagem Orientada a Objetos, provavelmente conhece o conceito de que objetos trocam mensagens entre si. A principal vantagem de criar um objeto invalido é que ele segue a mesma interface do objeto original, enquanto um nulo não conhece nada sobre o objeto original. Assim podemos continuar enviando a mesma mensagem, sem se preocupar se o objeto vai entender ou não.

Então mesmo que pareça fazer sentido utilizar um valor nulo para representar a falta de algum dado, estamos obrigando quem utiliza nossa função a prover um comportamento extra. Em algum lugar do código eventualmente vamos precisar fazer algo assim:

pedidos = Pedido.obter_historico_de_pedidos(usuario)
valor_total = pedidos.reduce(0) do |total, pedido|
  total += pedido.nil? ? 0 : pedido.total
end

Aquele nil? no meio da sua lógica tende a se espalhar em todo lugar que precisa de um pedido. Então, a menos que o método obter_historico_de_pedidos retorne um objeto nulo, quando não houver um pedido, toda parte do código vai precisar lidar com a checagem de nulo.

Apesar de parecer um trabalho grande criar um novo objeto só para representar um valor inválido, a manutenção fica fácil pois tudo fica concentrado em um lugar só. E utilizar um objeto é bem mais fácil do que utilizar a lógica toda.

Cada caso é um caso

O que o objeto nulo vai fazer depende muito da sua aplicação. No post anterior discutimos quando faz mais sentido retornar um objeto nulo ou lançar uma exceção, se você ainda não viu, corre lá pra evitar utilizar o padrão em um cenário onde ele não faz sentido.

Em alguns contexto o objeto nulo precisa ser mais complexo, como por exemplo quando existem outro objetos aninhados e eventualmente precisamos criar objetos nulos para eles também.

No entanto o objeto nulo também pode ser mais simples, digamos que você tenha uma lista de objetos, basta criar um lista vazia para garantir que o objeto será válido mas sem nenhum dado.

Compartilhe o texto com seus colegas para ajudá-los a melhorar o código deles também e continue acompanhando os posts da série [Refatorando tudo!] para melhorar ainda mais seu código!

Deixe seus comentário aqui no post ou fale direto comigo no twitter em @marcosbrizeno!

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s