<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tien Do</title>
    <description>The latest articles on DEV Community by Tien Do (@foreverlovewisdom).</description>
    <link>https://dev.to/foreverlovewisdom</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1022570%2F08b113a2-be0e-41c0-a15d-b878e2d282c1.png</url>
      <title>DEV Community: Tien Do</title>
      <link>https://dev.to/foreverlovewisdom</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/foreverlovewisdom"/>
    <language>en</language>
    <item>
      <title>When I Use AI — And When I Don’t</title>
      <dc:creator>Tien Do</dc:creator>
      <pubDate>Mon, 12 May 2025 12:44:20 +0000</pubDate>
      <link>https://dev.to/foreverlovewisdom/why-i-stopped-using-ai-for-coding-and-what-it-taught-me-about-simplicity-o4l</link>
      <guid>https://dev.to/foreverlovewisdom/why-i-stopped-using-ai-for-coding-and-what-it-taught-me-about-simplicity-o4l</guid>
      <description>&lt;p&gt;&lt;strong&gt;AI helped me ship faster, but it didn’t always allow me to ship better. Over time, I learned to separate speed from clarity and to use AI with more intention, not more dependence.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started using ChatGPT in late 2022, right after getting laid off. With no job, I had time — so I talked to it constantly. Some days, I spent 5–6 hours experimenting. Ideas bounced back and forth.&lt;/p&gt;

&lt;p&gt;At first, everything felt smooth. No red flags yet.&lt;/p&gt;

&lt;p&gt;After landing a new job at another startup, I integrated AI into my coding workflow. It felt like magic. Snippets, tests, and scaffolds appeared instantly. I called it my tireless junior dev.&lt;/p&gt;

&lt;p&gt;But a few weeks in, I noticed something off: I was shipping more but thinking less. Worse — I felt detached from the codebase.&lt;/p&gt;

&lt;p&gt;I used AI to refactor code, build new features, generate controller logic, mock APIs, and especially write RSpec tests. It saved me hours. I enjoy TDD, so I didn’t want to outsource that part — but I had to admit, the output was decent. Part of that came from my prompting skill — I’d spent months sharpening it during unemployment.&lt;/p&gt;

&lt;p&gt;On the surface, things looked efficient. PRs moved quickly. I felt productive. But the longer I used it, the more invisible costs started to show.&lt;/p&gt;




&lt;h3&gt;
  
  
  🚨 Problem 1: Fixing AI output took time
&lt;/h3&gt;

&lt;p&gt;When I used AI to generate logic-heavy code, I often spent more time fixing than writing. That’s not AI’s fault — it's about knowing when to use it, and where to trust my clarity instead. Even with multiple options, most suggestions weren’t up to my quality bar.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 Problem 2: I outsourced my thinking
&lt;/h3&gt;

&lt;p&gt;This one hit harder: critical thinking got slower. I realized I'd gradually handed over my problem-solving process to an assistant. It gave me the illusion that I don't have to think. I get paid to think. To solve real problems. Not to polish suggestions from a prediction engine.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚡ Problem 3: I became less patient
&lt;/h3&gt;

&lt;p&gt;AI gave me instant answers and I started expecting instant progress. I’ve never been perfectly patient. But, before AI, I at least respected the time it took to solve hard problems. With AI, I got frustrated faster. The illusion of speed trained my brain to expect shortcuts. And when the dopamine stopped, so did my tolerance for difficulty.&lt;/p&gt;




&lt;h3&gt;
  
  
  📉 Real-World Consequences
&lt;/h3&gt;

&lt;p&gt;When we use AI without thinking clearly, small problems pile up fast: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code looks like suggestions, not real decisions &lt;/li&gt;
&lt;li&gt;Debugging gets messy — nobody fully understands what the code is doing&lt;/li&gt;
&lt;li&gt;New teammates have to guess what’s going on&lt;/li&gt;
&lt;li&gt;You start to feel disconnected from the work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI helps move fast, yes. But if you're not careful, it also helps you get lost faster.&lt;/p&gt;




&lt;h3&gt;
  
  
  🛠 What I Do Now
&lt;/h3&gt;

&lt;p&gt;After another layoff (at the time of writing), I took a step back, not to quit AI, but to rebuild how I think with it.&lt;/p&gt;

&lt;p&gt;I went back to basics: pen, editor, whiteboard. Tools that slow me down just enough to reconnect with the thinking process itself.&lt;/p&gt;

&lt;p&gt;I still use AI — just differently now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dummy data &lt;/li&gt;
&lt;li&gt;JSON scaffolds&lt;/li&gt;
&lt;li&gt;Boilerplate test helpers&lt;/li&gt;
&lt;li&gt;... &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But for core architecture, debugging, or solving hard logic, I slow down and use my brain first. If I bring AI in, it’s as a sparring partner, not the driver.&lt;/p&gt;




&lt;p&gt;🧭 Final Thoughts&lt;/p&gt;

&lt;p&gt;AI isn’t bad. But full dependence is.&lt;/p&gt;

&lt;p&gt;Google helped. Stack Overflow helped. Social media helped. But overused? They made us distracted. AI just scales that effect.&lt;/p&gt;

&lt;p&gt;So now, I ask myself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does this tool increase clarity? &lt;/li&gt;
&lt;li&gt;Or does it let me avoid thinking?&lt;/li&gt;
&lt;li&gt;Could I still solve this without help?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try going AI-free for a week — not as a protest, but as a test.&lt;br&gt;
Watch how your brain responds. Track how often you revise AI output vs. your own. Is speed giving you clarity? Or just comfort?&lt;/p&gt;

&lt;p&gt;Tools will evolve. AI will stay. But clarity — that’s on us.&lt;/p&gt;

&lt;p&gt;I’ve made these mistakes too. That’s why I’m setting better boundaries. Still improving. Still figuring it out — like everyone else.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>3 Real-World Refactoring Principles That Help Me Tame Complexity in Startup Codebases</title>
      <dc:creator>Tien Do</dc:creator>
      <pubDate>Sun, 20 Apr 2025 07:41:54 +0000</pubDate>
      <link>https://dev.to/foreverlovewisdom/3-real-world-refactoring-principles-that-help-me-tame-complexity-in-startup-codebases-457n</link>
      <guid>https://dev.to/foreverlovewisdom/3-real-world-refactoring-principles-that-help-me-tame-complexity-in-startup-codebases-457n</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/foreverlovewisdom/first-post-and-complexity-in-software-engineer-149m"&gt;previous post&lt;/a&gt;, I talked about &lt;strong&gt;software complexity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One principle&lt;/strong&gt; I &lt;strong&gt;consistently&lt;/strong&gt; follow is:&lt;br&gt;&lt;br&gt;
👉 &lt;em&gt;“The code I touch should be easier to understand and maintain than before—unless I’m writing it from scratch.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I always start with the &lt;strong&gt;smallest unit in OOP&lt;/strong&gt;—which, coming from a Ruby background, is the &lt;strong&gt;function&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To me, a &lt;strong&gt;function is the most fundamental building block of a class&lt;/strong&gt;. Even if a class is 1,000+ lines long, the codebase is still workable if its functions are clear and well-structured. At the very least, it becomes easier to refactor in the future.&lt;/p&gt;

&lt;p&gt;In this post, I want to share &lt;strong&gt;three principles&lt;/strong&gt; I use to write clean, maintainable functions:&lt;/p&gt;


&lt;h3&gt;
  
  
  1️⃣ &lt;code&gt;Keep It Short (Lines of Code)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In Ruby, it’s idiomatic to keep functions short.&lt;/p&gt;

&lt;p&gt;When I was a tech lead, I often set a soft limit of 10–12 lines per function. But &lt;strong&gt;depending on the team’s experience level&lt;/strong&gt;, that might be too strict and slow the team down.&lt;/p&gt;

&lt;p&gt;A practical compromise I’ve found:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;20 lines is a reasonable maximum.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It keeps functions &lt;strong&gt;simple, readable, and maintainable—without introducing unnecessary friction for the team&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  📌 Example: Before &amp;amp; After
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;: A long, hard-to-scan function mixing multiple behaviors&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"Order not found"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;

  &lt;span class="n"&gt;payment_gateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PaymentGateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;payment_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;payment_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment_gateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;amount_cents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;payment_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;success?&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;status: :paid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;paid_at: &lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="no"&gt;AnalyticsLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log_payment_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="no"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_payment_confirmation_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;referral_code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;
      &lt;span class="n"&gt;reward_service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ReferralRewardService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;referral_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;reward_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_reward_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="no"&gt;SendThankYouGiftJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_later&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;amount_cents&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100_000&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;status: :payment_failed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;ErrorTracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Payment failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;order_id: &lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt;: Refactored with clarity, separation, and single-purpose focus&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"Order not found"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;charge_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;handle_successful_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;handle_failed_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;charge_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PaymentGateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;payment_token&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;amount_cents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;success?&lt;/span&gt;

  &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;status: :paid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;paid_at: &lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_successful_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;log_payment_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;notify_user_of_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;reward_referral_if_applicable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;send_thank_you_gift_if_high_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_failed_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;status: :payment_failed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;ErrorTracker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Payment failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;order_id: &lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log_payment_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;AnalyticsLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log_payment_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;user_id: &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;order_id: &lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;notify_user_of_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_payment_confirmation_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;reward_referral_if_applicable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;referral_code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;

  &lt;span class="n"&gt;reward_service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ReferralRewardService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;referral_code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;reward_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_reward_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_thank_you_gift_if_high_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;amount_cents&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100_000&lt;/span&gt;

  &lt;span class="no"&gt;SendThankYouGiftJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_later&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;2️⃣ &lt;code&gt;One Reason to Change&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A function should have only &lt;strong&gt;one reason to change&lt;/strong&gt;. This aligns with the &lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A quick test:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ask yourself, “What does this function do?”
If the answer includes “and” (e.g., “It charges the user and sends a confirmation email”), it’s doing too much.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the original example, the &lt;strong&gt;process_payment&lt;/strong&gt; function had several reasons to change:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Payment logic

Logging behavior

Notification flow

Referral rewards

Async background jobs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, &lt;strong&gt;each function focuses on just one behavior&lt;/strong&gt;, making changes easier and less risky.&lt;/p&gt;




&lt;p&gt;3️⃣ &lt;code&gt;Consistent Level of Abstraction&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This one’s subtle but powerful.&lt;/p&gt;

&lt;p&gt;If &lt;strong&gt;a function mixes different levels of abstraction&lt;/strong&gt;, it becomes &lt;strong&gt;mentally exhausting to understand&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the original version, the function:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Accessed the database (low-level)

Called an external payment API (infrastructure)

Applied business rules (mid-level)

Sent notifications (I/O)

Triggered background jobs (infra)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That’s a &lt;strong&gt;lot of context-switching&lt;/strong&gt; in one place.&lt;/p&gt;

&lt;p&gt;In the refactored version:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The main function (process_payment) stays at the orchestration level

Each helper function stays at a consistent “altitude”, making the whole flow easier to follow and evolve.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I’d love to hear your thoughts.&lt;br&gt;
What principles do you follow to keep your functions clean and maintainable?&lt;br&gt;
Let’s discuss 👇&lt;/p&gt;

</description>
      <category>cleancode</category>
      <category>softwareengineering</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>First post and complexity in software engineer</title>
      <dc:creator>Tien Do</dc:creator>
      <pubDate>Sun, 23 Feb 2025 23:44:45 +0000</pubDate>
      <link>https://dev.to/foreverlovewisdom/first-post-and-complexity-in-software-engineer-149m</link>
      <guid>https://dev.to/foreverlovewisdom/first-post-and-complexity-in-software-engineer-149m</guid>
      <description>&lt;h1&gt;
  
  
  A Bit About Me 👋
&lt;/h1&gt;

&lt;p&gt;Welcome to my technical/non-technical sharing on Dev.to! I’ve been making a living as a &lt;strong&gt;software engineer&lt;/strong&gt; (with stints as a &lt;strong&gt;product owner&lt;/strong&gt; and &lt;strong&gt;tech lead&lt;/strong&gt;) since &lt;strong&gt;2016&lt;/strong&gt;. I gained most of my experience in &lt;strong&gt;startups&lt;/strong&gt;—full of challenges, but every struggle was worth it.  &lt;/p&gt;

&lt;p&gt;In this space, I'll share my &lt;strong&gt;thoughts on software engineering and the tech industry&lt;/strong&gt;—covering both &lt;strong&gt;technical insights&lt;/strong&gt; and the &lt;strong&gt;broader business aspects&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;This is my &lt;strong&gt;first&lt;/strong&gt; technical blog—or technically, my &lt;strong&gt;second&lt;/strong&gt;. I wrote one before but deleted it because I didn’t think it was good enough. 😅 I &lt;strong&gt;do use&lt;/strong&gt; &lt;strong&gt;AI tools&lt;/strong&gt; to help refine my writing—&lt;strong&gt;rephrasing, proofreading, and improving clarity&lt;/strong&gt;—since &lt;strong&gt;English is not my native language&lt;/strong&gt;. But the &lt;strong&gt;core ideas&lt;/strong&gt; in every post are &lt;strong&gt;mine&lt;/strong&gt;, based on &lt;strong&gt;real-world experience&lt;/strong&gt; in the tech industry.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Why I’m Writing on Dev.to ✍️
&lt;/h2&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;For my future self&lt;/strong&gt;—so I can look back and see how far I’ve come.  &lt;/p&gt;

&lt;p&gt;2️⃣ &lt;strong&gt;For others on a similar path&lt;/strong&gt;—sharing what I’ve learned along the way.  &lt;/p&gt;

&lt;p&gt;3️⃣ &lt;strong&gt;For my future colleagues/partners&lt;/strong&gt;—so they can understand how I think about software engineering.  &lt;/p&gt;

&lt;p&gt;That said, these are &lt;strong&gt;not my final opinions&lt;/strong&gt;. &lt;strong&gt;Ideas evolve&lt;/strong&gt;—especially in this AI-driven era—so my thoughts will too.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Take everything with a grain of salt.&lt;/strong&gt; 🧂 If you have &lt;strong&gt;different opinions&lt;/strong&gt;, feel free to &lt;strong&gt;challenge them&lt;/strong&gt;! I don’t know how long or how often I’ll be sharing here, but for now, I have the motivation, so… I’m just going with the flow.  &lt;/p&gt;

&lt;p&gt;Alright, enough intro—let’s dive in. 🚀  &lt;/p&gt;




&lt;h2&gt;
  
  
  Complexity Enlightenment 🤯
&lt;/h2&gt;

&lt;p&gt;Today, I reread &lt;strong&gt;A Philosophy of Software Design&lt;/strong&gt; by &lt;strong&gt;John Ousterhout&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Right in &lt;strong&gt;Chapter 1: Introduction (It’s All About Complexity)&lt;/strong&gt;, this paragraph hit me hard:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This means that the greatest limitation in writing software is our ability to understand the systems we are creating. As a program grows and adds new features, it can become complex. This complexity arises from the hidden connections between its parts. As systems grow, they become more complex. This makes it difficult for programmers to remember everything when making changes. This slows down development and leads to bugs, which slow development even more and add to its cost. Complexity increases inevitably over the life of any program. The larger the program, and the more people that work on it, the more difficult it is to manage complexity."  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reading this paragraph summed up &lt;strong&gt;all the struggles my past teams and I faced&lt;/strong&gt;. It captured the &lt;strong&gt;essence of our frustrations&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;When reading technical books, some sections we &lt;strong&gt;skim&lt;/strong&gt;, and some we &lt;strong&gt;digest slowly&lt;/strong&gt;. I’m sure I read this paragraph before, but &lt;strong&gt;this time, it hit differently&lt;/strong&gt;. Maybe &lt;strong&gt;some realizations only come with experience&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;The funny thing is, I’ve also read &lt;strong&gt;Sandi Metz’s books&lt;/strong&gt; (since my background is &lt;strong&gt;Ruby on Rails&lt;/strong&gt;). She frequently talks about &lt;strong&gt;complexity&lt;/strong&gt;. But &lt;strong&gt;truly understanding&lt;/strong&gt; complexity? That takes &lt;strong&gt;time and firsthand experience&lt;/strong&gt;.  &lt;/p&gt;




&lt;h2&gt;
  
  
  How I Experienced Complexity in Startups 🏗️
&lt;/h2&gt;

&lt;p&gt;The most common pattern I’ve seen in previous startups goes like this:  &lt;/p&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;At the start, we ship code fast.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;2️⃣ &lt;strong&gt;Over time, things start slowing down.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;3️⃣ &lt;strong&gt;Adding new features takes longer and longer.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;4️⃣ &lt;strong&gt;We scale fast, but our codebase wasn’t built for change&lt;/strong&gt; (we wrote it just to &lt;strong&gt;“make things work”&lt;/strong&gt;).  &lt;/p&gt;

&lt;p&gt;5️⃣ &lt;strong&gt;We end up fixing more bugs than building new features.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;6️⃣ &lt;strong&gt;Business teams start asking:&lt;/strong&gt; “Why did things slow down? It was fast in the beginning!”  &lt;/p&gt;

&lt;p&gt;7️⃣ &lt;strong&gt;Guess who gets blamed?&lt;/strong&gt; Software engineers. 🙃  &lt;/p&gt;

&lt;p&gt;Yes, developers &lt;strong&gt;play a role&lt;/strong&gt;, but the real culprit is &lt;strong&gt;complexity and dependencies&lt;/strong&gt;. I’ve seen this pattern repeat in &lt;strong&gt;most startups&lt;/strong&gt; I’ve worked with. The only exceptions? &lt;strong&gt;Startups that failed too early—before complexity had time to emerge.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Of course, there are &lt;strong&gt;patterns, best practices, and conventions&lt;/strong&gt; to help control complexity, and I’ll share my experiences with them in future posts.  &lt;/p&gt;

&lt;p&gt;But here’s the catch: &lt;strong&gt;Tools alone don’t solve complexity.&lt;/strong&gt; Used &lt;strong&gt;blindly&lt;/strong&gt;, they can make things &lt;strong&gt;worse&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;One extra class, method, or design decision might add hidden complexity that bites us later.&lt;/strong&gt;  &lt;/p&gt;




&lt;h2&gt;
  
  
  The One Question I Now Ask Before Committing Code 🤔
&lt;/h2&gt;

&lt;p&gt;Before I commit my code, push it, and call it a day, I ask myself &lt;strong&gt;one question&lt;/strong&gt;:  &lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Am I reducing complexity for the codebase/team, or am I adding more complexity?&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;This has become &lt;strong&gt;my main guiding principle&lt;/strong&gt; before even thinking about a solution.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts &amp;amp; What’s Next 🎯
&lt;/h2&gt;

&lt;p&gt;Additionally, &lt;strong&gt;technical decisions should align with business goals&lt;/strong&gt;. At the end of the day, &lt;strong&gt;what’s the point of a technical solution if it doesn’t solve a business problem?&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;startups&lt;/strong&gt;, every decision &lt;strong&gt;directly&lt;/strong&gt; affects &lt;strong&gt;how fast we move, adapt, and survive&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;For my next posts, I’ll dive into &lt;strong&gt;how I handle complexity in real projects&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts—&lt;strong&gt;drop a comment below!&lt;/strong&gt; 👇 🚀  &lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>softwarecomplexity</category>
    </item>
  </channel>
</rss>
