From OOP to Functional programming: best approach to achieve composition behaviour in Elixir?

Hi everyone,

Simple example: I have a content that can have plain or html body and a static or dynamic abstract. We can model it to use composition in the following way:

So, it’s pretty simple to use and understand how it works. If I want plain text content with dynamic abstract I just build my Content object with the respective concrete classes. If I want a static abstract it’s just a matter of creating a new object.

Do we have anything similar in Elixir and/or functional programming in general? Should I think of this problem in a different way?

Thank you.

2 Likes

In short, need to think of it a different way. :slight_smile:

From a horribly broken OOP perspective, think of an interface as a ‘behaviour’, a ‘class definition’ as a module, and a ‘class instance’ as an Actor/Process (should use a GenServer most of the time). You pass the Actor/Process PID around like you would a pointer in OOP languages.

However, that is really quite wrong if you went all out like that, in reality functional composition is significantly shorter and more powerful than OOP constructs and those should be used in general. As per the XY Problem, instead of saying ‘how’ you want to accomplish something, say ‘what’ you are wanting to accomplish, like what inputs and what outputs, we can help you convert from OOP to better methods then (that can help you when in OOP languages too). :slight_smile:

2 Likes

First of all: thanks!

I suspected that from the beginning :smile:

Yep. Bad idea doing that.

Ok, so let’s imagine simple blog that works this way:

We have two fields: body and abstract.

  1. If someone fills the body and abstract, we have plain text and static abstract.
  2. If the abstract is not filled then we have dynamic abstract, that is created based on the body.
  3. If an URL is dropped in the content, the the page is loaded and we create an html content. The abstract then follows the same previous rules.

Is that better to explain this problem?

2 Likes

By body and abstract, what are the possible values they can contain, let’s define that first as that will drive the rest of the code. For this post I will assume:

body : string() # Body is always a string
abstract : string() | nil # abstract is also a string or nil
post : { body, abstract } # post is a tuple of a body and an abstract

As always you should access data via functions, so you’d have something like a get_abstract call, maybe like this:

def get_abstract({body, nil}), do: gen_abstract_from(body)
def get_abstract({_body, abstract}), do: abstract

So if abstract is nil, then generate an abstract from the body, else return the abstract

What URL? By content do you mean body?

Feel free to use pseudo-code to describe this too, I still have too much blood in my coffeestream and we are all programmers here. :slight_smile:

3 Likes

Let’s imagine the following form:

<form name="content">
    <input name="abstract" type="text">
    <textarea name="body">
    <input name="body-content-type" type="hidden">
 </form>

So we either have an empty input or a filled input for both fields.

Yes, I meant body. So if I fill an URL in the “body” textarea, a link to some news for instance, let’s suppose that the client will load the relevant html, fill the “body-content-type” and send it back to me.

Assuming that my content can be represented as

an_awesome_content = {type, body, abstract}

May this is a better approach?

defmodule Content
  def get_body({'text/plain', body, _}), do: handle_plain_text(body)
  def get_body({'text/html', body, _}),do: handle_html_text(body)
  def get_abstract({_type, body, nil}), do: gen_abstract_from(body)
  def get_abstract({_type, _body, abstract}), do: abstract
end
1 Like

Yeah that is a very usual functional way. :slight_smile:

What are you wanting to accomplish next?

2 Likes

Since I want to handle complex data - contents that have not only abstract and body, but also authorship metadata, publishing info, tags and other stuff - I guess I’m going to look into structs now.

Thank you very much for all your answers :smiley:

1 Like