[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"global":3,"blogpost-5-signs-of-bad-code":26},{"title":4,"description":5,"home_welcome_badge":6,"home_feature_cards":7,"home_newsletter":20},"Result Crafter Blog","In the era of AI, anyone can generate code overnight. But code that lasts years — you can debug, extend, and maintain — still requires discipline and care.","Welcome to the craft",[8,12,16],{"icon":9,"title":10,"description":11},"code","AI Tools & Workflows","Navigating the new landscape of AI assistance without losing your engineering fundamentals.",{"icon":13,"title":14,"description":15},"bug","Code Smells","Identifying subtle anti-patterns before they become untamable technical debt in your codebase.",{"icon":17,"title":18,"description":19},"cpu","Software Craftsmanship","Techniques for writing clean, testable, and maintainable systems that outlast the current hype cycle.",[21],{"headline":22,"description":23,"placeholder":24,"buttonLabel":25},"Don't miss an essay","Get occasional thoughts on software design, code quality, and building resilient systems delivered straight to your inbox. No spam, ever.","hello@example.com","Subscribe",{"post":27,"directusUrl":240},{"id":28,"title":29,"slug":30,"excerpt":31,"date_created":32,"category":14,"featured_image":33,"content":33,"blocks":34},"79124845-2e96-4b06-89fa-21911ab77507","5 signs of bad code you can fix today","5-signs-of-bad-code","Five concrete code smells that signal trouble in production code, and how to fix each one.","2026-04-29T09:44:06.838Z",null,[35,43,51,57,66,72,81,86,91,97,103,109,114,119,124,129,135,140,145,153,157,160,166,173,179,183,187,191,195,199,203,207,211,216,221,226,230,235],{"id":36,"sort":37,"collection":38,"item":39},"7583ea3c-de25-4a68-aec6-0f9fc3db79fd",1,"block_prose",{"id":40,"content":41,"width":42},"2a3445a5-5c93-4f53-8d23-5cde5f2067ac","\u003Cp>After 10+ years in this industry, I've reviewed thousands of lines of code. Pull requests from juniors, seniors, leads, architects. Code written at 2 PM and code written at 2 AM. Code that made me smile and code that made me close my laptop and go for a walk.\u003C\u002Fp>\u003Cp>Here's what I've learned: \u003Cstrong>bad code doesn't look bad at first\u003C\u002Fstrong>. It creeps in. One extra parameter. One more if-statement. One \"temporary\" workaround that's still there three years later.\u003C\u002Fp>\u003Cp>But there are \u003Cem>patterns\u003C\u002Fem>. Five of them show up everywhere — in every codebase, every language, every team. And the good news? You can fix all five of them \u003Cstrong>in one day\u003C\u002Fstrong>. No rewrite. No architecture overhaul. Just targeted improvements that make your code immediately more readable.\u003C\u002Fp>","full",{"id":44,"sort":45,"collection":46,"item":47},"5e6a45e7-9120-42ac-9f7a-3984995820a0",2,"block_callout",{"id":48,"type":49,"icon":33,"content":50,"width":42},15,"info","\u003Cp>\u003Cstrong>The 80\u002F20 of clean code:\u003C\u002Fstrong> These 5 patterns account for roughly \u003Cstrong>80% of readability problems\u003C\u002Fstrong> I see in code reviews. Fix them, and your teammates will genuinely notice the difference on Monday morning.\u003C\u002Fp>",{"id":52,"sort":53,"collection":38,"item":54},"692bda79-80c3-4038-b38f-4b75751f5a31",3,{"id":55,"content":56,"width":42},"5b2b8a95-0005-4438-8358-2b6db96ef8cf","\u003Ch2>\u003Cstrong>Sign 1:\u003C\u002Fstrong> Methods longer than 20 lines\u003C\u002Fh2>\n\u003Cp>You open a file and see a method that's 150 lines long. It validates the input, applies business rules, calls the database, sends an email, logs the result, and handles three different error cases. \u003Cem>All in one method.\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp>Here's the problem: your brain can hold about 7 things in short-term memory. A 150-line method asks you to hold 30. You can't. Nobody can.\u003C\u002Fp>\n\u003Cp>The fix is deceptively simple: \u003Cstrong>one method, one task\u003C\u002Fstrong>.\u003C\u002Fp>",{"id":58,"sort":59,"collection":60,"item":61},"dc773ab6-38c4-42cb-b856-7848a9ce6afa",4,"block_code",{"id":62,"code":63,"language":64,"filename":65,"highlight_lines":65,"width":42},13,"\u002F\u002F ❌ The 150-line monster\nfun processOrder(order: Order) {\n    \u002F\u002F Validate\n    if (order.items.isEmpty()) throw ValidationException(\"No items\")\n    if (order.customerId == null) throw ValidationException(\"No customer\")\n    for (item in order.items) {\n        if (item.quantity \u003C= 0) throw ValidationException(\"Bad quantity\")\n        if (item.price \u003C= 0) throw ValidationException(\"Bad price\")\n    }\n    \u002F\u002F Business logic\n    val total = order.items.sumOf { it.price * it.quantity }\n    val discount = if (total > 10000) total * 0.07 else 0.0\n    val finalAmount = total - discount\n    \u002F\u002F Save to DB\n    val entity = OrderEntity(\n        id = UUID.randomUUID(),\n        customerId = order.customerId,\n        total = finalAmount,\n        status = \"PROCESSED\"\n    )\n    database.save(entity)\n    \u002F\u002F Send email\n    val customer = customerRepo.findById(order.customerId)\n    emailService.send(\n        to = customer.email,\n        subject = \"Order ${entity.id} confirmed\",\n        body = \"Your order of $finalAmount has been processed.\"\n    )\n    \u002F\u002F ... and it keeps going for 100 more lines\n}","kotlin","",{"id":67,"sort":68,"collection":60,"item":69},"6298b86b-cc08-4f46-a7f6-7fc6b0bf087d",5,{"id":70,"code":71,"language":64,"filename":65,"highlight_lines":65,"width":42},12,"\u002F\u002F ✅ After: each method does ONE thing\nfun processOrder(order: Order) {\n    validate(order)\n    val processed = applyBusinessRules(order)\n    save(processed)\n    notifyCustomer(processed)\n}\n\nprivate fun validate(order: Order) {\n    require(order.items.isNotEmpty()) { \"No items\" }\n    requireNotNull(order.customerId) { \"No customer\" }\n    order.items.forEach { item ->\n        require(item.quantity > 0) { \"Bad quantity\" }\n        require(item.price > 0) { \"Bad price\" }\n    }\n}\n\nprivate fun applyBusinessRules(order: Order): ProcessedOrder {\n    val total = order.items.sumOf { it.price * it.quantity }\n    val discount = calculateDiscount(total)\n    return ProcessedOrder(order, total - discount)\n}",{"id":73,"sort":74,"collection":75,"item":76},"a0c85478-0488-4fb5-b25b-c388ae519c6f",6,"block_diagram",{"id":77,"source_type":78,"mermaid_code":79,"image":33,"caption":80,"width":42},7,"mermaid","flowchart TD\n    subgraph before [Before: The Monster]\n        direction TB\n        M1[\"validate()\"] --> M2[\"business rules\"]\n        M2 --> M3[\"save to DB\"]\n        M3 --> M4[\"send email\"]\n        M4 --> M5[\"logging\"]\n        M5 --> M6[\"error handling\"]\n    end\n\n    subgraph after [After: Clean Pieces]\n        direction TB\n        A1[\"validate() ✅ Testable\"]\n        A2[\"applyRules() ✅ Testable\"]\n        A3[\"save() ✅ Testable\"]\n        A4[\"notify() ✅ Testable\"]\n    end\n\n    before -.->|\"refactor\"|after\n\n    style before fill:#ffebee,stroke:#c62828,color:#1a1a1a\n    style after fill:#e8f5e9,stroke:#2e7d32,color:#1a1a1a\n    style M1 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style M2 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style M3 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style M4 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style M5 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style M6 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style A1 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style A2 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style A3 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style A4 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a","Before: one giant method. After: small, focused pieces you can read in seconds.",{"id":82,"sort":77,"collection":38,"item":83},"164e7670-1ce2-428a-9213-46694c40bcff",{"id":84,"content":85,"width":42},"5a91d30a-d18c-4887-8f15-1585d4b95f4d","\u003Ch2>\u003Cstrong>Sign 2:\u003C\u002Fstrong> Magic numbers\u003C\u002Fh2>\n\u003Cp>You're reading through the code and you see this:\u003C\u002Fp>\n\u003Cp>\u003Ccode>if (amount > 10000 && days > 30) { fee = amount * 0.07 }\u003C\u002Fcode>\u003C\u002Fp>\n\u003Cp>What's 10000? A currency limit? A fraud threshold? Something from a regulation? You don't know. \u003Cem>Nobody knows.\u003C\u002Fem> The person who wrote it left the company two years ago.\u003C\u002Fp>\n\u003Cp>These are \u003Cstrong>magic numbers\u003C\u002Fstrong> — values that appear in code without explanation. They're a readability nightmare because they force every reader to guess the intention.\u003C\u002Fp>\n\u003Cp>The fix is trivial: \u003Cstrong>named constants\u003C\u002Fstrong>. Give every number a name that explains its purpose.\u003C\u002Fp>",{"id":87,"sort":88,"collection":60,"item":89},"7682538a-d49d-478e-81f1-4e63b13dfb85",8,{"id":48,"code":90,"language":64,"filename":65,"highlight_lines":65,"width":42},"\u002F\u002F ❌ Magic numbers — what do these mean?\nif (amount > 10000 && days > 30) {\n    fee = amount * 0.07\n}\n\n\u002F\u002F ✅ Named constants — self-documenting\nval LARGE_TRANSACTION_THRESHOLD = BigDecimal(\"10000\")\nval RETENTION_PERIOD_DAYS = 30\nval EARLY_WITHDRAWAL_FEE_RATE = BigDecimal(\"0.07\")\n\nif (amount > LARGE_TRANSACTION_THRESHOLD && days > RETENTION_PERIOD_DAYS) {\n    fee = amount * EARLY_WITHDRAWAL_FEE_RATE\n}",{"id":92,"sort":93,"collection":38,"item":94},"b1aa53ef-2847-4034-b99f-0410710bc87b",9,{"id":95,"content":96,"width":42},"c15a7ddf-d9db-4d6f-a7ac-2a81f43915cb","\u003Ch2>\u003Cstrong>Sign 3:\u003C\u002Fstrong> Nested if-else pyramids\u003C\u002Fh2>\n\u003Cp>Code indented 5+ levels deep. An if inside an if inside an if inside an else inside an if. Like a pyramid of uncertainty. You have to scroll horizontally to read it. Your brain has to track every condition to know what code actually runs.\u003C\u002Fp>\n\u003Cp>The fix is a technique called \u003Cstrong>early return\u003C\u002Fstrong> (or guard clauses). Instead of nesting deeper and deeper, you handle the \"not valid\" cases first and return immediately. Then the happy path sits at the top level, easy to read.\u003C\u002Fp>",{"id":98,"sort":99,"collection":60,"item":100},"e7c90d78-3b06-458f-bb07-fbd4a68c031d",10,{"id":101,"code":102,"language":64,"filename":65,"highlight_lines":65,"width":42},14,"\u002F\u002F ❌ The pyramid of doom\nfun process(user: User?, order: Order?) {\n    if (user != null) {\n        if (user.isActive) {\n            if (order != null) {\n                if (order.isValid) {\n                    if (order.items.isNotEmpty()) {\n                        \u002F\u002F FINALLY — the actual logic\n                        \u002F\u002F 5 levels deep, can barely read it\n                        processOrder(order)\n                    }\n                }\n            }\n        }\n    }\n}\n\n\u002F\u002F ✅ Guard clauses — flat and readable\nfun process(user: User?, order: Order?) {\n    if (user == null) return\n    if (!user.isActive) return\n    if (order == null) return\n    if (!order.isValid) return\n    if (order.items.isEmpty()) return\n\n    \u002F\u002F Business logic at top level — easy to read\n    processOrder(order)\n}",{"id":104,"sort":105,"collection":75,"item":106},"c1818921-a9da-4bd3-86e9-0a9350c53818",11,{"id":88,"source_type":78,"mermaid_code":107,"image":33,"caption":108,"width":42},"flowchart TD\n    subgraph pyramid [Pyramid of Doom]\n        direction TB\n        P1{\"user != null?\"}\n        P1 -->|yes| P2{\"user.isActive?\"}\n        P1 -->|no| PE[\"end\"]\n        P2 -->|yes| P3{\"order != null?\"}\n        P2 -->|no| PE\n        P3 -->|yes| P4{\"order.isValid?\"}\n        P3 -->|no| PE\n        P4 -->|yes| P5{\"items empty?\"}\n        P4 -->|no| PE\n        P5 -->|no| PL[\"processOrder()\"]\n        P5 -->|yes| PE\n    end\n\n    subgraph guard [Guard Clauses]\n        direction TB\n        G1{\"user == null?\"}\n        G1 -->|yes| GR1[\"return\"]\n        G1 -->|no| G2{\"!user.isActive?\"}\n        G2 -->|yes| GR2[\"return\"]\n        G2 -->|no| G3{\"order == null?\"}\n        G3 -->|yes| GR3[\"return\"]\n        G3 -->|no| GL[\"processOrder()\"]\n    end\n\n    style pyramid fill:#ffebee,stroke:#c62828,color:#1a1a1a\n    style guard fill:#e8f5e9,stroke:#2e7d32,color:#1a1a1a\n    style PL fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style PE fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style GL fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style GR1 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style GR2 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style GR3 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a","Guard clauses flatten the control flow — your brain thanks you.",{"id":110,"sort":70,"collection":38,"item":111},"f1ab7ceb-4d22-49fe-b26b-7d2a4761d596",{"id":112,"content":113,"width":42},"d15a506d-b8aa-4515-ba7e-f38da622958d","\u003Ch2>\u003Cstrong>Sign 4:\u003C\u002Fstrong> Comments that explain HOW, not WHY\u003C\u002Fh2>\n\u003Cp>Most comments in code are useless. Not because comments are bad — but because they explain things the code already says.\u003C\u002Fp>\n\u003Cp>\u003Ccode>\u002F\u002F increment i by 1\u003C\u002Fcode> above \u003Ccode>i++\u003C\u002Fcode>? Thanks, I could read that.\u003C\u002Fp>\n\u003Cp>The code already tells you \u003Cstrong>how\u003C\u002Fstrong>. Comments should tell you \u003Cstrong>why\u003C\u002Fstrong>. Why does this number need +1? Why are we retrying exactly 3 times? Why is there a sleep here? Those are the questions comments should answer.\u003C\u002Fp>",{"id":115,"sort":62,"collection":60,"item":116},"3188258b-5c87-424a-b42f-417004d31ad2",{"id":117,"code":118,"language":64,"filename":65,"highlight_lines":65,"width":42},16,"\u002F\u002F ❌ Useless — the code already says this\n\u002F\u002F increment index by 1\ni++\n\n\u002F\u002F loop through all items\nfor (item in items) { ... }\n\n\u002F\u002F ✅ Useful — explains WHY, not HOW\n\u002F\u002F +1 because the API uses 1-based indexing\nval apiIndex = localIndex + 1\n\n\u002F\u002F Retry 3 times because the external payment service\n\u002F\u002F has transient failures during peak hours (see INC-2847)\nrepeat(3) { callPaymentService() }\n\n\u002F\u002F Sleep 500ms because the rate limiter allows\n\u002F\u002F max 2 requests per second (see API docs §3.2)\nThread.sleep(500)",{"id":120,"sort":101,"collection":38,"item":121},"50c224ba-e927-4227-82f4-f2a8f65561d3",{"id":122,"content":123,"width":42},"186f26a7-c008-4a4f-afff-3ea0d35ad9ba","\u003Ch2>\u003Cstrong>Sign 5:\u003C\u002Fstrong> The Mega Class\u003C\u002Fh2>\n\u003Cp>You know the one. A class that's 2000+ lines long. It handles user management, sends emails, generates reports, connects to the database, formats dates, and somehow also knows about the tax calculation logic. It's the class that does \u003Cem>everything\u003C\u002Fem>.\u003C\u002Fp>\n\u003Cp>This violates the \u003Cstrong>Single Responsibility Principle\u003C\u002Fstrong> — the S in SOLID. A class should have one reason to change. When your UserService knows about email templates, you have a problem.\u003C\u002Fp>\n\u003Cp>The fix: split responsibilities into separate classes. The diagram below shows exactly what I mean.\u003C\u002Fp>",{"id":125,"sort":48,"collection":75,"item":126},"9b4e83fb-5a7e-45c6-aa80-329fa1401588",{"id":93,"source_type":78,"mermaid_code":127,"image":33,"caption":128,"width":42},"flowchart TD\n    subgraph god [Mega Class: OrderManager]\n        direction TB\n        G1[\"createUser()\"]\n        G2[\"sendEmail()\"]\n        G3[\"generateReport()\"]\n        G4[\"calculateTax()\"]\n        G5[\"processPayment()\"]\n        G6[\"validateOrder()\"]\n        G7[\"formatDate()\"]\n    end\n\n    subgraph clean [Clean: Focused Classes]\n        direction TB\n        C1[\"UserService\\ncreateUser()\\nupdateUser()\"]\n        C2[\"EmailService\\nsendEmail()\\nsendTemplate()\"]\n        C3[\"ReportService\\ngenerateReport()\\nexportPDF()\"]\n        C4[\"TaxService\\ncalculateTax()\\ngetRate()\"]\n        C5[\"PaymentService\\nprocessPayment()\\nrefund()\"]\n    end\n\n    god -.->|\"split\"|clean\n\n    style god fill:#ffebee,stroke:#c62828,color:#1a1a1a\n    style clean fill:#e8f5e9,stroke:#2e7d32,color:#1a1a1a\n    style G1 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style G2 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style G3 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style G4 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style G5 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style G6 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style G7 fill:#ffcdd2,stroke:#c62828,color:#1a1a1a\n    style C1 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style C2 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style C3 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style C4 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a\n    style C5 fill:#c8e6c9,stroke:#2e7d32,color:#1a1a1a","Mega Class vs. Single Responsibility: one big blob vs. focused classes",{"id":130,"sort":117,"collection":131,"item":132},"3f594cb4-c66b-4880-8ba3-487f5c7b1d13","block_quote",{"id":74,"text":133,"author":134,"source":65,"width":42},"Clean code is not a talent. It's a habit. Start with one method, one file. Small improvements every day lead to readable code in a month.","Summary",{"id":136,"sort":137,"collection":60,"item":138},"4775a82c-370a-4fbd-8a33-14b76579ad75",999,{"id":88,"code":139,"language":64,"filename":33,"highlight_lines":33,"width":42},"\u002F\u002F ❌ Magic number\nThread.sleep(86400)\n\n\u002F\u002F ✅ Named constant\nconst val SECONDS_PER_DAY = 86_400\nThread.sleep(SECONDS_PER_DAY)",{"id":141,"sort":137,"collection":46,"item":142},"746ec874-3d75-43bc-9a6c-06d277500cb7",{"id":105,"type":143,"icon":33,"content":144,"width":42},"success","\u003Cp>\u003Cstrong>Start with magic values.\u003C\u002Fstrong> It's the easiest sign to fix — just extract named constants. Then tackle deep nesting with early returns. Build momentum.\u003C\u002Fp>",{"id":146,"sort":137,"collection":147,"item":148},"26eb3f78-c7ed-4d49-9039-3df435b46c2a","block_code_text",{"id":45,"code":149,"language":64,"filename":150,"text":151,"layout":152},"\u002F\u002F ✅ After: data class with named parameters\ndata class CreateUserRequest(\n    val name: String,\n    val email: String,\n    val age: Int = 0,\n    val city: String = \"\",\n    val role: String = \"user\",\n    val active: Boolean = true,\n    val score: Double = 0.0\n)\n\nfun createUser(req: CreateUserRequest): User {\n    \u002F\u002F Single parameter, everything is named\n}\n\n\u002F\u002F Call site is self-documenting:\ncreateUser(CreateUserRequest(\n    name = \"Alice\",\n    email = \"alice@example.com\"\n))","After.kt","\u003Cp>\u003Cstrong>The parameter object pattern.\u003C\u002Fstrong> Instead of 7 positional parameters, one data class carries all the context. Defaults handle optional fields, and the call site reads like configuration.\u003C\u002Fp>","code-left",{"id":154,"sort":137,"collection":38,"item":155},"3f172436-5af5-4181-a946-55734e144e34",{"id":156,"content":65,"width":42},"a788bf34-f53a-40c4-af5f-1da42b1f0640",{"id":158,"sort":137,"collection":46,"item":159},"f3bd2a9d-39a4-4fee-aa84-2bca72e3e1de",{"id":68,"type":143,"icon":33,"content":65,"width":42},{"id":161,"sort":137,"collection":131,"item":162},"21084669-3a10-4bb5-bae2-4c0aded67029",{"id":45,"text":163,"author":164,"source":165,"width":42},"\u003Cp>Any fool can write code that a computer can understand. Good programmers write code that \u003Cem>humans\u003C\u002Fem> can understand.\u003C\u002Fp>","Martin Fowler","Refactoring",{"id":167,"sort":137,"collection":147,"item":168},"c4bed1f9-47ab-44ed-b740-4eecf2426dec",{"id":53,"code":169,"language":64,"filename":170,"text":171,"layout":172},"\u002F\u002F ❌ Before: nested conditionals\nfun processOrder(order: Order) {\n    if (order != null) {\n        if (order.items.isNotEmpty()) {\n            if (order.payment != null) {\n                if (order.payment.isValid) {\n                    \u002F\u002F Finally! The actual logic\n                    fulfill(order)\n                }\n            }\n        }\n    }\n}","NestedBefore.kt","\u003Cp>\u003Cstrong>Fix: Flatten with early returns.\u003C\u002Fstrong> Each guard clause handles one invalid condition and exits immediately. The happy path sits at the lowest indentation level, where it's easy to read.\u003C\u002Fp>\u003Cp>This pattern — sometimes called the \"Bouncer Pattern\" — is one of the highest-impact refactorings you can do. It transforms code from \"find the real logic hidden in the nesting\" to \"read top to bottom, everything makes sense.\"\u003C\u002Fp>","code-right",{"id":174,"sort":137,"collection":147,"item":175},"c9f26436-9a19-4d81-983f-ea8058b5bc62",{"id":37,"code":176,"language":64,"filename":177,"text":178,"layout":172},"\u002F\u002F ❌ Before: too many parameters, order matters\nfun createUser(\n    name: String,\n    email: String,\n    age: Int,\n    city: String,\n    role: String,\n    active: Boolean,\n    score: Double\n): User {\n    \u002F\u002F 7 parameters — good luck remembering the order\n}","Before.kt","\u003Cp>\u003Cstrong>Fix: Group related parameters into a data class.\u003C\u002Fstrong> This reduces cognitive load, makes the call site self-documenting, and lets you add validation in one place.\u003C\u002Fp>\u003Cp>The data class becomes the single source of truth for what creating a user requires. Named parameters with defaults handle optional fields gracefully.\u003C\u002Fp>",{"id":180,"sort":137,"collection":38,"item":181},"578dcd3a-a92c-4732-87ad-33fd91e807c1",{"id":182,"content":65,"width":42},"75961324-52d2-41cc-9ab0-a774ca149778",{"id":184,"sort":137,"collection":46,"item":185},"cf483faa-1103-4138-9d91-a1ab694e8e92",{"id":53,"type":186,"icon":33,"content":65,"width":42},"warning",{"id":188,"sort":137,"collection":38,"item":189},"e0524970-d215-42ec-a7f1-b578dc9e876b",{"id":190,"content":65,"width":42},"61dc700c-83a4-48d9-8959-a3c43ba94650",{"id":192,"sort":137,"collection":38,"item":193},"85232135-8d44-4a60-bc7d-f802f1459ac5",{"id":194,"content":65,"width":42},"3a37e441-375a-4630-a9cb-01a9cd981109",{"id":196,"sort":137,"collection":38,"item":197},"b03e2b2d-59d1-4eed-9478-0b177e831d66",{"id":198,"content":65,"width":42},"b4281928-6803-4a8e-af51-af7f59710adb",{"id":200,"sort":137,"collection":46,"item":201},"a2856a34-dbda-4602-b743-5c3c53d1efe8",{"id":59,"type":202,"icon":33,"content":65,"width":42},"danger",{"id":204,"sort":137,"collection":38,"item":205},"e9ebf5d9-4655-4856-a545-a2427728a944",{"id":206,"content":65,"width":42},"9eb94f5a-e645-46b6-b2c5-211dbffacf30",{"id":208,"sort":137,"collection":38,"item":209},"0dfe3631-4cb4-44bf-a5b5-dce290293ad0",{"id":210,"content":65,"width":42},"670bf1d8-36fd-48a1-833f-8866bc1cbe9d",{"id":212,"sort":137,"collection":60,"item":213},"c069b036-e060-4bbd-8cef-a97577e11f77",{"id":53,"code":65,"language":64,"filename":214,"highlight_lines":215,"width":42},"MagicValues.kt","1,2,3,10,11,12,14,15,16",{"id":217,"sort":137,"collection":38,"item":218},"bb958484-f184-4be8-aabe-cd89719c1572",{"id":219,"content":220,"width":42},"b9f3663a-f21f-4803-9c78-5014adccac6d","\u003Cp>Not all bad code is obvious. Some patterns look fine on the surface but create problems that grow over time. Here are five signs your code needs attention — and fixes you can apply today.\u003C\u002Fp>",{"id":222,"sort":137,"collection":38,"item":223},"2377dfb9-7250-487a-81ee-e4709d7d133f",{"id":224,"content":225,"width":42},"c99efd1d-dd4e-43b6-92c5-760a9bfdcecb","\u003Ch2>Signs 1-2: Too many parameters & null checks everywhere\u003C\u002Fh2>\u003Cp>\u003Cstrong>Too many parameters.\u003C\u002Fstrong> When a function takes 5+ arguments, callers can't remember the order. Fix: group related parameters into a data class.\u003C\u002Fp>\u003Cp>\u003Cstrong>Wall-to-wall null checks.\u003C\u002Fstrong> If every other line is \u003Ccode>if (x != null)\u003C\u002Fcode>, you're fighting the type system. Fix: use Kotlin's safe call operator \u003Ccode>?.\u003C\u002Fcode> and the Elvis operator \u003Ccode>?:\u003C\u002Fcode> to handle nulls in one expression.\u003C\u002Fp>",{"id":227,"sort":137,"collection":60,"item":228},"316b0ff4-9c0d-4edb-92f6-6177ec336920",{"id":77,"code":229,"language":64,"filename":33,"highlight_lines":33,"width":42},"\u002F\u002F ❌ Too many parameters\nfun createUser(name: String, email: String, age: Int, city: String, role: String): User\n\n\u002F\u002F ✅ Group into a data class\ndata class CreateUserRequest(\n    val name: String,\n    val email: String,\n    val age: Int = 0,\n    val city: String = \"\",\n    val role: String = \"user\"\n)\n\nfun createUser(req: CreateUserRequest): User\n\n\u002F\u002F ❌ Null check wall\nif (user != null) {\n    if (user.name != null) {\n        return user.name.uppercase()\n    }\n}\nreturn \"UNKNOWN\"\n\n\u002F\u002F ✅ Kotlin way\nreturn user?.name?.uppercase() ?: \"UNKNOWN\"",{"id":231,"sort":137,"collection":38,"item":232},"19646e60-b286-4a6b-a0bf-f9215e69de53",{"id":233,"content":234,"width":42},"3f591397-73da-4b86-a0b3-68beb954bb0a","\u003Ch2>Signs 3-4: God objects & deep nesting\u003C\u002Fh2>\u003Cp>\u003Cstrong>God objects.\u003C\u002Fstrong> A class doing everything is a maintenance disaster. If you can't describe it in under 5 words, split it. Each class should have one reason to change.\u003C\u002Fp>\u003Cp>\u003Cstrong>Deep nesting.\u003C\u002Fstrong> Four levels of \u003Ccode>if\u003C\u002Fcode>\u002F\u003Ccode>for\u003C\u002Fcode> means the reader juggles four contexts. Fix: use early returns (guard clauses) to flatten the structure. The happy path should sit at the lowest indentation level.\u003C\u002Fp>",{"id":236,"sort":137,"collection":38,"item":237},"cc05ceb2-0868-4c0b-b900-edba14a435fd",{"id":238,"content":239,"width":42},"08e696ab-693f-460c-b31f-4634a501f9bd","\u003Ch2>Sign 5: Magic values\u003C\u002Fh2>\u003Cp>Hardcoded numbers scattered through code are time bombs. \u003Ccode>86400\u003C\u002Fcode> — is that seconds per day? An arbitrary timeout? Nobody knows. Extract named constants. It's the easiest fix with the most visible improvement.\u003C\u002Fp>","https:\u002F\u002Fd1.resultcrafter.com"]