Reduzindo condicionais em Linguagens Orientadas a Objetos (Ruby)

September 8, 2024

Introdução 🚀

Um assunto muito abordado quando estamos começando nossa carreira, é a tal da "lógica proposicional", os famosos if's else's que amamos e utilizamos para solucionar problemas simples e complexos. E uma das maiores dificuldades que enfrentamos nessa hora, é como reduzir ao maximo o numero e a complexidade de condicionais.

Felizmente existe a Orientação a Objetos 😁

O que são objetos?💡

Para entendimento geral vamos adotar um objeto, como toda instancia que possui uma classe de definição, hoje a maior parte das linguagens modernas aceitam Orientação a Objetos, mesmo que não seja o paradigma original ou mais usado.

Vamos ao exemplo pratico

Nós fomos contrados para desenvolver um sistema que abriga animais, e a unica coisa que foi solicitado é que seja possivel retornar o tipo do animal e quantas refeições ele precisa, então nós resolvemos implementar a classe Animal, que é composta pelo atributo kind, id e pelo metodo meals

class  Animal
  attr_reader  :kind

  def  initialize(kind:)
   @kind =  kind
  end

  def meals
    puts  "Needs 2 meals"
  end
end

Agora podemos instanciar um objeto da classe Animal, e chamar o metodo meals que irá nos exibir a mensagem Needs 2 meals

dog =  Animal.new(kind: "dog")
dog.meals
>>>  "Needs 2 meals"

Muito bem! Agora chegou mais uma tarefa, precisamos especializar o metodo meals para retornar o numero de refeições que esse animal precisa dependendo do kind dele. Então tivemos a brilhante ideia de fazer uma condicional utilizando o atributo kind

class  Animal
  ...
  def meals
    if kind == "dog"
      puts "Needs 3 meals"
    elsif kind == "bird"
      puts "Needs 2 meals"
    end
  end
end

Muito bem! Nós atendemos nosso problema, porém ja conseguimos sentir uma certa dificuldade com mais animais, vamos precisar de 15 ifs se continuarmos assim 🤣🤣

Great times are coming!

Bom, já entendemos que objetos tem implementações diferentes, e que eles possuem metodos especificos para cada implementação, sendo assim vamos usar essa capacidade para remover todos os ifs desse nosso problema.

Apenas para exemplificar, vamos implementar uma classe chamada Dog e uma chamada Bird

class Dog
  def meals
    "Needs 2 meals"
  end
end
class Bird
  def meals
    "Needs 1 meal"
  end
end

Agora vamos usar a magia da Composição, muito parecido com Injeção de dependencia, para compor essa nova classe Animal

class Animal
  attr_reader  :kind, :kind_klass

  def initialize(kind:, kind_klass:)
   @kind =  kind
   @kind_klass = kind_klass.new
  end

  def meals
    puts kind_klass.meals
  end
end

Otimo! Dessa forma não precisamos mais nos preocupar com ifs, cada classe e cada tipo de animal irá se comportar como quiser, sem a necessidade de tratarmos na classe Animal já que ela mesmo pode ser varios animais diferentes!

dog =  Animal.new(kind: "dog", kind_klass: Dog)
dog.meals
>>>  "Needs 2 meals"

Bonus

Bom, e quando não sabemos exatamente qual é o animal? Talvez seu primeiro impulso seja fazer algo parecido com isso:

class Animal
  attr_reader  :kind, :kind_klass

  def initialize(kind:, kind_klass:)
   @kind =  kind
   @kind_klass = kind_klass.new
  end

  def meals
    if kind_klass
      puts kind_klass.meals
    else
      puts "Needs 1 meals"
    end
  end
end

animal = Animal.new(kind: "Unknown", kind_klass: nil)
animal.meals
>>> "Needs 1 meals"

Resolve nosso problema, mas não estavamos tentando fugir de condicionais? Nós já preparamos o terreno, então vamos apenas nos aproveitar de ter feito uma boa arquitetura!

class DefaultAnimal
  def meals
    "Needs 1 meals"
  end
end

class Animal
  attr_reader  :kind, :kind_klass

  def initialize(kind:, kind_klass: DefaultAnimal)
   @kind =  kind
   @kind_klass = kind_klass.new
  end

  def meals
    kind_klass.meals
  end
end

animal = Animal.new(kind: "Unknown")
animal.meals
>>> "Needs 1 meals"

Dessa forma nós já temos um fallback para caso o usuario não saiba qual animal é, ou caso ainda não exista uma classe implementada pra ele.

Obrigado pela atenção e espero ter ajudado! 👍

Related:

← Back to home