Jake Worth

Jake Worth

Default to Programming Convention

Published: October 14, 2022 • Updated: February 09, 2023 2 min read

  • conventions

Trying to enforce unconventional coding preferences on a team is an uphill battle. When in doubt, default to convention.

Contrived Example

Consider this contrived example. Imagine that you don’t like Ruby on Rails delegators, which let you call a method on an instance through another instance. Here’s an example:

class Greeter < ActiveRecord::Base
  def hello
    'hello'
  end
end

class General < ActiveRecord::Base
  belongs_to :greeter
  delegate :hello, to: :greeter
end

General.new.hello # => "hello"

.hello is not defined on class General, yet we can call it because it is delegated to Greeter. Pretty cool!

Perhaps you don’t like this abstraction and would prefer that anytime hello is called, it’s done explicitly on the greeter instance:

General.new.greeter.hello # => "hello"

Maybe you don’t like this abstraction, or you want each developer to “know” where .hello is defined by seeing the greeter instance in the code.

So you make a rule: no delegators. You advocate for this more verbose style and ask for it in code reviews.

The Problem With Abandoning Convention

The problem with this preference is that delegators are a Ruby on Rails convention. They’ve been in the standard library for a long time. Everybody knows how they work. They’re uncontroversial.

And so, your programmers are going to use them, and your preference is inviting inconsistency. Programmers may follow the desired pattern in existing code, where examples of your preference exist, but they’ll forget to on new files. Unless you’re watching every PR or have installed supervisory tooling, delegate will start to popping up in your code. Why? Because it’s a convention.

Conventions exist for a reason. In this case, delegators support an idea that’s at least worth considering: the Law of Demeter. A template or programmer shouldn’t have to know that .hello isn’t defined on General; that’s an implementation detail. Or maybe you move .hello into General. No calls to .hello have to change if you’ve used a delegator.

Forbidding delegators in your code is opting out of a solution that solves a real problem. Are you certain you want to say they are never allowed?

Conclusion

If you’re going to buck convention, you must:

  • Have a great reason
  • Be willing to continually fight that battle
  • Accept the features and patterns you’re giving up

How does this advice align with your experience?

What are your thoughts on this? Let me know!


Join 100+ engineers who subscribe for advice, commentary, and technical deep-dives into the world of software.