EndPointCorp / end-point-blog

End Point Dev blog
https://www.endpointdev.com/blog/
17 stars 65 forks source link

Comments for Functional Handler - A Pattern in Ruby #916

Open phinjensen opened 6 years ago

phinjensen commented 6 years ago

Comments for https://www.endpointdev.com/blog/2014/01/functional-handler-pattern-in-ruby/ By Mike Farmer

To enter a comment:

  1. Log in to GitHub
  2. Leave a comment on this issue.
phinjensen commented 6 years ago
original author: Tim Case
date: 2014-01-22T13:57:44-05:00

Hi Mike, what you described looks exactly like a pattern known as Data-Context-Interaction or DCI which is a somewhat new topic of interest in the Rails world. What distinguishes what you did as DCI is:

1) You extracted to a separate class OrderControllerHandler instead of doing what would more commonly be done in the past which is to extract that logic to Order.

2) OrderControllerHandler#execute! very cleanly and obviously states with the use case is for the class:

def execute! lookup_order update_order calculate_tax calculate_shipping send_invoice end

From what little I know about DCI a major impetus for it is in the idea that there is a lot of value gained simply from describing some cohesive piece of logic in the "step through" algorithm like what you described above in the #execute! method. It's fairly easy for an outside observer not familiar with the code to look at the OrderControllerHandler and figure out what it does.

I'm still learning DCI myself: http://2drops.net/blog/my-first-try-with-dci/. Navigate down all the way to the bottom of this article and look at the code labeled "The Controller Action". Does that look familiar?

Now what distinguishes DCI from the pattern you described?

1) A slight semantic change, DCI would call your OrderControllerHandler class a "context" and you would name it a verb instead of a noun, perhaps: OrderUpdater, in Rails it's being proposed that you store this file as 'app/contexts/order_updater.rb'. Execute is a commonly used method so you would have OrderUpdater.execute!.

2) A "context" has a notion of "actors", in your example there is only one "actor" which is Order. DCI seems to excel at circumstances where you multiple collaborators needed for fulfilling a particular context. Where DCI takes an exotic turn is that in a DCI application your model objects would be simple dumb objects without much logic to interact with other classes. When a context is executed at runtime the "actors" passed into the context as arguments get the logic and methods necessary to fulfill the use case tacked onto them at runtime. What this does is to decouple the logic of use case from the classes that will be marshalled to execute the use case. If this last paragraph didn't make any sense trust that I'm trying to explain something interesting and probably doing a bad job of it, this is something that takes a few chapters of a book to explain properly.

The contexts exist as modules that can be included everytime you want to use them. The promise of DCI is that this smart logic can be combined and nested with other contexts to provide more complex interactions. As I listed above, you could begin to decouple the OrderControllerHandler by first naming it something that doesn't use the word controller or handler and more generally describes what it does. Finally I believe in your third question what you are describing as "payload" DCI describes as "actor".

This is all still very much a work in progress and the details of how it should all work is still being hammered out. Here's some resources if you are interested in learning more.

  1. DCI described by it's creator Trygve Reenskaug, (who also created another pattern you may have heard of called MVC)

  2. Clean Ruby by Jim Gay

  3. A sample DCI app in Ruby/Rails.

phinjensen commented 6 years ago
original author: Mike Farmer
date: 2014-01-23T14:32:15-05:00

Tim,

Thanks for the awesome comment. I haven't looked at DCI only just heard things about it. Now that you point out some of the similarities it has piqued my interest. I'll take a look!