<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/from-conditionals-to-polymorphism-inxv00dcw" -->

---
title: From Conditionals to Polymorphism | daily.dev
description: A step-by-step walkthrough of replacing a growing conditional with polymorphism using a 'time ago' formatter as the example. The post identifies Primitive...
canonical: https://daily.dev/posts/from-conditionals-to-polymorphism-inxv00dcw
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: From Conditionals to Polymorphism | daily.dev
og:description: A step-by-step walkthrough of replacing a growing conditional with polymorphism using a 'time ago' formatter as the example. The post identifies Primitive...
og:url: https://daily.dev/posts/from-conditionals-to-polymorphism-inxv00dcw
og:image: https://api.daily.dev/og/posts/inxv00Dcw.png
og:image:alt: From Conditionals to Polymorphism
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# From Conditionals to Polymorphism

**[Ruby Flow](https://daily.dev/sources/rubyflow)** · 13 min read · 0 upvotes · 0 comments

## Summary

A step-by-step walkthrough of replacing a growing conditional with polymorphism using a 'time ago' formatter as the example. The post identifies Primitive Obsession as the root smell, extracts a Duration class, then mechanically dismantles the case statement by turning each branch into a subclass (ZeroDuration, MinutesDuration, HoursDuration) and introducing a factory. It also covers when conditionals are legitimate vs. a smell, the Open/Closed principle in practice, the 'write the code you wish you had' design heuristic, and how the refactoring shifts existing tests from unit to integration tests while enabling new focused unit tests per variant.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://develclan.com/from-conditionals-to-polymorphism>

## Questions this post answers

### When is a conditional a code smell that should be replaced with polymorphism?

A conditional is a smell when it inspects a value to decide what kind of thing it is and picks behavior from that classification — it is doing type dispatch by hand. A conditional is legitimate when it answers a question that doesn't classify: a guard clause, a validation, a boundary, or a business rule comparing two values. The factory's case that picks a class is acceptable because its sole responsibility is object creation, not behavior dispatch.

_Developers refactoring legacy conditionals find the distinction between creation and behavior dispatch discussed regularly on daily.dev._

### How do I refactor a switch/case statement into polymorphism without breaking existing tests?

Follow four mechanical steps: isolate the conditional in one place, turn each branch into a method implementation on a separate class, introduce a factory method that picks the right class, then delete the original conditional. Work one branch at a time, running tests between each change. The conditional moves into the factory where its only job is choosing a class, not deciding behavior.

_Teams navigating this kind of incremental OO refactoring share patterns and pitfalls on daily.dev._

## Similar posts on daily.dev

- [494: Primitive Obsession](https://daily.dev/posts/494-primitive-obsession-lwfwy1srk) · RUBYLAND · 0 upvotes · 0 comments
- [Refactoring with Convergence Rules](https://daily.dev/posts/refactoring-with-convergence-rules-6ofmsa39f) · Ruby Flow · 0 upvotes · 0 comments
- [Level Up Your JavaScript – Detect Smells & Write Clean Code](https://daily.dev/posts/level-up-your-javascript-detect-smells-write-clean-code-hgp4gxycn) · freeCodeCamp · 51 upvotes · 5 comments

---

Tags: [#ruby](https://daily.dev/tags/ruby), [#design-patterns](https://daily.dev/tags/design-patterns)

[View this post on daily.dev](https://daily.dev/posts/from-conditionals-to-polymorphism-inxv00dcw)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"From Conditionals to Polymorphism","url":"https://daily.dev/posts/from-conditionals-to-polymorphism-inxv00dcw","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/from-conditionals-to-polymorphism-inxv00dcw"},"datePublished":"2026-08-07T15:32:25.140Z","dateModified":"2026-08-07T15:32:52.458Z","description":"A step-by-step walkthrough of replacing a growing conditional with polymorphism using a 'time ago' formatter as the example. The post identifies Primitive...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/7b837e26efd81839d01978232e694652?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/7b837e26efd81839d01978232e694652?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Ruby Flow","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Ruby Flow","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/a21aaa8bcbbf448193a016895c90a0e1","url":"https://daily.dev/sources/rubyflow"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/from-conditionals-to-polymorphism-inxv00dcw","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"ruby,design-patterns","timeRequired":"PT13M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Ruby Flow","item":"https://daily.dev/sources/rubyflow"},{"@type":"ListItem","position":3,"name":"From Conditionals to Polymorphism"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/from-conditionals-to-polymorphism-inxv00dcw#faq","mainEntity":[{"@type":"Question","name":"When is a conditional a code smell that should be replaced with polymorphism?","acceptedAnswer":{"@type":"Answer","text":"A conditional is a smell when it inspects a value to decide what kind of thing it is and picks behavior from that classification — it is doing type dispatch by hand. A conditional is legitimate when it answers a question that doesn't classify: a guard clause, a validation, a boundary, or a business rule comparing two values. The factory's case that picks a class is acceptable because its sole responsibility is object creation, not behavior dispatch. Developers refactoring legacy conditionals find the distinction between creation and behavior dispatch discussed regularly on daily.dev."}},{"@type":"Question","name":"How do I refactor a switch/case statement into polymorphism without breaking existing tests?","acceptedAnswer":{"@type":"Answer","text":"Follow four mechanical steps: isolate the conditional in one place, turn each branch into a method implementation on a separate class, introduce a factory method that picks the right class, then delete the original conditional. Work one branch at a time, running tests between each change. The conditional moves into the factory where its only job is choosing a class, not deciding behavior. Teams navigating this kind of incremental OO refactoring share patterns and pitfalls on daily.dev."}}]}
```

