Session
This is not a pipe: replicating a functional pattern in an OO way
== Briefly
Rene Magritte, Belgian surrealist, painted a picture of a common brown tobacco pipe and underneath wrote the words, "this is not a pipe" (in french: ceci n'est pas une pipe). The Treachery of Images is one of his most famous works and this representation of double meaning and imitation is how it can feel implementing a functional programming concept in a language like Ruby.
There is no `|>` operator here, where everything's an object and sending messages is the order of the day. How can we leverage this pattern in an object oriented way? And why might we want to?
After all, in Ruby, "ceci n'est pas une pipe".
== The Details
So often do I find myself wishing that there was a mechanism built in to Ruby that would make a series of discrete operations straightforward and easily parsed by my teammates. But I've found that because it isn't a first-class language feature of Ruby, many folks I've worked with are either not aware of its "enshrinement" as a pattern or have interacted with it quite infrequently.
The concept is not an uncommon one to programmers, our frequently used shells have a pipe operator, and even a brief daliance with UNIX sorcery will likely have yielded some familiarity with it. Functional languages often have the concept of pipes built in with an operator `|>` or the like. Method chaining and method(calls(that(nest(themselves)))) are hardly unfamiliar territory.
It's not difficult to see why this is a common concept, transformation of data is fundamental to what computer programs do, and functional pipelines offer a robust framework for understanding complex operations.
I intend this session to introduce more Ruby developers to the pipeline pattern, even if it is not a first-class citizen of the Ruby ecosystem. The concepts explained here will start from basic OO principles and presuppose no more knowledge than Ruby fundamentals. The examples should be enlightening to those who have not worked with this pattern before, and offer a focused dive into the concept for those who are familiar but want to see how it can be useful to them in their work.
The session will explain the pattern and demonstrate how to build a pipeline in Ruby using TDD. This will add the benefit of showing those who might struggle with TDD a practical example of the workflow.
I'll frame the discussion with an introduction to the artwork "The Treachery of Images" by Rene Magritte, the surrealist painter.
[Wikipedia entry for The Treachery of Images][1]
The artwork's representation of a physical object as image, and it's bold yet unarguable statement "this is NOT a pipe" offers a way to talk about how we can build the pipeline pattern in a concise, easily understandable and developer-happiness focused way, even without a specific operator built into the language.
If we have time, we'll take a brief trip into the pipe operator that briefly became a part of Ruby, talk about why it was introduced, and eventually removed.
I. Introduction to pipelines
* what are their properties
- it's all about composition, function composition
- the source stage, the beginning
- the sink, or consumer, the last stage
* how they're used in functional languages
- F#, Elm, Elixir's pipe operator
- with first order functions, like javascript
* why and when might they be helpful
- what kinds of problems are they good for solving
- data transformation
- game loops
- testing is A DREAM when done right
- when might that complexity be too much
* when might you have implemented them without knowing it?
- map, reduce, etc. lend themselves to this idea
- method chaining can sometimes be something of a pipeline
II. Two types?
1. where one fn output is another's input
* like using `|` on the command line
* order is important
- the step before's output will have an effect on what the next step does
- types must match one to the next
2. where one data structure is acted on but passed to all steps
* "passthrough" pipeline
- the mental model of "dropping" the payload through a series of actors
* steps might "decide" to act or not based on the information in the payload
* order is important
- a step might act or not depending on previous steps
- the payload type will be the same, types aren't the limiting factor
III. Straightforward implementation
* something like reduce and lambdas
* that doesn't feel like "the ruby way"
IV. More OO, "ruby-like" implementation
* how is it different than simply the |> operator
* Pipeline class that marshals the operation
* Step class with shared inherited behavior
V. Escape hatch
* stop moving forward if something errors, cancel all future steps
* return that error to the caller of the pipeline
* implement this feature in our OO pipeline
VI. Dynamic pipelines
* not only deciding should each step act or not, but what steps should
be a part of the pipeline?
* implement in our OO pipeline
[1]: https://en.wikipedia.org/wiki/The_Treachery_of_Images
== The Pitch
"waitaminute... did I just write another functional pipeline?"
This is common refrain for me (usually in my head) while working. The pipeline pattern (like graph theory) is an elegant solution to so many situations in our work, and yet the pattern and concept hasn't filtered into our community, out of the functional world enough.
Because it's so familiar to me, and as someone who pairs often at work, I have experienced both introducing teammates to the pipeline pattern, and the excitement that comes along with getting to wield such a useful tool. I've been able to come up with a concise mental model for describing the pattern and its usefulness, and I would like to share it with a wider audience of Rubyists.
I’ve been in tech for the better part of a decade, but I’ve been a speaker, mentor and communicator for almost 20 years. I’ve taken the stage at corporate conferences and trade shows, as well as theatres and circus rings.
I bring a lightness and exuberance to my talks in order to share the excitement I feel about the topics I cover. I'm an accomplished conference speaker, with consistently polished visuals supporting funny and informative presentations.
Aji Slater
Development Team Lead, thoughtbot
Chicago, Illinois, United States
Links
Please note that Sessionize is not responsible for the accuracy or validity of the data provided by speakers. If you suspect this profile to be fake or spam, please let us know.
Jump to top