Looking for some advice on how a seasoned Elixir developer might go about implementing the creation of a map/struct that is dependent on several other maps.
Let’s say we’re modelling something like a Freight Shipping Order, aka “Bill of Lading”. Generally speaking, these have a lot of fields. In our case, we need to make several API calls to just get the right information to assemble one.
Consider this pseudo code, typos are to be ignored.
def fetch_freight_order(id) do
# These all just return a Map, constructed from a JSON response.
shipping_customer = call_api(...)
receiving_customer = call_api(...)
line_items = call_api(...)
freight_company = call_api(...)
# ... and maybe 4-5 more calls to an api we don't control ...
# To assemble a freight_order, we need all of the parts above.
freight_order = new_freight_order(
shipping_customer,
receiving_customer,
line_items,
freight_company,
# ... 4-5 more arguments
)
end
Option 1
Would Elixir developers pass each argument or would they be more included to pass a keyword list, map, or use some other pattern?
# Easy to get confused at the call site which order these are all in.
def new_freight_order(
shipping_customer,
receiving_customer,
line_items,
freight_company,
# ... 4-5 more arguments
)
%{
# Populate shipping_customer fields
shipping_name: shipping_customer["Name"],
shipping_street: shipping_customer["Street"],
# Populate receiving_customer fields
receiving_name: receiving_customer["Name"],
receiving_street: receiving_customer["Street"],
# ... maybe 50+ more fields ...
}
end
Option 2
If we pass a single map, then we can pattern match in the function’s signature but it gets rather unwieldy pretty quickly and the call site also gets a lot busier:
def new_freight_order(%{
shipping_customer: shipping_customer,
receiving_customer: receiving_customer,
line_items: line_items,
# a bunch more matches...
}) do
# Merge into a single freight_order
end
Option 3
Or perhaps use single pattern matches:
def new_freight_order(freight_order, %{shipping_customer: shipping_customer}) do
# Merge in just the shipping fields
end
def new_freight_order(freight_order, %{receiving_customer: receiving_customer}) do
# Merge in just the receiving fields
end
Option 4
Alternatively, would anyone create separate functions for each section?
def populate_shipping_customer(freight_order, shipping_customer) do
end
def populate_receiving_customer(freight_order, receiving_customer) do
end
I appreciate that style is subjective, but as new Elixir devs, we’re curious what patterns might be preferred over others. This use-case comes up quite a bit for us. A lot of the data we’re working with within our Elixir app (and showing to the user), requires a considerable number of discrete API calls just to gather the required data before we can assemble it into some sort of local representation.
Thanks in advance.