Code Smell: Hardcoded Stateless Properties

Your constructors are hoarding useless roommates. Time to evict them with proper dependency injection.

Ditch Hardcoded Dependencies in Constructors Now — theAIcatchup

Key Takeaways

  • Evict hardcoded stateless utils from constructors — use DI or inline.
  • This smell tanks testability and hides coupling; linters catch it easy.
  • AI spits it out often, but detects it flawlessly when shown.

Picture this: devs everywhere buzzing about AI as the ultimate code whisperer, churning out bug-free masterpieces on demand. What we got? Code riddled with hardcoded stateless properties—those sneaky instance variables born in constructors via ‘new’. It’s like handing a surgeon a scalpel superglued to their palm. Useless for the next op.

And boom—this flips the script. No longer can you swap that utility class for a mock during tests, or tweak it without gutting the whole processor. Suddenly, your sleek UserProcessor becomes a jealous hoarder, clutching its MockDataProvider forever.

Why Does This Code Smell Even Exist in 2024?

Look, stateless classes—think formatters, validators, pure functions wrapped in objects—they’re cheap as dirt to spin up. No state, no drama. But shove one into a constructor like this:

class UserProcessor { private provider: MockDataProvider; constructor() { this.provider = new MockDataProvider(); // Guilty as charged. } process(data: any) { return this.provider.format(data); } }

You’re not just optimizing prematurely; you’re welding collaborators into permanent roommates. They fight. A lot.

Here’s the thing. Real-world workers grab tools as needed—hammer for nails, saw for wood. Not lugging an arsenal bolted to their belt. Software should mirror that fluidity. Hardcoding? It mimics a cyborg nightmare, half-human, half-toolbox.

But wait—AI generators devour this pattern. Feed ‘em a prompt, and out pops constructor-new madness. Why? Their training data’s polluted with quick-and-dirty scripts where DI feels like overkill. (Yeah, that GitHub repo you ‘borrowed’ from? Karma.)

“Coupling is the enemy of change” — Rich Hickey

Spot on. This smell births high coupling, testing hell, hidden side effects. Stack traces bloat. Intent muddles—readers think that provider’s core to the class, not a swappable sidekick.

How Bad Is Hardcoded Stateless Properties for Testing?

Brutal. Imagine unit testing UserProcessor. Can’t mock that private provider without reflection hacks or wrapper classes. Gross.

Switch to injection:

interface DataProvider { format(data: any): any; }

class UserProcessor { constructor(private readonly provider: DataProvider) {} process(data: any) { return this.provider.format(data); } }

Now? Mock city. new MockProvider() slides in easy. Or pass as parameter for one-offs:

process(data: any, provider: DataProvider = new MockDataProvider()) { return provider.format(data); }

Static methods? Even leaner for pure utils. Inline the logic if it’s tiny. Local vars for burst usage. Point is: flex.

And linters? They sniff ‘new’ in constructors like bloodhounds. Most flag private fields auto-instantiated. Listen to ‘em.

AI’s Blind Spot: Generating This Smell on Autopilot

So, everyone’s expecting AI to evolve into a clean code sage. Ha. It hallucinates this smell constantly—stateless utils hardcoded because “it just works.” Show it the code above, sans instructions? ChatGPT, Claude, they nod along. Prompt for fixes? Bam, DI enlightenment.

My unique twist: this echoes the ’90s OOP bloat, where every class hoarded helpers till systems ossified. Bold prediction—as AI scrapes more modern repos heavy on DI (think Spring, NestJS), it’ll natively dodge this by 2026. But right now? You’re the guardrail. Don’t buy the hype that AI code’s ready-to-ship. It’s beta—smelly beta.

Critique time: original posts call it opinion, sure, but companies peddle AI as flawless pair-programmers. Spin. They’re not. This smell proves humans still rule refactoring.

Inline It or Inject: Quick Fixes That Stick

Tired of stack clutter? Inline creation:

class UserProcessor { constructor() {} process(data: any) { return new MockDataProvider().format(data); // Fresh each call. No state baggage. } }

Zero coupling. Pure. But for reuse? DI wins.

Watch constructors. Hunt ‘new’. Refactor ruthlessly. Your future self? Thanks you with beer.

Premature optimization whispers “cache it.” Ignore. Stateless means stateless—create on demand.

Why Does This Matter for Developers Right Now?

AI floodgates are open. Copilot, Cursor, they’re everywhere. But without smell radar, your codebase turns Frankenstein—pieced from AI snippets, rigid as rebar.

Energy here: imagine AI + human vigilance = the platform shift. Codebases that morph like liquid metal. Hardcoded smells? First casualty.

Wander a sec—I’ve seen teams ship this, watch tests crumble under prod load. Side effects hid in that “stateless” provider. Boom.

Fix it. Inject. Pass params. Static. Local. Your call, but move.


🧬 Related Insights

Frequently Asked Questions

What is hardcoded stateless properties code smell?

It’s instantiating stateless utility classes (like formatters) directly in constructors as private instance vars—creates tight coupling, test woes, rigid designs.

How to fix hardcoded dependencies in constructors?

Use dependency injection via constructor params, pass as method args, static methods, or inline creation/logic. Linters help spot ‘em.

Why do AI code generators create hardcoded stateless properties?

Training on quick scripts favors ‘new’ in constructors for speed; lacks nuanced DI unless prompted. Humans must review.

Priya Sundaram
Written by

Hardware and infrastructure reporter. Tracks GPU wars, chip design, and the compute economy.

Frequently asked questions

What is hardcoded stateless properties code smell?
It's instantiating stateless utility classes (like formatters) directly in constructors as private instance vars—creates tight coupling, test woes, rigid designs.
How to fix hardcoded dependencies in constructors?
Use <a href="/tag/dependency-injection/">dependency injection</a> via constructor params, pass as method args, static methods, or inline creation/logic. Linters help spot 'em.
Why do AI code generators create hardcoded stateless properties?
Training on quick scripts favors 'new' in constructors for speed; lacks nuanced DI unless prompted. Humans must review.

Worth sharing?

Get the best AI stories of the week in your inbox — no noise, no spam.

Originally reported by dev.to

Stay in the loop

The week's most important stories from theAIcatchup, delivered once a week.