arashm

arashm

When to use Struct?

I read the “Programming Elixir” book, here is quote from the book:

At some point, the old object-orientation neurons still active in the nether regions of your brain might burst into life and you might think, “Hey, this is a bit like a class definition.” And you’d be right. You can write something akin to object-oriented code using structs (or maps) and modules.
This is a bad idea. Not because objects are intrinsically bad, but because you’ll be mixing paradigms and diluting the benefits a functional approach gives you.

Having this in the back of my mind, today I’m making a simple app which relies on data comes from a JSON API. The data structure is deeply nested and the API on different end-points uses different keys for same objects (imagine in one it returns name in another it returns title). So I thought I’d convert those JSON data to different structs and define a to_normalized_struct function in those to convert them to a struct that provides a same interface to be used through out the app.

But then… I thought maybe I’m coding OO here and may face wrath of functional programming gods later. So when is right to use structs? How would you implement the code for above problem?

Most Liked

slashdotdash

slashdotdash

A useful comparison of structs and maps is made in When to Use Structs, String-keyed Maps, and Atom-keyed Maps.

It lists six rules governing the best practice usage of these data structures.

  1. Always Use String-Keyed Maps for External Data.
  2. Convert External Data to Structs ASAP.
  3. Use Structs in All Other Code.
  4. Use Structs for Output Data.
  5. Avoid Using Atom-keyed Maps That Aren’t Structs.
  6. Use Keyword Lists Only for Function Arguments
bbense

bbense

My 2 cents. The way out of the OO trap is to think data and transformations.

I can’t answer your specific question w/o knowing the larger context, it might make sense to simply create a transform function for each JSON type to a standardized data form. Or it might make sense
to avoid the central form and just make transforms that extract the data you need.

The way to answer that question is to think about any transforms you need for the resulting data. What data structure makes the most “sense” in your problem? Rather than modeling “things”[1], start thinking about transforms and the inputs and outputs they need.

The Struct construct handy in that it provides both an easy to read access syntax and it constrains your transforms to a specific set of keys in a Map. However, the problem with Struct is the dual of it strengths, you lose the ability to dynamically change the structure of the data as the problem evolves. Struct requires that you “model” the problem in advance. This is not a terrible thing; in fact the strong type people would claim this is a very good thing. It does take away some of the flexibility and power of a dynamic language.

So as a practical guide, I’d suggest that if you are either constantly adding fields to your Struct or creating many slightly different, but almost the same structs, then you probably don’t understand the problem well enough yet to use a struct. The other thing to be aware of is that Struct only constrains the keys, not the values. If you find yourself putting wildly different values under the same struct key, then you’re probably in the weeds.

[1]- Experience suggests this is also the source of most problems with OO design as well.

AstonJ

AstonJ

I am just going through the Elixir and Phoenix Bootcamp course and in my notes I have written:

Structs

Just like Maps but with 2 advantages:

  • Can be assigned default values
  • Additional compile-time checking of properties

If we know the properties we are going to be working with we will use a Struct instead of a Map.

Where Next?

Popular in Questions Top

electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

Other popular topics Top

lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New

We're in Beta

About us Mission Statement