parse_title(raw_api_response),

parse_title(raw_api_response),

Jun 03, 2026 domain-driven-design ruby-on-rails software-architecture technical-debt clean-code software-development

Last week, I was debugging a payment bug that cost our client $12,000 in erroneous refunds. The code looked perfect. The tests passed. The API responses were parsed correctly. But somewhere between the database and the business reality, something got lost in translation.

Sound familiar? This happens more often than we admit in our industry. And it usually traces back to one root cause: our code speaks "framework" instead of "domain."

The Telephone Game Nobody Talks About

Here's a scenario I've seen play out repeatedly across different teams and different codebases:

A stakeholder requests a feature to display "active users" in their dashboard. The product manager writes it in a ticket. The developer implements it by querying WHERE status = 'active'. Three months later, finance discovers the "active users" count includes thousands of bot accounts, trial users who never converted, and accounts with subscriptions that were cancelled but never properly deactivated.

Nobody purposely introduced this bug. The stakeholder meant "paying customers who can currently access the platform." The developer understood "users with an active status flag." The product manager just passed it along.

This is the telephone game of software engineering, and it happens because we skip the most important step: establishing a shared, unambiguous language before writing a single line of code.

Where Rails Makes It Easy to Go Wrong

Now, here's where Rails—bless its opinionated little heart—can work against us.

Rails encourages convention over configuration. It gives us ready-made nouns: User, Order, Product, Job. When we build models, we often map these directly to our database tables. And when stakeholders use words like "Job," "Order," or "User," we just create a model with that name and move on.

But business domains are messy. They have words that look like synonyms but aren't. They have concepts that look identical on the surface but have critically different meanings in context.

Take the word "hired." To HR, this might mean a candidate who accepted an offer and signed a contract. To a manager, "hired" might mean someone who actually showed up on their first day. To payroll, "hired" might mean someone who's been added to the system and is eligible for benefits. One word. Three different business meanings.

When our models use the same vocabulary without understanding these distinctions, we create systems that silently produce wrong results. The code doesn't crash. It just does the wrong thing—and you don't discover that until someone manually audits the output.

The Anti-Pattern Nobody Warns You About

You've probably seen service objects like this:

class JobCreationService
  def call
    return existing_job if existing_job

    job = Job.new(prepare_attributes)
    job.save!
    job.trigger_side_effects

    job
  end

  private

  def prepare_attributes
    {

Read in other languages: