Pra quem já programou alguma coisa em C, deve estar familiarizado com a palavra Struct. Lembro que utilizei bastante na faculdade, programando aquelas calculadoras e carrinhos de compra imaginários, utilizando os saudosos Dev C++ ou o Code Blocks (se você se identificou, já sei que está ficando velho igual a mim), enfim… vamos ao que interessa.

O que é uma Struct?

Uma maneira simples de entender uma Struct é vê-la como uma Classe simplificada que pode também ter métodos e/ou atributos mas sem precisar de fato criar uma Classe.

what?

what?

Vamos falar mais sobre Structs e ver um pouco de código pra entender melhor.

Quando utilizar Structs?

Se de maneira simples entendemos que uma Struct é uma espécie de Classe simplificada, então faz sentido o uso em casos que precisamos dar mais significado aos dados.

Como assim?

Vamos supor que estamos trabalhando com um produto, vamos descreve-lo dentro de um Array:

notebook = ["i7 CPU", "16GB RAM", "256 HD"]

Podemos acessar os dados de configuração do notebook através dos índices notebook[0], notebook[1] ou notebook[2], correto?

Mas analisando bem, se não precisamos de um notebook representado por uma classe Product por exemplo e queremos algo mais organizado e explícito que um Array, podemos utilizar uma Struct:

Notebook = Struct.new(:cpu, :ram, :ssd)
notebook = Notebook.new("i7", "16GB", "256SSD") 

Dessa forma podemos acessar os atributos de uma forma bem mais significativa através dos atributos notebook.cpu, notebook.ram, notebook.ssd. Agora temos uma representação do notebook com atributos explícitos.

Também podemos utilizar métodos dentro das Structs:

Notebook = Struct.new(:cpu, :ram, :ssd) do
  def all_configs
    "PC configs: #{cpu} - #{ram} - #{ssd}"
  end
end

notebook = Notebook.new("i7", "16GB", "256") 

Quando não utilizar Structs?

Uma vez definida a Struct Notebook os atributos não poderão ser alterados, então não poderíamos adicionar simplesmente um atributo : gpu por exemplo, nesse caso seria necessária a criação de uma nova Struct. Se existe a necessidade de mudanças nos atributos com certeza a melhor opção é um Hash ou um Array.

Conclusão

Como vimos, Structs são bastante úteis em determinados momentos do nosso código, principalmente quando precisamos de uma estrutura de dados que possamos acessar seus atributos ou métodos, mas não precisamos de uma Classe pra isso. Eu particularmente gostei bastante da abordagem de Struct como retorno de um Service (PORO), exemplo:

Imagine um Service responsável apenas por tratar o resultado de uma requisição externa e retornar se houve sucesso ou falha na requisição e os erros caso haja algum.

class StatusService

  Status = Struct.new(success?, errors)

  def initialize(request_params)
    @request_params = request_params
  end

  def call
    if @request_params[:status].present? && @request_params[:status] == "success"
      status = Status.new(true, nil)
    else
      status = Status.new(false, @request_params[:errors])
    end
  end
end

Poderíamos retornar um Hash ou Array sem problemas, mas utilizando Struct retornamos um status no qual podemos acessar o seu atributo :success? e :errors, melhorando bastante a compreensão e tratamento do StatusService através do seu retorno.

É isso, espero que tenham gostado!

Ahhh, e é claro, se você puder, curta a página dá Vídeos de Ti no Facebook ou ainda siga nas redes sociais e cadastrem-se na newsletter semanal! ;-)

Um forte abraço e até a próxima!

Valeu. :D