After writing about the team that deleted 200,000 lines of AI-generated code without breaking their app, a few people asked me:
“If AI is getting so good at writing code, why can’t it also reuse code properly?”
That’s the heart of the problem.
AI can produce code.
It can suggest patterns.
But it doesn’t understand why one abstraction should exist and why another should not.
It has no concept of design intent, evolution over time, or maintainability.
And that’s why AI-generated code often fails at the very thing great software engineering is built upon: reusability.
Reusability Isn’t About Copying Code
Let’s start with what reusability really means.
It’s not about reusing text.
It’s about reusing thought.
When you make code reusable, you’re encoding an idea a shared rule or process in one place, so it can serve multiple contexts.
That requires understanding how your domain behaves and where boundaries should exist.
Here’s a small example in Ruby 3.4:
# A naive AI-generated version
class InvoiceService
def create_invoice(customer, items)
total = items.sum { |i| i[:price] * i[:quantity] }
tax = total * 0.22
{
customer: customer,
total: total,
tax: tax,
grand_total: total + tax
}
end
def preview_invoice(customer, items)
total = items.sum { |i| i[:price] * i[:quantity] }
tax = total * 0.22
{
preview: true,
total: total,
tax: tax,
grand_total: total + tax
}
end
end
It works. It looks fine.
But the duplication here is silent debt.
A small tax change or business rule adjustment would require edits in multiple places which the AI wouldn’t warn you about.
Now, here’s how a thoughtful Rubyist might approach the same logic:
class InvoiceCalculator
TAX_RATE = 0.22
def initialize(items)
@items = items
end
def subtotal = @items.sum { |i| i[:price] * i[:quantity] }
def tax = subtotal * TAX_RATE
def total = subtotal + tax
end
class InvoiceService
def create_invoice(customer, items, preview: false)
calc = InvoiceCalculator.new(items)
{
customer: customer,
total: calc.subtotal,
tax: calc.tax,
grand_total: calc.total,
preview: preview
}
end
end
Now the logic is reusable, testable, and flexible.
If tax logic changes, it’s centralized.
If preview behavior evolves, it stays isolated.
This is design thinking not just text prediction.
Why AI Struggles with This
AI doesn’t understand context it understands correlation.
When it generates code, it pulls from patterns it has seen before. It recognizes that “invoices” usually involve totals, taxes, and items.
But it doesn’t understand the relationship between those things in your specific system.
It doesn’t reason about cohesion (what belongs together) or coupling (what should stay apart).
That’s why AI-generated abstractions often look reusable but aren’t truly so.
They’re usually overgeneralized (“utility” modules that do too much) or underabstracted (duplicate logic with slightly different names).
In other words:
AI doesn’t design for reuse it duplicates for confidence.
A Real Example: Reusability in Rails
Let’s look at something familiar to Rubyists: ActiveRecord scopes.
An AI might generate this:
class Order < ApplicationRecord
scope :completed, -> { where(status: 'completed') }
scope :recent_completed, -> { where(status: 'completed').where('created_at > ?', 30.days.ago) }
end
Looks fine, right?
But you’ve just duplicated the status: 'completed' filter.
A thoughtful approach is:
class Order < ApplicationRecord
scope :completed, -> { where(status: 'completed') }
scope :recent, -> { where('created_at > ?', 30.days.ago) }
scope :recent_completed, -> { completed.recent }
end
It’s subtle but it’s how reusability works.
You extract intent into composable units.
You think about how the system wants to be extended later.
That level of foresight doesn’t exist in AI-generated code.
The Human Element: Judgment and Intent
Reusability isn’t just an engineering principle it’s a leadership one.
Every reusable component is a promise to your future self and your team.
You’re saying: “This logic is safe to depend on.”
AI can’t make that promise.
It can’t evaluate trade-offs or organizational conventions.
It doesn’t know when reuse creates value and when it adds friction.
That’s why good engineers are editors, not just producers.
We don’t chase volume; we curate clarity.
My Takeaway
AI is incredible at generating examples.
But examples are not design.
Reusability real, human-level reusability comes from understanding what stays constant when everything else changes.
And that’s something no model can infer without human intent behind it.
So yes AI can write Ruby.
It can even generate elegant-looking methods.
But it still can’t think in Ruby.
It can’t feel the rhythm of the language, or the invisible architecture behind a clean abstraction.
That’s still our job.
And it’s the part that makes engineering worth doing.
Written by Ivan Turkovic; technologist, Rubyist, and blockchain architect exploring how AI and human craftsmanship intersect in modern software engineering.