Recent Posts

Unfinished: Designing helpful service objects. Part 2. Practice

11 minute read

This is a partially-written post, which will never be complete

I've been writing this article on-and-off since June 2020. I didn't like how it turned out and re-wrote it numerous times.

It tries to cover way too many things at once, and that's the problem I can't resolve without removing everything I've done and re-working the whole series. There are way too many assumptions and things which are missing for the complete picture. The reader would need the context for the article to be useful

However, the work still might serve as an inspiration or an example to some. Even as an anti-example. So I'm leaving it here with an "unfinished" notice

I’ve had countless arguments about software engineering, and “service objects” are one of the hot topics. I published an article where I assessed different approaches to designing service objects. I’ve planned to have a three-part series of posts:

Right now, I want to demonstrate how to apply those principles in practice.

This article may read like a tutorial on adding service objects to Rails app. Frankly, it is a tutorial on adding service objects to Rails app.

Designing helpful service objects. Part 1. Choosing the right design

17 minute read

I’ve been programming for a long time and I’ve had countless arguments about different things. I’d like to list top four reasons I’ve had an argument online.

Style guide. Thankfully, the number of arguments reduces as I mature, but I’m still spending a lot of time on them. I’d rather have an extremely opinionated styleguide and just stop talking about it. Something like wemake-python-styleguide, but for Ruby.

Monads. I have to admit that this word is almost banned from my vocabulary because of how many arguments I’ve had about it. It’s getting better, but people still like to argue about them. I wrote an article recently about them in hope to show that there’s nothing special to argue about – monads are just abstractions that may or may not be helpful. It all depends on your problems and approaches.

How to design domain logic. It may be an extremely interesting and helpful discussion, or it may turn into a useless argument. When it goes bad, it’s usually because we’re trying to discuss insignificant details and lower-level things. Where do we put arguments? What about dependency injection? How do we use instance variables? Fat model? Service objects? Ughh!

Different interpretation of common terminology. What do we mean when we say “interactor”? What about “architecture”? Is it a state when we’re just passing values from function to function? Is duck typing really an absence of types? What is a type, anyway? What does it mean to write “object oriented” code? What about “functional” approach? Do we need immutability in OO design? Those topics lead to endless discussions with little output.

As much as I love learning about new things, those arguments are extremely energy-draining. They got me thinking: since we’re usually going over the same thing, why don’t we just dump the knowledge somewhere and refer to it instead of arguing? That’s what I’m going to do.

I’m starting a series of blog posts about different topics in Ruby world. My goal is to describe different approaches to the same problems and highlight pros and cons of each one. Perhaps, pick a favorite one and promote it.

Right now I want to focus on two larger topics:

  1. Designing service objects
  2. Handling errors in domain logic. Exceptions, values, result objects

This is a first post of the series, and it will cover the first topic: building helpful service objects.

We will go through the basics: what are we talking about when we say “service object”. We’ll look through different approaches and see which ones bring the most benefit and which ones should probably be put to rest. In the end, I’m going to suggest a working design and a couple of guidelines you can use to improve your service object game.

Should I really use monads?

18 minute read

A couple of weeks ago I witnessed a dialogue in a Ruby chat. I’m paraphrasing, but it went like this:

xxx: What is dry? I’ve seen this gem prefix and discussions, but never actually learned about it.
yyy: It’s a set of libraries to tackle some problems.
zzz: Yeah, and introduce new ones, such as “How do I explain to my colleague that they need monads”.

Let’s be honest. I felt so many emotions that I couldn’t think straight. I’ve been discussing this exact topic so many times that I’ve exhausted myself. There’s a lot of misconceptions, frustration and plain skepticism around monads, and it all leads to aggressive rejection by many.

Right now, I want to finish this topic once and for all. Not going to do it in this post, though. I’m writing a huge piece on error handling techniques in Ruby, which will cover strong and weak points of different techniques, including monads.

In this post, I will try to step back and speak about monads from a more practical and emotional perspective. I will briefly explain what a monad really is, why is it valuable, and some of the common issues with it. It’s about people and technology, so don’t expect to see any code.

dry-rb 1.0: upgrading validations, types and schemas

9 minute read

I’m enthusiastic about dry-rb gems. Actually, I’ve never worked on Ruby projects without a dry-rb gem. However, some people are sceptical, as a lot of core dry-rb gems are still in their 0.x phase, which leads to a lot of breaking changes and hours of refactoring.

I’m happy to see dry-rb mature: dry-monads entered 1.0 phase in Summer 2018, and now two more libraries hit v1.0 milestones: dry-types and dry-struct; and dry-validation is in its 1.0 RC phase.

I haven’t updated my dry-rb gems for a couple of months, so I’ve missed a lot of breaking changes. Finally, I decided to upgrade the gems and write about the process. I’ll take a swing at automating my upgrade process as much as I can.

Partial application in Ruby

7 minute read

Ruby is a multi-paradigm language with a strong bias towards object-oriented programming. You can argue that its design is influenced by Alan Kay and Smalltalk, as opposed to C++/Java-style object-oriented languages. Thankfully, this object-oriented design doesn’t mean we can’t use ideas from functional programming. There’s a small list of functional traits in Ruby:

  • Expression-oriented syntax
  • Geeky names for Enumerable methods: filter, map, reduce, flat_map
  • Idiomatic monads
  • Railway oriented programming
  • lambdas and procs
  • … I can go on and on

There’s also one specific empowering feature: built-in support for partial application. In this article, I want to talk about implementation and use-cases for partial application in Ruby.