Stop Monkey Patching Everything

Ruby is an awesome, dynamically typed language that has very strong OO features and excellent syntatic sugar. You can write very expressive software in few lines that looks good. It should sound like music to your ears if you’re coming from some kind of ugly templated behemoth. After all, Ruby’s motto is “a programmer’s best friend” – and it is – but only if you don’t suck.

A small case study

Let’s say we have a zoo. You hire a bootcamp graduate and they prepare for you the perfect class hierarchy to manage your steed. It looks something like this.

class Animal
  def initialize(name, sound)
    @name, @sound = name, sound
  end

  def some_important_hook
    # things
  end
  
  def do_trick
    raise NotImplementedError 'haha pls implement'
  end
end

Impressed by your developer’s capacity to innovate, you let them go study the behavior of your animals so that they could write some software. They find out that it’s quite easy to turn both of these animals into glue. During code review, an engineering manager will berate them for producing this disgusting duplicate code.

class Horse < Animal
  def do_trick
    "http://elmers.com/"
  end
end

class Rabbit < Animal
  def do_trick
    "http://elmers.com/"
  end
end

Your developer studies for a fortnight before arriving to this solution. For those not in the loop, include will decorate your class’ instance methods with those found in the module. All sarcasm aside, this is the correct solution, and we should stop here.

module Gluable
  def do_trick
    "http://elmers.com/"
  end
end

class Horse < Animal
  include Gluable
end

class Rabbit < Animal
  include Gluable
end

…instead, management now wants some synergy every time #some_important_hook is run. Your developer thinks he is clever and produces this. Including a module into every subclass seems sooooooo 2006. Instead, we can type acts_as_gluable in our subclass! How clever!

module Gluable
  def self.included(other)
    other.extend(ClassMethods)
  end

  def do_trick
    "http://elmers.com/"
  end

  def some_important_hook
    # overly complex and poorly tested business logic
    super
  end

  module ClassMethods
    def acts_as_gluable
      include Gluable
    end
  end
end

How NOT clever

Replace Animal with ActiveRecord::Base and prepare for the biggest clusterfuck you’ve ever seen. Everybody thinks it’s fashionable to make crude monkeypatches to the base AR class and ends up bringing in Railtie dependencies when their library really focuses on adding two numbers or doing some geocoding. Here is an example of a geocoding library doing a lot of not-geocoding. Additionally, to facilitate their mess, they will override core ActiveRecord lifecycle hooks (e.g. #before/after_*), or append their own methods in ActiveRecord::FinderMethods that depend on other methods in that external module. Are you crying yet? You should be.

Why is it a problem?

The DSL methods that they include to decorate your model with domain specific functionality now exists in every model your project will ever have. Additionally, the support required to do this patching/integration usually ends up adding either a large part of active_support or rails as a dependency. This is not even the worse part; sometimes these patches will break other libraries or even ActiveRecord itself.

It is 2017. Myself and many other developers prefer to work on microservice oriented applications. If sharing a database is something that your architecture requires (not all of us do the most clever, 3489248923423-Kafka-shard with 8394248e+01 ElasticSearch cluster services), then you don’t get to make portable models. Today while attempting to package all of our database models in an external gem, I had to read through the source of at least 5+ libraries to find out how to make their functions available without Rails. It isn’t necissarily difficult to do – but I noticed that most of the code was just to provide this convenient DSL sugar…and for no benefit at all.

I really don’t mean to sound so angry, but not everybody uses Rails for everything anymore. And that’s a good thing. Our ecosystem is maturing, finding alternatives, growing. Ruby’s metaprogramming facilities make it so easy for someone to write all of this seemingly “automagic” software, with include and extend hooks, great reflection support, and the whole 9 yards. It also makes it 100x easier for you to forget that you are committing abuses just becuase committing them is so much fun. If Ruby is to continue maturing, we need to exercise some self control as a community – or Ruby will become a thing of the past. And wouldn’t that be a damn shame.

G4 MDD: Debian Sid!

I’m installing Debian on my FW 800 MDD PowerMac G4, and I’m going to talk about it here so you too can convince yourself that your Friday night, is in fact, probably better.

OS 9 Retrolust, Part 1

My buddy Ari is giving me his PowerMac G4 MDD 1.25. I’ve always collected old Apple machines but this is going to be quite an experience for me. When I was younger, my parents bought me an iBook G4 1.42 14” to do schoolwork on, but see – it was a “New World” Mac that was never capable of running Mac OS 9. The only reason for this I suspect is some kind of assertion in Apple’s OpenFirmware flavor. Fun fact (if you didn’t already read the Wikipedia page): Sun is responsible for OF and was kind of a big deal back in the day. Never as big as our new EFI standards, but I digress.

Bye, GitHub Pages

To keep in spirit with New Years Resolutions, I decided to redo this page by finding a nice template and moving some stuff around. I am generally not one to click on adverts or even jump ship to new products, but the folks at Netlify seem to be doing something right. Previously, I had used GitHub Pages to host this; it did a great job, except I wanted one thing (even though, I serve static content, so the point is completely and utterly moot) – I wanted SSL. Netlify gave me free SSL via Let’s Encrypt, and furthermore, they made it easy. The set-up from start to finish was mostly cosmetic, I had to edit my A and CNAME records with my DNS provider and then just click a big giant “enable cert” button in my new admin panel.

PS4 Network MITM

I decided that I wanted to run my PS4 through a proxy so I can see if the version assertion could possibly be ‘fixed’ by some network manipulation. I found a bunch of things out but was unsuccessful!