<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged codesmell</title>
<link>https://coderlegion.com/tag/codesmell</link>
<description>Powered by Question2Answer</description>
<item>
<title>Code Smell 322 - Request Data in Long-Lived Variables (PHP Vulnerability)</title>
<link>https://coderlegion.com/32009/code-smell-322-request-data-in-long-lived-variables-php-vulnerability</link>
<description>&lt;p&gt;&lt;em&gt;Your request is gone. Your pointer is not.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Don't keep request-owned pointers in long-lived variables, or the next request reads freed memory.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-&quot;&gt;Problems 😔&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Dangling_pointer&quot;&gt;Use after free&lt;/a&gt; on stale request memory&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Arbitrary_code_execution&quot;&gt;Remote code execution&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Hidden &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-209-side-effects&quot;&gt;side effects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stale state crosses into a later request&lt;/li&gt;
&lt;li&gt;Stale values, like a bad &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-49-caches&quot;&gt;cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Tests miss cross-request failures&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-&quot;&gt;Solutions 😃&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&quot;&gt;Scope state&lt;/a&gt; per request&lt;/li&gt;
&lt;li&gt;Centralize state ownership&lt;/li&gt;
&lt;li&gt;Initialize before early consumers&lt;/li&gt;
&lt;li&gt;Clear references before freeing&lt;/li&gt;
&lt;li&gt;Cover every exit path&lt;/li&gt;
&lt;li&gt;Block late writes&lt;/li&gt;
&lt;li&gt;Test consecutive worker requests&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactorings-&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&quot;&gt;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context-&quot;&gt;Context 💬&lt;/h2&gt;
&lt;p&gt;A server process can live for hours and handle many requests in a row, while a request may last milliseconds.&lt;/p&gt;
&lt;p&gt;When you store a request's pointer in a process-wide variable, you tie two lifetimes together without saying so.&lt;/p&gt;
&lt;p&gt;The request ends and the runtime frees its memory, but the variable keeps the address.&lt;/p&gt;
&lt;p&gt;The next request starts, and some code runs before initialization and reads that variable.&lt;/p&gt;
&lt;p&gt;It trusts the address, but something else may already be using that memory.&lt;/p&gt;
&lt;p&gt;A fatal error can interrupt an operation before it resets its state.&lt;/p&gt;
&lt;p&gt;Timeouts, uncaught errors, and memory exhaustion can all trigger this path.&lt;/p&gt;
&lt;p&gt;Late writes can also repopulate state after shutdown has already cleared it.&lt;/p&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6337/we-need-to-stop-the-bugs&quot;&gt;defect&lt;/a&gt; depends on both sides: one operation leaves stale state behind, and another operation reads or acts on it.&lt;/p&gt;
&lt;p&gt;An attacker needs two requests handled by the same worker: one that leaves a stale value and one that reads it.&lt;/p&gt;
&lt;p&gt;Under the right memory layout, that sequence turns a use after free into remote code execution.&lt;/p&gt;
&lt;p&gt;This smell lives in native code, like a language runtime or an extension, where you manage memory by hand.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-&quot;&gt;Sample Code 💻&lt;/h2&gt;
&lt;h3 id=&quot;wrong-&quot;&gt;Wrong 🚫&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;// CONCEPTUAL MODEL: NOT php-src code and NOT an exploit.
// Don't use this skeleton to try to reproduce the real
// attack vector. It exists only to show the lifetime defect.
// All names are invented, except the quoted TODO at the end.
//
// A worker serves many requests in a row.
// Its globals live as long as the worker does.
static error_state *last_error;  // points into request memory

void request_shutdown(void) {
    if (fatal_error_happened) {
        free_request_memory();
        return;  // skips the reset below
    }
    free_request_memory();
    last_error = NULL;
}

// A second way to get stale state: a late warning during
// shutdown refills the global AFTER it was cleared.
void late_diagnostic(const char *message) {
    last_error = new_error_state(message);
}

// The next request calls this before it initializes
// anything, and trusts the stale value.
void report_error(void) {
    use(last_error);
}

// Real, from ext/session/session.c: a TODO the patch
// removed from php_rinit_session_globals():
// &quot;These could be moved to MINIT and removed.
//  These should be initialized by
//  php_rshutdown_session_globals() always when
//  execution is finished.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-&quot;&gt;Right 👉&lt;/h3&gt;
&lt;p&gt;The first example shows selected excerpts from the actual &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/php/php-src/commit/31c0ea7d7ff&quot;&gt;PHP fix&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;// EXCERPTS FROM THE PHP FIX: commit 31c0ea7d7ff (reordered).
// This is NOT the complete fix. The commit also replaces
// out-of-memory bailouts with a delayed soft failure plus a
// hard exit at a higher threshold, and it touches many
// runtime components. Only resets and early init shown here.
// They illustrate Solutions 3, 4 and 5.
//
// Ref: Zend/zend_execute_API.c,
//      zend_shutdown_executor_values()
// The backtrace field below exists only in PHP 8.5.
/* may be used by zend_error_zstr_at before init_executor */
ZVAL_UNDEF(&amp;amp;EG(last_fatal_error_backtrace));
EG(record_errors) = false;
EG(num_errors) = 0;
EG(errors) = NULL;
EG(error_handling) = EH_NORMAL;
EG(exception) = NULL;

// Ref: main/main.c, php_request_shutdown()
/* May be accessed before php_request_startup() */
// (inside the loop that destroys each http_global)
ZVAL_UNDEF(&amp;amp;PG(http_globals)[i]);
// (end of the function)
PG(modules_activated) = 0;

// Ref: ext/session/session.c,
//      php_session_rfc1867_callback(),
//      case MULTIPART_EVENT_START
/* This runs before RINIT, so we need to clear these early */
php_rinit_session_globals();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second example is a design sketch, not PHP code.&lt;/p&gt;
&lt;p&gt;It illustrates one possible approach to managing state ownership and cleanup.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;// DESIGN LESSON: NOT the PHP patch, only a sketch.
// It isn't production-ready: it needs real ownership
// and lifetime rules for every resource it touches.
// It shows Solutions 1 to 6.
//
// The request owns its state, so nothing outlives it.
void handle_request(worker *w) {
    request_ctx ctx;
    request_ctx_init(&amp;amp;ctx);
    // run_request() must come back here on fatal errors
    // too, so cleanup runs on every exit path.
    run_request(w, &amp;amp;ctx);
    request_ctx_cleanup(&amp;amp;ctx);
}

// Each state owner gets an explicit cleanup operation.
void errors_owner_cleanup(errors_owner *owner) {
    // 1. Refuse late updates. This alone isn't enough:
    //    every other path that can publish a reference
    //    must also go through the owner.
    owner-&amp;gt;accepting_updates = false;
    // 2. Clear every reference into request memory.
    clear_references_into_request_memory(owner);
    // 3. Release what the owner owns.
    release_owned_resources(owner);
}

// Call it before request memory is released, on every
// exit path. Then initialize the owner before any early
// consumer can read it during the next request.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-&quot;&gt;Detection 🔍&lt;/h2&gt;
&lt;p&gt;[X] Semi-Automatic&lt;/p&gt;
&lt;p&gt;You search for variables that hold a pointer to request memory but live in process scope.&lt;/p&gt;
&lt;p&gt;You compare every startup initialization with its shutdown reset, and a variable missing from one of them is suspect.&lt;/p&gt;
&lt;p&gt;Symmetry alone isn't enough, because a late write can bring the stale value back after the reset.&lt;/p&gt;
&lt;p&gt;For runtime or native-extension code, you need an instrumented build with AddressSanitizer or Valgrind, sometimes with the runtime's own allocator disabled.&lt;/p&gt;
&lt;p&gt;You send consecutive requests through the same worker, make the first one fail on purpose, and inject allocation failures so the error paths run.&lt;/p&gt;
&lt;h2 id=&quot;exceptions-&quot;&gt;Exceptions 🛑&lt;/h2&gt;
&lt;p&gt;Data that truly belongs to the process, like configuration or compiled &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-49-caches&quot;&gt;caches&lt;/a&gt;, can live as long as the process.&lt;/p&gt;
&lt;p&gt;The smell appears only when that data refers to request-owned memory or state.&lt;/p&gt;
&lt;p&gt;The smell matters most in runtimes with persistent workers, where one process serves many requests in a row.&lt;/p&gt;
&lt;p&gt;You shouldn't rely on a process dying to clean up after you.&lt;/p&gt;
&lt;h2 id=&quot;tags-&quot;&gt;Tags 🏷️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-&quot;&gt;Level 🔋&lt;/h2&gt;
&lt;p&gt;[x] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important-&quot;&gt;Why the Bijection Is Important 🗺️&lt;/h2&gt;
&lt;p&gt;A request is a bounded interaction in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When it ends, everything that belongs to it ends too.&lt;/p&gt;
&lt;p&gt;When your code lets a piece of that interaction survive in a global, you break the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The model now holds something that no longer exists in the MAPPER.&lt;/p&gt;
&lt;p&gt;The next interaction inherits a stale reference and trusts it, because nothing marked it as dead.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-&quot;&gt;AI Generation 🤖&lt;/h2&gt;
&lt;p&gt;AI-generated code can introduce this smell when it uses global state to avoid passing dependencies explicitly.&lt;/p&gt;
&lt;p&gt;You ask for a shared status value, a cache, or a shortcut that avoids passing a parameter through five functions.&lt;/p&gt;
&lt;p&gt;Using a global may seem like the smallest change that solves the problem.&lt;/p&gt;
&lt;p&gt;The risk grows when the code runs in long-lived workers and stores references to shorter-lived memory.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-&quot;&gt;AI Detection 🧲&lt;/h2&gt;
&lt;p&gt;AI can detect it if you ask for a lifetime analysis.&lt;/p&gt;
&lt;p&gt;Try: &quot;List every global that stores a pointer to request-scoped memory and show where each one gets reset, including error paths.&quot;&lt;/p&gt;
&lt;p&gt;A generic review prompt may miss lifetime problems that appear only on error paths or across consecutive requests.&lt;/p&gt;
&lt;h3 id=&quot;try-them-&quot;&gt;Try Them! 🛠&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Find every global that holds a pointer to request-scoped memory, give each long-lived variable an explicit reset, and run it on every exit path before the request's memory is freed&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Find+every+global+that+holds+a+pointer+to+request-scoped+memory%2C+give+each+long-lived+variable+an+explicit+reset%2C+and+run+it+on+every+exit+path+before+the+request%27s+memory+is+freed%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Find+every+global+that+holds+a+pointer+to+request-scoped+memory%2C+give+each+long-lived+variable+an+explicit+reset%2C+and+run+it+on+every+exit+path+before+the+request%27s+memory+is+freed%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Find+every+global+that+holds+a+pointer+to+request-scoped+memory%2C+give+each+long-lived+variable+an+explicit+reset%2C+and+run+it+on+every+exit+path+before+the+request%27s+memory+is+freed%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Find+every+global+that+holds+a+pointer+to+request-scoped+memory%2C+give+each+long-lived+variable+an+explicit+reset%2C+and+run+it+on+every+exit+path+before+the+request%27s+memory+is+freed%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Find+every+global+that+holds+a+pointer+to+request-scoped+memory%2C+give+each+long-lived+variable+an+explicit+reset%2C+and+run+it+on+every+exit+path+before+the+request%27s+memory+is+freed%3A+%60%60%60c%0D%0A%2F%2F+CONCEPTUAL+MODEL%3A+NOT+php-src+code+and+NOT+an+exploit.%0D%0A%2F%2F+Don%27t+use+this+skeleton+to+try+to+reproduce+the+real%0D%0A%2F%2F+attack+vector.+It+exists+only+to+show+the+lifetime+defect.%0D%0A%2F%2F+All+names+are+invented%2C+except+the+quoted+TODO+at+the+end.%0D%0A%2F%2F%0D%0A%2F%2F+A+worker+serves+many+requests+in+a+row.%0D%0A%2F%2F+Its+globals+live+as+long+as+the+worker+does.%0D%0Astatic+error_state+%2Alast_error%3B++%2F%2F+points+into+request+memory%0D%0A%0D%0Avoid+request_shutdown%28void%29+%7B%0D%0A++++if+%28fatal_error_happened%29+%7B%0D%0A++++++++free_request_memory%28%29%3B%0D%0A++++++++return%3B++%2F%2F+skips+the+reset+below%0D%0A++++%7D%0D%0A++++free_request_memory%28%29%3B%0D%0A++++last_error+%3D+NULL%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+A+second+way+to+get+stale+state%3A+a+late+warning+during%0D%0A%2F%2F+shutdown+refills+the+global+AFTER+it+was+cleared.%0D%0Avoid+late_diagnostic%28const+char+%2Amessage%29+%7B%0D%0A++++last_error+%3D+new_error_state%28message%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+The+next+request+calls+this+before+it+initializes%0D%0A%2F%2F+anything%2C+and+trusts+the+stale+value.%0D%0Avoid+report_error%28void%29+%7B%0D%0A++++use%28last_error%29%3B%0D%0A%7D%0D%0A%0D%0A%2F%2F+Real%2C+from+ext%2Fsession%2Fsession.c%3A+a+TODO+the+patch%0D%0A%2F%2F+removed+from+php_rinit_session_globals%28%29%3A%0D%0A%2F%2F+%22These+could+be+moved+to+MINIT+and+removed.%0D%0A%2F%2F++These+should+be+initialized+by%0D%0A%2F%2F++php_rshutdown_session_globals%28%29+always+w&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-&quot;&gt;Conclusion 🏁&lt;/h2&gt;
&lt;p&gt;A global can outlive the memory its pointer references.&lt;/p&gt;
&lt;p&gt;That mismatch is what makes it a smell.&lt;/p&gt;
&lt;p&gt;When you see a long-lived variable pointing at short-lived memory, you should move it into request scope or reset it on every exit path.&lt;/p&gt;
&lt;p&gt;You should also initialize it before any early consumer can read it, and block late writes from bringing the old value back.&lt;/p&gt;
&lt;p&gt;You can't count on the error path never running, so you should test it.&lt;/p&gt;
&lt;h2 id=&quot;relations-&quot;&gt;Relations 👩❤️💋👨&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-32-singletons&quot;&gt;https://maximilianocontieri.com/code-smell-32-singletons&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-60-global-classes&quot;&gt;https://maximilianocontieri.com/code-smell-60-global-classes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-49-caches&quot;&gt;https://maximilianocontieri.com/code-smell-49-caches&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-209-side-effects&quot;&gt;https://maximilianocontieri.com/code-smell-209-side-effects&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-&quot;&gt;More Information 📕&lt;/h2&gt;
&lt;p&gt;The PHP team recommends upgrading to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, because configuration changes don't make a vulnerable installation safe.&lt;/p&gt;
&lt;p&gt;PHP 8.1 and older no longer get updates, but the PHP team published source-only backports for 7.4, 8.0 and 8.1, and some vendors ship their own fixes.&lt;/p&gt;
&lt;p&gt;One commit fixes both CVEs: CVE-2026-109619 (stale global state) matches this smell, while CVE-2026-109618 (out-of-memory bailout) is a related early-exit problem that fits only partly.&lt;/p&gt;
&lt;p&gt;Apache mod_php has a demonstrated exploitation path and PHP-FPM has documented exposure under specific conditions, so you shouldn't assume another SAPI removes the risk.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/php/php-src/commit/31c0ea7d7ff&quot;&gt;The fix: php-src commit 31c0ea7d7ff, &quot;Avoid state corruption via bailout&quot;&lt;/a&gt; (one combined patch for both CVEs below; it also replaces out-of-memory bailouts with a delayed soft failure, plus a hard exit at a higher threshold)&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp&quot;&gt;https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w&quot;&gt;https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://research.jfrog.com/post/php2shell-all-you-need-to-know-about-cve-2026-109618-and-cve-2026-109619/&quot;&gt;PHP2Shell: all you need to know (JFrog)&lt;/a&gt; (this write-up pairs the CVE numbers with the opposite mechanisms; the GitHub advisories above are the reference)&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://cwe.mitre.org/data/definitions/416.html&quot;&gt;https://cwe.mitre.org/data/definitions/416.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://cwe.mitre.org/data/definitions/824.html&quot;&gt;https://cwe.mitre.org/data/definitions/824.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;quote&quot;&gt;Quote&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;Simplicity is prerequisite for reliability.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Edsger W. Dijkstra&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;disclaimer-&quot;&gt;Disclaimer 📘&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;credits-&quot;&gt;Credits 🙏&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@hdbernd&quot;&gt;Bernd Dittrich&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/photos/a-trail-of-footprints-in-the-sand-of-a-desert-9CyJgj8Wsq4&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/32009/code-smell-322-request-data-in-long-lived-variables-php-vulnerability</guid>
<pubDate>Wed, 21 Oct 2026 23:57:47 +0000</pubDate>
</item>
<item>
<title>Code Smell 321 - Getter Piggybacking</title>
<link>https://coderlegion.com/25086/code-smell-321-getter-piggybacking</link>
<description>&lt;p&gt;&lt;em&gt;One broken window invites another&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Don't reuse an existing getter to bolt on new business logic from outside the object.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems--1&quot;&gt;Problems 😔&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-46-repeated-code&quot;&gt;Duplicated business rules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Broken encapsulation&lt;/li&gt;
&lt;li&gt;Scattered comparison logic&lt;/li&gt;
&lt;li&gt;Hidden domain knowledge&lt;/li&gt;
&lt;li&gt;Fragile refactoring&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-67-middle-man&quot;&gt;Law of Demeter&lt;/a&gt; violation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions--1&quot;&gt;Solutions 😃&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Add real behavior methods&lt;/li&gt;
&lt;li&gt;Keep comparisons inside object&lt;/li&gt;
&lt;li&gt;Pass collaborators, not primitives&lt;/li&gt;
&lt;li&gt;Reserve getters for rendering&lt;/li&gt;
&lt;li&gt;Follow &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-08-long-chains-of-collaborations&quot;&gt;tell, don't ask&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactorings--1&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-027-remove-getters&quot;&gt;https://maximilianocontieri.com/refactoring-027-remove-getters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-013-remove-repeated-code&quot;&gt;https://maximilianocontieri.com/refactoring-013-remove-repeated-code&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context--1&quot;&gt;Context 💬&lt;/h2&gt;
&lt;p&gt;An object exposes a getter for one legitimate reason: some other part of the system needs to read that value, usually to display it.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-68-getters&quot;&gt;Getters&lt;/a&gt; are a code smell, but this one gets a pass, for now.&lt;/p&gt;
&lt;p&gt;Later on, you discover that you need new business logic that depends on the same value.&lt;/p&gt;
&lt;p&gt;You already have the getter, so you write a function outside the object that calls it and does the comparison itself, breaking the encapsulation principle.&lt;/p&gt;
&lt;p&gt;Someone else needs slightly different logic based on the same value.&lt;/p&gt;
&lt;p&gt;They also call the getter and write their own version of the comparison.&lt;/p&gt;
&lt;p&gt;Now &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-46-repeated-code&quot;&gt;two places decide what that value means&lt;/a&gt;, and neither of them is the object that owns it. Typical.&lt;/p&gt;
&lt;p&gt;You didn't add a second getter this time.&lt;/p&gt;
&lt;p&gt;You reused the first one, because it was already there.&lt;/p&gt;
&lt;p&gt;That's the trap.&lt;/p&gt;
&lt;p&gt;The getter existed for one reason, and you let it justify skipping the real fix: a method on the object that answers the question itself, instead of handing out the raw value for every caller to interpret on their own.&lt;/p&gt;
&lt;p&gt;Don't &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-173-broken-windows&quot;&gt;break more windows&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;sample-code--1&quot;&gt;Sample Code 💻&lt;/h2&gt;
&lt;h3 id=&quot;wrong--1&quot;&gt;Wrong 🚫&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Food needs to show its use-by date on the shelf
// label, so useByDate() exists for that one reason.
//
// Later, removeExpiredFood() needs to pull expired
// products, so it reuses useByDate() and compares the
// result to today itself, outside Food.
//
// flagNearExpiryFood() needs almost the same check, so
// it also calls useByDate() and writes its own slightly
// different comparison.
//
// Now two functions decide what &quot;expired&quot; means, and
// neither of them is Food.
class Food {
  constructor(name, useByDate) {
    this.name = name;
    this.useByDateValue = useByDate;
  }

  useByDate() {
    return this.useByDateValue;
  }
}

function removeExpiredFood(shelf, today) {
  return shelf.filter(
    food =&amp;gt; food.useByDate() &amp;gt;= today
  );
}

function flagNearExpiryFood(
  shelf, today, warningDays
) {
  return shelf.filter(food =&amp;gt; {
    const daysLeft = daysBetween(
      food.useByDate(), today
    );
    return daysLeft &amp;gt;= 0 &amp;amp;&amp;amp;
      daysLeft &amp;lt;= warningDays;
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right--1&quot;&gt;Right 👉&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Food still exposes useByDate() for the shelf label.
//
// Being expired is now a question Food answers itself,
// through isExpiredOn(), instead of every external
// function reimplementing the comparison from the
// getter on its own.
class Food {
  constructor(name, useByDate) {
    this.name = name;
    this.useByDateValue = useByDate;
  }

  useByDate() {
    return this.useByDateValue;
  }

  isExpiredOn(today) {
    return this.useByDateValue &amp;lt; today;
  }

  daysUntilExpiryFrom(today) {
    return daysBetween(this.useByDateValue, today);
  }
}

function removeExpiredFood(shelf, today) {
  return shelf.filter(food =&amp;gt; !food.isExpiredOn(today));
}

function flagNearExpiryFood(shelf, today, warningDays) {
  return shelf.filter(food =&amp;gt; {
    const daysLeft = food.daysUntilExpiryFrom(today);
    return daysLeft &amp;gt;= 0 &amp;amp;&amp;amp; daysLeft &amp;lt;= warningDays;
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection--1&quot;&gt;Detection 🔍&lt;/h2&gt;
&lt;p&gt;[X] Manual&lt;/p&gt;
&lt;p&gt;This is a design smell, and no linter is coming to save you.&lt;/p&gt;
&lt;p&gt;Search for a getter that appears inside &lt;code&gt;if&lt;/code&gt;, comparison, or filter expressions in more than one place outside its own class.&lt;/p&gt;
&lt;p&gt;If two call sites read the same getter and each writes its own comparison against it, the object is missing a method, and the getter is carrying logic it was never meant to carry.&lt;/p&gt;
&lt;h2 id=&quot;exceptions--1&quot;&gt;Exceptions 🛑&lt;/h2&gt;
&lt;p&gt;The smell appears when you reuse that same getter as a shortcut for business logic instead of adding the method the logic actually belongs to.&lt;/p&gt;
&lt;p&gt;Don't point to &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-40-dtos&quot;&gt;DTOs&lt;/a&gt; as a counterexample. A DTO doesn't excuse this. It just breaks encapsulation on purpose and gives the practice a name.&lt;/p&gt;
&lt;h2 id=&quot;tags--1&quot;&gt;Tags 🏷️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Encapsulation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level--1&quot;&gt;Level 🔋&lt;/h2&gt;
&lt;p&gt;[x] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--1&quot;&gt;Why the Bijection Is Important 🗺️&lt;/h2&gt;
&lt;p&gt;The rule behind that value is a concept that belongs to the object in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;, not to whichever function happens to call the getter first.&lt;/p&gt;
&lt;p&gt;When you keep that rule inside the object, every caller shares the same &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; between the object and the real-world thing it represents.&lt;/p&gt;
&lt;p&gt;When you let each caller reimplement the rule from a getter, you create as many private definitions of that concept as you have call sites, and they drift apart the moment one of them changes.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation--1&quot;&gt;AI Generation 🤖&lt;/h2&gt;
&lt;p&gt;AI generators create this smell often.&lt;/p&gt;
&lt;p&gt;You ask for a function that needs a value the object already exposes through a getter, and it writes a standalone function around that getter, because that's the smallest diff that satisfies the request.&lt;/p&gt;
&lt;p&gt;It won't add a method to the object unless you ask for that explicitly.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection--1&quot;&gt;AI Detection 🧲&lt;/h2&gt;
&lt;p&gt;AI can detect it, but only if you point it at the pattern.&lt;/p&gt;
&lt;p&gt;Try: &quot;Find getters called from more than one place where the caller performs its own comparison or business rule on the result.&quot;&lt;/p&gt;
&lt;p&gt;Without that prompt, the code passes tests and looks idiomatic, so most assistants won't flag it on their own.&lt;/p&gt;
&lt;h3 id=&quot;try-them--1&quot;&gt;Try Them! 🛠&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Move the comparison logic from external functions into a real method on the object so callers stop reimplementing it from the getter&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Move+the+comparison+logic+from+external+functions+into+a+real+method+on+the+object+so+callers+stop+reimplementing+it+from+the+getter%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Move+the+comparison+logic+from+external+functions+into+a+real+method+on+the+object+so+callers+stop+reimplementing+it+from+the+getter%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Move+the+comparison+logic+from+external+functions+into+a+real+method+on+the+object+so+callers+stop+reimplementing+it+from+the+getter%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Move+the+comparison+logic+from+external+functions+into+a+real+method+on+the+object+so+callers+stop+reimplementing+it+from+the+getter%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Move+the+comparison+logic+from+external+functions+into+a+real+method+on+the+object+so+callers+stop+reimplementing+it+from+the+getter%3A+%60%60%60javascript%0D%0A%2F%2F+Food+needs+to+show+its+use-by+date+on+the+shelf%0D%0A%2F%2F+label%2C+so+useByDate%28%29+exists+for+that+one+reason.%0D%0A%2F%2F%0D%0A%2F%2F+Later%2C+removeExpiredFood%28%29+needs+to+pull+expired%0D%0A%2F%2F+products%2C+so+it+reuses+useByDate%28%29+and+compares+the%0D%0A%2F%2F+result+to+today+itself%2C+outside+Food.%0D%0A%2F%2F%0D%0A%2F%2F+flagNearExpiryFood%28%29+needs+almost+the+same+check%2C+so%0D%0A%2F%2F+it+also+calls+useByDate%28%29+and+writes+its+own+slightly%0D%0A%2F%2F+different+comparison.%0D%0A%2F%2F%0D%0A%2F%2F+Now+two+functions+decide+what+%22expired%22+means%2C+and%0D%0A%2F%2F+neither+of+them+is+Food.%0D%0Aclass+Food+%7B%0D%0A++constructor%28name%2C+useByDate%29+%7B%0D%0A++++this.name+%3D+name%3B%0D%0A++++this.useByDateValue+%3D+useByDate%3B%0D%0A++%7D%0D%0A%0D%0A++useByDate%28%29+%7B%0D%0A++++return+this.useByDateValue%3B%0D%0A++%7D%0D%0A%7D%0D%0A%0D%0Afunction+removeExpiredFood%28shelf%2C+today%29+%7B%0D%0A++return+shelf.filter%28%0D%0A++++food+%3D%3E+food.useByDate%28%29+%3E%3D+today%0D%0A++%29%3B%0D%0A%7D%0D%0A%0D%0Afunction+flagNearExpiryFood%28%0D%0A++shelf%2C+today%2C+warningDays%0D%0A%29+%7B%0D%0A++return+shelf.filter%28food+%3D%3E+%7B%0D%0A++++const+daysLeft+%3D+daysBetween%28%0D%0A++++++food.useByDate%28%29%2C+today%0D%0A++++%29%3B%0D%0A++++return+daysLeft+%3E%3D+0+%26%26%0D%0A++++++daysLeft+%3C%3D+warningDays%3B%0D%0A++%7D%29%3B%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion--1&quot;&gt;Conclusion 🏁&lt;/h2&gt;
&lt;p&gt;A getter you added for one legitimate reason doesn't grant permission to skip every method that comes after it.&lt;/p&gt;
&lt;p&gt;When you find yourself reaching for an existing getter to write new business logic outside the object, stop and add the method instead.&lt;/p&gt;
&lt;p&gt;The object already knows the information.&lt;/p&gt;
&lt;p&gt;Let it hold the rule too.&lt;/p&gt;
&lt;p&gt;Stop treating it like a vending machine that only hands out data to whoever asks nicely.&lt;/p&gt;
&lt;h2 id=&quot;relations--1&quot;&gt;Relations 👩❤️💋👨&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-68-getters&quot;&gt;https://maximilianocontieri.com/code-smell-68-getters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-89-math-feature-envy&quot;&gt;https://maximilianocontieri.com/code-smell-89-math-feature-envy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-63-feature-envy&quot;&gt;https://maximilianocontieri.com/code-smell-63-feature-envy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7246/code-smell-01-anemic-models&quot;&gt;https://coderlegion.com/7246/code-smell-01-anemic-models&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-246-expiration-date&quot;&gt;https://maximilianocontieri.com/code-smell-246-expiration-date&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-64-inappropriate-intimacy&quot;&gt;https://maximilianocontieri.com/code-smell-64-inappropriate-intimacy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-173-broken-windows&quot;&gt;https://maximilianocontieri.com/code-smell-173-broken-windows&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information--1&quot;&gt;More Information 📕&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/nude-models-part-ii-getters&quot;&gt;https://maximilianocontieri.com/nude-models-part-ii-getters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://martinfowler.com/bliki/TellDontAsk.html&quot;&gt;https://martinfowler.com/bliki/TellDontAsk.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)&quot;&gt;Encapsulation&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;quote-1&quot;&gt;Quote&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;OOP to me means only messaging, local retention and protection and hiding of state-process.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Alan Kay&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;disclaimer--1&quot;&gt;Disclaimer 📘&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;credits--1&quot;&gt;Credits 🙏&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/es/@nathaliarosa&quot;&gt;Nathália Rosa&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/es/fotos/productos-en-estanteria-rWMIbqmOxrY&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/25086/code-smell-321-getter-piggybacking</guid>
<pubDate>Fri, 21 Aug 2026 12:43:11 +0000</pubDate>
</item>
<item>
<title>Real-Life Refactoring Example: ~3x Less Code to Read</title>
<link>https://coderlegion.com/24442/real-life-refactoring-example-3x-less-code-to-read</link>
<description>&lt;p&gt;There is a popular idea that refactoring is making code shorter. It is not entirely wrong. Repetition, pointless conditional branches, and dead variables do make code longer for no reason. But the usual topmost problems are when the intentions of a class's main public method, the business or operational ones, are unclear to a reader.&lt;/p&gt;
&lt;details class=&quot;--contents&quot;&gt;

- [The Main Method Refactor](#the-main-method-refactor)
- [A Private Helper Is Not Automatically a Public API](#a-private-helper-is-not-automatically-a-public-api)
- [One String, Two Names](#one-string-two-names)
- [Logging Had Become Its Own Mini-Application](#logging-had-become-its-own-mini-application)
- [Deeply Buried Intention](#deeply-buried-intention)
- [Actual Refactorings Used](#actual-refactorings-used)
  - [Make The Public Storage Flow Readable](#make-the-public-storage-flow-readable)
  - [Clarify Storage Vocabulary and Logging](#clarify-storage-vocabulary-and-logging)
- [Result](#result)

&lt;summary&gt;&lt;b&gt;&lt;a&gt;Contents&lt;/a&gt;&lt;/b&gt;&lt;/summary&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;p&gt;I had such a case in an S3 document-upload adapter.&lt;/p&gt;
&lt;p&gt;The adapter was not doing anything unusual. It had to stream a document to S3-compatible storage, count actual bytes, calculate a checksum, reject empty or too-large content, normalize S3 errors, clean up a stored object where needed, and write technical logs. This is a substantial piece of work. The problem was that the public &lt;code&gt;store()&lt;/code&gt; method contained most of it directly.&lt;/p&gt;
&lt;p&gt;At a glance it looked like a method that stores a document. In practice, reading it meant walking through AWS SDK setup, &lt;code&gt;try/catch&lt;/code&gt; blocks, S3 error-object construction, cleanup, and a large logging payload before reaching the returned value.&lt;/p&gt;
&lt;p&gt;The code was not unreadable because it had many lines. It was unreadable because the important lines had no space to stand out.&lt;/p&gt;
&lt;h3 id=&quot;the-main-method-refactor&quot;&gt;The Main Method Refactor&lt;/h3&gt;
&lt;p&gt;The main method did not show the adapter's use case. Before the refactoring, upload execution was part of &lt;code&gt;store()&lt;/code&gt; itself:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;try {
 response = await new Upload({
  client: this.#s3_client,
  params: {
   Bucket: this.#bucket_name,
   Key: documentStorageKey,
   Body: countedStream,
   ContentType: file.mime_type
  },
  leavePartsOnError: false
 }).done();
} catch (error: unknown) {
 // Detect validation errors.
 // Build an S3 error object.
 // Build an application exception.
 // Log it.
 // Throw it.
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How do I decide what to refactor? ne rule of thumb is to watch the nesting depth. In my book, a class should not contain more than three levels of nesting. The first is the class declaration, the second is the method level, and the third is at most one level of nesting within a method - inline object literals and deeply nested objects are not allowed.&lt;/p&gt;
&lt;p&gt;The second rule - the main public methods must reveal their intention clearly by their names and their internal code must reveal the story of how the method does what it does in the domain or integration terms.&lt;/p&gt;
&lt;p&gt;So the first refactoring was to extract that &lt;code&gt;try/catch&lt;/code&gt; into a story-telling method:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;const response = await this.uploadToStorage(documentUUID, documentStorageKey, file, countedStream, startedAt);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It was &quot;Extract Method&quot; refactoring, described by Martin Fowler in his Refactoring book. The main method started to read as a story because the implementation was hidden and the method name revealed intention. It packed 40+ lines into one intention-revealing call — roughly 40x less implementation detail to scan in the main flow.&lt;/p&gt;
&lt;p&gt;I used the same approach to extract two conditionals converting a raw S3 error into an application error, and to delete an empty object and throw another error. The first turned ~20 lines into one call, and the second reduced another ~30 lines to one call. Together, roughly 90 lines of implementation detail became three intention-revealing calls — about 30x less code to scan at this level. And look at the method names — they continue the story&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;this.throwIfS3Error(storedObjectKey, response, httpStatusCode, startedAt);
await this.throwIfUploadedFileIsEmpty(storedObjectKey, file, countedStream, startedAt);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moreover, now a reader can answer the first useful question quickly: what happens when a document is stored? It is uploaded. The response is checked. Empty content and errors are dealt with.&lt;/p&gt;
&lt;p&gt;The helper methods still contain difficult code. That is fine. Difficult code should exist where it belongs. It should not hide the business flow of the public method.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;[!INFO]&lt;br&gt;
The main &lt;code&gt;store()&lt;/code&gt; method shrank from 121 lines to 39 — a 68% or 3x reduction in code to read.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;a-private-helper-is-not-automatically-a-public-api&quot;&gt;A Private Helper Is Not Automatically a Public API&lt;/h3&gt;
&lt;p&gt;The next request looked small. The upload service needed to delete the object it had just stored when a duplicate document was found, or when persistence failed later in the transaction.&lt;/p&gt;
&lt;p&gt;There was already a private cleanup method.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;private async cleanupStoredObject(documentUUID: string, documentStorageKey: string, startedAt: number): Promise&amp;lt;void&amp;gt; {}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A tempting change was to make it public. That would have been wrong.&lt;/p&gt;
&lt;p&gt;The private method accepted a document UUID, a storage key, and a timestamp. The timestamp existed only because the method wrote a cleanup-failure log. It also swallowed a deletion error. That was correct for the empty-upload path: the caller must receive the original “empty upload” error even when cleanup itself fails.&lt;/p&gt;
&lt;p&gt;It is not a public removal contract. The public operation became this instead:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;public async remove(storedObjectKey: string): Promise&amp;lt;void&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It now owns the S3 request. It owns the timing of the S3 operation. It normalizes the provider error. It writes the technical storage event. It throws the normalized error to its caller and it is universally used by the adapter and its caller.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;public async remove(storedObjectKey: string): Promise&amp;lt;void&amp;gt; {
    const removalStartedAt = Date.now();

    try {
        await this.#s3_client.send(new DeleteObjectCommand({
            Bucket: this.#bucket_name,
            Key: storedObjectKey
        }));
    } catch (error: unknown) {
        const normalizedFailure = this.normalizeStorageFailure(error);

        this.logStorageEvent({
            logLevel: ELogLevel.ERROR,
            eventName: EDocumentStorageLogEventName.DOCUMENT_STORAGE_CLEANUP_FAILED,
            outcome: ELogOutcome.FAILURE,
            operationName: DOCUMENT_STORAGE_LOG_CONSTANTS.operation.remove,
            storedObjectKey,
            startedAt: removalStartedAt,
            error: normalizedFailure
        });

        throw normalizedFailure;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The caller decides what to do with that error.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;remove()&lt;/code&gt; itself catches it for an empty upload because empty content remains the reported result. The adapter's caller - the upload service - will catch it for a duplicate upload because a duplicate remains the domain concern, not the adapter's one. These are different decisions made by different owners.&lt;/p&gt;
&lt;h3 id=&quot;one-string-two-names&quot;&gt;One String, Two Names&lt;/h3&gt;
&lt;p&gt;Naming was not cosmetic in this refactoring. The application has a document UUID. The S3 adapter uses an object key. They were used in the multiple adapter logging methods extracted from the main &lt;code&gt;store()&lt;/code&gt; method.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;private logFailure(documentUUID: string, documentStorageKey: string, error: MinimalRAGException, startedAt: number): void {}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The document UUID is part of the key:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;const storedObjectKey = `raw/${documentUUID}`;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The domain value object returns it as &lt;code&gt;document_storage_key&lt;/code&gt;, because it is document metadata from the domain side. Inside the S3 adapter, it is &lt;code&gt;storedObjectKey&lt;/code&gt;, because it is passed to the AWS SDK as &lt;code&gt;Key&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The difference matters most when deleting an object.&lt;/p&gt;
&lt;p&gt;At one point, removal was proposed as &lt;code&gt;remove(documentUUID)&lt;/code&gt;, with the adapter reconstructing &lt;code&gt;raw/&amp;lt;UUID&amp;gt;&lt;/code&gt;. It looked tidy. But the exact key is already known after &lt;code&gt;store()&lt;/code&gt; returns. Rebuilding it makes removal depend on a key layout which may later change. Passing the known stored object key is simpler and more honest.&lt;/p&gt;
&lt;p&gt;The final refactoring replaces multiple log methods with one (Parameterize Method), parameterized with an object instead of a long list of positional parameters (Introduce Parameter Object). The method signature becomes 2x shorter, with intention-revealing names that are clear at first sight.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;private logStorageEvent(options: TLogStorageEventOptions): void {}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;logging-had-become-its-own-mini-application&quot;&gt;Logging Had Become Its Own Mini-Application&lt;/h3&gt;
&lt;p&gt;This refactoring describes the other dimension of the refactoring result shown above.&lt;/p&gt;
&lt;p&gt;The adapter had a method for successful storage. Another for successful removal. Another for S3 failure. Another for validation failure. Another for cleanup failure.&lt;/p&gt;
&lt;p&gt;They all built nearly the same event:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;{
    event_name,
    event_type: ELogEventType.INTEGRATION,
    outcome,
    resource: { storage_key: storedObjectKey },
    operation,
    error_code?,
    error?
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Different logging events are useful. Five separate ways to construct 70%-identical logging event are not.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;private logSuccess(documentUUID: string, documentStorageKey: string, startedAt: number, actualByteSize: bigint, httpStatusCode: number | undefined): void {}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is where a long argument list becomes a real problem. Six positional arguments might compile. Nobody wants to remember their order during a production incident.&lt;/p&gt;
&lt;p&gt;The final code uses the single logging method and one parameter object:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;type TLogStorageEventOptions = TLogStorageSuccessOptions &amp;amp; {
 logLevel: ELogLevel;
 outcome: ELogOutcome;
 error?: MinimalRAGException;
};

// ...

this.logStorageEvent({
 logLevel: ELogLevel.WARN,
 eventName: EDocumentStorageLogEventName.DOCUMENT_STORAGE_VALIDATION_FAILED,
 outcome: ELogOutcome.FAILURE,
 operationName: DOCUMENT_STORAGE_LOG_CONSTANTS.operation.store,
 storedObjectKey,
 startedAt,
 actualByteSize: countedStream.actual_byte_size,
 error: rejection
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The refactoring reduced roughly 90 lines the reader previously had to scan to about 30.&lt;/p&gt;
&lt;h3 id=&quot;deeply-buried-intention&quot;&gt;Deeply Buried Intention&lt;/h3&gt;
&lt;p&gt;The builder of the logged object initially contained code like this, which is completely opaque:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;{
    operation: new LogOperationVO({
        // other fields
        ...(cause?.request_id ? { provider_request_id: cause.request_id } : {})
    }),
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That conditional object spread was very far from readable.&lt;/p&gt;
&lt;p&gt;I extracted values into interim constants with intention-revealing names and used them in the logged object construction:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// Extract all ternaries to the clearly named constants
const actualByteSize = options.actualByteSize?.toString() ?? null;
const httpStatusCode = options.httpStatusCode ?? cause?.http_status_code ?? null;
const providerRequestId = cause?.request_id ?? null;
const storageError = cause
 ? new LogErrorVO({
    name: cause.error_name,
    message: cause.error_message,
    dependency: DOCUMENT_STORAGE_LOG_CONSTANTS.dependency
   })
 : null;

// Call the logger
this.#logger.log(options.logLevel, {
 operation: new LogOperationVO({
  // Other fields
  actual_byte_size: actualByteSize,
  http_status_code: httpStatusCode,
  provider_request_id: providerRequestId
 }),
 error: storageError
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This makes the final log event construction boring. That is good. Logging is repeated often enough throughout an application that it should better be DRY.&lt;/p&gt;
&lt;h3 id=&quot;actual-refactorings-used&quot;&gt;Actual Refactorings Used&lt;/h3&gt;
&lt;p&gt;For readers who care about Fowler’s refactoring names, here is the short record.&lt;/p&gt;
&lt;h4 id=&quot;make-the-public-storage-flow-readable&quot;&gt;Make The Public Storage Flow Readable&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Change                                                                 &lt;/th&gt;&lt;th&gt;Fowler refactoring&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Move inline upload and its error handling into &lt;code&gt;uploadToStorage(...)&lt;/code&gt;. &lt;/td&gt;&lt;td&gt;Extract Method&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Move raw S3 error conversion into &lt;code&gt;normalizeStorageFailure(...)&lt;/code&gt;.      &lt;/td&gt;&lt;td&gt;Extract Method&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Move empty-object deletion into &lt;code&gt;cleanupStoredObject(...)&lt;/code&gt;.            &lt;/td&gt;&lt;td&gt;Extract Method&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Move response and empty-stream checks into named methods.              &lt;/td&gt;&lt;td&gt;Extract Method&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Move successful-storage logging out of &lt;code&gt;store()&lt;/code&gt;.                      &lt;/td&gt;&lt;td&gt;Extract Method&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;clarify-storage-vocabulary-and-logging&quot;&gt;Clarify Storage Vocabulary and Logging&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Change                                                        &lt;/th&gt;&lt;th&gt;Fowler refactoring&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;documentUuid&lt;/code&gt; to &lt;code&gt;documentUUID&lt;/code&gt;.                             &lt;/td&gt;&lt;td&gt;Rename Variable / Rename Parameter&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Repeated S3 literals into &lt;code&gt;DOCUMENT_STORAGE_LOG_CONSTANTS&lt;/code&gt;.   &lt;/td&gt;&lt;td&gt;Replace Magic Literal with Symbolic Constant&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;documentStorageKey&lt;/code&gt; to &lt;code&gt;storedObjectKey&lt;/code&gt; inside the adapter. &lt;/td&gt;&lt;td&gt;Rename Variable&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Long logging parameters into &lt;code&gt;TLogStorageEventOptions&lt;/code&gt;.       &lt;/td&gt;&lt;td&gt;Introduce Parameter Object&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Conditional payload expressions into named locals.            &lt;/td&gt;&lt;td&gt;Extract Variable&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Separate log methods into &lt;code&gt;logStorageEvent(...)&lt;/code&gt;.             &lt;/td&gt;&lt;td&gt;Extract Method&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The public &lt;code&gt;remove(storedObjectKey)&lt;/code&gt; method is not a Fowler refactoring. It is a new adapter capability. The validation event rename is not one either. It changes the meaning of the logged outcome. Calling every improvement a refactoring only makes the word less useful.&lt;/p&gt;
&lt;h3 id=&quot;result&quot;&gt;Result&lt;/h3&gt;
&lt;p&gt;The adapter did not become magically small. It should not. It now does more than it did before: it exposes removal, logs useful operational information, returns a named S3 response type, and gives the upload service a clean cleanup operation.&lt;/p&gt;
&lt;p&gt;And the public path is now readable as a path:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;const response = await this.uploadToStorage(...);
this.throwIfS3Error(...);
await this.throwIfUploadedFileIsEmpty(...);
this.logStorageEvent(...);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is the result I want from refactoring - saving the reader's cognitive capacity for the really important work: deciding what, when and how the application should do in business and integration terms.&lt;/p&gt;
&lt;p&gt;NB: The initial code implementation I had to refactor was written by AI.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24442/real-life-refactoring-example-3x-less-code-to-read</guid>
<pubDate>Tue, 11 Aug 2026 12:45:48 +0000</pubDate>
</item>
<item>
<title>Code Smell 138 - Packages Dependency</title>
<link>https://coderlegion.com/24177/code-smell-138-packages-dependency</link>
<description>&lt;p&gt;&lt;em&gt;There's an industry trend to avoid writing code as much as possible, because who has time to write eight lines when a stranger already published a package for it. Turns out that convenience isn't free&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Write your code unless you need an existing complex solution&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems--2&quot;&gt;Problems 😔&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;Coupling&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://nakedsecurity.sophos.com/2022/05/25/poisoned-python-and-php-packages-purloin-passwords-for-aws-access/&quot;&gt;Security problems&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Architectural complexity&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bleepingcomputer.com/news/security/dev-corrupts-npm-libs-colors-and-faker-breaking-thousands-of-apps/&quot;&gt;Packages Corruption&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions--2&quot;&gt;Solutions 😃&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Implement trivial solutions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rely on mature dependencies&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;context--2&quot;&gt;Context 💬&lt;/h2&gt;
&lt;p&gt;Recently, there's a trend to rely on dependencies so hard to trace you'd need a private investigator, not a debugger.&lt;/p&gt;
&lt;p&gt;This introduces coupling into your designs and architectural solutions, which is a polite way of saying you handed strangers the keys to your codebase.&lt;/p&gt;
&lt;p&gt;In August 2026, an attacker compromised the maintainer account behind &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.aikido.dev/blog/keyv-and-friends-compromised-in-npm-supply-chain-attack&quot;&gt;Keyv&lt;/a&gt; and injected credential-stealing code into it, right around the time thousands of developers were happily typing &lt;code&gt;npm install&lt;/code&gt; without a second thought.&lt;/p&gt;
&lt;p&gt;The malware spread through worm-like propagation to at least 444 packages across more than 2 billion monthly installs before anyone noticed, because auditing your transitive dependency tree is apparently nobody's job until it explodes.&lt;/p&gt;
&lt;p&gt;You had no way to see this coming just by reading your own code, which was the whole point of importing it instead of writing it.&lt;/p&gt;
&lt;h2 id=&quot;sample-code--2&quot;&gt;Sample Code 💻&lt;/h2&gt;
&lt;h3 id=&quot;wrong--2&quot;&gt;Wrong 🚫&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;$ npm install --save is-odd

// https://www.npmjs.com/package/is-odd
// This package has about 500k weekly downloads

module.exports = function isOdd(value) {
  const n = Math.abs(value); 
  return (n % 2) === 1;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right--2&quot;&gt;Right 👉&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function isOdd(value) {
  const n = Math.abs(value); 
  return (n % 2) === 1;
};

// Just solve it inline
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection--2&quot;&gt;Detection 🔍&lt;/h2&gt;
&lt;p&gt;[X] Automatic &lt;/p&gt;
&lt;p&gt;You can check your external dependencies and stick to the minimum, assuming you can list them all without opening a spreadsheet.&lt;/p&gt;
&lt;p&gt;You can also depend on a certain concrete version to avoid hijacking, though pinning a version just means you trust yesterday's stranger instead of today's.&lt;/p&gt;
&lt;h2 id=&quot;tags--2&quot;&gt;Tags 🏷️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level--2&quot;&gt;Level 🔋&lt;/h2&gt;
&lt;p&gt;[X] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--2&quot;&gt;Why the Bijection Is Important 🗺️&lt;/h2&gt;
&lt;p&gt;Your design should map to the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt; with a clean &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you pull in an external package for a trivial rule, you stop owning that piece of the model.&lt;/p&gt;
&lt;p&gt;The package maintainer's decisions become part of your bijection, whether you reviewed them or not.&lt;/p&gt;
&lt;p&gt;You lose traceability between your domain concept and the code that implements it.&lt;/p&gt;
&lt;p&gt;A concrete version pin restores part of that bijection, but you still depend on someone else's model matching yours.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation--2&quot;&gt;AI Generation 🤖&lt;/h2&gt;
&lt;p&gt;AI code generators often suggest importing a popular package for problems you could solve in a few lines.&lt;/p&gt;
&lt;p&gt;They pattern-match toward the most common solution in their training data, which is usually &quot;there's a package for that.&quot;&lt;/p&gt;
&lt;p&gt;Ask an assistant to check if a number is odd, and it may reach for a library instead of a single modulo operation, because apparently even parity checks need a supply chain now.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection--2&quot;&gt;AI Detection 🧲&lt;/h2&gt;
&lt;p&gt;AI generators rarely flag unnecessary dependencies on their own.&lt;/p&gt;
&lt;p&gt;They don't weigh the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;coupling&lt;/a&gt; cost of a package against the cost of writing the trivial logic yourself.&lt;/p&gt;
&lt;p&gt;You need to explicitly instruct the assistant to prefer inline solutions for trivial problems and reserve dependencies for real complexity.&lt;/p&gt;
&lt;h2 id=&quot;try-them--2&quot;&gt;Try Them! 🛠&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Replace the trivial external package dependency with a small inline implementation that removes the unnecessary coupling&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Fix+this+code+smell%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Replace+the+trivial+external+package+dependency+with+a+small+inline+implementation+that+removes+the+unnecessary+coupling%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Fix+this+code+smell%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Replace+the+trivial+external+package+dependency+with+a+small+inline+implementation+that+removes+the+unnecessary+coupling%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Fix+this+code+smell%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Replace+the+trivial+external+package+dependency+with+a+small+inline+implementation+that+removes+the+unnecessary+coupling%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Fix+this+code+smell%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Replace+the+trivial+external+package+dependency+with+a+small+inline+implementation+that+removes+the+unnecessary+coupling%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Fix+this+code+smell%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Replace+the+trivial+external+package+dependency+with+a+small+inline+implementation+that+removes+the+unnecessary+coupling%3A+%60%60%60javascript%0D%0A%24+npm+install+--save+is-odd%0D%0A%0D%0A%2F%2F+https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fis-odd%0D%0A%2F%2F+This+package+has+about+500k+weekly+downloads%0D%0A%0D%0Amodule.exports+%3D+function+isOdd%28value%29+%7B%0D%0A++const+n+%3D+Math.abs%28value%29%3B+%0D%0A++return+%28n+%25+2%29+%3D%3D%3D+1%3B%0D%0A%7D%3B%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;conclusion--2&quot;&gt;Conclusion 🏁&lt;/h2&gt;
&lt;p&gt;Lazy programmers push reuse to absurd limits.&lt;/p&gt;
&lt;p&gt;You need a good balance between code duplication and crazy reuse.&lt;/p&gt;
&lt;p&gt;As always, there are rules of thumb, no rigid rules, and plenty of developers who'll learn the difference the hard way anyway.&lt;/p&gt;
&lt;h2 id=&quot;relations--2&quot;&gt;Relations 👩❤️💋👨&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-94-too-many-imports&quot;&gt;https://maximilianocontieri.com/code-smell-94-too-many-imports&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-300-package-hallucination&quot;&gt;https://maximilianocontieri.com/code-smell-300-package-hallucination&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information--2&quot;&gt;More Information 📕&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://nakedsecurity.sophos.com/2022/05/25/poisoned-python-and-php-packages-purloin-passwords-for-aws-access/&quot;&gt;Poisoned Packages&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bleepingcomputer.com/news/security/dev-corrupts-npm-libs-colors-and-faker-breaking-thousands-of-apps/&quot;&gt;Packages Corruption&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://qz.com/646467/how-one-programmer-broke-the-internet-by-deleting-a-tiny-piece-of-code/&quot;&gt;Copyright Threats&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://therecord.media/malware-found-in-npm-package-with-millions-of-weekly-downloads/&quot;&gt;Malware in Packages&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.aikido.dev/blog/keyv-and-friends-compromised-in-npm-supply-chain-attack&quot;&gt;Keyv Supply Chain Attack&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;disclaimer--2&quot;&gt;Disclaimer 📘&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;credits--2&quot;&gt;Credits 🙏&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@moneyphotos&quot;&gt;olieman.eth&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/security-box&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thanks to Ramiro Rela for this smell&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Complexity kills. It sucks the life out of developers, it makes products difficult to plan, build and test, it introduces security challenges, and it causes end-user and administrator frustration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Ray Ozzie&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/13786/software-engineering-great-quotes&quot;&gt;https://coderlegion.com/13786/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24177/code-smell-138-packages-dependency</guid>
<pubDate>Thu, 06 Aug 2026 00:19:32 +0000</pubDate>
</item>
<item>
<title>Code Smell 208 - Null Island</title>
<link>https://coderlegion.com/23892/code-smell-208-null-island</link>
<description>&lt;p&gt;&lt;em&gt;You can avoid null if you try&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Don't use null for real places&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems--3&quot;&gt;Problems 😔&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Tight Coupling&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unexpected Results&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions--3&quot;&gt;Solutions 😃&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Model unknown locations polymorphically&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;context--3&quot;&gt;Context 💬&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Null_Island&quot;&gt;Null Island&lt;/a&gt; is a fictional place that sits at &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.google.com/maps/place/0%C2%B000'00.0%22N+0%C2%B000'00.0%22E/@0,0,35771m/&quot;&gt;0°N 0°E&lt;/a&gt;, at the intersection of the Prime Meridian and the Equator in the Atlantic Ocean. &lt;/p&gt;
&lt;p&gt;Many GPS systems place data with missing or invalid coordinates at this exact point. That's where the name &quot;Null Island&quot; comes from.&lt;/p&gt;
&lt;p&gt;There's no landmass at this location. It's open ocean. &lt;/p&gt;
&lt;p&gt;This point has become a popular reference for geographic information systems (GIS) and mapping software, because it helps filter out errors in location data.&lt;/p&gt;
&lt;p&gt;Data visualization specialists started using the term around 2008, after noticing that failed geocoding requests and invalid coordinate entries often defaulted to (0, 0).&lt;/p&gt;
&lt;p&gt;Natural Earth, a public domain mapping dataset, deliberately includes a fictional one-square-meter island at that exact point to help catch geocoding errors. The trick works: researchers have found more than 300,000 Flickr photos and countless social media posts geotagged to Null Island, and during the COVID-19 pandemic, Johns Hopkins' tracking dashboard plotted confirmed cases there whenever the real location was missing.&lt;/p&gt;
&lt;h2 id=&quot;sample-code--3&quot;&gt;Sample Code 💻&lt;/h2&gt;
&lt;h3 id=&quot;wrong--3&quot;&gt;Wrong 🚫&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;class Person(val name: String, 
             val latitude: Double,
             val longitude: Double)

fun main() {
    val people = listOf(
        Person(&quot;Alice&quot;, 40.7128, -74.0060), 
        // New York City
        Person(&quot;Bob&quot;, 51.5074, -0.1278), 
        // London
        Person(&quot;Charlie&quot;, 48.8566, 2.3522), 
        // Paris
        Person(&quot;Tony Hoare&quot;, 0.0, 0.0) 
        // Null Island
    )
    
    for (person in people) {
        if (person.latitude == 0.0 &amp;amp;&amp;amp; person.longitude == 0.0) {
            println(&quot;${person.name} lives on Null Island!&quot;)
        } else {
            println(&quot;${person.name} lives at &quot; +
                    &quot;(${person.latitude}, ${person.longitude}).&quot;)
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right--3&quot;&gt;Right 👉&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;abstract class Location {
    abstract fun calculateDistance(other: Location): Double
    abstract fun ifKnownOrElse(knownAction: (Location) -&amp;gt; Unit,
        unknownAction: () -&amp;gt; Unit)
}

class EarthLocation(val latitude: Double, val longitude: Double): 
  Location() {
    override fun calculateDistance(other: Location): Double {
        val earthRadius = 6371.0
        val latDistance = Math.toRadians(
            latitude - (other as EarthLocation).latitude)
        val lngDistance = Math.toRadians(
            longitude - other.longitude)
        val a = sin(latDistance / 2) * sin(latDistance / 2) +
          cos(Math.toRadians(latitude)) * 
          cos(Math.toRadians(other.latitude)) *
          sin(lngDistance / 2) * sin(lngDistance / 2)
        val c = 2 * atan2(sqrt(a), sqrt(1 - a))
        return earthRadius * c
}
    
    override fun ifKnownOrElse(knownAction: 
      (Location) -&amp;gt; Unit, unknownAction: () -&amp;gt; Unit) {
        knownAction(this)
    }
}

class UnknownLocation : Location() {
    override fun calculateDistance(other: Location): Double {
        throw IllegalArgumentException(
            &quot;Can't calculate distance&quot; +
            &quot; from an unknown location.&quot;)
    }

    override fun ifKnownOrElse(knownAction:
        (Location) -&amp;gt; Unit, unknownAction: () -&amp;gt; Unit) {
            unknownAction()
    }
}

class Person(val name: String, val location: Location)

fun main() {
    val people = listOf(
        Person(&quot;Alice&quot;, EarthLocation(40.7128, -74.0060)), 
        // New York City
        Person(&quot;Bob&quot;, EarthLocation(51.5074, -0.1278)), 
        // London
        Person(&quot;Charlie&quot;, EarthLocation(48.8566, 2.3522)),
        // Paris
        Person(&quot;Tony&quot;, UnknownLocation()) 
        // Unknown location
    )
    val rio = EarthLocation(-22.9068, -43.1729)
    // Rio de Janeiro coordinates

    for (person in people) {
          person.location.ifKnownOrElse(
              { location -&amp;gt; println(&quot;${person.name} is &quot; +
                  &quot;${location.calculateDistance(rio)} kilometers &quot; +
                  &quot;from Rio.&quot;) },
              { println(&quot;${person.name} is at an unknown &quot; +
                  &quot;location.&quot;) }
          )
      }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection--3&quot;&gt;Detection 🔍&lt;/h2&gt;
&lt;p&gt;[X] Semi-Automatic &lt;/p&gt;
&lt;p&gt;You can check for special numbers used as nulls&lt;/p&gt;
&lt;h2 id=&quot;tags--3&quot;&gt;Tags 🏷️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Null&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level--3&quot;&gt;Level 🔋&lt;/h2&gt;
&lt;p&gt;[X] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--3&quot;&gt;Why the Bijection Is Important 🗺️&lt;/h2&gt;
&lt;p&gt;Real coordinates map to real places on Earth. That is the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; between your model and the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you reuse (0, 0) to mean &quot;unknown location,&quot; you collapse two different concepts into a single representation. &lt;/p&gt;
&lt;p&gt;A real point in the Atlantic Ocean and the absence of data aren't the same thing, and your model shouldn't pretend they are.&lt;/p&gt;
&lt;p&gt;Modeling the unknown location as its own type keeps the mapping honest. &lt;/p&gt;
&lt;p&gt;Real coordinates always mean a real place, and missing data gets its own explicit representation instead of borrowing one that already means something else.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation--3&quot;&gt;AI Generation 🤖&lt;/h2&gt;
&lt;p&gt;AI generators create this smell often. &lt;/p&gt;
&lt;p&gt;When you ask for a location class, they default to primitive latitude and longitude doubles and reach for (0.0, 0.0) as a convenient placeholder for missing data, the same shortcut developers take under deadline pressure.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection--3&quot;&gt;AI Detection 🧲&lt;/h2&gt;
&lt;p&gt;AI generators rarely catch this smell on their own. &lt;/p&gt;
&lt;p&gt;Unless you explicitly ask for a type that represents unknown locations, they treat (0.0, 0.0) as a normal default value and won't suggest polymorphism unless you request it.&lt;/p&gt;
&lt;h3 id=&quot;try-them--3&quot;&gt;Try Them! 🛠&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Replace the (0.0, 0.0) sentinel value with a polymorphic Location type that separates known coordinates from an explicit unknown location&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Replace+the+%280.0%2C+0.0%29+sentinel+value+with+a+polymorphic+Location+type+that+separates+known+coordinates+from+an+explicit+unknown+location%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Replace+the+%280.0%2C+0.0%29+sentinel+value+with+a+polymorphic+Location+type+that+separates+known+coordinates+from+an+explicit+unknown+location%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Replace+the+%280.0%2C+0.0%29+sentinel+value+with+a+polymorphic+Location+type+that+separates+known+coordinates+from+an+explicit+unknown+location%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Replace+the+%280.0%2C+0.0%29+sentinel+value+with+a+polymorphic+Location+type+that+separates+known+coordinates+from+an+explicit+unknown+location%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Replace+the+%280.0%2C+0.0%29+sentinel+value+with+a+polymorphic+Location+type+that+separates+known+coordinates+from+an+explicit+unknown+location%3A+%60%60%60kotlin%0D%0Aclass+Person%28val+name%3A+String%2C+%0D%0A+++++++++++++val+latitude%3A+Double%2C%0D%0A+++++++++++++val+longitude%3A+Double%29%0D%0A%0D%0Afun+main%28%29+%7B%0D%0A++++val+people+%3D+listOf%28%0D%0A++++++++Person%28%22Alice%22%2C+40.7128%2C+-74.0060%29%2C+%0D%0A++++++++%2F%2F+New+York+City%0D%0A++++++++Person%28%22Bob%22%2C+51.5074%2C+-0.1278%29%2C+%0D%0A++++++++%2F%2F+London%0D%0A++++++++Person%28%22Charlie%22%2C+48.8566%2C+2.3522%29%2C+%0D%0A++++++++%2F%2F+Paris%0D%0A++++++++Person%28%22Tony+Hoare%22%2C+0.0%2C+0.0%29+%0D%0A++++++++%2F%2F+Null+Island%0D%0A++++%29%0D%0A++++%0D%0A++++for+%28person+in+people%29+%7B%0D%0A++++++++if+%28person.latitude+%3D%3D+0.0+%26%26+person.longitude+%3D%3D+0.0%29+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+on+Null+Island%21%22%29%0D%0A++++++++%7D+else+%7B%0D%0A++++++++++++println%28%22%24%7Bperson.name%7D+lives+at+%22+%2B%0D%0A++++++++++++++++++++%22%28%24%7Bperson.latitude%7D%2C+%24%7Bperson.longitude%7D%29.%22%29%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion--3&quot;&gt;Conclusion 🏁&lt;/h2&gt;
&lt;p&gt;Don't use &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6462/null-the-billion-dollar-mistake&quot;&gt;Null&lt;/a&gt; to represent &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-126-fake-null-object&quot;&gt;real objects&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;relations--3&quot;&gt;Relations 👩❤️💋👨&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/9248/code-smell-12-null&quot;&gt;https://coderlegion.com/9248/code-smell-12-null&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-126-fake-null-object&quot;&gt;https://maximilianocontieri.com/code-smell-126-fake-null-object&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-160-invalid-id-9999&quot;&gt;https://maximilianocontieri.com/code-smell-160-invalid-id-9999&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information--3&quot;&gt;More Information 📕&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6462/null-the-billion-dollar-mistake&quot;&gt;https://coderlegion.com/6462/null-the-billion-dollar-mistake&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Null_Island&quot;&gt;https://en.wikipedia.org/wiki/Null_Island&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A research buoy once sat right at 0°N 0°E collecting climate data until 2021, and the exact antipode of Null Island, at 0°N 180°E, is nicknamed &quot;Antinull Island.&quot;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/v/daiCb6pT1qY&quot;&gt;https://www.youtube.com/v/daiCb6pT1qY&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;disclaimer--3&quot;&gt;Disclaimer 📘&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;The billion dollar mistake of having null in the language. And since JavaScript has both null and undefined, it's the two billion dollar mistake.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Anders Hejlsberg&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/13786/software-engineering-great-quotes&quot;&gt;https://coderlegion.com/13786/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23892/code-smell-208-null-island</guid>
<pubDate>Fri, 31 Jul 2026 15:58:10 +0000</pubDate>
</item>
<item>
<title>Code Smell 320 - Vanity Coverage</title>
<link>https://coderlegion.com/21230/code-smell-320-vanity-coverage</link>
<description>&lt;p&gt;&lt;em&gt;Brushing Over Real Problems&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: You write tests that touch every line but verify nothing, creating false confidence in a broken system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems--4&quot;&gt;Problems 😔&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;False confidence&lt;/li&gt;
&lt;li&gt;Hidden production &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6337/we-need-to-stop-the-bugs&quot;&gt;defects&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Misleading metrics&lt;/li&gt;
&lt;li&gt;Wasted test effort&lt;/li&gt;
&lt;li&gt;Untested edge cases&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions--4&quot;&gt;Solutions 😃&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Use mutation testing&lt;/li&gt;
&lt;li&gt;Test real behaviors&lt;/li&gt;
&lt;li&gt;Write assertive tests&lt;/li&gt;
&lt;li&gt;Delete coverage-only tests&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactorings--2&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/20855/refactoring-011-replace-comments-with-tests&quot;&gt;https://coderlegion.com/20855/refactoring-011-replace-comments-with-tests&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context--4&quot;&gt;Context 💬&lt;/h2&gt;
&lt;p&gt;Many teams set a coverage threshold: 80%, 90%, or even 100%.&lt;/p&gt;
&lt;p&gt;When you chase that number, you write tests that call methods without checking the actual results.&lt;/p&gt;
&lt;p&gt;A test that calls &lt;code&gt;calculateTax()&lt;/code&gt; but only asserts &lt;code&gt;result is not None&lt;/code&gt; executes the line.&lt;/p&gt;
&lt;p&gt;It doesn't verify the tax calculation is correct.&lt;/p&gt;
&lt;p&gt;The dashboard turns green.&lt;/p&gt;
&lt;p&gt;Defects survive in production.&lt;/p&gt;
&lt;p&gt;This is vanity coverage: cosmetic metrics that hide real problems. Like brushes that make surfaces look smooth while the rot stays underneath.&lt;/p&gt;
&lt;p&gt;Mutation testing reveals the truth.&lt;/p&gt;
&lt;p&gt;When you mutate production code and no tests fail, your coverage numbers lied.&lt;/p&gt;
&lt;h2 id=&quot;sample-code--4&quot;&gt;Sample Code 💻&lt;/h2&gt;
&lt;h3 id=&quot;wrong--4&quot;&gt;Wrong 🚫&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;describe('BankAccount', () =&amp;gt; {
  test('deposit', () =&amp;gt; {
    const account = new BankAccount(100);
    account.deposit(50);
    // Only checking it didn't crash
    expect(account).toBeDefined();
  });

  test('withdraw', () =&amp;gt; {
    const account = new BankAccount(100);
    const result = account.withdraw(30);
    // No assertion about the result!
  });

  test('transfer', () =&amp;gt; {
    const source = new BankAccount(200);
    const target = new BankAccount(0);
    // Just calling the method to &quot;cover&quot; the line
    source.transfer(50, target);
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right--4&quot;&gt;Right 👉&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;describe('BankAccount', () =&amp;gt; {
  test('deposit increases balance', () =&amp;gt; {
    const account = new BankAccount(100);
    account.deposit(50);
    expect(account.balance()).toBe(150);
  });

  test('withdraw decreases balance', () =&amp;gt; {
    const account = new BankAccount(100);
    account.withdraw(30);
    expect(account.balance()).toBe(70);
  });

  test('withdraw raises on insufficient funds', () =&amp;gt; {
    const account = new BankAccount(50);
    expect(() =&amp;gt; account.withdraw(100))
      .toThrow(InsufficientFundsError);
  });

  test('transfer moves money between accounts', () =&amp;gt; {
    const source = new BankAccount(200);
    const target = new BankAccount(0);
    source.transfer(50, target);
    expect(source.balance()).toBe(150);
    expect(target.balance()).toBe(50);
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection--4&quot;&gt;Detection 🔍&lt;/h2&gt;
&lt;p&gt;[X] Semi-Automatic&lt;/p&gt;
&lt;p&gt;Run a mutation testing tool (&lt;a rel=&quot;nofollow&quot; href=&quot;https://pitest.org/&quot;&gt;PIT&lt;/a&gt; for Java, &lt;a rel=&quot;nofollow&quot; href=&quot;https://stryker-mutator.io/&quot;&gt;Stryker&lt;/a&gt; for JavaScript, &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/boxed/mutmut&quot;&gt;mutmut&lt;/a&gt; for Python).&lt;/p&gt;
&lt;p&gt;Count the surviving mutants.&lt;/p&gt;
&lt;p&gt;If coverage is high but mutants survive, you have vanity coverage.&lt;/p&gt;
&lt;p&gt;You can also search for assertion-free tests, single &lt;code&gt;assertNotNull()&lt;/code&gt; assertions, or tests that still pass after you delete the entire production method body.&lt;/p&gt;
&lt;h2 id=&quot;exceptions--2&quot;&gt;Exceptions 🛑&lt;/h2&gt;
&lt;p&gt;Smoke tests that call endpoints to verify the system starts are acceptable without detailed assertions.&lt;/p&gt;
&lt;p&gt;These work when they complement a real test suite, not replace it.&lt;/p&gt;
&lt;h2 id=&quot;tags--4&quot;&gt;Tags 🏷️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level--4&quot;&gt;Level 🔋&lt;/h2&gt;
&lt;p&gt;[x] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--4&quot;&gt;Why the Bijection Is Important 🗺️&lt;/h2&gt;
&lt;p&gt;Your test suite must map each test to a real behavior in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When a test covers a line without verifying observable behavior, you break that &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Coverage tools only measure &quot;lines executed.&quot;&lt;/p&gt;
&lt;p&gt;Chase the number without &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; and your suite looks complete while missing real requirements entirely.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation--4&quot;&gt;AI Generation 🤖&lt;/h2&gt;
&lt;p&gt;AI code generators sometimes produce vanity coverage.&lt;/p&gt;
&lt;p&gt;Ask one to &quot;add tests to reach 80% coverage,&quot; and it writes tests that call methods and assert trivially true facts.&lt;/p&gt;
&lt;p&gt;The metric goes up.&lt;/p&gt;
&lt;p&gt;Nothing gets verified.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection--4&quot;&gt;AI Detection 🧲&lt;/h2&gt;
&lt;p&gt;AI can detect vanity coverage, but only if you ask the right questions.&lt;/p&gt;
&lt;p&gt;Try: &quot;Find tests with no real assertions&quot; or &quot;Find tests that pass when I delete the production method body.&quot;&lt;/p&gt;
&lt;p&gt;Without those prompts, most AI tools see a green test and call it good.&lt;/p&gt;
&lt;h3 id=&quot;try-them--4&quot;&gt;Try Them! 🛠&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Replace vanity coverage tests with tests that verify real behaviors and fail when production code is wrong&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Replace+vanity+coverage+tests+with+tests+that+verify+real+behaviors+and+fail+when+production+code+is+wrong%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Replace+vanity+coverage+tests+with+tests+that+verify+real+behaviors+and+fail+when+production+code+is+wrong%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Replace+vanity+coverage+tests+with+tests+that+verify+real+behaviors+and+fail+when+production+code+is+wrong%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Replace+vanity+coverage+tests+with+tests+that+verify+real+behaviors+and+fail+when+production+code+is+wrong%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Replace+vanity+coverage+tests+with+tests+that+verify+real+behaviors+and+fail+when+production+code+is+wrong%3A+%60%60%60javascript%0D%0Adescribe%28%27BankAccount%27%2C+%28%29+%3D%3E+%7B%0D%0A++test%28%27deposit%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++account.deposit%2850%29%3B%0D%0A++++%2F%2F+Only+checking+it+didn%27t+crash%0D%0A++++expect%28account%29.toBeDefined%28%29%3B%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27withdraw%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+account+%3D+new+BankAccount%28100%29%3B%0D%0A++++const+result+%3D+account.withdraw%2830%29%3B%0D%0A++++%2F%2F+No+assertion+about+the+result%21%0D%0A++%7D%29%3B%0D%0A%0D%0A++test%28%27transfer%27%2C+%28%29+%3D%3E+%7B%0D%0A++++const+source+%3D+new+BankAccount%28200%29%3B%0D%0A++++const+target+%3D+new+BankAccount%280%29%3B%0D%0A++++%2F%2F+Just+calling+the+method+to+%22cover%22+the+line%0D%0A++++source.transfer%2850%2C+target%29%3B%0D%0A++%7D%29%3B%0D%0A%7D%29%3B%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion--4&quot;&gt;Conclusion 🏁&lt;/h2&gt;
&lt;p&gt;Coverage is a signal, not a goal.&lt;/p&gt;
&lt;p&gt;When you treat it as a goal, you create vanity coverage that hides real &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6337/we-need-to-stop-the-bugs&quot;&gt;defects&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Use mutation testing to discover what your suite actually verifies.&lt;/p&gt;
&lt;p&gt;Write tests that describe real behaviors, not tests that execute lines.&lt;/p&gt;
&lt;h2 id=&quot;relations--4&quot;&gt;Relations 👩❤️💋👨&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-104-assert-true&quot;&gt;https://maximilianocontieri.com/code-smell-104-assert-true&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-76-generic-assertions&quot;&gt;https://maximilianocontieri.com/code-smell-76-generic-assertions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-175-changes-without-coverage&quot;&gt;https://maximilianocontieri.com/code-smell-175-changes-without-coverage&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-30-mocking-business&quot;&gt;https://maximilianocontieri.com/code-smell-30-mocking-business&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-203-irrelevant-test-information&quot;&gt;https://maximilianocontieri.com/code-smell-203-irrelevant-test-information&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information--4&quot;&gt;More Information 📕&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Mutation_testing&quot;&gt;https://en.wikipedia.org/wiki/Mutation_testing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://martinfowler.com/bliki/TestCoverage.html&quot;&gt;https://martinfowler.com/bliki/TestCoverage.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://stryker-mutator.io/&quot;&gt;https://stryker-mutator.io/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;quote-2&quot;&gt;Quote&lt;/h2&gt;
&lt;blockquote&gt;&lt;p&gt;The most dangerous kind of waste is the waste we don't recognize.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Shigeo Shingo&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;disclaimer--4&quot;&gt;Disclaimer 📘&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;credits--3&quot;&gt;Credits 🙏&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/es/@jamie452&quot;&gt;Jamie Street&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/es/fotos/foto-macro-de-tres-brochas-de-maquillaje-marrones-JBQdeLezIxQ&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/21230/code-smell-320-vanity-coverage</guid>
<pubDate>Wed, 24 Jun 2026 00:20:26 +0000</pubDate>
</item>
<item>
<title>Code Smell 319 - Hardcoded Stateless Properties</title>
<link>https://coderlegion.com/14389/code-smell-319-hardcoded-stateless-properties</link>
<description>&lt;p&gt;&lt;em&gt;Don't turn collaborators into permanent roommates&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: You should avoid storing stateless utility classes as instance variables initialized with new.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Hardcoded dependencies&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing difficulties&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;coupling&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hidden side effects&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rigid design&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Misleading intent&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Premature Optimization&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stack clutter &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions&quot;&gt;Solutions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Use dependency injection&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass as parameter&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use static methods&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inline the logic&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use local variables&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inline object creation&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactorings--3&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&quot;&gt;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-030-inline-attributes&quot;&gt;https://maximilianocontieri.com/refactoring-030-inline-attributes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/13328/refactoring-007-extract-class&quot;&gt;https://coderlegion.com/13328/refactoring-007-extract-class&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;Hardcoding a stateless class in the constructor creates permanent coupling.&lt;/p&gt;
&lt;p&gt;Even if the class is cheap to instantiate, you lose the ability to swap it.&lt;/p&gt;
&lt;p&gt;Stateless objects shouldn't be part of the object's internal state.&lt;/p&gt;
&lt;p&gt;You confuse readers by making a tool look essential to the object's identity.&lt;/p&gt;
&lt;p&gt;It makes testing harder because you can't mock the hardcoded dependency.&lt;/p&gt;
&lt;h2 id=&quot;sample-code&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;class UserProcessor {
  private provider: MockDataProvider;

  constructor() {
    // You hardcode the dependency here.
    // This makes the class harder to test.
    this.provider = new MockDataProvider();
  }

  process(data: any) {
    return this.provider.format(data);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;interface DataProvider {
  format(data: any): any;
}

class UserProcessor {
  // You inject the dependency via constructor.
  // Now you can swap it or mock it easily.
  constructor(private readonly provider: DataProvider) {}

  process(data: any) {
    return this.provider.format(data);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// Simpler but coupled
 class UserProcessor {
    constructor() {
      // Empty
    }
  
    process(data: any) {
      return new MockDataProvider().format(data);
    }
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;detection&quot;&gt;Detection&lt;/h3&gt;
&lt;p&gt;Look for the &lt;code&gt;new&lt;/code&gt; keyword inside constructors.&lt;/p&gt;
&lt;p&gt;Watch for private properties instantiated directly in the constructor rather than passed as parameters.&lt;/p&gt;
&lt;p&gt;Most linters flag this pattern automatically when you create instances and assign them to private fields.&lt;/p&gt;
&lt;h3 id=&quot;tags--5&quot;&gt;Tags ️&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Premature Optimization&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;level&quot;&gt;Level&lt;/h3&gt;
&lt;p&gt;[X] Beginner&lt;/p&gt;
&lt;h3 id=&quot;why-the-bijection-is-important--5&quot;&gt;Why the Bijection Is Important ️&lt;/h3&gt;
&lt;p&gt;Software should mimic a &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt; of the real world.&lt;/p&gt;
&lt;p&gt;In reality, a worker might use a tool to complete a task.&lt;/p&gt;
&lt;p&gt;The tool is not a permanent physical attachment to the worker.&lt;/p&gt;
&lt;p&gt;When you refactor to use dependency injection, you respect the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; by treating collaborators as external entities, not internal state.&lt;/p&gt;
&lt;p&gt;This keeps your simulation flexible and accurate.&lt;/p&gt;
&lt;h3 id=&quot;ai-generation&quot;&gt;AI Generation&lt;/h3&gt;
&lt;p&gt;AI generators frequently create this smell.&lt;/p&gt;
&lt;p&gt;They often suggest code that just works by instancing dependencies directly in the constructor to save time.&lt;/p&gt;
&lt;h3 id=&quot;ai-detection&quot;&gt;AI Detection&lt;/h3&gt;
&lt;p&gt;AI can easily detect this smell without explicit instructions.&lt;/p&gt;
&lt;p&gt;When you show AI a class with &lt;code&gt;new&lt;/code&gt; keywords in the constructor, it recognizes the pattern as hardcoded coupling.&lt;/p&gt;
&lt;p&gt;AI identifies that stateless utility classes should be injected rather than instantiated internally.&lt;/p&gt;
&lt;p&gt;The detection is straightforward because the pattern is syntactically obvious and semantically harmful.&lt;/p&gt;
&lt;h3 id=&quot;try-them--5&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: remove the cached attribute&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=remove+the+cached+attribute%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=remove+the+cached+attribute%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=remove+the+cached+attribute%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=remove+the+cached+attribute%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=remove+the+cached+attribute%3A+%60%60%60typescript%0D%0Aclass+UserProcessor+%7B%0D%0A++private+provider%3A+MockDataProvider%3B%0D%0A%0D%0A++constructor%28%29+%7B%0D%0A++++%2F%2F+You+hardcode+the+dependency+here.%0D%0A++++%2F%2F+This+makes+the+class+harder+to+test.%0D%0A++++this.provider+%3D+new+MockDataProvider%28%29%3B%0D%0A++%7D%0D%0A%0D%0A++process%28data%3A+any%29+%7B%0D%0A++++return+this.provider.format%28data%29%3B%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Storing stateless dependencies as instance variables makes your code rigid.&lt;/p&gt;
&lt;p&gt;When you inject these dependencies instead, you improve testability and keep your objects focused on their true purpose.&lt;/p&gt;
&lt;h3 id=&quot;relations--5&quot;&gt;Relations ❤️&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8216/code-smell-06-too-clever-programmer&quot;&gt;https://coderlegion.com/8216/code-smell-06-too-clever-programmer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-20-premature-optimization&quot;&gt;https://maximilianocontieri.com/code-smell-20-premature-optimization&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;disclaimer&quot;&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;credits&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/es/@possessedphotography&quot;&gt;Possessed Photography&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Coupling is the enemy of change&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Rich Hickey&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/13786/software-engineering-great-quotes&quot;&gt;https://coderlegion.com/13786/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/14389/code-smell-319-hardcoded-stateless-properties</guid>
<pubDate>Fri, 10 Apr 2026 02:01:39 +0000</pubDate>
</item>
<item>
<title>Code Smell 17 - Global Functions</title>
<link>https://coderlegion.com/12270/code-smell-17-global-functions</link>
<description>&lt;p&gt;&lt;em&gt;Discouraged by Object-Oriented Programming, Many mixed languages support it. And developers abuse them.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Global functions bring a lot of coupling. Don't use them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-1&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Tight Coupling&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Poor Readability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintainability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hidden side-effects&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-1&quot;&gt;Solutions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Wrap the function in a context object.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;refactorings--4&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-007-extract-class&quot;&gt;https://maximilianocontieri.com/refactoring-007-extract-class&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-010-extract-method-object&quot;&gt;https://maximilianocontieri.com/refactoring-010-extract-method-object&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-020-transform-static-functions&quot;&gt;https://maximilianocontieri.com/refactoring-020-transform-static-functions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&quot;&gt;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;External Resources Access, Database access, Time and Operating System resources.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-1&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;When you place a function in the global scope, you allow any part of your system to access it at any time.&lt;/p&gt;
&lt;p&gt;This sounds convenient, but it creates a web of invisible connections. &lt;/p&gt;
&lt;p&gt;If you want to change how that function works, you must check every corner of your application.&lt;/p&gt;
&lt;p&gt;This practice also makes testing nearly impossible. &lt;/p&gt;
&lt;p&gt;When a method calls a global function like getSystemTime() or saveToDatabase(), you cannot easily replace that function with a mock or a fake version during a test. &lt;/p&gt;
&lt;p&gt;You end up testing the entire environment instead of just your logic.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-1&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-1&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

class Employee {
    function taxesPayedUntilToday() {
        return database()-&amp;gt;select(
            &quot;SELECT TAXES FROM EMPLOYEE&quot;.
            &quot; WHERE ID = &quot; . $this-&amp;gt;id() .
            &quot; AND DATE &amp;lt; &quot; . currentDate());
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-1&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

final class EmployeeTaxesCalculator {
    function taxesPayedUntilToday($context) {
        return $context-&amp;gt;SelectTaxesForEmployeeUntil(
            $this-&amp;gt;ssn,
            $context-&amp;gt;currentDate());
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-1&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;Many modern languages avoid them. For the permissive ones, scope rules can be applied and automatically checked.&lt;/p&gt;
&lt;h2 id=&quot;exceptions&quot;&gt;Exceptions&lt;/h2&gt;
&lt;p&gt;Some languages use global functions as their core library (like &lt;em&gt;str_len&lt;/em&gt; in C or some PHP functions). &lt;/p&gt;
&lt;p&gt;In these cases, you might &lt;strong&gt;wrap&lt;/strong&gt; them in your own objects to improve testability, but the functions themselves are part of the platform.&lt;/p&gt;
&lt;h2 id=&quot;tags--6&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Globals&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-1&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[x] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--6&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;In the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;, objects have responsibilities and specific contexts. &lt;/p&gt;
&lt;p&gt;A Global Function doesn't exist in a real-world simulation because every action belongs to an actor or a component. &lt;/p&gt;
&lt;p&gt;When you use global functions, you break the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; between your code and the entities you model. &lt;/p&gt;
&lt;p&gt;You create a God-like action that exists nowhere and everywhere at the same time.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-1&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI tools often suggest global functions because they look for the shortest code path. &lt;/p&gt;
&lt;p&gt;They frequently provide &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-22-helpers&quot;&gt;utility&lt;/a&gt; snippets that live in the global scope because they don't know the specific architecture of your project.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-1&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;You can ask an AI to &quot;Refactor these global functions into domain objects&quot; or &quot;Apply dependency injection to remove global scope dependencies.&quot; &lt;/p&gt;
&lt;p&gt;Many AI models are very good at identifying which class should own a specific logic.&lt;/p&gt;
&lt;h3 id=&quot;try-them--6&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Take these global functions and group them into logical context objects. Use dependency injection so I can test the classes that use them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Take+these+global+functions+and+group+them+into+logical+context+objects.+Use+dependency+injection+so+I+can+test+the+classes+that+use+them.%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Take+these+global+functions+and+group+them+into+logical+context+objects.+Use+dependency+injection+so+I+can+test+the+classes+that+use+them.%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Take+these+global+functions+and+group+them+into+logical+context+objects.+Use+dependency+injection+so+I+can+test+the+classes+that+use+them.%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Take+these+global+functions+and+group+them+into+logical+context+objects.+Use+dependency+injection+so+I+can+test+the+classes+that+use+them.%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Take+these+global+functions+and+group+them+into+logical+context+objects.+Use+dependency+injection+so+I+can+test+the+classes+that+use+them.%3A+%60%60%60php%0A%3C%3F%0A%0Aclass+Employee+%7B%0A++++function+taxesPayedUntilToday%28%29+%7B%0A++++++++return+database%28%29-%3Eselect%28%0A++++++++++++%22SELECT+TAXES+FROM+EMPLOYEE%22.%0A++++++++++++%22+WHERE+ID+%3D+%22+.+%24this-%3Eid%28%29+.%0A++++++++++++%22+AND+DATE+%3C+%22+.+currentDate%28%29%29%3B%0A++++%7D%0A%7D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-1&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Structured programming considers global functions &lt;strong&gt;harmful&lt;/strong&gt;. Yet, we can observe some bad practices cross paradigm boundaries.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Singleton and Classes are global points of access.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;relations--6&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-60-global-classes&quot;&gt;https://maximilianocontieri.com/code-smell-60-global-classes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6959/singleton-the-root-of-all-evil&quot;&gt;https://coderlegion.com/6959/singleton-the-root-of-all-evil&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-22-helpers&quot;&gt;https://maximilianocontieri.com/code-smell-22-helpers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-209-side-effects&quot;&gt;https://maximilianocontieri.com/code-smell-209-side-effects&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-1&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Global_variable&quot;&gt;https://en.wikipedia.org/wiki/Global_variable&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;credits-1&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@picoftasty&quot;&gt;Mae Mu&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/spaghetti&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;The road to programming hell is paved with global variables.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Steve McConnell&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/12270/code-smell-17-global-functions</guid>
<pubDate>Sat, 28 Feb 2026 15:57:25 +0000</pubDate>
</item>
<item>
<title>Code Smell 16 - Ripple Effect</title>
<link>https://coderlegion.com/11940/code-smell-16-ripple-effect</link>
<description>&lt;p&gt;&lt;em&gt;Small changes yield unexpected problems.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: If small changes have big impact, you need to decouple your system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-2&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;High &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;Coupling&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Low maintainability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Side effects&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High risk&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing difficulty&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-2&quot;&gt;Solutions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Decouple your components.&lt;/li&gt;
&lt;li&gt;Cover with tests.&lt;/li&gt;
&lt;li&gt;Refactor and isolate what is changing.&lt;/li&gt;
&lt;li&gt;Depend on interfaces.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-decouple-a-legacy-system&quot;&gt;https://maximilianocontieri.com/how-to-decouple-a-legacy-system&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;refactorings--5&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-007-extract-class&quot;&gt;https://maximilianocontieri.com/refactoring-007-extract-class&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&quot;&gt;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-1&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Legacy Systems&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-2&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;The ripple effect happens when you design a system where objects know too much about each other. &lt;/p&gt;
&lt;p&gt;When you modify a specific behavior, the impact spreads through the codebase like a stone thrown into a pond. &lt;/p&gt;
&lt;p&gt;You feel this pain when a simple requirement change requires you to touch dozens of files. &lt;/p&gt;
&lt;p&gt;Your classes have direct dependencies on concrete implementations rather than abstractions.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-2&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-2&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class Time {
   constructor(hour, minute, seconds) {
     this.hour = hour;    
     this.minute = minute;  
     this.seconds = seconds;  
  }
    now() {
      // call operating system
    }  
}

// Adding a TimeZone will have a big Ripple Effect
// Changing now() to consider timezone will also bring the effect
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-2&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class Time {
   constructor(hour, minute, seconds, timezone) {
     this.hour = hour;    
     this.minute = minute;  
     this.seconds = seconds;  
     this.timezone = timezone;  
  }  
  // Removed now() since is invalid without context
}

class RelativeClock {
   constructor(timezone) {
     this.timezone = timezone;
   }
   now(timezone) {
     var localSystemTime = this.localSystemTime();
     var localSystemTimezone = this.localSystemTimezone();
     // Do some math translating timezones
     // ...
     return new Time(..., timezone);     
   }  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-2&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;It is not easy to detect problems before they happen. &lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Mutation_testing&quot;&gt;Mutation Testing&lt;/a&gt; and root cause analysis of &lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Single_point_of_failure&quot;&gt;single points of failures&lt;/a&gt; may help.&lt;/p&gt;
&lt;h2 id=&quot;tags--7&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Coupling&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-2&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[x] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--7&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;In a proper &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt;, a change in a single real-world concept should only lead to a change in a single program component. &lt;/p&gt;
&lt;p&gt;When you break the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt; , one concept spreads across your code. &lt;/p&gt;
&lt;p&gt;This creates the ripple effect because you didn't represent the original idea as a single, isolated unit.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-2&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI generators often create this smell because they suggest &quot;quick fixes&quot; that access global states or direct dependencies. &lt;/p&gt;
&lt;p&gt;They focus on making the local code work without seeing the architectural ripple they cause elsewhere.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-2&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI can fix this if you provide the context of the related classes. &lt;/p&gt;
&lt;p&gt;When you ask an AI to &quot;decouple these two classes using dependency injection,&quot; it usually does a great job of breaking the link.&lt;/p&gt;
&lt;h3 id=&quot;try-them--7&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Refactor this class to remove direct dependencies on global objects. Use constructor-based dependency injection and depend on interfaces or abstractions instead of concrete implementations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Refactor+this+class+to+remove+direct+dependencies+on+global+objects.+Use+constructor-based+dependency+injection+and+depend+on+interfaces+or+abstractions+instead+of+concrete+implementations.%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Refactor+this+class+to+remove+direct+dependencies+on+global+objects.+Use+constructor-based+dependency+injection+and+depend+on+interfaces+or+abstractions+instead+of+concrete+implementations.%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Refactor+this+class+to+remove+direct+dependencies+on+global+objects.+Use+constructor-based+dependency+injection+and+depend+on+interfaces+or+abstractions+instead+of+concrete+implementations.%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Refactor+this+class+to+remove+direct+dependencies+on+global+objects.+Use+constructor-based+dependency+injection+and+depend+on+interfaces+or+abstractions+instead+of+concrete+implementations.%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Refactor+this+class+to+remove+direct+dependencies+on+global+objects.+Use+constructor-based+dependency+injection+and+depend+on+interfaces+or+abstractions+instead+of+concrete+implementations.%3A+%60%60%60javascript%0D%0Aclass+Time+%7B%0D%0A+++constructor%28hour%2C+minute%2C+seconds%29+%7B%0D%0A+++++this.hour+%3D+hour%3B++++%0D%0A+++++this.minute+%3D+minute%3B++%0D%0A+++++this.seconds+%3D+seconds%3B++%0D%0A++%7D%0D%0A++++now%28%29+%7B%0D%0A++++++%2F%2F+call+operating+system%0D%0A++++%7D++%0D%0A%7D%0D%0A%0D%0A%2F%2F+Adding+a+TimeZone+will+have+a+big+Ripple+Effect%0D%0A%2F%2F+Changing+now%28%29+to+consider+timezone+will+also+bring+the+effect%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-2&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There are multiple strategies to deal with Legacy and coupled systems. &lt;/p&gt;
&lt;p&gt;You should deal with this problem before it explodes under your eyes.&lt;/p&gt;
&lt;h2 id=&quot;relations--7&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-08-long-chains-of-collaborations&quot;&gt;https://maximilianocontieri.com/code-smell-08-long-chains-of-collaborations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-176-changes-in-essence&quot;&gt;https://maximilianocontieri.com/code-smell-176-changes-in-essence&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-2&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-decouple-a-legacy-system&quot;&gt;https://maximilianocontieri.com/how-to-decouple-a-legacy-system&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;credits-2&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@jtindall&quot;&gt;Jack Tindall&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/big-wave&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Architecture is the tension between coupling and cohesion.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Neal Ford&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/11940/code-smell-16-ripple-effect</guid>
<pubDate>Fri, 20 Feb 2026 00:25:46 +0000</pubDate>
</item>
<item>
<title>How to Find the Stinky Parts of Your Code</title>
<link>https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code</link>
<description>&lt;p&gt;&lt;em&gt;The code smells badly. Let's see how to change the aromas.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: A Compilation of bad smells in code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this series, we will see several symptoms and situations that make us doubt the quality of our development. We will present possible solutions.&lt;/p&gt;
&lt;p&gt;Most of these smells are just &lt;em&gt;hints&lt;/em&gt; of something that might be wrong. They are not rigid rules.&lt;/p&gt;
&lt;h2 id=&quot;code-smells&quot;&gt;Code Smells&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7246/code-smell-01-anemic-models&quot;&gt;https://coderlegion.com/7246/code-smell-01-anemic-models&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7475/code-smell-02-constants-and-magic-numbers&quot;&gt;https://coderlegion.com/7475/code-smell-02-constants-and-magic-numbers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7617/code-smell-03-functions-are-too-long&quot;&gt;https://coderlegion.com/7617/code-smell-03-functions-are-too-long&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7929/code-smell-04-string-abusers&quot;&gt;https://coderlegion.com/7929/code-smell-04-string-abusers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8106/code-smell-05-comment-abusers&quot;&gt;https://coderlegion.com/8106/code-smell-05-comment-abusers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8216/code-smell-06-too-clever-programmer&quot;&gt;https://coderlegion.com/8216/code-smell-06-too-clever-programmer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/9110/code-smell-07-boolean-variables&quot;&gt;https://coderlegion.com/9110/code-smell-07-boolean-variables&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-08-long-chains-of-collaborations&quot;&gt;https://maximilianocontieri.com/code-smell-08-long-chains-of-collaborations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8495/code-smell-09-dead-code&quot;&gt;https://coderlegion.com/8495/code-smell-09-dead-code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8662/code-smell-10-too-many-arguments&quot;&gt;https://coderlegion.com/8662/code-smell-10-too-many-arguments&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-11-subclassification-for-code-reuse&quot;&gt;https://maximilianocontieri.com/code-smell-11-subclassification-for-code-reuse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/9248/code-smell-12-null&quot;&gt;https://coderlegion.com/9248/code-smell-12-null&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/9517/code-smell-13-empty-constructors&quot;&gt;https://coderlegion.com/9517/code-smell-13-empty-constructors&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/10362/code-smell-14-god-objects&quot;&gt;https://coderlegion.com/10362/code-smell-14-god-objects&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;... and many more to come.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=17420168902730004549&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@icsike2&quot;&gt;Richard Ecsedi&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@icsike2&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Smells are certain structures in the code that suggest (sometimes they scream for) the possibility of refactoring&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Martin Fowler&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Part of the objective of this series is to generate spaces for debate and discussion on software design.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6864/object-design-checklist&quot;&gt;https://coderlegion.com/6864/object-design-checklist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We look forward to your comments and suggestions on this article.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10942/how-to-find-the-stinky-parts-of-your-code</guid>
<pubDate>Mon, 02 Feb 2026 16:28:10 +0000</pubDate>
</item>
<item>
<title>Code Smell 15 - Missed Preconditions</title>
<link>https://coderlegion.com/10793/code-smell-15-missed-preconditions</link>
<description>&lt;p&gt;&lt;em&gt;Assertions, Preconditions, Postconditions and invariants are our allies to avoid invalid objects. Avoiding them leads to hard-to-find errors.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: If you turn off your assertions just in production your phone will ring at late hours.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-3&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Consistency&lt;/li&gt;
&lt;li&gt;Contract breaking&lt;/li&gt;
&lt;li&gt;Hard debugging&lt;/li&gt;
&lt;li&gt;Late failures&lt;/li&gt;
&lt;li&gt;Bad cohesion&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-3&quot;&gt;Solutions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Create strong preconditions&lt;/li&gt;
&lt;li&gt;Raise exceptions&lt;/li&gt;
&lt;li&gt;Use &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7024/fail-fast-principle&quot;&gt;Fail-Fast&lt;/a&gt; principle&lt;/li&gt;
&lt;li&gt;Defensive Programming &lt;/li&gt;
&lt;li&gt;Enforce object invariants&lt;/li&gt;
&lt;li&gt;Avoid &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7246/code-smell-01-anemic-models&quot;&gt;anemic models&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;refactorings--6&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-016-build-with-the-essence&quot;&gt;https://maximilianocontieri.com/refactoring-016-build-with-the-essence&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-035-separate-exception-types&quot;&gt;https://maximilianocontieri.com/refactoring-035-separate-exception-types&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-2&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Constructors are an excellent &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-016-build-with-the-essence&quot;&gt;first line of defense&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7246/code-smell-01-anemic-models&quot;&gt;Anemic Objects&lt;/a&gt; lack these rules.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-40-dtos&quot;&gt;DTOs&lt;/a&gt; are also a common mistake in the industry.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-3&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;You often assume that &quot;someone else&quot; checked the objects before it reached your function. &lt;/p&gt;
&lt;p&gt;This assumption is a trap. When you create objects without enforcing their internal rules, you create &quot;Ghost Constraints.&quot; &lt;/p&gt;
&lt;p&gt;These are rules that exist in your mind but not in the code.&lt;/p&gt;
&lt;p&gt;If you allow a &quot;User&quot; object to exist without an email or a &quot;Transaction&quot; to have a negative amount, you create a time bomb. &lt;/p&gt;
&lt;p&gt;The error won't happen when you create the object; it will happen much later when you try to use it. &lt;/p&gt;
&lt;p&gt;This makes finding the root cause very difficult. &lt;/p&gt;
&lt;p&gt;You must ensure that once you create an object, it remains valid from the very birth throughout its entire lifecycle.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-3&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-3&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class Date:
  def __init__(self, day, month, year):
    self.day = day
    self.month = month
    self.year = year

  def setMonth(self, month):
    self.month = month

startDate = Date(3, 11, 2020)
# OK

startDate = Date(31, 11, 2020)
# Should fail

startDate.setMonth(13)
# Should fail
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-3&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class Date:
  def __init__(self, day, month, year):
  if month &amp;gt; 12:
    raise Exception(&quot;Month should not exceed 12&quot;)
    #
    # etc ...
  
    self._day = day
    self._month = month
    self._year = year
 
startDate = Date(3, 11, 2020)
# OK

startDate = Date(31, 11, 2020)
# fails

startDate.setMonth(13)
# fails since invariant makes object immutable
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-3&quot;&gt;Detection&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;It's difficult to find missing preconditions, as long with assertions and invariants.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tags--8&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Fail-Fast&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-3&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[x] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--8&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;In the MAPPER, a person cannot have a negative age or an empty name. &lt;/p&gt;
&lt;p&gt;If your code allows these states, you break the bijection. &lt;/p&gt;
&lt;p&gt;When you maintain a strict one-to-one relationship between your business rules and your code, you eliminate a whole category of &quot;impossible&quot; defects.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-3&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI generators often create &quot;happy path&quot; code.&lt;/p&gt;
&lt;p&gt;They frequently skip validations to keep the examples short and concise. &lt;/p&gt;
&lt;p&gt;You must explicitly ask them to include preconditions.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-3&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI tools are great at spotting missing validations. &lt;/p&gt;
&lt;p&gt;If you give them a class and ask &quot;What invariants are missing here?&quot;, they usually find the missing edge cases quickly.&lt;/p&gt;
&lt;h3 id=&quot;try-them--8&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Add constructor preconditions to this class to ensure it never enters an invalid state based on real-world constraints. Fail fast if the input is wrong.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Add+constructor+preconditions+to+this+class+to+ensure+it+never+enters+an+invalid+state+based+on+real-world+constraints.+Fail+fast+if+the+input+is+wrong.%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Add+constructor+preconditions+to+this+class+to+ensure+it+never+enters+an+invalid+state+based+on+real-world+constraints.+Fail+fast+if+the+input+is+wrong.%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Add+constructor+preconditions+to+this+class+to+ensure+it+never+enters+an+invalid+state+based+on+real-world+constraints.+Fail+fast+if+the+input+is+wrong.%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Add+constructor+preconditions+to+this+class+to+ensure+it+never+enters+an+invalid+state+based+on+real-world+constraints.+Fail+fast+if+the+input+is+wrong.%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Add+constructor+preconditions+to+this+class+to+ensure+it+never+enters+an+invalid+state+based+on+real-world+constraints.+Fail+fast+if+the+input+is+wrong.%3A+%60%60%60python%0D%0Aclass+Date%3A%0D%0A++def+__init__%28self%2C+day%2C+month%2C+year%29%3A%0D%0A++++self.day+%3D+day%0D%0A++++self.month+%3D+month%0D%0A++++self.year+%3D+year%0D%0A%0D%0A++def+setMonth%28self%2C+month%29%3A%0D%0A++++self.month+%3D+month%0D%0A%0D%0AstartDate+%3D+Date%283%2C+11%2C+2020%29%0D%0A%23+OK%0D%0A%0D%0AstartDate+%3D+Date%2831%2C+11%2C+2020%29%0D%0A%23+Should+fail%0D%0A%0D%0AstartDate.setMonth%2813%29%0D%0A%23+Should+fail%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-3&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Always be explicit on object integrity.&lt;/p&gt;
&lt;p&gt;Turn on production assertions. &lt;/p&gt;
&lt;p&gt;Yes, even if it means taking a small performance hit.&lt;/p&gt;
&lt;p&gt;Trust me, tracking down object corruption is way harder than preventing it upfront.&lt;/p&gt;
&lt;p&gt;Embracing the fail-fast approach isn't just good practice - it's a lifesaver.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7024/fail-fast-principle&quot;&gt;https://coderlegion.com/7024/fail-fast-principle&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;relations--8&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7246/code-smell-01-anemic-models&quot;&gt;https://coderlegion.com/7246/code-smell-01-anemic-models&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-189-not-sanitized-input&quot;&gt;https://maximilianocontieri.com/code-smell-189-not-sanitized-input&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-40-dtos&quot;&gt;https://maximilianocontieri.com/code-smell-40-dtos&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-3&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Object-Oriented_Software_Construction&quot;&gt;https://en.wikipedia.org/wiki/Object-Oriented_Software_Construction&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;credits-3&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@jon_chng&quot;&gt;Jonathan Chng&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/running-track&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Writing a class without its contract would be similar to producing an engineering component (electrical circuit, VLSI (Very Large Scale Integration) chip, bridge, engine...) without a spec. No professional engineer would even consider the idea.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Bertrand Meyer&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10793/code-smell-15-missed-preconditions</guid>
<pubDate>Sat, 31 Jan 2026 00:51:20 +0000</pubDate>
</item>
<item>
<title>Code Smell 14 - God Objects</title>
<link>https://coderlegion.com/10362/code-smell-14-god-objects</link>
<description>&lt;p&gt;&lt;em&gt;An object that knows too much or does too much.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Don't take too many responsibilities in a single class.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-4&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Low cohesion&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;coupling&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Single Responsibility Violation&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-4&quot;&gt;Solutions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Split responsibilities.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Follow the Single Responsibility Principle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apply the &lt;a rel=&quot;nofollow&quot; href=&quot;https://medium.com/@biratkirat/step-8-the-boy-scout-rule-robert-c-martin-uncle-bob-9ac839778385&quot;&gt;Boy Scout Rule&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;refactorings--7&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-007-extract-class&quot;&gt;https://maximilianocontieri.com/refactoring-007-extract-class&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-002-extract-method&quot;&gt;https://maximilianocontieri.com/refactoring-002-extract-method&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-3&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-4&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;God Objects form when you concentrate too many responsibilities in a single class. &lt;/p&gt;
&lt;p&gt;These objects become central hubs that know everything and control everything in your system. &lt;/p&gt;
&lt;p&gt;You create them gradually, with each added method making the class harder to maintain.&lt;/p&gt;
&lt;p&gt;Libraries and &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-22-helpers&quot;&gt;utility&lt;/a&gt; classes from procedural programming encouraged this pattern in the 1960s.&lt;/p&gt;
&lt;p&gt;Object-oriented design distributes responsibilities across many focused objects.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-4&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-4&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class Soldier {
   run() {}
   fight() {}
   driveGeneral() {}
   clean() {} 
   fire() {} 
   bePromoted() {}
   serialize() {}
   display() {} 
   persistOnDatabase() {}
   toXML() {}
   jsonDecode() {}
  
  // ...
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-4&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class Soldier {
   run() {}
   fight() {}
   clean() {}    
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-4&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;Linters can count methods and warn against a threshold.&lt;/p&gt;
&lt;h2 id=&quot;exceptions-1&quot;&gt;Exceptions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Facade_pattern&quot;&gt;Facades&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tags--9&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Coupling&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-4&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--9&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;When you model your software, you need to maintain a clear bijection between your code and the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;God Objects break this mapping by lumping multiple real-world concepts into a single artificial construct. &lt;/p&gt;
&lt;p&gt;You will not find a single entity that manages users, processes payments, sends emails, and generates reports.&lt;/p&gt;
&lt;p&gt;You have distinct roles and responsibilities. &lt;/p&gt;
&lt;p&gt;When you create a God Object, you lose this clear &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;correspondence&lt;/a&gt;, making your code harder to understand and maintain.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-4&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI code generators frequently create God Objects when you ask them to &quot;create a complete system&quot; or &quot;build a payment system.&quot;.&lt;/p&gt;
&lt;p&gt;They tend to group related functionality into convenient single classes rather than distributing responsibilities properly. &lt;/p&gt;
&lt;p&gt;You need to explicitly instruct them to separate concerns and create focused classes.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-4&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI tools can detect God Objects when you provide clear instructions. &lt;/p&gt;
&lt;p&gt;The assistants can count methods, analyze dependencies, and suggest splitting classes. &lt;/p&gt;
&lt;p&gt;They struggle to determine the right boundaries without domain knowledge about your specific system.&lt;/p&gt;
&lt;h3 id=&quot;try-them--9&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Suggest how to split it into smaller, cohesive classes, each handling a single responsibility&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Suggest+how+to+split+it+into+smaller%2C+cohesive+classes%2C+each+handling+a+single+responsibility%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Suggest+how+to+split+it+into+smaller%2C+cohesive+classes%2C+each+handling+a+single+responsibility%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Suggest+how+to+split+it+into+smaller%2C+cohesive+classes%2C+each+handling+a+single+responsibility%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Suggest+how+to+split+it+into+smaller%2C+cohesive+classes%2C+each+handling+a+single+responsibility%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Suggest+how+to+split+it+into+smaller%2C+cohesive+classes%2C+each+handling+a+single+responsibility%3A+%60%60%60javascript%0D%0Aclass+Soldier+%7B%0D%0A+++run%28%29+%7B%7D%0D%0A+++fight%28%29+%7B%7D%0D%0A+++driveGeneral%28%29+%7B%7D%0D%0A+++clean%28%29+%7B%7D+%0D%0A+++fire%28%29+%7B%7D+%0D%0A+++bePromoted%28%29+%7B%7D%0D%0A+++serialize%28%29+%7B%7D%0D%0A+++display%28%29+%7B%7D+%0D%0A+++persistOnDatabase%28%29+%7B%7D%0D%0A+++toXML%28%29+%7B%7D%0D%0A+++jsonDecode%28%29+%7B%7D%0D%0A++%0D%0A++%2F%2F+...%0D%0A++%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-4&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Libraries were fine in the 1960s.&lt;/p&gt;
&lt;p&gt;In Object-Oriented Programming, you need to distribute responsibilities among many objects.&lt;/p&gt;
&lt;h2 id=&quot;relations--9&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-34-too-many-attributes&quot;&gt;https://maximilianocontieri.com/code-smell-34-too-many-attributes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-202-god-constant-class&quot;&gt;https://maximilianocontieri.com/code-smell-202-god-constant-class&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-124-divergent-change&quot;&gt;https://maximilianocontieri.com/code-smell-124-divergent-change&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-22-helpers&quot;&gt;https://maximilianocontieri.com/code-smell-22-helpers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-143-data-clumps&quot;&gt;https://maximilianocontieri.com/code-smell-143-data-clumps&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-4&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/God_object&quot;&gt;https://en.wikipedia.org/wiki/God_object&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://refactoring.guru/es/smells/large-class&quot;&gt;https://refactoring.guru/es/smells/large-class&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;also-known-as&quot;&gt;Also Known as&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Large Class&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;credits-4&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@tank_ghisletti&quot;&gt;Francisco Ghisletti&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/greek-god-statue&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10362/code-smell-14-god-objects</guid>
<pubDate>Fri, 23 Jan 2026 13:12:23 +0000</pubDate>
</item>
<item>
<title>Code Smell 13 - Empty Constructors</title>
<link>https://coderlegion.com/9517/code-smell-13-empty-constructors</link>
<description>&lt;p&gt;&lt;em&gt;Non-Parameterized constructors are a code smell of an &lt;strong&gt;invalid&lt;/strong&gt; object that will dangerously mutate. Incomplete objects cause lots of issues.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Pass the essence to all your objects so they will not need to mutate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-5&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Mutability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incomplete objects&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Concurrency inconsistencies between creation and essence setting.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/nude-models-part-i-setters&quot;&gt;Setters&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-5&quot;&gt;Solutions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Pass the object's essence on creation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create objects with their &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6742/the-evil-power-of-mutants]&quot;&gt;immutable&lt;/a&gt; essence.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Refactorings ⚙️&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-001-remove-setters&quot;&gt;https://maximilianocontieri.com/refactoring-001-remove-setters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-016-build-with-the-essence&quot;&gt;https://maximilianocontieri.com/refactoring-016-build-with-the-essence&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-4&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Some persistence frameworks in static typed languages require an empty constructor.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;sample-code-5&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-5&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class AirTicket {
   constructor() {     
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-5&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class AirTicket {
   constructor(origin,
                destination, 
                arline,
                departureTime,
                passenger) {     
     
  // ...
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-5&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;Any linter can warn this (possible) situation.&lt;/p&gt;
&lt;h2 id=&quot;exceptions-2&quot;&gt;Exceptions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stateless objects. Always better solution than &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-18-static-functions&quot;&gt;static class methods&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tags--10&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Anemic Models&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-5&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important&quot;&gt;Why the Bijection Is Important&lt;/h2&gt;
&lt;p&gt;In the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;, objects correspond to real-world entities. &lt;/p&gt;
&lt;p&gt;Real people aren't born nameless and formless, then gradually acquire attributes. &lt;/p&gt;
&lt;p&gt;You don't meet someone who &lt;em&gt;temporarily&lt;/em&gt; has no age or email address. &lt;/p&gt;
&lt;p&gt;When you &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;model&lt;/a&gt; a person, you should capture their essential attributes at birth, just like reality. &lt;/p&gt;
&lt;p&gt;Breaking this bijection by creating hollow objects forces you to represent impossible states. &lt;/p&gt;
&lt;p&gt;Empty constructors create phantom and invalid objects that don't exist in your domain model, violating the mapping between your code and reality.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-5&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI code generators frequently produce this smell because they often follow common ORM patterns.&lt;/p&gt;
&lt;p&gt;When you prompt AI to &quot;create a Person class,&quot; it typically generates empty constructors with getters and setters.&lt;/p&gt;
&lt;p&gt;AI tools trained on legacy codebases inherit these patterns and propagate them unless you explicitly request immutable objects with required constructor parameters.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-5&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI tools can detect and fix this smell when you provide clear instructions. &lt;/p&gt;
&lt;p&gt;You need to specify that objects should be immutable with required constructor parameters. &lt;/p&gt;
&lt;p&gt;Without explicit guidance, AI tools may not recognize empty constructors as problematic since they appear frequently in training data.&lt;/p&gt;
&lt;h3 id=&quot;try-them--10&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Create an immutable class with required information. Include constructor validation and no setters. Make all fields final and use constructor parameters only&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Create+an+immutable+class+with+required+information.+Include+constructor+validation+and+no+setters.+Make+all+fields+final+and+use+constructor+parameters+only%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Create+an+immutable+class+with+required+information.+Include+constructor+validation+and+no+setters.+Make+all+fields+final+and+use+constructor+parameters+only%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Create+an+immutable+class+with+required+information.+Include+constructor+validation+and+no+setters.+Make+all+fields+final+and+use+constructor+parameters+only%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Create+an+immutable+class+with+required+information.+Include+constructor+validation+and+no+setters.+Make+all+fields+final+and+use+constructor+parameters+only%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Create+an+immutable+class+with+required+information.+Include+constructor+validation+and+no+setters.+Make+all+fields+final+and+use+constructor+parameters+only%3A+%60%60%60javascript%0D%0Aclass+AirTicket+%7B%0D%0A+++constructor%28%29+%7B+++++%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-5&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Always create complete objects. Make their essence immutable to endure through time.&lt;/p&gt;
&lt;p&gt;Every object needs its essence to be a valid one since inception.&lt;/p&gt;
&lt;p&gt;We should read Plato's ideas about immutability and create entities in a complete and immutable way.&lt;/p&gt;
&lt;p&gt;These immutable objects favor bijection and survive the passing of time.&lt;/p&gt;
&lt;h2 id=&quot;relations--10&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7246/code-smell-01-anemic-models&quot;&gt;https://coderlegion.com/7246/code-smell-01-anemic-models&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-28-setters&quot;&gt;https://maximilianocontieri.com/code-smell-28-setters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-40-dtos&quot;&gt;https://maximilianocontieri.com/code-smell-40-dtos&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8662/code-smell-10-too-many-arguments&quot;&gt;https://coderlegion.com/8662/code-smell-10-too-many-arguments&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-116-variables-declared-with-var&quot;&gt;https://maximilianocontieri.com/code-smell-116-variables-declared-with-var&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-5&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://codexposed.hashnode.dev/constructors-demystified&quot;&gt;https://codexposed.hashnode.dev/constructors-demystified&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6742/the-evil-power-of-mutants&quot;&gt;https://coderlegion.com/6742/the-evil-power-of-mutants&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8662/code-smell-10-too-many-arguments&quot;&gt;https://coderlegion.com/8662/code-smell-10-too-many-arguments&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;credits-5&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by Brett Jordan in Pexels&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;In a purely functional program, the value of a [constant] never changes, and yet, it changes all the time! A paradox!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Joel Spolski&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/9517/code-smell-13-empty-constructors</guid>
<pubDate>Sat, 10 Jan 2026 23:04:37 +0000</pubDate>
</item>
<item>
<title>Code Smell 12 - Null</title>
<link>https://coderlegion.com/9248/code-smell-12-null</link>
<description>&lt;p&gt;&lt;em&gt;Programmers use Null as different flags. It can hint at an absence, an undefined value, en error etc. Multiple semantics lead to coupling and defects.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Null is schizophrenic and does not exist in real-world. Its creator regretted and programmers around the world suffer from it. Don't be a part of it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-6&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Coupling between callers and senders.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-get-rid-of-annoying-ifs-forever&quot;&gt;If&lt;/a&gt;/&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-36-switchcaseelseifelseif-statements&quot;&gt;Switch&lt;/a&gt;/Case Polluting.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Null is not polymorphic with real objects. Hence, &lt;em&gt;Null Pointer Exception&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Null does not exist on real-world. Thus, it violates &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;Bijection Principle&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-6&quot;&gt;Solutions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Avoid Null.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the &lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Null_object_pattern&quot;&gt;NullObject pattern&lt;/a&gt; to avoid ifs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html&quot;&gt;Optionals&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6462/null-the-billion-dollar-mistake&quot;&gt;https://coderlegion.com/6462/null-the-billion-dollar-mistake&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;refactorings--8&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-015-remove-null&quot;&gt;https://maximilianocontieri.com/refactoring-015-remove-null&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-029-replace-null-with-collection&quot;&gt;https://maximilianocontieri.com/refactoring-029-replace-null-with-collection&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-014-remove-if&quot;&gt;https://maximilianocontieri.com/refactoring-014-remove-if&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context-5&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;When you use null, you encode multiple meanings into a single value.&lt;/p&gt;
&lt;p&gt;Sometimes you want to represent an absence. &lt;/p&gt;
&lt;p&gt;Sometimes you mean you have not loaded your objects yet. &lt;/p&gt;
&lt;p&gt;Sometimes you mean error. &lt;/p&gt;
&lt;p&gt;Callers must guess your intent and add conditionals to protect themselves. &lt;/p&gt;
&lt;p&gt;You spread knowledge about internal states across your codebase.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-6&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-6&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class CartItem {
    constructor(price) {
        this.price = price;
    }
}

class DiscountCoupon {
    constructor(rate) {
        this.rate = rate;
    }
}

class Cart {
    constructor(selecteditems, discountCoupon) {
        this.items = selecteditems;
        this.discountCoupon = discountCoupon;
    }

    subtotal() {
        return this.items.reduce((previous, current) =&amp;gt; 
            previous + current.price, 0);
    }

    total() {
        if (this.discountCoupon == null)
            return this.subtotal();
        else
            return this.subtotal() * (1 - this.discountCoupon.rate);
    }
}

cart = new Cart([
    new CartItem(1),
    new CartItem(2),
    new CartItem(7)
    ], new DiscountCoupon(0.15)]);
// 10 - 1.5 = 8.5

cart = new Cart([
    new CartItem(1),
    new CartItem(2),
    new CartItem(7)
    ], null);
// 10 - null  = 10
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-6&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class CartItem {
    constructor(price) {
        this.price = price;
    }
}

class DiscountCoupon {
    constructor(rate) {
        this.rate = rate;
    }

    discount(subtotal) {
        return subtotal * (1 - this.rate);
    }
}

class NullCoupon {
    discount(subtotal) {
        return subtotal;
    }
}

class Cart {
    constructor(selecteditems, discountCoupon) {
        this.items = selecteditems;
        this.discountCoupon = discountCoupon;
    }

    subtotal() {
        return this.items.reduce(
            (previous, current) =&amp;gt; previous + current.price, 0);
    }

    total() {
        return this.discountCoupon.discount(this.subtotal());
    }
}

cart = new Cart([
    new CartItem(1),
    new CartItem(2),
    new CartItem(7)
    ], new DiscountCoupon(0.15));
// 10 - 1.5 = 8.5

cart = new Cart([
    new CartItem(1),
    new CartItem(2),
    new CartItem(7)
    ], new NullCoupon());
// 10 - nullObject = 10
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-6&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;Most Linters can flag null usages and warn you.&lt;/p&gt;
&lt;h2 id=&quot;exceptions-3&quot;&gt;Exceptions&lt;/h2&gt;
&lt;p&gt;You sometimes need to deal with null when you integrate with databases, legacy APIs, or external protocols.&lt;/p&gt;
&lt;p&gt;You must contain null at the boundaries and convert it immediately into meaningful objects.&lt;/p&gt;
&lt;h2 id=&quot;tags--11&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Null&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-6&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[x] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--10&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;When you use null, you break the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; between your code and the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nothing in the mapper behaves like null. &lt;/p&gt;
&lt;p&gt;Absence, emptiness, and failure mean different things. &lt;/p&gt;
&lt;p&gt;When you collapse them into null, you force your program to guess reality and you invite defects.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-6&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI generators often introduce this smell. &lt;/p&gt;
&lt;p&gt;They default to null when they lack context or want to keep examples short and also because it is widespread (but harmful) industry default.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-6&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;You can instruct AI to remove nulls with simple rules. &lt;/p&gt;
&lt;p&gt;When you ask for explicit domain objects and forbid nullable returns, generators usually fix the smell correctly.&lt;/p&gt;
&lt;h3 id=&quot;try-them--11&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Rewrite this code to remove all null returns. Model absence explicitly using domain objects or collections. Do not add conditionals&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;conclusion-6&quot;&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Null is the billion-dollar mistake. Yet, most program languages support them and libraries suggest its usage.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;relations--11&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-88-lazy-initialization&quot;&gt;https://maximilianocontieri.com/code-smell-88-lazy-initialization&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-157-balance-at-0&quot;&gt;https://maximilianocontieri.com/code-smell-157-balance-at-0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-93-send-me-anything&quot;&gt;https://maximilianocontieri.com/code-smell-93-send-me-anything&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-get-rid-of-annoying-ifs-forever&quot;&gt;https://maximilianocontieri.com/how-to-get-rid-of-annoying-ifs-forever&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-36-switchcaseelseifelseif-statements&quot;&gt;https://maximilianocontieri.com/code-smell-36-switchcaseelseifelseif-statements&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-149-optional-chaining&quot;&gt;https://maximilianocontieri.com/code-smell-149-optional-chaining&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-212-elvis-operator&quot;&gt;https://maximilianocontieri.com/code-smell-212-elvis-operator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-192-optional-attributes&quot;&gt;https://maximilianocontieri.com/code-smell-192-optional-attributes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-126-fake-null-object&quot;&gt;https://maximilianocontieri.com/code-smell-126-fake-null-object&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-208-null-island&quot;&gt;https://maximilianocontieri.com/code-smell-208-null-island&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-160-invalid-id-9999&quot;&gt;https://maximilianocontieri.com/code-smell-160-invalid-id-9999&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-100-goto&quot;&gt;https://maximilianocontieri.com/code-smell-100-goto&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-42-warningsstrict-mode-off&quot;&gt;https://maximilianocontieri.com/code-smell-42-warningsstrict-mode-off&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-23-instance-type-checking&quot;&gt;https://maximilianocontieri.com/code-smell-23-instance-type-checking&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-6&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6462/null-the-billion-dollar-mistake&quot;&gt;https://coderlegion.com/6462/null-the-billion-dollar-mistake&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;credits-6&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@kydroon&quot;&gt;Kurt Cotoaga&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/black-hole&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Tony Hoare&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/9248/code-smell-12-null</guid>
<pubDate>Sun, 04 Jan 2026 13:30:27 +0000</pubDate>
</item>
<item>
<title>Code Smell 07 - Boolean Variables</title>
<link>https://coderlegion.com/9110/code-smell-07-boolean-variables</link>
<description>&lt;p&gt;&lt;em&gt;Using Boolean variables as flags introduces accidental implementation complexity and pollutes the code with Ifs.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Avoid Boolean variables, they lead to conditional logic and force you to write Ifs. Create polymorphic states instead.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-7&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Extensibility&lt;/li&gt;
&lt;li&gt;Comparison in some languages&lt;/li&gt;
&lt;li&gt;Missed &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-014-remove-if&quot;&gt;polymorphism&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Limited semantics&lt;/li&gt;
&lt;li&gt;Primitive obsession&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-7&quot;&gt;Solutions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;If Boolean maps to a real-world entity is safe.&lt;/li&gt;
&lt;li&gt;Model Booleans as a State to favor Extensibility following the &lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle&quot;&gt;Open/Closed Principle&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create intention-revealing objects&lt;/li&gt;
&lt;li&gt;Replace Booleans with &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-014-remove-if&quot;&gt;polymorphism&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;refactorings--9&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-014-remove-if&quot;&gt;https://maximilianocontieri.com/refactoring-014-remove-if&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-5&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Flags&lt;/li&gt;
&lt;li&gt;Status indicators&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-6&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;Boolean variables tempt you to oversimplify complex domains. &lt;/p&gt;
&lt;p&gt;When you use a Boolean, you force two states where many might exist. &lt;/p&gt;
&lt;p&gt;This creates coupling because you hardcode behavior based on &lt;em&gt;true/false&lt;/em&gt; checks scattered throughout your code.&lt;/p&gt;
&lt;p&gt;Booleans also hide intent. A variable named flag tells you nothing about what it represents in the real world. &lt;/p&gt;
&lt;p&gt;Even descriptive names like &lt;em&gt;isActive&lt;/em&gt; or &lt;em&gt;hasPermission&lt;/em&gt; leak implementation details instead of revealing domain concepts.&lt;/p&gt;
&lt;p&gt;The problems multiply when you need a third state. You cannot extend a Boolean without breaking existing code. &lt;/p&gt;
&lt;p&gt;You end up with multiple Boolean combinations that create implicit states, making your code fragile and hard to understand.&lt;/p&gt;
&lt;p&gt;Real-world entities rarely have just two states. &lt;/p&gt;
&lt;p&gt;A traffic light isn't &quot;on&quot; or &quot;off&quot;—it's red, yellow, or green. An order isn't just &quot;paid&quot; or &quot;unpaid&quot;—it might be pending, processed, shipped, or delivered. &lt;/p&gt;
&lt;h2 id=&quot;sample-code-7&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-7&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

function processBatch(
    bool $useLogin,
    bool $deleteEntries,
    bool $beforeToday) {
    // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-7&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

function processBatch(
    LoginStrategy $login,
    DeletionPolicy $deletionPolicy,
    Date $cutoffDate) {
    // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-7&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;[X] Manual&lt;/p&gt;
&lt;p&gt;Automatic detection can warn for B usage, but this can yield false positives.&lt;/p&gt;
&lt;p&gt;You can search for boolean attributes in classes, Boolean parameters in methods, and conditional statements that check Boolean values. &lt;/p&gt;
&lt;p&gt;Look for variables with &quot;is&quot;, &quot;has&quot;, &quot;can&quot;, or &quot;flag&quot; in their names. &lt;/p&gt;
&lt;p&gt;Watch for multiple Boolean combinations that represent different states.&lt;/p&gt;
&lt;h2 id=&quot;exceptions-4&quot;&gt;Exceptions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Real-world true/false rules&lt;/li&gt;
&lt;li&gt;Some languages have issues with Boolean comparators.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=8425574696456169922&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In these coupled with accidental complexity languages, Booleans are a common error source.&lt;/p&gt;
&lt;h2 id=&quot;tags--12&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;IFs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-7&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[x ] Intermediate  &lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--11&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;Your code should always mirror reality. &lt;/p&gt;
&lt;p&gt;When you use a Boolean to represent an employee's status, you break the bijection between your software and the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Real employees don't have a &lt;em&gt;true/false&lt;/em&gt; state. They have concrete statuses like &quot;on vacation&quot; or &quot;working remotely.&quot;&lt;/p&gt;
&lt;p&gt;This broken &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;mapping&lt;/a&gt; creates a gap between how domain experts think and how your code works. Business people talk about &quot;vacation status&quot; or &quot;remote work,&quot; not about &quot;is_on_vacation equals true.&quot; &lt;/p&gt;
&lt;p&gt;When you model with Booleans, you force translation between business language and code, increasing cognitive load and error potential.&lt;/p&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;bijection&lt;/a&gt; violation compounds when requirements change. Adding a new employee status means modifying all the boolean logic scattered across your codebase. &lt;/p&gt;
&lt;p&gt;With proper domain modeling, you simply add a new status class. The broken mapping makes your code rigid where reality is flexible.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-7&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI code generators frequently create Boolean flags because they optimize for brevity and simplicity. &lt;/p&gt;
&lt;p&gt;They often suggest &lt;em&gt;is_active&lt;/em&gt; or &lt;em&gt;has_permission&lt;/em&gt; flags when generating boilerplate code. &lt;/p&gt;
&lt;p&gt;You need to explicitly request domain modeling to avoid this pattern.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-7&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI tools can detect Boolean variables with medium accuracy when you provide context. &lt;/p&gt;
&lt;p&gt;You need to specify that you want domain-driven design and state pattern usage. &lt;/p&gt;
&lt;p&gt;Simple prompts might not catch the smell without explicit instructions to avoid Booleans.&lt;/p&gt;
&lt;h3 id=&quot;try-them--12&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: correct=Replace Boolean variables with polymorphism&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=correct%3DReplace+Boolean+variables+with+polymorphism%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=correct%3DReplace+Boolean+variables+with+polymorphism%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=correct%3DReplace+Boolean+variables+with+polymorphism%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=correct%3DReplace+Boolean+variables+with+polymorphism%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=correct%3DReplace+Boolean+variables+with+polymorphism%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+processBatch%28%0D%0A++++bool+%24useLogin%2C%0D%0A++++bool+%24deleteEntries%2C%0D%0A++++bool+%24beforeToday%29+%7B%0D%0A++++%2F%2F+...%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-7&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Take extra care when declaring something &lt;em&gt;Boolean&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Flags are difficult to maintain and extend.&lt;/p&gt;
&lt;p&gt;Learn more about the domain. Try migrating to &lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/State_pattern&quot;&gt;state design pattern&lt;/a&gt;. Use polymorphism instead of ifs/switch/cases.&lt;/p&gt;
&lt;h2 id=&quot;relations--12&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-51-double-negatives&quot;&gt;https://maximilianocontieri.com/code-smell-51-double-negatives&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-62-flag-variables&quot;&gt;https://maximilianocontieri.com/code-smell-62-flag-variables&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-104-assert-true&quot;&gt;https://maximilianocontieri.com/code-smell-104-assert-true&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-24-boolean-coercions&quot;&gt;https://maximilianocontieri.com/code-smell-24-boolean-coercions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-101-comparison-against-booleans&quot;&gt;https://maximilianocontieri.com/code-smell-101-comparison-against-booleans&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-122-primitive-obsession&quot;&gt;https://maximilianocontieri.com/code-smell-122-primitive-obsession&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-199-gratuitous-booleans&quot;&gt;https://maximilianocontieri.com/code-smell-199-gratuitous-booleans&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-270-boolean-apis&quot;&gt;https://maximilianocontieri.com/code-smell-270-boolean-apis&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-7&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://martinfowler.com/bliki/FlagArgument.html&quot;&gt;https://martinfowler.com/bliki/FlagArgument.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;also-known-as-1&quot;&gt;Also Known as&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Flag Abuser&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;credits-7&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@philhearing&quot;&gt;Phil Hearing&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/flag-finish&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/9110/code-smell-07-boolean-variables</guid>
<pubDate>Wed, 31 Dec 2025 01:38:55 +0000</pubDate>
</item>
<item>
<title>Code Smell 318 - Refactoring Dirty Code</title>
<link>https://coderlegion.com/9018/code-smell-318-refactoring-dirty-code</link>
<description>&lt;p&gt;&lt;em&gt;You polish code that nobody touches while the real hotspots burn&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Don't waste time refactoring code that never changes; focus on frequently modified problem areas.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-8&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Wasted effort&lt;/li&gt;
&lt;li&gt;Wrong priorities&lt;/li&gt;
&lt;li&gt;Missed real issues&lt;/li&gt;
&lt;li&gt;Team productivity drop&lt;/li&gt;
&lt;li&gt;Resource misallocation&lt;/li&gt;
&lt;li&gt;False progress feeling&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-8&quot;&gt;Solutions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Analyze change frequency&lt;/li&gt;
&lt;li&gt;Identify code hotspots&lt;/li&gt;
&lt;li&gt;Use version control data&lt;/li&gt;
&lt;li&gt;Focus on active areas&lt;/li&gt;
&lt;li&gt;Measure code churn&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactorings--10&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-021-remove-dead-code&quot;&gt;https://maximilianocontieri.com/refactoring-021-remove-dead-code&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context-7&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;This is the anti code smell.&lt;/p&gt;
&lt;p&gt;You come across ugly code with &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-36-switchcaseelseifelseif-statements&quot;&gt;complex conditionals&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7617/code-smell-03-functions-are-too-long&quot;&gt;long functions&lt;/a&gt;, and &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-33-abbreviations&quot;&gt;poor naming&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You remember Uncle Bob's motto of leaving the campsite better than when you found it.&lt;/p&gt;
&lt;p&gt;Your refactoring instinct kicks in, and you spend days cleaning it up.&lt;/p&gt;
&lt;p&gt;You feel productive, but you've been wasting your time.&lt;/p&gt;
&lt;p&gt;Bad code is only problematic when &lt;strong&gt;you need to change it&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Stable code, even if poorly written, doesn't hurt your productivity.&lt;/p&gt;
&lt;p&gt;The real technical debt lies in code hotspots: areas that are both problematic and frequently modified.&lt;/p&gt;
&lt;p&gt;Most codebases follow an extreme distribution where &lt;a rel=&quot;nofollow&quot; href=&quot;https://refactoring.fm/p/everything-as-code-hotspots-and-process&quot;&gt;5% of the code receives 90% of the changes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Without analyzing version control history, you cannot identify which messy code actually matters.&lt;/p&gt;
&lt;p&gt;You end up fixing the wrong things while the real problems remain untouched.&lt;/p&gt;
&lt;p&gt;You need to address the technical debt by prioritizing code with poor quality and high change frequency.&lt;/p&gt;
&lt;p&gt;Everything else is premature optimization disguised as craftsmanship.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-8&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong--5&quot;&gt;Wrong ❌&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# This authentication module hasn't changed in 3 years
# It's deprecated and will be removed next quarter
# But you spend a week &quot;improving&quot; it

class LegacyAuthenticator:
    def authenticate(self, user, pwd):
        # Original messy code from 2019
        if user != None:
            if pwd != None:
                if len(pwd) &amp;gt; 5:
                    # Complex nested logic...
                    result = self.check_db(user, pwd)
                    if result == True:
                        return True
                    else:
                        return False
        return False

# After your &quot;refactoring&quot; (that nobody asked for):
class LegacyAuthenticator:
    def authenticate(self, user: str, pwd: str) -&amp;gt; bool:
        if not self._is_valid_input(user, pwd):
            return False
        return self._verify_credentials(user, pwd)
    
    def _is_valid_input(self, user: str, pwd: str) -&amp;gt; bool:
        return user and pwd and len(pwd) &amp;gt; 5
    
    def _verify_credentials(self, user: str, pwd: str) -&amp;gt; bool:
        return self.check_db(user, pwd)

# Meanwhile, the actively developed payment module
# (modified 47 times this month) remains a mess
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-8&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# You analyze git history first:
# git log --format=format: --name-only | 
# grep -E '\.py$' | sort | uniq -c | sort -rn

# Results show PaymentProcessor changed 47 times this month
# And it does not have good enough coverage
# LegacyAuthenticator: 0 changes in 3 years

# Focus on the actual hotspot:
class PaymentProcessor:
    # This gets modified constantly and is hard to change
    # REFACTOR THIS FIRST
    def process_payment(self, amount, card, user, promo_code,
                       installments, currency, gateway):
        # 500 lines of tangled logic here
        # Changed 47 times this month
        # Every change takes 2+ days due to complexity
        pass

# Ignore stable legacy code
# But you can use IA to cover existing functionality
# With acceptance tests validated by a human product owner

class LegacyAuthenticator:
    # Leave this ugly code alone
    # It works, it's stable, it's being deprecated
    # Your time is better spent elsewhere
    def authenticate(self, user, pwd):
        if user != None:
            if pwd != None:
                if len(pwd) &amp;gt; 5:
                    result = self.check_db(user, pwd)
                    if result == True:
                        return True
        return False
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-8&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;[X] Semi-Automatic&lt;/p&gt;
&lt;p&gt;You can detect this smell by analyzing your version control history.&lt;/p&gt;
&lt;p&gt;Track which files change most frequently and correlate that with code quality metrics.&lt;/p&gt;
&lt;p&gt;Tools like &lt;a rel=&quot;nofollow&quot; href=&quot;https://codescene.com/&quot;&gt;CodeScene&lt;/a&gt;, git log analysis, or custom scripts can show your actual hotspots.&lt;/p&gt;
&lt;p&gt;Track your &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6337/we-need-to-stop-the-bugs&quot;&gt;defects&lt;/a&gt; to the code you change more often.&lt;/p&gt;
&lt;h2 id=&quot;exceptions-5&quot;&gt;Exceptions&lt;/h2&gt;
&lt;p&gt;Sometimes you must refactor stable code when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New feature development requires adaptive changes&lt;/li&gt;
&lt;li&gt;Security vulnerabilities require fixes&lt;/li&gt;
&lt;li&gt;Regulatory compliance demands changes&lt;/li&gt;
&lt;li&gt;You're about to reactivate dormant features&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key is intentional decision-making based on real data, not assumptions.&lt;/p&gt;
&lt;h2 id=&quot;tags--13&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Technical Debt&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-8&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--12&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;While you build a &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt; between your code and real-world behavior, you will notice some parts of your system are more actively changed than others.&lt;/p&gt;
&lt;p&gt;Your &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; should reflect this reality.&lt;/p&gt;
&lt;p&gt;When you refactor stable code, you break the correspondence between development effort and actual business value.&lt;/p&gt;
&lt;p&gt;You treat all code equally in your mental model, but the real world shows extreme usage patterns where a small percentage of code handles the vast majority of changes.&lt;/p&gt;
&lt;p&gt;You optimize for an imaginary world where all code matters equally.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-8&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;Some code generators suggest refactorings without considering change frequency.&lt;/p&gt;
&lt;p&gt;AI tools and linters analyze code statically and recommend improvements based on patterns alone, not usage.&lt;/p&gt;
&lt;p&gt;They do not access your version control history to understand which improvements actually matter unless you &lt;em&gt;explicitly&lt;/em&gt; tell them to do it.&lt;/p&gt;
&lt;p&gt;AI might flag every long function or complex conditional, treating a dormant 500-line legacy method the same as an equally messy function you modify daily.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-8&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI can help you to fix this code smell if you provide it with proper context.&lt;/p&gt;
&lt;p&gt;You need to give it version control data showing change frequencies. Without that information, AI will make the same mistakes humans do: recommending refactorings based purely on code structure.&lt;/p&gt;
&lt;h3 id=&quot;try-them--13&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Analyze this codebase's git history to identify files with high change frequency. Then review code quality metrics for those files. Recommend refactoring only the intersection of high-churn and low-quality code. Ignore stable low-quality code.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;conclusion-8&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You cannot improve productivity by polishing code that never changes.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-148-todos&quot;&gt;Technical debt&lt;/a&gt; only matters when it slows you down, which happens in code you actually modify.&lt;/p&gt;
&lt;p&gt;Focus your refactoring efforts where they multiply your impact: the hotspots where poor quality meets frequent change.&lt;/p&gt;
&lt;p&gt;Everything else is &lt;strong&gt;procrastination&lt;/strong&gt; disguised as engineering excellence.&lt;/p&gt;
&lt;p&gt;Let stable ugly code rest in peace.&lt;/p&gt;
&lt;p&gt;Your human time is too valuable to waste on problems that don't exist.&lt;/p&gt;
&lt;h2 id=&quot;relations--13&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8216/code-smell-06-too-clever-programmer&quot;&gt;https://coderlegion.com/8216/code-smell-06-too-clever-programmer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-20-premature-optimization&quot;&gt;https://maximilianocontieri.com/code-smell-20-premature-optimization&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-148-todos&quot;&gt;https://maximilianocontieri.com/code-smell-148-todos&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7617/code-smell-03-functions-are-too-long&quot;&gt;https://coderlegion.com/7617/code-smell-03-functions-are-too-long&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-36-switchcaseelseifelseif-statements&quot;&gt;https://maximilianocontieri.com/code-smell-36-switchcaseelseifelseif-statements&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-60-global-classes&quot;&gt;https://maximilianocontieri.com/code-smell-60-global-classes&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-8&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/v/F5WkftHqexQ&quot;&gt;https://www.youtube.com/v/F5WkftHqexQ&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;disclaimer-1&quot;&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;credits-8&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@viktorkeri&quot;&gt;Viktor Keri&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/photos/person-in-black-pants-and-black-hiking-shoes-mzfiko3Uehs&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;The first rule of optimization is: Don't do it. The second rule is: Don't do it yet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Michael A. Jackson&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/9018/code-smell-318-refactoring-dirty-code</guid>
<pubDate>Sun, 28 Dec 2025 13:55:55 +0000</pubDate>
</item>
<item>
<title>Code Smell 10 - Too Many Arguments</title>
<link>https://coderlegion.com/8662/code-smell-10-too-many-arguments</link>
<description>&lt;p&gt;&lt;em&gt;Objects or Functions need too many arguments to work.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Don't pass more than three arguments to your functions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-9&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Low maintainability&lt;/li&gt;
&lt;li&gt;Low Reuse &lt;/li&gt;
&lt;li&gt;Coupling&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-9&quot;&gt;Solutions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Find cohesive relations among arguments&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a &quot;context&quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consider using a &lt;a rel=&quot;nofollow&quot; href=&quot;https://wiki.c2.com/?MethodObject&quot;&gt;Method Object&lt;/a&gt; Pattern.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid &quot;basic&quot; Types: strings, arrays, integers, etc. Think on objects.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactorings--11&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-007-extract-class&quot;&gt;https://maximilianocontieri.com/refactoring-007-extract-class&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-010-extract-method-object&quot;&gt;https://maximilianocontieri.com/refactoring-010-extract-method-object&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-034-reify-parameters&quot;&gt;https://maximilianocontieri.com/refactoring-034-reify-parameters&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context-8&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;When you add arguments to make a function work, you encode knowledge in position and order. &lt;/p&gt;
&lt;p&gt;You force your callers to remember rules that belong to the domain.&lt;/p&gt;
&lt;p&gt;When you do this, you move behavior away from meaningful objects, and you replace intent with mechanics.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-9&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-8&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class Printer {   
  void print(String documentToPrint, 
           String papersize,
           String orientation, 
           boolean grayscales,
           int pagefrom,
           int pageTo,
           int copies,
           float marginLeft,
           float marginRight,
           float marginTop,
           float marginBottom         
        ) {
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-9&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;final public class PaperSize { }
final public class Document { }
final public class PrintMargins { }
final public class PrintRange { }  
final public class ColorConfiguration { }
final public class PrintOrientation { }
// Class definition with methods and properties omitted for simplicity

final public class PrintSetup {
    public PrintSetup(PaperSize papersize,
           PrintOrientation orientation, 
           ColorConfiguration color,
           PrintRange range,
           int copiesCount,
           PrintMargins margins
           ) {}
}

final public class Printer {   
  void print(
         Document documentToPrint, 
         PrintSetup setup        
        ) {
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-9&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;Most linters warn when the arguments list is too large.&lt;/p&gt;
&lt;p&gt;You can also detect this smell when a function signature grows over time.&lt;/p&gt;
&lt;h2 id=&quot;exceptions-6&quot;&gt;Exceptions&lt;/h2&gt;
&lt;p&gt;Operations in real-world needing not cohesive collaborators.&lt;/p&gt;
&lt;p&gt;Some low-level functions mirror external APIs or system calls. &lt;/p&gt;
&lt;p&gt;In those cases, argument lists reflect constraints you cannot control.&lt;/p&gt;
&lt;h2 id=&quot;tags--14&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Bloaters&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-9&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--13&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;Good design keeps a clear &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; between concepts in the program and concepts in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you spread a concept across many arguments, you break that mapping.&lt;/p&gt;
&lt;p&gt;You force callers to assemble meaning manually, and the model stops representing the domain.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-9&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI generators often create this smell. &lt;/p&gt;
&lt;p&gt;They optimize for quick success and keep adding parameters instead of creating new abstractions.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-9&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI generators can fix this smell when you ask for value objects or domain concepts explicitly. &lt;/p&gt;
&lt;h3 id=&quot;try-them--14&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Refactor this function by grouping related parameters into meaningful domain objects and reduce the argument list to one parameter&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Refactor+this+function+by+grouping+related+parameters+into+meaningful+domain+objects+and+reduce+the+argument+list+to+one+parameter%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Refactor+this+function+by+grouping+related+parameters+into+meaningful+domain+objects+and+reduce+the+argument+list+to+one+parameter%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Refactor+this+function+by+grouping+related+parameters+into+meaningful+domain+objects+and+reduce+the+argument+list+to+one+parameter%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Refactor+this+function+by+grouping+related+parameters+into+meaningful+domain+objects+and+reduce+the+argument+list+to+one+parameter%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Refactor+this+function+by+grouping+related+parameters+into+meaningful+domain+objects+and+reduce+the+argument+list+to+one+parameter%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-9&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Relate arguments and group them.&lt;/p&gt;
&lt;p&gt;Always favor real-world mappings. Find in real-world how to group the arguments in cohesive objects.&lt;/p&gt;
&lt;p&gt;If a function gets too many arguments, some of them might be related to the class construction. This is a design smell too.&lt;/p&gt;
&lt;h2 id=&quot;relations--14&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-34-too-many-attributes&quot;&gt;https://maximilianocontieri.com/code-smell-34-too-many-attributes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-13-empty-constructors&quot;&gt;https://maximilianocontieri.com/code-smell-13-empty-constructors&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-87-inconsistent-parameters-sorting&quot;&gt;https://maximilianocontieri.com/code-smell-87-inconsistent-parameters-sorting&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;credits-9&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@tobiastu&quot;&gt;Tobias Tullius&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/loaded&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/8662/code-smell-10-too-many-arguments</guid>
<pubDate>Sun, 21 Dec 2025 01:26:55 +0000</pubDate>
</item>
<item>
<title>Engineering DebtDrone: Building a High-Performance AST-Based Static Analyzer in Go</title>
<link>https://coderlegion.com/8619/engineering-debtdrone-building-a-high-performance-ast-based-static-analyzer-in-go</link>
<description>&lt;p&gt;The Limitations of Lexical Analysis&lt;br&gt;
In the world of static analysis, there is a distinct hierarchy of capability. At the bottom, you have lexical analysis—tools that treat code as a stream of strings. These are your grep-based linters. They are incredibly fast ($O(n)$ where $n$ is characters), but they are structurally blind.&lt;/p&gt;
&lt;p&gt;To a regex linter, a function signature is just a pattern to match. It cannot reliably distinguish between a nested closure, a generic type definition, or a comment that looks like code.&lt;/p&gt;
&lt;p&gt;When I set out to build DebtDrone, I wanted to measure Cognitive Complexity, not just cyclomatic complexity. Cyclomatic complexity counts paths through code (if/else/switch), but it fails to account for nesting. A flat switch statement with 50 cases is easy to read. A function with 3 levels of nested loops and conditionals is a maintenance nightmare.&lt;/p&gt;
&lt;p&gt;To measure this accurately, lexical analysis is insufficient. We need Syntactic Analysis. We need a tool that understands the code structure exactly as the compiler does.&lt;/p&gt;
&lt;p&gt;The Engine: Abstract Syntax Trees (AST)&lt;br&gt;
DebtDrone leverages Tree-sitter, an incremental parsing system that builds a concrete syntax tree for a source file. Unlike abstract syntax trees (ASTs) generated by language-specific compilers (like Go's go/ast), Tree-sitter provides a unified interface for traversing trees across 11+ languages.&lt;/p&gt;
&lt;p&gt;Parsing vs. Matching&lt;br&gt;
Consider the following Go snippet:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func process(items []string) {
    if len(items) &amp;gt; 0 {              // +1 Nesting
        for _, item := range items { // +2 Nesting (1 + 1 penalty)
            if item == &quot;stop&quot; {      // +3 Nesting (2 + 1 penalty)
                return
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A regex tool might count the keywords if and for, giving this a score of 3. DebtDrone parses this into a tree structure. By traversing the tree, we can track nesting depth context. Every time we enter a Block node that is a child of an IfStatement or ForStatement, we increment a depth counter.&lt;/p&gt;
&lt;p&gt;The score isn't just 1 + 1 + 1. It is weighted by depth:&lt;/p&gt;
&lt;p&gt;Level 0: Base cost&lt;br&gt;
Level 1: Base cost + 1 (Nesting penalty)&lt;br&gt;
Level 2: Base cost + 2 (Nesting penalty)&lt;br&gt;
This yields a &quot;Cognitive Complexity&quot; score that accurately reflects the mental overhead required to understand the function.&lt;/p&gt;
&lt;p&gt;Architectural Decision: Why Go?&lt;br&gt;
I chose Go for three primary architectural reasons:&lt;/p&gt;
&lt;p&gt;Concurrency Primitives: Static analysis is an &quot;embarrassingly parallel&quot; problem. Each file can be parsed in isolation. Go's Goroutines and Channels allow DebtDrone to fan-out parsing tasks across all available CPU cores with minimal overhead.&lt;/p&gt;
&lt;p&gt;Memory Safety &amp;amp; Speed: While Rust was a contender (and Tree-sitter has excellent Rust bindings), Go provided the fastest iteration loop for the CLI's UX and plumbing, while still offering near-C execution speed.&lt;/p&gt;
&lt;p&gt;Single Binary Distribution: The ultimate goal was a zero-dependency binary that could drop into any CI/CD pipeline (GitHub Actions, GitLab CI, Jenkins) without requiring a runtime like Node.js or Python.&lt;/p&gt;
&lt;p&gt;The Engineering Challenge: CGO and Cross-Compilation&lt;br&gt;
The most significant technical hurdle was the dependency on go-tree-sitter. Because Tree-sitter is implemented in C for performance, incorporating it requires CGO (CGO_ENABLED=1).&lt;/p&gt;
&lt;p&gt;In the Go ecosystem, CGO is often considered a &quot;dealbreaker&quot; for easy distribution. Standard Go cross-compilation (GOOS=linux go build) is trivial because the Go compiler knows how to generate machine code for different architectures. However, once you enable CGO, you are bound by the host system's C linker.&lt;/p&gt;
&lt;p&gt;You cannot compile a macOS binary on a Linux CI runner using the standard gcc. You need a macOS-compatible linker and system headers.&lt;/p&gt;
&lt;p&gt;The Solution: goreleaser-cross&lt;br&gt;
To solve this, I architected the release pipeline around Dockerized Cross-Compilers. Instead of relying on the bare-metal runner, the release process spins up a container (ghcr.io/goreleaser/goreleaser-cross) that contains a massive collection of cross-compilation toolchains:&lt;/p&gt;
&lt;p&gt;o64-clang: For building macOS (Darwin) binaries on Linux.&lt;br&gt;
mingw-w64: For building Windows binaries on Linux.&lt;br&gt;
aarch64-linux-gnu-gcc: For ARM64 Linux builds.&lt;br&gt;
This configuration is managed via .goreleaser.yaml, where we dynamically inject the correct C compiler (CC) based on the target architecture:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;builds:
  - id: debtdrone-cli
    env:
      - CGO_ENABLED=1
      # Dynamic Compiler Selection
      - CC={{ if eq .Os &quot;darwin&quot; }}o64-clang{{ else if eq .Os &quot;windows&quot; }}x86_64-w64-mingw32-gcc{{ else }}gcc{{ end }}
      - CXX={{ if eq .Os &quot;darwin&quot; }}o64-clang++{{ else if eq .Os &quot;windows&quot; }}x86_64-w64-mingw32-g++{{ else }}g++{{ end }}
    goos:
      - linux
      - darwin
      - windows
    goarch:
      - amd64
      - arm64
This setup allows a standard Ubuntu GitHub Actions runner to produce native binaries for Mac (Intel/Apple Silicon), Windows, and Linux in a single pass.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Distribution Strategy: Homebrew Taps&lt;br&gt;
For v1.0.0, accessibility was key. While curl | bash scripts are common, they lack version management. I implemented a custom Homebrew Tap to treat DebtDrone as a first-class citizen on macOS.&lt;/p&gt;
&lt;p&gt;By adding a brews section to the GoReleaser config, the pipeline automatically:&lt;/p&gt;
&lt;p&gt;Generates a Ruby formula (debtdrone.rb) with the correct SHA256 checksums.&lt;br&gt;
Commits this formula to a separate homebrew-tap repository.&lt;br&gt;
Allows users to install/upgrade via brew install endrilickollari/tap/debtdrone.&lt;br&gt;
Beyond the Code: Impact by Role&lt;br&gt;
While the engineering behind DebtDrone is fascinating, its real value lies in how it empowers different stakeholders in the software development lifecycle.&lt;/p&gt;
&lt;p&gt;For the Developer: The &quot;Self-Check&quot; Before Commit&lt;br&gt;
We've all been there: you're deep in the zone, solving a complex edge case. You add a flag, then a nested if, then a loop to handle a collection. It works, but you've just created a &quot;complexity bomb.&quot;&lt;/p&gt;
&lt;p&gt;DebtDrone acts as a mirror. By running debtdrone check . locally, you get immediate feedback:&lt;/p&gt;
&lt;p&gt;&quot;Warning: processTransaction has a complexity score of 25 (Threshold: 15).&quot;&lt;/p&gt;
&lt;p&gt;This prompts a refactor before the code even reaches a pull request. It encourages writing smaller, more composable functions, which are inherently easier to test and debug.&lt;/p&gt;
&lt;p&gt;For the Team Lead: Objective Code Quality&lt;br&gt;
Code reviews can be subjective. &quot;This looks too complex&quot; is an opinion; &quot;This function has a complexity score of 42&quot; is a fact.&lt;/p&gt;
&lt;p&gt;DebtDrone provides an objective baseline for discussions. It helps leads identify:&lt;/p&gt;
&lt;p&gt;Hotspots: Which files are the most dangerous to touch?&lt;br&gt;
Trends: Is the codebase getting cleaner or messier over time?&lt;br&gt;
Gatekeeping: Preventing technical debt from leaking into the main branch by setting hard thresholds in CI.&lt;br&gt;
For DevOps: The Quality Gate&lt;br&gt;
In a CI/CD pipeline, DebtDrone serves as a lightweight, fast quality gate. Because it compiles to a single binary with zero dependencies, it can be dropped into any pipeline (GitHub Actions, GitLab CI, Jenkins) without complex setup.&lt;/p&gt;
&lt;p&gt;It supports standard exit codes (non-zero on failure) and can output results in JSON for integration with dashboarding tools. This ensures that &quot;maintainability&quot; is treated with the same rigor as &quot;passing tests.&quot;&lt;/p&gt;
&lt;p&gt;For the Business Analyst: Velocity &amp;amp; ROI&lt;br&gt;
Why should a business care about Abstract Syntax Trees? Because complexity kills velocity.&lt;/p&gt;
&lt;p&gt;High cognitive complexity directly correlates with:&lt;/p&gt;
&lt;p&gt;Longer onboarding times for new developers.&lt;br&gt;
Higher bug rates due to misunderstood logic.&lt;br&gt;
Slower feature delivery as developers spend more time deciphering old code than writing new code.&lt;br&gt;
By investing in tools like DebtDrone, organizations are investing in their long-term agility. It's not just about &quot;clean code&quot;—it's about sustainable development speed.&lt;/p&gt;
&lt;p&gt;Conclusion&lt;br&gt;
DebtDrone v1.0.0 represents a shift from &quot;linting as an afterthought&quot; to &quot;architectural analysis as a standard.&quot; By moving from Regex to ASTs, we eliminate false positives. By solving the CGO cross-compilation puzzle, we ensure the tool is available everywhere.&lt;/p&gt;
&lt;p&gt;The result is a CLI that runs locally, respects data privacy, and provides immediate, actionable feedback on technical debt.&lt;/p&gt;
&lt;p&gt;GitHub Repository: endrilickollari/debtdrone-cli&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/8619/engineering-debtdrone-building-a-high-performance-ast-based-static-analyzer-in-go</guid>
<pubDate>Fri, 19 Dec 2025 11:11:48 +0000</pubDate>
</item>
<item>
<title>Code Smell 09 - Dead Code</title>
<link>https://coderlegion.com/8495/code-smell-09-dead-code</link>
<description>&lt;p&gt;&lt;em&gt;Code that is no longer used or needed.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Do not keep code &quot;just in case I need it&quot;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-10&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Maintainability&lt;/li&gt;
&lt;li&gt;Extra reading&lt;/li&gt;
&lt;li&gt;Broken intent&lt;/li&gt;
&lt;li&gt;Wasted effort&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-10&quot;&gt;Solutions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Remove the code&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/KISS_principle&quot;&gt;KISS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Shrink codebase&lt;/li&gt;
&lt;li&gt;Test behavior only&lt;/li&gt;
&lt;li&gt;Trust version control&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactorings--12&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-021-remove-dead-code&quot;&gt;https://maximilianocontieri.com/refactoring-021-remove-dead-code&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-6&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gold plating code or &lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it&quot;&gt;Yagni&lt;/a&gt; code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-9&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;Dead code appears when you change requirements, and you fear deleting things. &lt;/p&gt;
&lt;p&gt;You comment logic, keep old branches, or preserve unused methods just in case. &lt;/p&gt;
&lt;p&gt;When you do that, you lie about what the system can actually do. &lt;/p&gt;
&lt;p&gt;The code promises behavior that never happens.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-10&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-9&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class Robot {   
  walk() {
    // ...
    }
  serialize() {
    // ..
  }
  persistOnDatabase(database) {
    // ..
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-10&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;class Robot {   
  walk() {
    // ...
    }  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-10&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;Coverage tools can find dead code (uncovered) if you have a great suite of tests.&lt;/p&gt;
&lt;h2 id=&quot;exceptions-7&quot;&gt;Exceptions&lt;/h2&gt;
&lt;p&gt;Avoid metaprogramming. When used, it is very difficult to find references to the code.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/laziness-i-meta-programming&quot;&gt;https://maximilianocontieri.com/laziness-i-meta-programming&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;tags--15&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;YAGNI&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-10&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[x] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--14&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;Your program must mirror the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt; with a clear &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dead code breaks that mapping. The domain has no such behavior, yet the code claims it exists. &lt;/p&gt;
&lt;p&gt;When you do that, you destroy trust. &lt;/p&gt;
&lt;p&gt;Readers cannot know what matters and what does not.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-10&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI generators often create dead code. &lt;/p&gt;
&lt;p&gt;They add defensive branches, legacy helpers, and unused abstractions to look complete. &lt;/p&gt;
&lt;p&gt;When you do not review the result, the smell stays.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-10&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI tools can remove this smell with simple instructions. &lt;/p&gt;
&lt;p&gt;You can ask them to delete unreachable code and align logic with tests. &lt;/p&gt;
&lt;p&gt;They work well when you already have coverage.&lt;/p&gt;
&lt;h3 id=&quot;try-them--15&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: correct=remove dead code&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=correct%3Dremove+dead+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=correct%3Dremove+dead+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=correct%3Dremove+dead+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=correct%3Dremove+dead+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=correct%3Dremove+dead+code%3A+%60%60%60javascript%0D%0Aclass+Robot+%7B+++%0D%0A++walk%28%29+%7B%0D%0A++++%2F%2F+...%0D%0A++++%7D%0D%0A++serialize%28%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A++persistOnDatabase%28database%29+%7B%0D%0A++++%2F%2F+..%0D%0A++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-10&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Remove dead code for simplicity.&lt;/p&gt;
&lt;p&gt;If you are uncertain of your code, you can temporarily disable it using &lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Feature_toggle&quot;&gt;Feature Toggle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Removing code is always more rewarding than adding.&lt;/p&gt;
&lt;h2 id=&quot;relations--15&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-54-anchor-boats&quot;&gt;https://maximilianocontieri.com/code-smell-54-anchor-boats&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-9&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/laziness-i-meta-programming&quot;&gt;https://maximilianocontieri.com/laziness-i-meta-programming&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;credits-10&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://pixabay.com/users/ray_shrewsberry-7673058/&quot;&gt;Ray Shrewsberry&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://pixabay.com/&quot;&gt;Pixabay&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/8495/code-smell-09-dead-code</guid>
<pubDate>Tue, 16 Dec 2025 02:28:27 +0000</pubDate>
</item>
<item>
<title>Code Smell 316 - Nitpicking</title>
<link>https://coderlegion.com/8451/code-smell-316-nitpicking</link>
<description>&lt;p&gt;&lt;em&gt;When syntax noise hides real design problems&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: When you focus code reviews on syntax, you miss architecture, security, design and intent.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-11&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Syntax fixation&lt;/li&gt;
&lt;li&gt;Design blindness&lt;/li&gt;
&lt;li&gt;Missed risks&lt;/li&gt;
&lt;li&gt;Bad feedback&lt;/li&gt;
&lt;li&gt;Useless discussions&lt;/li&gt;
&lt;li&gt;Reviewer fatigue&lt;/li&gt;
&lt;li&gt;False quality&lt;/li&gt;
&lt;li&gt;Shallow feedback&lt;/li&gt;
&lt;li&gt;Syntax Police&lt;/li&gt;
&lt;li&gt;Low team morale&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-11&quot;&gt;Solutions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Leave the boring work to the IA&lt;/li&gt;
&lt;li&gt;Automate &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-032-apply-consistent-style-rules&quot;&gt;style checks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Review architecture first&lt;/li&gt;
&lt;li&gt;Discuss intent early with technical analysis and control points&lt;/li&gt;
&lt;li&gt;Enforce review roles&lt;/li&gt;
&lt;li&gt;Raise abstraction level&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactorings--13&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-032-apply-consistent-style-rules&quot;&gt;https://maximilianocontieri.com/refactoring-032-apply-consistent-style-rules&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-016-build-with-the-essence&quot;&gt;https://maximilianocontieri.com/refactoring-016-build-with-the-essence&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context-10&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;When you review code, you choose where to spend your valuable human attention.&lt;/p&gt;
&lt;p&gt;When you spend that attention on commas, naming trivia, or formatting, you ignore the parts that matter.&lt;/p&gt;
&lt;p&gt;This smell appears when teams confuse cleanliness with correctness. Syntax looks clean. Architecture rots.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-11&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong--6&quot;&gt;Wrong ❌&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php

class UserRepository {
    public function find($id){
        $conn = mysqli_connect(
             &quot;localhost&quot;, // Pull Request comment - Bad indentation
            &quot;root&quot;,
            &quot;password123&quot;,
            &quot;app&quot;
        );

        $query = &quot;Select * FROM users WHERE id = $id&quot;;
        // Pull Request comment - SELECT should be uppercase
        return mysqli_query($conn, $query);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-11&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php

final class UserRepository {
    private Database $database;

    public function __construct(Database $database) {
        $this-&amp;gt;database = $database;
    }

    public function find(UserId $id): User {
        return $this-&amp;gt;database-&amp;gt;fetchUser($id);
    }
}

// You removed credentials, SQL, and infrastructure noise.
// Now reviewers can discuss design and behavior.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-11&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;[X] Manual&lt;/p&gt;
&lt;p&gt;You can detect this smell by examining pull request comments.&lt;/p&gt;
&lt;p&gt;When you see multiple comments about &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-48-code-without-standards&quot;&gt;formatting&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-164-mixed-indentations&quot;&gt;indentation&lt;/a&gt;, trailing commas, or variable naming conventions, you lack proper automation.&lt;/p&gt;
&lt;p&gt;Check your continuos integration pipeline configuration. If you don't enforce linting and formatting before human review, you force reviewers to catch these issues manually.&lt;/p&gt;
&lt;p&gt;Review your code review metrics. If you spend more time discussing style than architecture, you have this smell.&lt;/p&gt;
&lt;p&gt;Automated tools like SonarQube, ESLint, and Prettier can identify when you don't enforce rules automatically.&lt;/p&gt;
&lt;h2 id=&quot;tags--16&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Standards&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-11&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[x] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--15&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;Code review represents the quality assurance process in the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you break the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; by having humans perform mechanical checks instead of judgment-based evaluation, you mismodel the review process.&lt;/p&gt;
&lt;p&gt;You no longer validate whether the concepts, rules, and constraints match the domain.&lt;/p&gt;
&lt;p&gt;You only validate formatting.&lt;/p&gt;
&lt;p&gt;That gap creates systems that look clean and behave wrong.&lt;/p&gt;
&lt;p&gt;The broken bijection manifests as reviewer fatigue and missed bugs. You restore proper mapping by separating mechanical verification (automated) from architectural review (human).&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-11&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI generators often create this smell.&lt;/p&gt;
&lt;p&gt;They produce syntactically correct code with weak boundaries and unclear intent.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-11&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI can reduce this smell when you instruct it to focus on architecture, invariants, and risks instead of formatting.&lt;/p&gt;
&lt;p&gt;Give them clear prompts and describe the role and skills of the reviewer.&lt;/p&gt;
&lt;h3 id=&quot;try-them--16&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Find real problems in the code beyond nitpicking, review this code focusing on architecture, responsibilities, security risks, and domain alignment. Ignore formatting and style.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Find+real+problems+in+the+code+beyond+nitpicking%2C+review+this+code+focusing+on+architecture%2C+responsibilities%2C+security+risks%2C+and+domain+alignment.+Ignore+formatting+and+style.%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Find+real+problems+in+the+code+beyond+nitpicking%2C+review+this+code+focusing+on+architecture%2C+responsibilities%2C+security+risks%2C+and+domain+alignment.+Ignore+formatting+and+style.%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Find+real+problems+in+the+code+beyond+nitpicking%2C+review+this+code+focusing+on+architecture%2C+responsibilities%2C+security+risks%2C+and+domain+alignment.+Ignore+formatting+and+style.%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Find+real+problems+in+the+code+beyond+nitpicking%2C+review+this+code+focusing+on+architecture%2C+responsibilities%2C+security+risks%2C+and+domain+alignment.+Ignore+formatting+and+style.%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Find+real+problems+in+the+code+beyond+nitpicking%2C+review+this+code+focusing+on+architecture%2C+responsibilities%2C+security+risks%2C+and+domain+alignment.+Ignore+formatting+and+style.%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0Aclass+UserRepository+%7B%0D%0A++++public+function+find%28%24id%29%7B%0D%0A++++++++%24conn+%3D+mysqli_connect%28%0D%0A+++++++++++++%22localhost%22%2C+%2F%2F+Pull+Request+comment+-+Bad+indentation%0D%0A++++++++++++%22root%22%2C%0D%0A++++++++++++%22password123%22%2C%0D%0A++++++++++++%22app%22%0D%0A++++++++%29%3B%0D%0A%0D%0A++++++++%24query+%3D+%22Select+%2A+FROM+users+WHERE+id+%3D+%24id%22%3B%0D%0A++++++++%2F%2F+Pull+Request+comment+-+SELECT+should+be+uppercase%0D%0A++++++++return+mysqli_query%28%24conn%2C+%24query%29%3B%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-11&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Code reviews should improve systems, not satisfy linters.&lt;/p&gt;
&lt;p&gt;When you automate syntax, you free humans to think.&lt;/p&gt;
&lt;p&gt;That shift turns reviews into real design conversations.&lt;/p&gt;
&lt;h2 id=&quot;relations--16&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8216/code-smell-06-too-clever-programmer&quot;&gt;https://coderlegion.com/8216/code-smell-06-too-clever-programmer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-48-code-without-standards&quot;&gt;https://maximilianocontieri.com/code-smell-48-code-without-standards&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8106/code-smell-05-comment-abusers&quot;&gt;https://coderlegion.com/8106/code-smell-05-comment-abusers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-173-broken-windows&quot;&gt;https://maximilianocontieri.com/code-smell-173-broken-windows&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-236-unwrapped-lines&quot;&gt;https://maximilianocontieri.com/code-smell-236-unwrapped-lines&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;disclaimer-2&quot;&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;credits-11&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@portuguesegravity&quot;&gt;Portuguese Gravity&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/photos/gray-stainless-steel-fork-and-spoon-on-white-ceramic-plate-qxR_MIyCoAw&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Design is about intent, not syntax.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Grady Booch&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/8451/code-smell-316-nitpicking</guid>
<pubDate>Sun, 14 Dec 2025 02:42:18 +0000</pubDate>
</item>
<item>
<title>Code Smell 06 - Too Clever Programmer</title>
<link>https://coderlegion.com/8216/code-smell-06-too-clever-programmer</link>
<description>&lt;p&gt;&lt;em&gt;Code is hard to read when you use tricky names with no semantics or rely on accidental language complexity.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Don't try to look too smart. Clean code emphasizes readability and simplicity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-12&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Readability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintainability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code Quality&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-20-premature-optimization&quot;&gt;Premature Optimization&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-12&quot;&gt;Solutions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Refactor the code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/what-exactly-is-a-name-part-i-the-quest&quot;&gt;good names&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refactor tricky code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prefer clarity first&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid hidden tricks&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimize only later with strong real evidence&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;refactorings--14&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-005-replace-comment-with-function-name&quot;&gt;https://maximilianocontieri.com/refactoring-005-replace-comment-with-function-name&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-7&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Optimized loops&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-11&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;You might feel the urge to show off your skills with complex tricks or cryptic names.&lt;/p&gt;
&lt;p&gt;This makes your code harder to read, debug, and extend.&lt;/p&gt;
&lt;p&gt;You must remember that you write code for humans, not machines.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-12&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-10&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function primeFactors(n) {
  var f = [],  i = 0, d = 2;  
  
  for (i = 0; n &amp;gt;= 2; ) {
     if(n % d == 0) {
       f[i++]=(d); 
       n /= d;
    }
    else {
      d++;
    }     
  }
  return f;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-12&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function primeFactors(numberToFactor) {
  var factors = [], 
      divisor = 2,
      remainder = numberToFactor;
  
  while(remainder&amp;gt;=2) {
    if(remainder % divisor === 0) {
       factors.push(divisor); 
       remainder = remainder / divisor;
    }
    else {
      divisor++;
    }     
  }
  return factors;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-12&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;[X] Semi-Automatic&lt;/p&gt;
&lt;p&gt;Automatic detection is possible in some languages.&lt;/p&gt;
&lt;p&gt;Look for warnings about complexity, bad names, post-increment variables, and similar patterns.&lt;/p&gt;
&lt;h2 id=&quot;exceptions-8&quot;&gt;Exceptions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Optimized code for low-level operations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tags--17&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Complexity&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-12&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Intermediate&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--16&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;When you keep a clear &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; between your program and the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;MAPPER&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Other developers and your future self can understand it quickly.&lt;/p&gt;
&lt;p&gt;Clever tricks break this mapping and force future readers to guess instead of reading.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-12&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI models sometimes generate clever one-liners or compressed solutions.&lt;/p&gt;
&lt;p&gt;They might look smart but lack readability and semantics.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-12&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI assistants can rewrite clever code into readable code if you instruct them to prefer clarity to optimization.&lt;/p&gt;
&lt;h3 id=&quot;try-them--17&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: correct=Remove cleverness from code&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;conclusion-12&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Clever developers write cryptic code to brag.&lt;/p&gt;
&lt;p&gt;Smart developers write clean code.&lt;/p&gt;
&lt;p&gt;Clear beats clever.&lt;/p&gt;
&lt;h2 id=&quot;relations--17&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7475/code-smell-02-constants-and-magic-numbers&quot;&gt;https://coderlegion.com/7475/code-smell-02-constants-and-magic-numbers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-20-premature-optimization&quot;&gt;https://maximilianocontieri.com/code-smell-20-premature-optimization&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-44-magic-corrections&quot;&gt;https://maximilianocontieri.com/code-smell-44-magic-corrections&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-41-regular-expression-abusers&quot;&gt;https://maximilianocontieri.com/code-smell-41-regular-expression-abusers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-78-callback-hell&quot;&gt;https://maximilianocontieri.com/code-smell-78-callback-hell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-51-double-negatives&quot;&gt;https://maximilianocontieri.com/code-smell-51-double-negatives&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-33-abbreviations&quot;&gt;https://maximilianocontieri.com/code-smell-33-abbreviations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-48-code-without-standards&quot;&gt;https://maximilianocontieri.com/code-smell-48-code-without-standards&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-196-javascript-array-constructors&quot;&gt;https://maximilianocontieri.com/code-smell-196-javascript-array-constructors&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-25-pattern-abusers&quot;&gt;https://maximilianocontieri.com/code-smell-25-pattern-abusers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-93-send-me-anything&quot;&gt;https://maximilianocontieri.com/code-smell-93-send-me-anything&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-145-short-circuit-hack&quot;&gt;https://maximilianocontieri.com/code-smell-145-short-circuit-hack&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-212-elvis-operator&quot;&gt;https://maximilianocontieri.com/code-smell-212-elvis-operator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-180-bitwise-optimizations&quot;&gt;https://maximilianocontieri.com/code-smell-180-bitwise-optimizations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-129-structural-optimizations&quot;&gt;https://maximilianocontieri.com/code-smell-129-structural-optimizations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-32-singletons&quot;&gt;https://maximilianocontieri.com/code-smell-32-singletons&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-21-anonymous-functions-abusers&quot;&gt;https://maximilianocontieri.com/code-smell-21-anonymous-functions-abusers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-24-boolean-coercions&quot;&gt;https://maximilianocontieri.com/code-smell-24-boolean-coercions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-69-big-bang-javascript-ridiculous-castings&quot;&gt;https://maximilianocontieri.com/code-smell-69-big-bang-javascript-ridiculous-castings&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-10&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://ardalis.com/are-boolean-flags-on-methods-a-code-smell/&quot;&gt;https://ardalis.com/are-boolean-flags-on-methods-a-code-smell/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;also-known-as-2&quot;&gt;Also Known as&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Obfuscator&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;credits-12&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@neonbrand&quot;&gt;NeONBRAND&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/smart-brain&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Programming can be fun, so can cryptography; however they should not be combined.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Kreitzberg &amp;amp; Shneiderman&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/8216/code-smell-06-too-clever-programmer</guid>
<pubDate>Sat, 06 Dec 2025 00:33:31 +0000</pubDate>
</item>
<item>
<title>Code Smell 05 - Comment Abusers</title>
<link>https://coderlegion.com/8106/code-smell-05-comment-abusers</link>
<description>&lt;p&gt;&lt;em&gt;The code has lots of comments. Comments are coupled to implementation and hardly maintained.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Leave comments just for important design decisions. Don't explain the obvious.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-13&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Maintainability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Obsolete Documentation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Readability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Duplication between code and comments&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-13&quot;&gt;Solutions&lt;/h2&gt;
&lt;p&gt;1) Refactor methods.&lt;/p&gt;
&lt;p&gt;2) Rename methods with more declarative names.&lt;/p&gt;
&lt;p&gt;3) Break down large methods.&lt;/p&gt;
&lt;p&gt;4) If a comment describes what a method does, &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-005-replace-comment-with-function-name&quot;&gt;name the method with this description&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;5) Just comment on important design decisions.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/what-exactly-is-a-name-part-i-the-quest&quot;&gt;https://maximilianocontieri.com/what-exactly-is-a-name-part-i-the-quest&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;refactorings--15&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-005-replace-comment-with-function-name&quot;&gt;https://maximilianocontieri.com/refactoring-005-replace-comment-with-function-name&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-011-replace-comments-with-tests&quot;&gt;https://maximilianocontieri.com/refactoring-011-replace-comments-with-tests&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-002-extract-method&quot;&gt;https://maximilianocontieri.com/refactoring-002-extract-method&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-8&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Libraries&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Class Comments&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Method Comments&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-12&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;You write comments when you feel your code does not speak by itself. &lt;/p&gt;
&lt;p&gt;Most of the time, you add noise instead of clarity.  &lt;/p&gt;
&lt;p&gt;Later, those comments lie when you change the code but forget to update the explanation. &lt;/p&gt;
&lt;p&gt;Instead of helping, they hurt.  &lt;/p&gt;
&lt;h2 id=&quot;sample-code-13&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-11&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

final class ChatBotConnectionHelper {
    // ChatBotConnectionHelper is used
    // to create connection strings to Bot Platform
    // Use this class with getString() function
    // to get connection string to platform

    function getString() {
        // Get Connection String from Chatbot
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-13&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

final class ChatBotConnectionSequenceGenerator {

    function connectionSequence() {
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-13&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;[X] Semi-Automatic&lt;/p&gt;
&lt;p&gt;Linters can detect comments and check the ratio of comments to lines of code against a predefined threshold.&lt;/p&gt;
&lt;h2 id=&quot;tags--18&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Comments&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-13&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Beginner &lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--17&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;Your software should reflect the domain with no translators in between.&lt;/p&gt;
&lt;p&gt;When you use comments as crutches, you break the one-to-one mapping between the real-world concept and its code representation.&lt;/p&gt;
&lt;p&gt;This mismatch creates confusion and bugs.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-13&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI tools often generate comments to explain code in natural language.&lt;/p&gt;
&lt;p&gt;This can pollute your source when the code already speaks for itself.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-13&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI tools can easily remove redundant comments and suggest clearer names.&lt;/p&gt;
&lt;p&gt;You only need to instruct them to &quot;remove obvious comments and refactor for clarity.&quot;&lt;/p&gt;
&lt;h3 id=&quot;try-them--18&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: correct=Remove all Comments&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=correct%3DRemove+all+Comments%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=correct%3DRemove+all+Comments%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=correct%3DRemove+all+Comments%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=correct%3DRemove+all+Comments%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=correct%3DRemove+all+Comments%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afinal+class+ChatBotConnectionHelper+%7B%0D%0A++++%2F%2F+ChatBotConnectionHelper+is+used%0D%0A++++%2F%2F+to+create+connection+strings+to+Bot+Platform%0D%0A++++%2F%2F+Use+this+class+with+getString%28%29+function%0D%0A++++%2F%2F+to+get+connection+string+to+platform%0D%0A%0D%0A++++function+getString%28%29+%7B%0D%0A++++++++%2F%2F+Get+Connection+String+from+Chatbot%0D%0A++++%7D%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-13&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Leave comments just for important design decisions. Don't comment on a method with a bad name, rename it.&lt;/p&gt;
&lt;h2 id=&quot;relations--18&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-75-comments-inside-a-method&quot;&gt;https://maximilianocontieri.com/code-smell-75-comments-inside-a-method&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-57-versioned-functions&quot;&gt;https://maximilianocontieri.com/code-smell-57-versioned-functions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-168-undocumented-decisions&quot;&gt;https://maximilianocontieri.com/code-smell-168-undocumented-decisions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-151-commented-code&quot;&gt;https://maximilianocontieri.com/code-smell-151-commented-code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-183-obsolete-comments&quot;&gt;https://maximilianocontieri.com/code-smell-183-obsolete-comments&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-146-getter-comments&quot;&gt;https://maximilianocontieri.com/code-smell-146-getter-comments&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-11&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://refactoring.guru/es/smells/comments&quot;&gt;https://refactoring.guru/es/smells/comments&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/what-exactly-is-a-name-part-i-the-quest&quot;&gt;https://maximilianocontieri.com/what-exactly-is-a-name-part-i-the-quest&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/alexbunardzic/code-comments-are-a-sign-that-something-s-off-19e1&quot;&gt;https://dev.to/alexbunardzic/code-comments-are-a-sign-that-something-s-off-19e1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://arter.dev/how-to-comment-your-code-like-a-boss&quot;&gt;https://arter.dev/how-to-comment-your-code-like-a-boss&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;credits-13&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@lunarts&quot;&gt;Volodymyr Hryshchenko&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/chat&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;If you have to spend effort looking at a fragment of code and figuring out what it’s doing, then you should extract it into a function and name the function after the what.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Martin Fowler&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/8106/code-smell-05-comment-abusers</guid>
<pubDate>Wed, 03 Dec 2025 00:17:10 +0000</pubDate>
</item>
<item>
<title>Code Smell 315 - Cloudflare Feature Explosion</title>
<link>https://coderlegion.com/7979/code-smell-315-cloudflare-feature-explosion</link>
<description>&lt;p&gt;&lt;em&gt;When bad configuration kills all internet proxies&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Overly large auto-generated config can crash your system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-14&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Config overload&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7475/code-smell-02-constants-and-magic-numbers&quot;&gt;Hardcoded&lt;/a&gt; limit&lt;/li&gt;
&lt;li&gt;Lack of validations&lt;/li&gt;
&lt;li&gt;Crash on overflow&lt;/li&gt;
&lt;li&gt;Fragile &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;coupling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cascading Failures&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-198-hidden-assumptions&quot;&gt;Hidden Assumptions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Silent duplication&lt;/li&gt;
&lt;li&gt;Unexpected crashes&lt;/li&gt;
&lt;li&gt;Thread panics in critical paths&lt;/li&gt;
&lt;li&gt;Treating internal data as trusted input&lt;/li&gt;
&lt;li&gt;Poor observability&lt;/li&gt;
&lt;li&gt;Single point of failure in internet infrastructure&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-14&quot;&gt;Solutions&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Validate inputs early&lt;/li&gt;
&lt;li&gt;Enforce soft limits&lt;/li&gt;
&lt;li&gt;Fail-fast on parse&lt;/li&gt;
&lt;li&gt;Monitor config diffs&lt;/li&gt;
&lt;li&gt;Version config safely&lt;/li&gt;
&lt;li&gt;Use backpressure mechanisms&lt;/li&gt;
&lt;li&gt;Degrade functionality gracefully&lt;/li&gt;
&lt;li&gt;Log and continue&lt;/li&gt;
&lt;li&gt;Improve degradation metrics&lt;/li&gt;
&lt;li&gt;Implement proper Result/Option handling with fallbacks&lt;/li&gt;
&lt;li&gt;Treat all configuration as untrusted input&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactorings--16&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-004-remove-unhandled-exceptions&quot;&gt;https://maximilianocontieri.com/refactoring-004-remove-unhandled-exceptions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&quot;&gt;https://maximilianocontieri.com/refactoring-024-replace-global-variables-with-dependency-injection&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-035-separate-exception-types&quot;&gt;https://maximilianocontieri.com/refactoring-035-separate-exception-types&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;context-13&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;In the early hours of November 18, 2025, Cloudflare’s global network began failing to deliver core HTTP traffic, generating a &lt;a rel=&quot;nofollow&quot; href=&quot;https://mgx.dev/blog/cloudflare1119&quot;&gt;flood of 5xx errors&lt;/a&gt; to end users.&lt;/p&gt;
&lt;p&gt;This was not caused by an external attack or security problem.&lt;/p&gt;
&lt;p&gt;The outage stemmed from an internal &quot;latent defect&quot; triggered by a &lt;a rel=&quot;nofollow&quot; href=&quot;https://techcrunch.com/2025/11/18/cloudflare-blames-massive-internet-outage-on-latent-bug/&quot;&gt;routine configuration change&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The failure fluctuated over time, until a fix was fully deployed.&lt;/p&gt;
&lt;p&gt;The root cause lay in a software bug in Cloudflare’s Bot Management module and its downstream proxy logic.&lt;/p&gt;
&lt;p&gt;The Technical Chain of Events&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database Change (11:05 UTC)&lt;/strong&gt;: A ClickHouse permissions update made previously implicit table access explicit, allowing users to see metadata from both the &lt;code&gt;default&lt;/code&gt; and &lt;code&gt;r0&lt;/code&gt; databases.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SQL Query Assumption&lt;/strong&gt;: A Bot Management query lacked a database name filter:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT name, type FROM system.columns
WHERE table = 'http_requests_features'
ORDER BY name;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This query began returning duplicate rows—once for &lt;code&gt;default&lt;/code&gt; database, once for &lt;code&gt;r0&lt;/code&gt; database.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feature File Explosion&lt;/strong&gt;: The machine learning feature file doubled from ~60 features to over 200 features with duplicate entries.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hard Limit Exceeded&lt;/strong&gt;: The Bot Management module had a hard-coded limit of 200 features (for memory pre-allocation), which was now exceeded.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Fatal &lt;a rel=&quot;nofollow&quot; href=&quot;https://doc.rust-lang.org/std/?search=unwrap&quot;&gt;.unwrap()&lt;/a&gt;&lt;/strong&gt;: The Rust code called &lt;code&gt;.unwrap()&lt;/code&gt; on a Result that was now returning an error, causing the thread to panic with &quot;called Result::unwrap() on an Err value&quot;. &lt;em&gt;see code below&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global Cascade&lt;/strong&gt;: This panic propagated across all 330+ data centers globally, bringing down core CDN services, Workers KV, Cloudflare Access, Turnstile, and the dashboard.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The estimated financial impact across affected businesses ranges from $180-360 million.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-14&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong--7&quot;&gt;Wrong ❌&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;let features: Vec&amp;lt;Feature&amp;gt; = load_features_from_db();
let max = 200;
assert!(features.len() &amp;lt;= max);
# This magic number assumption 
# is actually wrong                              
                              
for f in features {
    proxy.add_bot_feature(f.unwrap());
    # You also call unwrap() on every feature. 
    # If the database returns an invalid entry 
    # or a parsing error,
    # you trigger another panic. 
    # You give your runtime no chance to recover. 
    # You force a crash on a single bad element.
}
                              
# A quiet config expansion turns into
# a full service outage 
# because you trust input that you should validate 
# and you use failure primitives (assert!, unwrap()) 
# that kills your program 
# instead of guiding it to safety
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-14&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-rust&quot;&gt;fn load_and_validate(max: usize) -&amp;gt; Result&amp;lt;Vec&amp;lt;Feature&amp;gt;, String&amp;gt; {
    let raw: Vec&amp;lt;Result&amp;lt;Feature, Error&amp;gt;&amp;gt; = load_features_from_db();
    
    if raw.len() &amp;gt; max {
        return Err(format!(
            &quot;too many features: {} &amp;gt; {}&quot;, 
            raw.len(), max
        ));
    }
    
    Ok(raw.into_iter()
        .filter_map(|r| r.ok())
        .collect())
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-14&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;You can detect this code smell by searching your codebase for specific keywords:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.unwrap()&lt;/code&gt; - Any direct call to this method&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.expect()&lt;/code&gt; - Similarly dangerous&lt;/li&gt;
&lt;li&gt;&lt;code&gt;panic!()&lt;/code&gt; - Explicit panics in non-test code&lt;/li&gt;
&lt;li&gt;&lt;code&gt;thread::panic_any()&lt;/code&gt; - Panic without context&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you find these patterns, ask yourself: &quot;What happens to my system when this Result contains an Err?&quot; If your honest answer is &quot;the thread crashes and the request fails,&quot; then you've found the smell.&lt;/p&gt;
&lt;p&gt;You can also use automated linters. Most Rust style guides recommend tools like &lt;code&gt;clippy&lt;/code&gt;, which flags &lt;code&gt;unwrap()&lt;/code&gt; usage in production code paths. &lt;/p&gt;
&lt;p&gt;When you configure &lt;code&gt;clippy&lt;/code&gt; with the &lt;code&gt;#![deny(unwrap_in_result)]&lt;/code&gt; attribute, you prevent new &lt;code&gt;unwrap()&lt;/code&gt; calls from entering your codebase.&lt;/p&gt;
&lt;h2 id=&quot;tags--19&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Fail-Fast&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-14&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[x] Advanced&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--18&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;Your internal config generator must map exactly what your code expects. &lt;/p&gt;
&lt;p&gt;A mismatched config (e.g., duplicated metadata) breaks the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; between what your config represents and what your proxy code handles. &lt;/p&gt;
&lt;p&gt;When you assume &quot;this file will always have ≤200 entries&quot;, you break that &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;mapping&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Reality sends 400 entries → your model explodes → the real world wins, your service loses.&lt;/p&gt;
&lt;p&gt;That mismatch causes subtle failures that cascade, especially when you ignore validation or size constraints.&lt;/p&gt;
&lt;p&gt;Ensuring a clean &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6102/current-software-design-problems-addressed-in-a-minimalist-way&quot;&gt;mapping&lt;/a&gt; between the config source and code input helps prevent crashes and unpredictable behavior.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-14&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI generators often prioritize &lt;strong&gt;correct&lt;/strong&gt; logic over &lt;strong&gt;resilient&lt;/strong&gt; logic. &lt;/p&gt;
&lt;p&gt;If you ask an AI to &quot;ensure the list is never larger than 200 items,&quot; it might generate an assertion or a panic because that is the most direct way to satisfy the requirement, introducing this smell.&lt;/p&gt;
&lt;p&gt;The irony: Memory-safe languages like Rust prevent undefined behavior and memory corruption, but they can't prevent logic errors, poor error handling, or architectural assumptions. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Memory safety ≠ System safety.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-14&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI can easily detect this if you instruct it to look for availability risks. &lt;/p&gt;
&lt;p&gt;You can use linters combined with AI to flag panic calls in production code.&lt;/p&gt;
&lt;p&gt;Human review on critical functions is more important than ever.&lt;/p&gt;
&lt;h3 id=&quot;try-them--19&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: remove all .unwrap() and .expect() calls. Return Result instead and validate the vector bounds explicitly&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;conclusion-14&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Auto-generated config can hide duplication or grow unexpectedly.&lt;/p&gt;
&lt;p&gt;If your code assumes size limits or blindly trusts its input, you risk a catastrophic crash.&lt;/p&gt;
&lt;p&gt;Validating inputs is good; crashing because an input is slightly off is a disproportionate response that turns a minor defect into a global outage.&lt;/p&gt;
&lt;p&gt;Validate config, enforce limits, handle failures, and avoid assumptions.&lt;/p&gt;
&lt;p&gt;That’s how you keep your system stable and fault-tolerant.&lt;/p&gt;
&lt;h2 id=&quot;relations--19&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-122-primitive-obsession&quot;&gt;https://maximilianocontieri.com/code-smell-122-primitive-obsession&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7475/code-smell-02-constants-and-magic-numbers&quot;&gt;https://coderlegion.com/7475/code-smell-02-constants-and-magic-numbers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-198-hidden-assumptions&quot;&gt;https://maximilianocontieri.com/code-smell-198-hidden-assumptions&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-12&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://techcrunch.com/2025/11/18/cloudflare-blames-massive-internet-outage-on-latent-bug/&quot;&gt;https://techcrunch.com/2025/11/18/cloudflare-blames-massive-internet-outage-on-latent-bug/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.cloudflarestatus.com/incidents/8gmgl950y3h&quot;&gt;https://www.cloudflarestatus.com/incidents/8gmgl950y3h&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://techcrunch.com/2025/11/18/cloudflare-blames-massive-internet-outage-on-latent-bug/&quot;&gt;https://techcrunch.com/2025/11/18/cloudflare-blames-massive-internet-outage-on-latent-bug/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://mgx.dev/blog/cloudflare1119&quot;&gt;https://mgx.dev/blog/cloudflare1119&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://hackaday.com/2025/11/20/how-one-uncaught-rust-exception-took-out-cloudflare/&quot;&gt;https://hackaday.com/2025/11/20/how-one-uncaught-rust-exception-took-out-cloudflare/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.cnbc.com/2025/11/18/cloudflare-outage-briefly-takes-chatgpt-claude-services-offline.html&quot;&gt;https://www.cnbc.com/2025/11/18/cloudflare-outage-briefly-takes-chatgpt-claude-services-offline.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;disclaimer-3&quot;&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;A good programmer is someone who always looks both ways before crossing a one-way street&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Douglas Crockford&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/7979/code-smell-315-cloudflare-feature-explosion</guid>
<pubDate>Sat, 29 Nov 2025 22:18:03 +0000</pubDate>
</item>
<item>
<title>Code Smell 04 - String Abusers</title>
<link>https://coderlegion.com/7929/code-smell-04-string-abusers</link>
<description>&lt;p&gt;&lt;em&gt;Too much parsing, exploding, regex, strcmp, strpos and string manipulation functions.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Use real abstractions and real objects instead of accidental string manipulation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-15&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Complexity&lt;/li&gt;
&lt;li&gt;Readability&lt;/li&gt;
&lt;li&gt;Maintainability&lt;/li&gt;
&lt;li&gt;Lack of abstractions&lt;/li&gt;
&lt;li&gt;Fragile logic&lt;/li&gt;
&lt;li&gt;Hidden intent&lt;/li&gt;
&lt;li&gt;Hard debugging&lt;/li&gt;
&lt;li&gt;Poor modeling &lt;/li&gt;
&lt;li&gt;Regex mess&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-15&quot;&gt;Solutions&lt;/h2&gt;
&lt;p&gt;1) Work with objects instead.&lt;/p&gt;
&lt;p&gt;2) Replace strings with data structures dealing with object relations.&lt;/p&gt;
&lt;p&gt;3) Go back to Perl :) &lt;/p&gt;
&lt;p&gt;4) identify &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; problems between real objects and the strings.&lt;/p&gt;
&lt;h2 id=&quot;examples-9&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Serializers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Parsers&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-14&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;When you abuse strings, you try to represent structured concepts with plain text.&lt;/p&gt;
&lt;p&gt;You parse, explode, and regex your way around instead of modeling the domain.&lt;/p&gt;
&lt;p&gt;This creates fragile code that breaks with small input changes.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-15&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-12&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php

$schoolDescription = 'College of Springfield';

preg_match('/[^ ]*$/', $schoolDescription, $results);
$location = $results[0]; // $location = 'Springfield'.

$school = preg_split('/[\s,]+/', $schoolDescription, 3)[0]; 
//'College'
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-15&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

class School {
    private $name;
    private $location;

    function description() {
        return $this-&amp;gt;name . ' of ' . $this-&amp;gt;location-&amp;gt;name;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-15&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;[X] Semi-Automatic&lt;/p&gt;
&lt;p&gt;Automated detection is not easy. &lt;/p&gt;
&lt;p&gt;If your code uses too many string functions, linters can trigger a warning.&lt;/p&gt;
&lt;h2 id=&quot;tags--20&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Primitive Obsession&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-15&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--19&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;You must mirror the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;real-world&lt;/a&gt; domain in your code.&lt;/p&gt;
&lt;p&gt;When you flatten roles, addresses, or money into raw strings, you lose control. &lt;/p&gt;
&lt;p&gt;This mismatch leads to errors, duplication, and weak models. &lt;/p&gt;
&lt;p&gt;One-to-one mapping between domain and code gives you clarity and robustness.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-15&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI generators often produce string-abusing code because it looks shorter and easier. &lt;/p&gt;
&lt;p&gt;The generated solution can be correct for toy cases but fragile in real systems.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-15&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;You can instruct AI tools to replace string checks with domain objects.&lt;/p&gt;
&lt;p&gt;With clear prompts, AI can spot and fix string abuse effectively. &lt;/p&gt;
&lt;h3 id=&quot;try-them--20&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Reify Strings to objects&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Reify+Strings+to+objects%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Reify+Strings+to+objects%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Reify+Strings+to+objects%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Reify+Strings+to+objects%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Reify+Strings+to+objects%3A+%60%60%60php%0D%0A%3C%3Fphp%0D%0A%0D%0A%24schoolDescription+%3D+%27College+of+Springfield%27%3B%0D%0A%0D%0Apreg_match%28%27%2F%5B%5E+%5D%2A%24%2F%27%2C+%24schoolDescription%2C+%24results%29%3B%0D%0A%24location+%3D+%24results%5B0%5D%3B+%2F%2F+%24location+%3D+%27Springfield%27.%0D%0A%0D%0A%24school+%3D+preg_split%28%27%2F%5B%5Cs%2C%5D%2B%2F%27%2C+%24schoolDescription%2C+3%29%5B0%5D%3B+%0D%0A%2F%2F%27College%27%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-15&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Don't abuse strings. &lt;/p&gt;
&lt;p&gt;Favor real objects. &lt;/p&gt;
&lt;p&gt;Add missing protocol to distinguish them from raw strings.&lt;/p&gt;
&lt;h2 id=&quot;relations--20&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-122-primitive-obsession&quot;&gt;https://maximilianocontieri.com/code-smell-122-primitive-obsession&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-121-string-validations&quot;&gt;https://maximilianocontieri.com/code-smell-121-string-validations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-295-string-concatenation&quot;&gt;https://maximilianocontieri.com/code-smell-295-string-concatenation&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-13&quot;&gt;More Information&lt;/h2&gt;
&lt;h2 id=&quot;credits-14&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@nshuman1291&quot;&gt;Nathaniel Shuman&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/7929/code-smell-04-string-abusers</guid>
<pubDate>Fri, 28 Nov 2025 23:13:52 +0000</pubDate>
</item>
<item>
<title>Code Smell 03 - Functions Are Too Long</title>
<link>https://coderlegion.com/7617/code-smell-03-functions-are-too-long</link>
<description>&lt;p&gt;&lt;em&gt;Humans get bored after line five.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Refactor and extract functions longer than five lines.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-16&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Low cohesion&lt;/li&gt;
&lt;li&gt;High coupling&lt;/li&gt;
&lt;li&gt;Hard to read&lt;/li&gt;
&lt;li&gt;Low reusability&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-16&quot;&gt;Solutions&lt;/h2&gt;
&lt;p&gt;1) &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-010-extract-method-object&quot;&gt;Refactor&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2) Create small objects to handle specific tasks. Unit-test them.&lt;/p&gt;
&lt;p&gt;3) Compose methods &lt;/p&gt;
&lt;p&gt;4) &lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Divide-and-conquer_algorithm&quot;&gt;Divide and conquer&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;refactorings--17&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-010-extract-method-object&quot;&gt;https://maximilianocontieri.com/refactoring-010-extract-method-object&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-025-decompose-regular-expressions&quot;&gt;https://maximilianocontieri.com/refactoring-025-decompose-regular-expressions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-002-extract-method&quot;&gt;https://maximilianocontieri.com/refactoring-002-extract-method&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-10&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Libraries&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-15&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;When you write a long function, you hide too many details in one place.&lt;/p&gt;
&lt;p&gt;You force the reader to hold multiple concepts in mind.&lt;/p&gt;
&lt;p&gt;You mix unrelated responsibilities and make the code hard to test.&lt;/p&gt;
&lt;p&gt;You create a rigid block that breaks easily when you change it.&lt;/p&gt;
&lt;p&gt;Short, focused functions let you read, test, and modify code faster.      &lt;/p&gt;
&lt;h2 id=&quot;sample-code-16&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-13&quot;&gt;Wrong&lt;/h3&gt;
&lt;p&gt;[Gist Url]: # (&lt;a rel=&quot;nofollow&quot; href=&quot;https://gist.github.com/mcsee/1f12fb2d0cb9f8eea202526597cf4b83&quot;&gt;https://gist.github.com/mcsee/1f12fb2d0cb9f8eea202526597cf4b83&lt;/a&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

function setUpChessBoard() {
    $this-&amp;gt;placeOnBoard($this-&amp;gt;whiteTower);
    $this-&amp;gt;placeOnBoard($this-&amp;gt;whiteKnight);
    // A lot more lines
    
    // Empty space to pause definition
    $this-&amp;gt;placeOnBoard($this-&amp;gt;blackTower);
    $this-&amp;gt;placeOnBoard($this-&amp;gt;blackKnight);
    // A lot more lines
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-16&quot;&gt;Right&lt;/h3&gt;
&lt;p&gt;[Gist Url]: # (&lt;a rel=&quot;nofollow&quot; href=&quot;https://gist.github.com/mcsee/0f66ce8c2bba8990e44a36495fa4c3e1&quot;&gt;https://gist.github.com/mcsee/0f66ce8c2bba8990e44a36495fa4c3e1&lt;/a&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

function setUpChessBoard() {
    $this-&amp;gt;placeWhitePieces();
    $this-&amp;gt;placeBlackPieces();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-16&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;[X] Automatic&lt;/p&gt;
&lt;p&gt;All linters can measure and warn when methods exceed a predefined threshold.&lt;/p&gt;
&lt;h2 id=&quot;tags--21&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Bloaters&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-16&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--20&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;A &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;real-world&lt;/a&gt; action should map to a clear, concise function.&lt;/p&gt;
&lt;p&gt;When you pack many actions into one function, you lose that mapping.&lt;/p&gt;
&lt;p&gt;Developers must mentally reconstruct the steps, which slows comprehension and increases errors.     &lt;/p&gt;
&lt;h2 id=&quot;ai-generation-16&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI generators often create long functions if you give them vague prompts.&lt;/p&gt;
&lt;p&gt;They tend to cram all logic into one place unless you explicitly request modular code.  &lt;/p&gt;
&lt;h2 id=&quot;ai-detection-16&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI tools can fix this smell with the right instructions to split code into small, focused functions. &lt;/p&gt;
&lt;h3 id=&quot;try-them--21&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Break long functions using extract method refactoring&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Break+long+functions+using+extract+method+refactoring%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Break+long+functions+using+extract+method+refactoring%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Break+long+functions+using+extract+method+refactoring%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Break+long+functions+using+extract+method+refactoring%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Break+long+functions+using+extract+method+refactoring%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+setUpChessBoard%28%29+%7B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EwhiteKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A++++%0D%0A++++%2F%2F+Empty+space+to+pause+definition%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackTower%29%3B%0D%0A++++%24this-%3EplaceOnBoard%28%24this-%3EblackKnight%29%3B%0D%0A++++%2F%2F+A+lot+more+lines%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-16&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Extract long methods into smaller pieces. &lt;/p&gt;
&lt;p&gt;Break complex algorithms into parts. &lt;/p&gt;
&lt;p&gt;You can also unit test these parts.&lt;/p&gt;
&lt;h2 id=&quot;relations--21&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-75-comments-inside-a-method&quot;&gt;https://maximilianocontieri.com/code-smell-75-comments-inside-a-method&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-102-arrow-code&quot;&gt;https://maximilianocontieri.com/code-smell-102-arrow-code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-206-long-ternaries&quot;&gt;https://maximilianocontieri.com/code-smell-206-long-ternaries&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-107-variables-reuse&quot;&gt;https://maximilianocontieri.com/code-smell-107-variables-reuse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-74-empty-lines&quot;&gt;https://maximilianocontieri.com/code-smell-74-empty-lines&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-154-too-many-variables&quot;&gt;https://maximilianocontieri.com/code-smell-154-too-many-variables&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-83-variables-reassignment&quot;&gt;https://maximilianocontieri.com/code-smell-83-variables-reassignment&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-14&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://refactoring.guru/es/smells/long-method&quot;&gt;https://refactoring.guru/es/smells/long-method&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;also-known-as-3&quot;&gt;Also Known as&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Long Method&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;credits-15&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@invisibleecho&quot;&gt;Hari Panicker&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/long-road&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Programs are meant to be read by humans and only incidentally for computers to execute.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Donald Knuth&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/7617/code-smell-03-functions-are-too-long</guid>
<pubDate>Sat, 22 Nov 2025 14:35:23 +0000</pubDate>
</item>
<item>
<title>Code Smell 02 - Constants and Magic Numbers</title>
<link>https://coderlegion.com/7475/code-smell-02-constants-and-magic-numbers</link>
<description>&lt;p&gt;&lt;em&gt;A method makes calculations with lots of numbers without describing their semantics&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Avoid Magic numbers without explanation. You don't know their source and are very afraid of changing them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-17&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;Coupling&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Low testability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Low readability&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-17&quot;&gt;Solutions&lt;/h2&gt;
&lt;p&gt;1) Rename the constant to a meaningful, intention-revealing name.&lt;/p&gt;
&lt;p&gt;2) &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-003-extract-constant&quot;&gt;Replace constants with parameters&lt;/a&gt;, so you can mock them from the outside.&lt;/p&gt;
&lt;p&gt;3) The constant definition is often a different object than the constant (ab)user.&lt;/p&gt;
&lt;h2 id=&quot;refactorings--18&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-003-extract-constant&quot;&gt;https://maximilianocontieri.com/refactoring-003-extract-constant&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-025-decompose-regular-expressions&quot;&gt;https://maximilianocontieri.com/refactoring-025-decompose-regular-expressions&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-11&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Algorithms Hyper Parameters&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-16&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;Magic numbers are literal values embedded directly into your code without explanation. &lt;/p&gt;
&lt;p&gt;They often appear in algorithms, configuration rules, or business logic as unexplained numeric values. &lt;/p&gt;
&lt;p&gt;At first, they might feel faster to write, but over time they turn into hidden assumptions that no one remembers. &lt;/p&gt;
&lt;p&gt;Future maintainers must guess their meaning, increasing the risk of errors when the values need to change. &lt;/p&gt;
&lt;p&gt;Constants help, but naming them meaningfully and placing them in the right context is what turns a magic number into a reliable, self-explanatory part of your code.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-17&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong-14&quot;&gt;Wrong&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?

function energy($mass) {
    return $mass * (299792 ** 2)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-17&quot;&gt;Right&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;# Storing magnitudes without units is another smell
class PhysicsConstants
   LIGHT_SPEED = 299792458.freeze
end

def energy(mass)
    mass * PhysicsConstants::LIGHT_SPEED ** 2
end
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-17&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;[X] Semi-Automatic&lt;/p&gt;
&lt;p&gt;Many linters can detect number literals in attributes and methods.&lt;/p&gt;
&lt;h2 id=&quot;tags--22&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Declarative Code&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-17&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--21&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;When you replace a magic number with a named constant, you create a &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; between the value and its meaning. &lt;/p&gt;
&lt;p&gt;This one-to-one relationship ensures every numeric value has a clear, unambiguous purpose in your system. &lt;/p&gt;
&lt;p&gt;Without it, the same number could be reused for different reasons, leading to confusion and accidental coupling. &lt;/p&gt;
&lt;p&gt;A bijection between meaning and value makes the code easier to navigate, test, and evolve without fear of breaking unrelated parts.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-17&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;Large Language Models can introduce magic numbers when generating code, especially in examples or algorithm implementations. &lt;/p&gt;
&lt;p&gt;Treat AI-generated values with the same suspicion you would any human-written literal. &lt;/p&gt;
&lt;p&gt;Always check if the number is a placeholder, a real-world constant, or an algorithmic parameter, and replace it with a meaningful name before merging it into production code.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-17&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;Code reviewers should stay alert to magic numbers introduced by AI tools, which often lack context or semantic naming. &lt;/p&gt;
&lt;p&gt;Automated linters can flag number literals, but human insight is critical to understand if a value requires refactoring into a named constant. &lt;/p&gt;
&lt;p&gt;Keep your eyes open for AI-generated black box numbers that might slip past initial checks but can cause maintenance headaches later.&lt;/p&gt;
&lt;h3 id=&quot;try-them--22&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Replace Magic numbers with constants&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Without Proper Instructions    &lt;/th&gt;&lt;th&gt;With Specific Instructions&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.openai.com/?q=Replace+Magic+numbers+with+constants%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;ChatGPT&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://claude.ai/new?q=Replace+Magic+numbers+with+constants%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Claude&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.perplexity.ai/?q=Replace+Magic+numbers+with+constants%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Perplexity&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.bing.com/chat?showconv=1&amp;amp;sendquery=1&amp;amp;q=Replace+Magic+numbers+with+constants%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;Copilot&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Correct+and+explain+this+code%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://you.com/search?q=Replace+Magic+numbers+with+constants%3A+%60%60%60php%0D%0A%3C%3F%0D%0A%0D%0Afunction+energy%28%24mass%29+%7B%0D%0A++++return+%24mass+%2A+%28299792+%2A%2A+2%29%0D%0A%7D%0D%0A%60%60%60&quot;&gt;You&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.deepseek.com/&quot;&gt;DeepSeek&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/chat&quot;&gt;Meta AI&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.meta.ai/&quot;&gt;Meta AI&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://grok.com/&quot;&gt;Grok&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt; &lt;/td&gt;&lt;td&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://chat.qwen.ai/&quot;&gt;Qwen&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;conclusion-17&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You should address and remove your magic numbers to safeguard your code's readability, maintainability, and testability. &lt;/p&gt;
&lt;p&gt;Clear, semantic naming and decoupling constants from their consumers are essential steps toward crafting cleaner, more resilient software. &lt;/p&gt;
&lt;p&gt;Every magic number you replace with intention-revealing logic is a step away from brittle code and closer to robust, professional craftsmanship. &lt;/p&gt;
&lt;p&gt;Don't let numbers dictate your code; define their purpose and context instead.&lt;/p&gt;
&lt;h2 id=&quot;relations--22&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-158-variables-not-variable&quot;&gt;https://maximilianocontieri.com/code-smell-158-variables-not-variable&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-127-mutable-constants&quot;&gt;https://maximilianocontieri.com/code-smell-127-mutable-constants&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-06-too-clever-programmer&quot;&gt;https://maximilianocontieri.com/code-smell-06-too-clever-programmer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-162-too-many-parentheses&quot;&gt;https://maximilianocontieri.com/code-smell-162-too-many-parentheses&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-198-hidden-assumptions&quot;&gt;https://maximilianocontieri.com/code-smell-198-hidden-assumptions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-202-god-constant-class&quot;&gt;https://maximilianocontieri.com/code-smell-202-god-constant-class&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-15&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://refactoring.guru/es/replace-magic-number-with-symbolic-constant&quot;&gt;https://refactoring.guru/es/replace-magic-number-with-symbolic-constant&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-decouple-a-legacy-system&quot;&gt;https://maximilianocontieri.com/how-to-decouple-a-legacy-system&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;credits-16&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/@krisroller&quot;&gt;Kristopher Roller&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://unsplash.com/s/photos/magic&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;In a purely functional program, the value of a [constant] never changes, and yet, it changes all the time! A paradox!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Joel Spolsky&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Other</category>
<guid isPermaLink="true">https://coderlegion.com/7475/code-smell-02-constants-and-magic-numbers</guid>
<pubDate>Tue, 18 Nov 2025 14:43:55 +0000</pubDate>
</item>
<item>
<title>Code Smell 01 - Anemic Models</title>
<link>https://coderlegion.com/7246/code-smell-01-anemic-models</link>
<description>&lt;p&gt;&lt;em&gt;Your objects have no behavior.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;TL;DR: Don't use objects as data structures&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;problems-18&quot;&gt;Problems&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Lack of encapsulation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;mapping&lt;/a&gt; to real-world entities&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Duplicated Code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6634/coupling-the-one-and-only-software-design-problem&quot;&gt;Coupling&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Writer / Reader mismatch&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Missing behavior&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;solutions-18&quot;&gt;Solutions&lt;/h2&gt;
&lt;p&gt;1) Find Responsibilities.&lt;/p&gt;
&lt;p&gt;2) Protect your attributes.&lt;/p&gt;
&lt;p&gt;3) Hide implementations. &lt;/p&gt;
&lt;p&gt;4) Follow Tell-Don't-Ask principle&lt;/p&gt;
&lt;h2 id=&quot;refactorings--19&quot;&gt;Refactorings ⚙️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-016-build-with-the-essence&quot;&gt;https://maximilianocontieri.com/refactoring-016-build-with-the-essence&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-009-protect-public-attributes&quot;&gt;https://maximilianocontieri.com/refactoring-009-protect-public-attributes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/refactoring-001-remove-setters&quot;&gt;https://maximilianocontieri.com/refactoring-001-remove-setters&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;examples-12&quot;&gt;Examples&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;DTOs&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;context-17&quot;&gt;Context&lt;/h2&gt;
&lt;p&gt;If you let your objects become data buckets, you kill the connection between your logic and your language.  &lt;/p&gt;
&lt;p&gt;Anemic models are classes that contain only data (properties) with little or no behavior. &lt;/p&gt;
&lt;p&gt;They're essentially glorified data structures with getters and setters.&lt;/p&gt;
&lt;p&gt;When you create anemic models, you end up putting all the logic that should live in these objects into service classes instead duplicated the logic across multiple services.&lt;/p&gt;
&lt;p&gt;This approach breaks object-oriented principles by separating data from the behavior that manipulates it. &lt;/p&gt;
&lt;p&gt;You'll find yourself writing procedural code that pulls data out of objects, performs operations on it, and then pushes the results back in. &lt;/p&gt;
&lt;p&gt;This creates tight coupling between your services and objects, making your codebase harder to maintain and evolve.&lt;/p&gt;
&lt;p&gt;When you identify an anemic model in your code, it's a sign that you're missing opportunities for better encapsulation and more intuitive object design. &lt;/p&gt;
&lt;p&gt;Rich domain models lead to code that's more maintainable, testable, and closer to how you think about the problem domain.&lt;/p&gt;
&lt;h2 id=&quot;sample-code-18&quot;&gt;Sample Code&lt;/h2&gt;
&lt;h3 id=&quot;wrong--8&quot;&gt;Wrong ❌&lt;/h3&gt;
&lt;p&gt;[Gist Url]: # (&lt;a rel=&quot;nofollow&quot; href=&quot;https://gist.github.com/mcsee/73f84d80f7c3e89a216dd9e40ab71bcc&quot;&gt;https://gist.github.com/mcsee/73f84d80f7c3e89a216dd9e40ab71bcc&lt;/a&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class Song {
   String name;
   String authorName;
   String albumName;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;right-18&quot;&gt;Right&lt;/h3&gt;
&lt;p&gt;[Gist Url]: # (&lt;a rel=&quot;nofollow&quot; href=&quot;https://gist.github.com/mcsee/78f2dd78120db843c960ed41839f29cb&quot;&gt;https://gist.github.com/mcsee/78f2dd78120db843c960ed41839f29cb&lt;/a&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class Song {
   private String name;
   private Artist author; // Will reference rich objects
   private Album album; // instead of primitive data types

   public String albumName() {
     return album.name() ;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;detection-18&quot;&gt;Detection&lt;/h2&gt;
&lt;p&gt;[X] Semi-Automatic&lt;/p&gt;
&lt;p&gt;Sophisticated linters can automate detection.&lt;/p&gt;
&lt;p&gt;They should ignore &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/nude-models-part-i-setters&quot;&gt;setters&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/nude-models-part-ii-getters&quot;&gt;getters&lt;/a&gt; and count real behavior methods.&lt;/p&gt;
&lt;h2 id=&quot;tags--23&quot;&gt;Tags ️&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Anemic Models&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;level-18&quot;&gt;Level&lt;/h2&gt;
&lt;p&gt;[X] Beginner&lt;/p&gt;
&lt;h2 id=&quot;why-the-bijection-is-important--22&quot;&gt;Why the Bijection Is Important ️&lt;/h2&gt;
&lt;p&gt;If we ask a domain expert to describe an entity he/she would hardly tell it is &lt;em&gt;'a bunch of attributes'&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The power of object-oriented programming comes from modeling real-world concepts directly in code. &lt;/p&gt;
&lt;p&gt;When you create anemic models, you break the &lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/6313/just-follow-this-design-principle&quot;&gt;bijection&lt;/a&gt; between the domain and your code.&lt;/p&gt;
&lt;h2 id=&quot;ai-generation-18&quot;&gt;AI Generation&lt;/h2&gt;
&lt;p&gt;AI code generators often produce anemic models because they follow common but flawed patterns found in many codebases. &lt;/p&gt;
&lt;p&gt;When you ask an AI to generate a basic model class, it will typically create a class with properties and getters/setters but no behavior. &lt;/p&gt;
&lt;p&gt;This perpetuates the anemic model anti-pattern.&lt;/p&gt;
&lt;p&gt;You need to specifically instruct AI tools to generate rich domain models with behavior, not just data holders. &lt;/p&gt;
&lt;p&gt;Be explicit in your prompts about including relevant methods that encapsulate business logic within the model.&lt;/p&gt;
&lt;h2 id=&quot;ai-detection-18&quot;&gt;AI Detection&lt;/h2&gt;
&lt;p&gt;AI tools can help identify anemic models with simple instructions like &quot;find classes with many getters/setters but few business methods&quot; or &quot;identify service classes that should be refactored into domain models.&quot;&lt;/p&gt;
&lt;p&gt;Determining which behavior truly belongs in a model requires domain knowledge and design judgment that current AI tools lack. &lt;/p&gt;
&lt;p&gt;AI can flag potential issues, but you still need to make the final decision about where behavior belongs.&lt;/p&gt;
&lt;h3 id=&quot;try-them--23&quot;&gt;Try Them!&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Remember: AI Assistants make lots of mistakes&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Suggested Prompt: Convert the anemic object into a rich one focusing on behavior instead of structure&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;conclusion-18&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Anemic models might seem convenient at first, but they lead to scattered logic, poor encapsulation, and maintenance headaches. &lt;/p&gt;
&lt;p&gt;Senior developers create rich domain models focusing on their behavior.&lt;/p&gt;
&lt;p&gt;By moving logic from services into models, you create code that's more intuitive, maintainable, and aligned with object-oriented principles. &lt;/p&gt;
&lt;p&gt;Your objects should do things, not just store data. &lt;/p&gt;
&lt;p&gt;Avoid anemic models. Focus always on protocol instead of data.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/no-silver-bullet&quot;&gt;behavior&lt;/a&gt; is essential, data is accidental.&lt;/p&gt;
&lt;h2 id=&quot;relations--23&quot;&gt;Relations ❤️&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-28-setters&quot;&gt;https://maximilianocontieri.com/code-smell-28-setters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-15-missed-preconditions-1&quot;&gt;https://maximilianocontieri.com/code-smell-15-missed-preconditions-1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/code-smell-210-dynamic-properties&quot;&gt;https://maximilianocontieri.com/code-smell-210-dynamic-properties&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;more-information-16&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://en.wikipedia.org/wiki/Anemic_domain_model&quot;&gt;https://en.wikipedia.org/wiki/Anemic_domain_model&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://refactoring.guru/es/smells/data-class&quot;&gt;https://refactoring.guru/es/smells/data-class&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/nude-models-part-i-setters&quot;&gt;https://maximilianocontieri.com/nude-models-part-i-setters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/nude-models-part-ii-getters&quot;&gt;https://maximilianocontieri.com/nude-models-part-ii-getters&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-decouple-a-legacy-system&quot;&gt;https://maximilianocontieri.com/how-to-decouple-a-legacy-system&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;also-known-as-4&quot;&gt;Also Known as&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Data Class&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;disclaimer-4&quot;&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;Code Smells are my &lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/i-wrote-more-than-90-articles-on-2021-here-is-what-i-learned&quot;&gt;opinion&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;credits-17&quot;&gt;Credits&lt;/h2&gt;
&lt;p&gt;Photo by Stacey Vandergriff on Unsplash&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Object-oriented programming increases the value of these metrics by managing this complexity. The most effective tool available for dealing with complexity is abstraction. Many types of abstraction can be used, but encapsulation is the main form of abstraction by which complexity is managed in object-oriented programming.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Rebecca Wirfs-Brock&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/software-engineering-great-quotes&quot;&gt;https://maximilianocontieri.com/software-engineering-great-quotes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This article is part of the CodeSmell Series.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&quot;&gt;https://maximilianocontieri.com/how-to-find-the-stinky-parts-of-your-code&lt;/a&gt;&lt;/p&gt;
</description>
<category>Other</category>
<guid isPermaLink="true">https://coderlegion.com/7246/code-smell-01-anemic-models</guid>
<pubDate>Wed, 12 Nov 2025 12:41:16 +0000</pubDate>
</item>
</channel>
</rss>