juanseph

juanseph

OOP like handler inheritance

I have been doing functional for a while already, but there’s some OOP pattern that I still like and can’t find the right approach to it

This pattern is a hierarchy of objects, a set of handlers (per object type) and a factory to instantiate the right handler based on caracteristics of the object.

I was wondering if someone has a nice and elegant implementation of this whole thing (behaviors with something else maybe?). I guess with pattern matching it can be cool

Some OOP example

Msg1 extends Msg extends Dao
Msg2 extends Msg extends Dao

Abstract MsgDispatcher
Abstract send(Msg m)

DispatcherOne extend MsgDispatcher
send(Msg m): ...

DispatcherTwo extend MsgDispatcher
send(Msg m): ...

Factory.getDispatcher(Msg1).send(Msg1) will invoke the method in DispatcherOne

Thanks!

Most Liked Responses

kokolegorille

kokolegorille

No inheritance, rather composition.

That’s a good fit for Protocol.

Pattern matching? Multi clause functions should do the job, maybe.

ityonemo

ityonemo

the official way to do this is with behaviours protocols, and a liberal use of defdelegate.

If you don’t want to do it with protocols directly, you can also use a protocol-lite:

defmodule Api do
  @callback foo(struct) :: integer
  @callback bar(struct) :: integer 
end

defmodule Msg1 do 
  defstruct [... fields ...]

  @behaviour Api

  def foo(struct), do: ...
  def bar(struct), do: ...
end

defmodule Msg2 do
  # demonstrates oop-style multiple-dispatch
  defstruct [... fields ...]

  @behaviour Api

  def foo(struct), do: ...
  def bar(struct), do: ...
end

defmodule Msg3 do
  # demonstrates OOP-style inheritance
  defstruct [... fields ...]
  
  @behaviour Api

  # note that the fields in Msg3 type must be compatible with the Msg1 and Msg2
  # function expectations of the field parameters, or else you will have a bad time.
  defdelegate foo(struct), to: Msg1
  defdelegate bar(struct), to: Msg2
end

defmodule Action do
  def adds_foo_and_bar(msg = %msg_type{}) do
    msg_type.foo(msg) + msg_type.bar(msg)
  end
end

# these statements dispatch against their respective module's foo and bar statements
Action.adds_foo_and_bar(%Msg1{...})
Action.adds_foo_and_bar(%Msg2{...})
Action.adds_foo_and_bar(%Msg3{...})

Note that making sure that the structs have compatible fields you need is your responsibility, if you want you can probably whip up some compile time macros to check that the structs are compliant**. And the “inheritance” of your functional components is also very much explicit, there’s no “inherit” that makes your code consumer guess what gets inherited and what doesn’t.

** hints: A module with defstruct implements the __struct__/0 function and at compile time you can retrieve the module’s struct-being built with Module.get_attribute(__MODULE__, :struct)

Anyways this kind of stuff is a little bit on the hard side because maybe this sort of abstraction is not necessarily the best thing to do. I’m still not sure if it’s a good pattern from OOP or an antipattern.

Where Next?

Popular in Discussions Top

andre1sk
A big advantage to Elixir is all the distributed goodness but for many applications running on multiple nodes having integrated Etcd, Zoo...
New
Rustixir
Hi everyone, im working on find best language/framework/system for high concurrency, high performance and stable performance after wor...
New
jeramyRR
This is an interesting article to read. Elixir’s performance, like usual, is excellent. However, it seems like the high CPU usage is co...
New
WolfDan
After doing a port from a c++ library to my project in phoenix I’ve seen that I need a faster way to run this algorithm and I found this ...
New
fireproofsocks
This is more of a general question, but I’m wondering how other people in the community think about the pattern matching in function sign...
New
praveenperera
How We Replaced React with Phoenix By: Thought Bot
New
IVR
Hi all, I’ve seen a number of related threads in the past, but I’d still be very curious to hear an up-to-date opinion on this topic. I...
New
acrolink
How does the two languages compare when it comes to server side application development? Any experiences or ideas? Thank you.
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
Markusxmr
Since Drab has been developed for a while in the open, introducing the Liveview functionality in a way it happend appears to undermine th...
New

Other popular topics Top

Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
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
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

We're in Beta

About us Mission Statement