My modules are too object-oriented...help?

Hi, all,

I’m new to functional programming in general and decided to start by learning Elixir. My background is in procedural and object-oriented programming, C and C++ from college and Python/JavaScript since then. I plan to eventually build web applications with Elixir, but I’ve read that “Phoenix isn’t your app” so I want to get a good understanding of structuring a software project in Elixir first before adding a Phoenix application as a “web interface”, Ecto as the “database interface”, etc.

With the news that Meetup may be switching to a paid model, I decided it would be fun to build some of the core Meetup functionality as an Elixir app. My thinking was that I could build a Meetup application for the core details, like attendance tracking, marking attendees as paid, generating instances of recurring meetups, and similar stuff like that, then extend that functionality for custom Meetup types like tournaments.

I’ve taken PragDave’s Elixir for Programmers course, so i have that code as a reference. I also have a ton of books that I’m slowly working through as I’m building this Meetup clone, but I don’t think the “Elixir way” of building out functionality is sinking in. Why? Because my first version of the modules I’m building look awfully object-oriented to me.

I have a module for Attendance, which is basically just a finite state machine between “signed up” and “checked in” with a “paid” attribute. I thought “well, easy enough.” I created a structure containing the “signup” state and a boolean for payment status.

Next, I moved on to a module for recurrence rules. I basically created a wrapper around the ExCal library. Every recurrence has a frequency, a list of days to repeat on, and a starting day. “Oh, easy enough to model”, I thought, and promptly made a structure containing those three attributes.

Hmm…I’m seeing a pattern here…

My final module was an Event module. This had more details: location, duration of each meetup, an identifier, an organizer…so I made a struct for that too.

Before I knew it, I had three modules with structs and collections of functions that worked on those structs. In other words, three classes.

I guess I’m still stuck in my object-oriented / database-table ways, but I can’t get it through my head how to structure this type of application, where I can:

  • create new meetups
  • add attendees to the meetups
  • set a price for a meetup
  • set when the meetup happens through a recurrence rule
  • get instances of the meetup
  • edit meetup attendee details, i.e. if they’ve paid and if they’ve checked in

For those of you who’ve done this for a while, how would you recommend I refactor? Is there an example out there of ways to structure this type of application “the Elixir way”? It’s not really a game, like the Elixir for Programmers course covers, so that may not have been the most useful guide for me. Is there a resource out there that structures an Elixir application – no Phoenix yet – that has similar goals to my CRUD-y Meetup clone?

Thanks in advance!

4 Likes

Hello and welcome to the forum,

It’s normal to design your business model with concept like User, Meetup, both in OOP and FP.

But You do not process them the same way. Design patterns in OOP and FP are totally different.

I would recommend this book (Examples are in F#).

Which was written by the author of this video

Please remember FP is just a mean to achieve Concurrency. Immutability allows a better isolation between processes. Erlang is described as CSP.

It is complicate to model concurrency in OOP, but it is a building block of Erlang/Elixir, with OTP. And supervision tree allows tolerance to failure.

2 Likes

If You want to understand Erlang/Elixir, I will also recommend You this video, from the author of Elixir in Action.

1 Like

Not really the subject but have you heard of mobilizon which is a clone of meet-up written in elixir.
It’s backed by a non profit organization (framasoft) and had a successful crowfunding campain.

Hi @dcrck, what I’d recommend to exercise is trying to separate your “schemas” from doing more logic, defining the structs, managing table mappings and changesets is already quite a responsibility. Persistence related logic, for example, could be defined in a “store” module (e.g. EventStore is the one that does Event finding, creating, updating etc), or you could be doing something more like contexts.

This article can also be interesting for you.

Cheers

2 Likes

As long as you keep away from shared mutable state, the exact design patterns of your app don’t have to conform 100% to the common wisdom.

The most important thing is that you (and your team) get around in the code easily and it’s quick to introduce changes. A blend between academism and practicality does it. :slight_smile:

5 Likes

Hi all,

Thank you for your links and explanations! I appreciate it. I’ll take a look at those resources once I get on a more stable connection and post again if I have any more questions in this same vein. :slight_smile:

1 Like