DEV Community

Federico Ramirez
Federico Ramirez

Posted on

On Adding Types to Ruby

This post started out as a reply on Reddit about this blog post, but it ended up being so long, I think a blog post would make more sense.

Basically, the blog post talks about how Ruby 3 will implement type checks.

Static typing vs Dynamic typing

I've always had mixed feelings when it comes to dynamic vs static typing. One one side, it's great to have a strict type system where you can easily apply enterprise design patterns, like Hexagonal Architecture and whatnot. It makes it much easier to work with big systems, with lots of developers.

On the other side, Ruby (and particularly Rails) was born from the opposite point of view: "We don't need all this crap to build our little app". So I can see why many Ruby devs dislike adding types to the language.

There's also the argument that for small teams of senior devs, a dynamic language like Ruby can make you more productive. Just good design and strict good practices is enough to have maintainable software.

The problem is not everyone is on the same page where it comes to code, and when working with junior devs, or external libraries, it's easy to end up mixing everything up.

I used to believe conventions and "good code" was enough, but after having to work with junior devs, particularly when you cant just write everything yourself and need to delegate stuff, limitations end up being a good thing.

Otherwise, you are stuck in an endless cycle or reviewing code and nobody is happy. The junior dev is frustrated because you bounce their code over and over again, and you are frustrated you have to review it many times, and end up looking like a strict asshole. What's worse, you might end up lowering the bar and just allowing for bad code in order to "get things done", which is one of the worst things that can happen to software.

A common mistake junior devs do is not caring about inconsistency in their return types. Sometimes they return an object, other times nil. A type system can easily catch this, and force them to make a decision. No need for you to point it out, the compiler/checker can do it. Many common mistakes like that can be fixed just by having a stricter language/ecosystem.

I love Ruby. It's by far my favorite language, and I feel very productive with it. But Ruby gives you too much power, after years of using it, sometimes I just want a simpler, redundant, less powerful solution with less possible headaches.

That being said though, I can't help but think: "Yeah but if you really want types, why use Ruby at all?" Sometimes, you are just stuck with a big codebase, and there's no way around it. But for new projects, it feels like the wrong language if you worry about that. And that's okay. Ruby doesn't have to do everything.

Discussion (2)

Collapse
erikwhiting88 profile image
Erik W

"Sometimes they return an object, other times nil." I don't understand what's wrong with this. Sometimes you want all or nothing, no?

Collapse
gosukiwi profile image
Federico Ramirez Author • Edited

The problem is that subtle bugs can appear when you are not consistent with your return types. For example:

find_person("Mike").greet # => this will error if find_person returns nil

# not even mentioning when LoD is broken
post.comments.first.person.name.titleize # if anything along the line here returns nil, it breaks

A solution to the above is always returning something that quacks like a person, so you can use the null object pattern and create a NullPerson, or even throwing an exception instead of returning nil is preferred.

Alternatively, you can use some kind of optional monad.