temper

temper

Hello,

I have a question that is probably not limited only to Elixir, but I would like to have your opinion about ‘Elixir’-like, or ‘Elixir way’ solution to the question.

The problem I would like to discuss is the application of the ‘design by contract’ software design principle. In short, when designing a data exchange protocol, both sides of the interface agree on the data types and the boundaries of values used when calling the interface/protocol methods. And in the implementation the caller of the function ensures that the protocol is not violated.
I am coming from a world of languages like C++, Java, Python where design by contract is (at least in theory) applied quite often and to some degree supported by the compilers (C++/Java), Despite this fact, the actual implementations of the protocol are full of checks of the potential protocol violations to ensure that the program will not crash (a classical example is checking for the null value of variables passed as parameters to the method/function calls).

Although I am new to Elixir I feel that this problem can be solved quite elegant in many cases by clever application of proper data structures. But I am curious whether there are some best practices established in Elixir.

I have one concrete example illustrating the problem and the possible (as far as I can see) solutions:

  1. The business logic of my application operates on the data structure representing a week. I encoded it as
defmodule WeeklyTimeDistribution do
  defstruct ~w[mo tu we th fr sa su]a
end
  1. The business logic fills each entry of the WeeklyTimeDistribution with a struct, containing, between other the date of a specific day.

  2. At the end of the processing I store the WeeklyTimeDistribution to external data storage via some boundary module. The module defines a protocol, that operates on the instance of the WeeklyTimeDistribution struct.

  3. The API implementation takes days of the struct and tries to store them. Sometimes however, the storage is not allowed, so I need to exclude some days from storing (I know, it sounds a bit strange, but it is something I cannot change - without going into details: days of the week with dates in the future cannot be stored).

From this point I believe there are two choices:

  1. Setup a ‘contract’ where I set the nil values for the days of the week not to be stored and implement the storage API to skip the days with ‘nil’ values from storing.
  2. Change the data type used between the business logic and storage API by passing a map or a list of only valid days of the week (excluding the days in the future). So the contract says in this case: whatever I pass is “legal” and the boundary shall just store it without any checking.

The 2nd option looks more appealing to me because it makes the boundary (data storage module) simple (no checks for ‘nil’ prior to writing. The storage API just iterates over the passed data structure and stores the data.

Is there a common Elixir design pattern for this problem? Shall the boundary classes be just plain absorbers of the data? Or does some defensive programming still make sense in Elixir? What do you think?

Showing Posts 1 to 8

ityonemo

ityonemo

I am not a design by contract expert but i feel like 1) is better. It lets you keep strong typing on the week data structure. You can then typespec the week data structure to have it’s fields be nil or Day.t and in your typedoc specify that nil is only valid for future dates (you could probably even write a runtime check for that in your Week consumer).

lud

lud

Defensive programming is discouraged because we have other ways, but defensive data checking a.k.a. validation is still a thing. So I would say 1. too.

gregvaughn

gregvaughn

One compromise is to write some sort of

WeeklyTimeDistribution.persistable_values(%__MODULE__{} = wtd)

function which could return something like a keyword list of the non-nil values. Then your peristence module can remain ignorant about avoiding nil values. It just prepares the values by calling that function.

dimitarvp

dimitarvp

Coding style nitpick: better don’t do this. When working in teams, most people I worked with found it really hard to follow and track in the code.

Better invest in some code snippets software (or VSCode / Emacs / VIM plugin) to just do this:

defstruct [:mo, :tu, :we, :th, :fr, :sa, :su]
temper

temper OP

Thanks for the advice @ityonemo.

temper

temper OP

Thanks @lud for the advice

temper

temper OP

Thanks for the tip @gregvaughn. I find it interesting approach. It keeps the logic completely at the business logic side. Probably I will need to try the both approaches as a small exercise and see which looks better

temper

temper OP

Thanks for the tip @dimitarvp. Indeed, the project I am working on is the one-man initiative, and also language exploration exercise for me. So I play with some less popular language constructions to see what works and what not.

— All posts loaded —

Where Next? Top

Trending in Discussions Top

cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
wmnnd
Hey folks, I wanted to share with you a project I’ve been working on for a while: It’s an Open Source (AGPLv3) newsletter tool. Think Ma...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New
sntran
In my third year of college, around 2010, I found Erlang. A few years later, I found Elixir. I liked the ideas at once: many small proces...
New
Ganna
Hi everyone, I have 8 years of production experience with Erlang/OTP and I’m just starting to get to know Elixir. What would you learn f...
New
gtcode
I’ve been tinkering with Lynx (by José) via hold_ledger. I used AI to write the code, a separate specification, the tests, and the Lean p...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
kip
In 2021 I started a new library called Tempo with the objective of modelling time as a set of intervals - not as instants. In 2022 I gave...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews