<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Gridli]]></title><description><![CDATA[I'm a senior developer on web technology. I like to discover and learn, and always believe there's a better way to code.]]></description><link>https://blog.post80s.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 13 Apr 2026 02:19:02 GMT</lastBuildDate><atom:link href="https://blog.post80s.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Write Clean Code (Part 1)]]></title><description><![CDATA[Clean Code with Functional Programming
There are thousands of ways to write codes that achieve the same goal: Developers have different wisdoms, experiences and of course individual preferences.
But developers don't work alone. 
Multiple studies show...]]></description><link>https://blog.post80s.com/how-to-write-clean-code-part-1</link><guid isPermaLink="true">https://blog.post80s.com/how-to-write-clean-code-part-1</guid><category><![CDATA[clean code]]></category><category><![CDATA[PHP]]></category><category><![CDATA[Functional Programming]]></category><category><![CDATA[procedural programming]]></category><dc:creator><![CDATA[Li Li]]></dc:creator><pubDate>Tue, 25 Oct 2022 21:41:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666733828088/YirSI-MBW.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-clean-code-with-functional-programming">Clean Code with Functional Programming</h1>
<p>There are thousands of ways to write codes that achieve the same goal: Developers have different wisdoms, experiences and of course individual preferences.</p>
<p>But developers don't work alone. </p>
<p><a target="_blank" href="https://bayrhammer-klaus.medium.com/you-spend-much-more-time-reading-code-than-writing-code-bc953376fe19">Multiple studies</a> show that developers spend much more time to read code than the time spent on thinking and actual coding.</p>
<p>How do we make sure developers understand each other's code quickly? We write clean code. </p>
<p>I personally recommend <a target="_blank" href="https://www.amazon.ca/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?qid=1666710596&amp;refinements=p_27%3ARobert+Martin&amp;s=books&amp;sr=1-1&amp;text=Robert+Martin">Clean Code by Robert Martin</a> for general techniques to write clean code.</p>
<p>Some good old Functional Programming wisdom of experience can help us write clean code, too!</p>
<h2 id="heading-functional-programming-and-declarative-programming">Functional Programming and Declarative Programming</h2>
<p>Functional Programming (FP) is <strong>Declarative Programming</strong>. </p>
<p>While <strong>Imperative Programming</strong> spends lines of code describing the specific steps (flow control), <strong>How to do things</strong>, used to achieve the desired results, <strong>Declarative Programming</strong> abstracts the flow control process, and instead spend lines of code describing <strong>What to Do</strong>.</p>
<p><img src="https://kwize.com/pics/Linus-Torvalds-quote-about-talking-2a9797.jpg" alt="Talk is cheap. Show me the code." /></p>
<p>Let's say we are going to write a function to cook a fried rice dish. You may write the code like this in a step-by-step style (Imperative Programming):</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cookFriedRice</span>(<span class="hljs-params"></span>) </span>{
    standUp();
    walkToKitchenSink();
    washHands();
    dryHands();
    walkToCupboard();
    openCubboard();
    grabAContainer();
    locateRiceInCubboard();
    getRiceIntoContainer();
    closeCupboard();
    walkToSink();
    rinseRice();
    walkToRiceCooker();
    cookRiceUsingRiceCooker();
    walkToFridge();
    grabAnEggFromFridge();
    walkToCupboard();
    grabAContainer();
    placeEggIntoContainer();
    beatEgg();
    waitUntilRiceIsCooked();
    <span class="hljs-comment">// It's very nice of you to read this long to this line. </span>
    <span class="hljs-comment">// As you can imagine, things go on</span>
    <span class="hljs-comment">// and on and on</span>
}
</code></pre>
<h3 id="heading-whats-the-problem-with-imperative-programming">What's the problem with Imperative Programming?</h3>
<p>It's actually quite natural to start coding in <strong>Imperative Programming</strong> paradigm: listing out every step required to solve a problem. Get our hands dirty and dive right in!</p>
<p>But after one month, there is something wrong with the code (like fatal error) or you are tasked to extend the function so that it produces fried rice with egg and <strong>bacon</strong>.</p>
<p>First step, you need to (re)visit the code. Now you don't remember what you have done, or you have no idea because other developer(s) wrote or enhanced it before you.</p>
<p>You start from the first line and after reading the first 5 lines (in reality it could be more), you still don't know why these 5 lines are related to frying rice.</p>
<pre><code class="lang-php">    standUp();
    walkToKitchenSink();
    washHands();
    dryHands();
    walkToCupboard();
    openCubboard();
</code></pre>
<p>The time to read those 5 lines is precious for any develop who wants to quickly understand the function.</p>
<h3 id="heading-solution-declarative-programming">Solution: Declarative Programming</h3>
<p>How do we make the code cleaner so that developers can cooperate more efficiently?</p>
<p>We need to abstract the original code a bit more. </p>
<p>Instead of listing every single step to show <strong>how to fry rice</strong>, we describe <strong>what we do</strong> to fry rice. The Declarative Programming paradigm:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cookFriedRice</span>(<span class="hljs-params"></span>) </span>{
    $rice = getRice();
    $egg = getEgg();
    <span class="hljs-keyword">return</span> fry($rice, $egg);
}
</code></pre>
<h3 id="heading-practical-example">Practical Example</h3>
<p>We have the following Imperative Programming code:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">practicalExample</span>(<span class="hljs-params">$input1, $input2</span>)
</span>{
    <span class="hljs-comment">// Loop #1</span>
    <span class="hljs-keyword">foreach</span> ($input1 <span class="hljs-keyword">as</span> $k =&gt; $v) {
        <span class="hljs-comment">// 1000 lines of code</span>
    }

    <span class="hljs-comment">// Loop #2</span>
    <span class="hljs-keyword">foreach</span> ($input2 <span class="hljs-keyword">as</span> $k =&gt; $v) {
        <span class="hljs-comment">// 2000 lines of code</span>
    }

    <span class="hljs-comment">// Loop #3</span>
    <span class="hljs-keyword">foreach</span> ($someArray <span class="hljs-keyword">as</span> $k =&gt; $v) {
        <span class="hljs-comment">// 1000 lines of code</span>
        <span class="hljs-comment">// 1</span>
        <span class="hljs-comment">// 2</span>
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// At line #500 and it throws an error</span>
        $loop3CalculatedField1 = calculate($v, $a);
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// 999</span>
        $return .= $loop3CalculatedField1;
    }

    <span class="hljs-keyword">return</span> $return;
}
</code></pre>
<p>After the first glance of the function, we notice that the function returns an array <code>$return</code> and 3 loops run. And it looks like Loop #1 and #2 prepare some variables which Loop #3 needs.</p>
<p>An error occurs at Line #500 in Loop #3, and you are assigned to solve the issue.</p>
<p>Let's assume it only takes one minute to discover there's no problem in the <code>calculate()</code> function. The problem is <code>$a</code> is invalid. Now we need to find out why and where <code>$a</code> is wrong.</p>
<h4 id="heading-whats-the-problem">What's the problem?</h4>
<p>It takes a lot of time to identify <code>$a</code> because it can be defined/set anywhere in the <code>1000 + 2000 = 3000</code> lines of code above Loop #3. After a few hours of reading code, we realize the following:</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">practicalExample</span>(<span class="hljs-params">$input1, $input2</span>)
</span>{
    <span class="hljs-comment">// Loop #1</span>
    <span class="hljs-keyword">foreach</span> ($input1 <span class="hljs-keyword">as</span> $k =&gt; $v) {
        <span class="hljs-comment">// 1000 lines of code</span>
        <span class="hljs-comment">// 1</span>
        <span class="hljs-comment">// 2</span>
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// So deep inside Loop #1, there's a variable computed and you can't identify this line by the first glance</span>
        $loop1CalculatedField1 = <span class="hljs-keyword">array</span>(<span class="hljs-string">'...'</span>);
        <span class="hljs-comment">// ...</span>
        $loop1CalculatedField2 = <span class="hljs-keyword">array</span>(<span class="hljs-string">'...'</span>);
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// 1000</span>
    }

    <span class="hljs-comment">// Loop #2</span>
    <span class="hljs-keyword">foreach</span> ($input2 <span class="hljs-keyword">as</span> $k =&gt; $v) {
        <span class="hljs-comment">// 2000 lines of code</span>
        <span class="hljs-comment">// 1</span>
        <span class="hljs-comment">// 2</span>
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// So deep inside Loop #2, there's a variable computed, and you can't identify this line by the first glance</span>
        $loop2CalculatedField1 = <span class="hljs-string">''</span>;
        <span class="hljs-comment">// ...</span>
        $loop2CalculatedField2 = $loop1CalculatedField1;
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// So deep inside.. and it modifies a variable defined in Loop #1 as well</span>
        $loop1CalculatedField2[] = $loop2CalculatedField1;
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// 2000</span>
    }

    <span class="hljs-comment">// Loop #3</span>
    <span class="hljs-keyword">foreach</span> ($loop1CalculatedField1 <span class="hljs-keyword">as</span> $k =&gt; $v) {
        <span class="hljs-comment">// 1000 lines of code</span>
        <span class="hljs-comment">// 1</span>
        <span class="hljs-comment">// 2</span>
        <span class="hljs-comment">// ...</span>
        $loop3CalculatedField1 = calculate($v, $loop1CalculatedField2);
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// 999</span>
        $return .= $loop3CalculatedField1;
    }

    <span class="hljs-keyword">return</span> $return;
}
</code></pre>
<p>The problematic <code>$a</code> is first defined in Loop #1 (<code>$loop1CalculatedField2</code>), and it's later modified in Loop #2.</p>
<h4 id="heading-solution">Solution</h4>
<p>How do we write cleaner code?</p>
<p>First of all, try to avoid putting too much comment and let the code speak for itself. Also, most of the time you need to tell your brain: <strong>Comment is not always right</strong> because comment might not be updated but code does.</p>
<p>What we really need to do is to <strong>describe the result</strong>. What do the Loop #1 and #2 give us?</p>
<p>The new Loop #1</p>
<pre><code class="lang-php"><span class="hljs-keyword">list</span>(<span class="hljs-string">'a'</span> =&gt; $loop1Calculated2, <span class="hljs-string">'b'</span> =&gt; $loop1Calculated1) = array_reduce(
    $input1,
    <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$carry, $v</span>) </span>{
        <span class="hljs-comment">// 1000 lines of code</span>
        <span class="hljs-comment">// 1</span>
        <span class="hljs-comment">// 2</span>
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// Define/set other variables and those variables will stay as local scope (this anonymous function)</span>
        $carry[<span class="hljs-string">'b'</span>] = <span class="hljs-keyword">array</span>(<span class="hljs-string">'...'</span>);
        <span class="hljs-comment">// ...</span>
        $carry[<span class="hljs-string">'a'</span>] = <span class="hljs-keyword">array</span>(<span class="hljs-string">'...'</span>);
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// 1000</span>
    }
);
</code></pre>
<p>The result of Loop #1 is 2 variables with no other side effects. The <em>first 3 lines</em> of code tell us what the following code block does:</p>
<ol>
<li><code>list('a' =&gt; $loop1Calculated2, 'b' =&gt; $loop1Calculated1) = ...</code> tells us the result is 2 new variables are created on the <code>practicalExample</code> function scope. And the corresponding values are what the code block returns <code>$a</code> and <code>$b</code></li>
<li><code>array_reduce($input1, ...</code> tells us we are looping array <code>$input1</code></li>
<li><code>function ($carry, $v) { ... }</code> tells us the code block does not require any other input</li>
</ol>
<p>That's all those 1000 lines of code do. I don't need to know how, I just need to know the result of it. </p>
<p><strong>By reading the first 3 lines of summary, I understand the whole picture on an abstract level.</strong></p>
<p><strong>Compared to the original code, I have to read through the whole Loop #1 in order to see the whole picture on an abstract level.</strong></p>
<p>The new Loop #2</p>
<pre><code class="lang-php"><span class="hljs-keyword">list</span>(<span class="hljs-string">'a'</span> =&gt; $loop2Calculated1, <span class="hljs-string">'b'</span> =&gt; $loop2Calculated2) = array_reduce(
    $input2,
    <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$carry, $v</span>) <span class="hljs-title">use</span> (<span class="hljs-params">&amp;$loop1Calculated2, $loop1Calculated1</span>) </span>{
        <span class="hljs-comment">// 2000 lines of code</span>
        <span class="hljs-comment">// 1</span>
        <span class="hljs-comment">// 2</span>
        <span class="hljs-comment">// ...</span>
        $carry[<span class="hljs-string">'a'</span>] = <span class="hljs-string">'...'</span>;
        <span class="hljs-comment">// ...</span>
        $carry[<span class="hljs-string">'b'</span>] = $loop1Calculated1;
        <span class="hljs-comment">// ...</span>
        $loop1Calculated2[] = $carry[<span class="hljs-string">'a'</span>];
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// 2000</span>
    }
);
</code></pre>
<p>The result of Loop #2 is:</p>
<ul>
<li><code>list('a' =&gt; $loop2Calculated1, 'b' =&gt; $loop2Calculated2) = ...</code> tells us 2 variables are created: <code>$loop2Calculated1</code> and <code>$loop2Calculated2</code></li>
<li><code>array_reduce($input2, ...)</code> tells us we are looping <code>$input2</code></li>
<li><code>function ($carry, $v) use (&amp;$loop1Calculated2, $loop1Calculated1) { ...</code> tells us the code block needs 2 more inputs <code>$loop1Calculated1</code> and <code>$loop1Calculated2</code> and there's <strong>side effect</strong>: may modify <code>$loop1Calculated2</code></li>
</ul>
<p>The new Loop #3</p>
<pre><code class="lang-php"><span class="hljs-keyword">return</span> array_reduce(
    $loop1Calculated1,
    <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$carry, $v</span>) <span class="hljs-title">use</span> (<span class="hljs-params">$loop1Calculated1, $loop1Calculated2, $loop2Calculated1, $loop2Calculated2</span>) </span>{
        <span class="hljs-comment">// 1000 lines of code</span>
        <span class="hljs-comment">// 1</span>
        <span class="hljs-comment">// 2</span>
        <span class="hljs-comment">// ...</span>
        $carry .= calculate($v, $loop1Calculated2);
        <span class="hljs-comment">// ...</span>
        <span class="hljs-comment">// 1000</span>
    },
    <span class="hljs-string">'initial return string'</span>
);
</code></pre>
<p>The result of Loop #3 is:</p>
<ul>
<li><code>return array_reduce(..., function () {...}, 'initial return string')</code> tells us the function returns a string</li>
<li><code>array_reduce($loop1Calculated1, ...)</code> tells us we are looping <code>$loop1Calculated1</code></li>
<li><code>function ($carry, $v) use ($loop1Calculated1, $loop1Calculated2, $loop2Calculated1, $loop2Calculated2) { ...</code> tells us the code block needs 4 input variables and there's no side effect</li>
</ul>
<p>The collapsed version of the new function</p>
<pre><code class="lang-php"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">paracticalExmaple</span>(<span class="hljs-params"></span>)
</span>{
    <span class="hljs-keyword">list</span>(<span class="hljs-string">'a'</span> =&gt; $loop1Calculated2, <span class="hljs-string">'b'</span> =&gt; $loop1Calculated2) = array_reduce(...);
    <span class="hljs-keyword">list</span>(<span class="hljs-string">'a'</span> =&gt; $loop2Calculated1, <span class="hljs-string">'b'</span> =&gt; $loop2Calculated2) = array_reduce(...);
    <span class="hljs-keyword">return</span> array_reduce(...);
}
</code></pre>
<p>After the code is refactored to Declarative Programming paradigm/style, it will help us to:</p>
<ul>
<li>Quickly understand <strong>What has been done</strong> without knowing how things are done<ul>
<li>Although the total lines of code is actually increased, by looking at the first part of the code blocks (loops), you will clearly see the results, side effects and the inputs required to run that code block</li>
<li>Back on the debugging <code>$loop1Calculated2</code> ($originally <code>$a</code>) topic, we can easily tell that it is involved in 2 different code blocks (loops) without much scrolling</li>
</ul>
</li>
<li>Group codes in individual code blocks<ul>
<li>Individual Scope<ul>
<li>Variables defined in this scope does not affect the parent scope</li>
</ul>
</li>
<li>It's like giving a summary line for each large code block. And multiple summary lines form a table of contents</li>
</ul>
</li>
</ul>
<h2 id="heading-summary">Summary</h2>
<p>Hope you enjoy this article. Next time I will talk about other techniques to write clean code. See you later!</p>
]]></content:encoded></item></channel></rss>