<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Clean Code｜林鼎淵 Dean Lin</title>
    <link>https://deanlin.net/tags/clean-code/</link>
    <image><url>https://deanlin.net/images/author_hu_aa256fc934e9a932.jpg</url><title>Clean Code｜林鼎淵 Dean Lin</title><link>https://deanlin.net/tags/clean-code/</link><width>144</width><height>144</height></image>
    <description>林鼎淵（Dean Lin）的部落格：生成式 AI 企業內訓講師、外商資安公司軟體專家、7 本書作者。400 多篇文章用白話分享生成式 AI 實戰、Claude Code 與 Vibe Coding 教學、團隊合作與職場成長。</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <copyright>© 2020–2026 林鼎淵 Dean Lin</copyright>
    <lastBuildDate>Fri, 18 Sep 2020 09:47:23 +0800</lastBuildDate>
    <atom:link href="https://deanlin.net/tags/clean-code/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>【Day3】努力寫出更好的程式碼，有時你不是一個人在戰鬥</title>
      <link>https://deanlin.net/blog/202009/fb-ig-crawler-day-03/</link>
      <pubDate>Fri, 18 Sep 2020 09:47:23 +0800</pubDate>
      <guid>https://deanlin.net/blog/202009/fb-ig-crawler-day-03/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>技術教學</category>
      <description>接下來幾天，我會把這個專案開發前所需具備的基礎知識分幾個主題向各位分享，希望這些文章能給初學者正確的觀念、也能讓老手思考自己開發上是否有忽略的細節</description>
      <media:content url="https://deanlin.net/blog/202009/fb-ig-crawler-day-03/images/cover_hu_ed394d249ded0599.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<blockquote>
<p>不是每個人都能成為明星，但是所有人都可以努力做到能力範圍的最好，並持續提高 - Henk Vermeyden</p>
</blockquote>
<p><mark>接下來幾天，我會把這個專案開發前所需具備的基礎知識分幾個主題向各位分享，希望這些文章能給初學者正確的觀念、也能讓老手思考自己開發上是否有忽略的細節</mark></p>
<h2 id="為什麼寫這篇文章">為什麼寫這篇文章？<a class="h-anchor" href="#%e7%82%ba%e4%bb%80%e9%ba%bc%e5%af%ab%e9%80%99%e7%af%87%e6%96%87%e7%ab%a0" aria-label="這個段落的連結"></a></h2>
<p>我直到近一年才真正意識到好的程式碼在團隊合作中有多麼重要</p>
<p>在團隊裡面你不只是要完成自己負責的功能，你更要<mark>讓其他同事能在短時間理解你的程式</mark></p>
<p>就算你是一個人獨立完成專案，好的程式碼能讓你在日後維護上節省更多的時間及精力</p>
<p>希望未來我們回頭看一年前寫的專案時，不求內心的小精靈呼喊:&ldquo;X，寫得太精采了!&quot;，只希望內心的小精靈不要滿嘴髒話就好</p>
<hr>
<h2 id="今日目標">今日目標<a class="h-anchor" href="#%e4%bb%8a%e6%97%a5%e7%9b%ae%e6%a8%99" aria-label="這個段落的連結"></a></h2>
<p>對我來說高效能演算法與複雜的語法並不是我所追求的東西（其實是因為筆者資質駑鈍看不懂）</p>
<p>所以今天的目標就是如何寫出讓笨笨的筆者都能看懂的程式XD，這在程式界有個專有名詞叫做 <code>Clean Code(無暇程式碼)</code></p>
<p>我將裡面幾個重要的點列在下方，並用我實際的經驗作解釋</p>
<ol>
<li>正確的宣告變數</li>
<li>有意義的命名</li>
<li>避免重複的程式碼</li>
<li>大眾都能理解的程式</li>
<li>好的註解</li>
<li>錯誤處理 &amp; 日誌(log)</li>
</ol>
<hr>
<h2 class="h-nomark" id="1-正確的宣告變數">1. 正確的宣告變數<a class="h-anchor" href="#1-%e6%ad%a3%e7%a2%ba%e7%9a%84%e5%ae%a3%e5%91%8a%e8%ae%8a%e6%95%b8" aria-label="這個段落的連結"></a></h2>
<p>用對的方式宣告變數才會讓人了解到他的意義</p>
<ul>
<li>
<p><strong>var</strong> : 作用範圍在函式(function裡面)，這樣的宣告方式讓他可以在函式內的任何位置使用，但因為容許重複宣告，所以<strong>會造成變數被覆寫的意外</strong>，請盡量減少使用</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">function</span> test() {
</span></span><span style="display:flex;"><span>  <span style="color:#8b949e;font-style:italic">// 宣告時給一個初始值
</span></span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">var</span> baby <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;寶寶本尊&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#8b949e;font-style:italic">// 再次宣告
</span></span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">var</span> baby <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;寶寶被污染了&#34;</span>
</span></span><span style="display:flex;"><span>  console.log(baby) <span style="color:#8b949e;font-style:italic">// 會印出&#39;寶寶被污染了&#39;
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></li>
<li>
<p><strong>let</strong> : 作用範圍在區塊(block裡面{})，可被重新指定值，<mark>let 與 const 皆不可重複宣告會報錯</mark></p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">function</span> test() {
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 宣告時給一個初始值
</span></span></span><span style="display:flex;"><span>    <span style="color:#ff7b72">let</span> baby <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;寶寶本尊&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 重新指定值
</span></span></span><span style="display:flex;"><span>    baby <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;寶寶變身&#34;</span>
</span></span><span style="display:flex;"><span>    console.log(baby) <span style="color:#8b949e;font-style:italic">// 會印出&#39;寶寶變身&#39;
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 再次宣告
</span></span></span><span style="display:flex;"><span>    <span style="color:#ff7b72">let</span> baby <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;寶寶壞掉了&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 會跳出錯誤 SyntaxError: Identifier &#39;baby&#39; has already been declared
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></li>
<li>
<p><strong>const</strong> : 作用範圍在區塊(block裡面{})，宣告後為不可被重新指定值的常數，使用他就是為了避免該常數被修改</p>
<ul>
<li>
<p>定義不做改變的常數 : const PI = 3.14159</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">function</span> test() {
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 宣告時給一個初始值
</span></span></span><span style="display:flex;"><span>    <span style="color:#ff7b72">const</span> baby <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;寶寶不可改變&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 重新指定值
</span></span></span><span style="display:flex;"><span>    baby <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;寶寶變身失敗&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 會跳出錯誤 TypeError: Assignment to constant variable.
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></li>
<li>
<p>特別注意如果 <strong>const 宣告陣列(array)或物件(object)時是可以被改變的</strong>，因為他們都是 reference type</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">function</span> test () {
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 宣告為物件
</span></span></span><span style="display:flex;"><span>    <span style="color:#ff7b72">const</span> baby <span style="color:#ff7b72;font-weight:bold">=</span> { name<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;寶寶本尊&#34;</span> }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 重新指定值
</span></span></span><span style="display:flex;"><span>    baby.name <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;寶寶變身&#34;</span>
</span></span><span style="display:flex;"><span>    console.log(baby) <span style="color:#8b949e;font-style:italic">// 會印出&#39;{ name: &#39;寶寶變身&#39; }&#39;
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></li>
</ul>
</li>
</ul>
<hr>
<h2 class="h-nomark" id="2-有意義的命名">2. 有意義的命名<a class="h-anchor" href="#2-%e6%9c%89%e6%84%8f%e7%be%a9%e7%9a%84%e5%91%bd%e5%90%8d" aria-label="這個段落的連結"></a></h2>
<p>這裡要看你工作環境的默契去做調整，但還是有幾個基礎要求</p>
<ul>
<li>
<p><strong>函式(function)的命名</strong></p>
<ul>
<li>
<p>要一眼就能明白他要做的事情</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 不好的命名，你無法從名字理解他要做的事情
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">function</span> abc(a, b) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">return</span> a <span style="color:#ff7b72;font-weight:bold">+</span> b
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 好的命名，淺顯易懂
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">function</span> sum(a, b) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">return</span> a <span style="color:#ff7b72;font-weight:bold">+</span> b
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></li>
<li>
<p>命名不要複雜化，做一件事情就好</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 不好的命名，一個函式做太多事情了
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">function</span> goBackpageWriteContent() {...}
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 好的命名，一個函式昨一件事，上面的function可以做拆分
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">function</span> goBackpage() {...}
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">function</span> writeContent() {...}
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p><strong>變數(variable)的命名能直接知道他代表甚麼</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 不好的命名，你看到會覺得疑惑
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">let</span> haha <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#39;猜猜看這個變數代表甚麼&#39;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 好的命名，非常直觀無須猜想
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">let</span> name <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#39;好想兔&#39;</span>
</span></span></code></pre></div></li>
</ul>
<hr>
<h2 class="h-nomark" id="3-避免重複的程式碼">3. 避免重複的程式碼<a class="h-anchor" href="#3-%e9%81%bf%e5%85%8d%e9%87%8d%e8%a4%87%e7%9a%84%e7%a8%8b%e5%bc%8f%e7%a2%bc" aria-label="這個段落的連結"></a></h2>
<p>在快速開發時期複製貼上是最爽的事情，但你在<mark>未來會付出沉重的代價</mark>如下</p>
<ul>
<li><strong>專案需求變更</strong> : 你會發現維護是如此的困難，你可能已經忘記之前有多少程式是複製貼上，導致不斷產生新的Bug</li>
<li><strong>程式體積龐大理解不易</strong> : 兩段長得很像的程式你會需要用大家來找碴的方式去思考</li>
</ul>
<p><strong>解決方案</strong></p>
<ul>
<li>如果有功能一模一樣且多次被不同檔案使用的函式建議你寫一個<strong>專案共用函式庫</strong>(ex: public.js)，這樣功能修改時只要改一個地方就好</li>
<li>如果遇到功能很接近的需求請把他們<strong>結合到一個函式</strong>中吧，你可以<strong>搭配參數</strong>來處理當中的差異性</li>
</ul>
<hr>
<h2 class="h-nomark" id="4-大眾都能理解的程式">4. 大眾都能理解的程式<a class="h-anchor" href="#4-%e5%a4%a7%e7%9c%be%e9%83%bd%e8%83%bd%e7%90%86%e8%a7%a3%e7%9a%84%e7%a8%8b%e5%bc%8f" aria-label="這個段落的連結"></a></h2>
<ul>
<li>我周圍曾經遇過程式能力極強，但是<strong>幾乎無法與人合作的工程師</strong>，他們所寫的程式有幾個特點
<ul>
<li><strong>程式邏輯非常難理解</strong>：他們可能使用效能最好的處理方案，但是邏輯非常跳躍晦澀難懂</li>
<li><strong>語法非常新潮</strong>：使用時代最尖端的語法，但同事在閱讀理解上會很痛苦</li>
</ul>
</li>
<li>也遇過只求完成功能<strong>得過且過的工程師</strong>，他們也有幾個特點
<ul>
<li><strong>他們不知道自己寫了甚麼</strong>：都是從網路上複製貼上，能跑就好，甚至參數命名都不改，於是交接的時候就是地獄，因為連他都不知道這段程式做了什麼</li>
<li><strong>功能都是複製貼上</strong>：就算是一模一樣的功能，由於過去都是從網路複製貼上完成，所以有時他們甚至忘記自己寫過他，再次從網路複製另一段程式不一樣但功能一樣的code貼上&hellip;，認真覺得這種解決事情的方法超級母湯</li>
</ul>
</li>
</ul>
<p>遇到前者是你的幸運也是你的不幸，雖然你可以與神同行，但是<strong>要不斷的提升自己</strong>才能夠勉強跟上他們的思路；遇到後者就當成鍛鍊，你要嘗試將這些不明所以的程式碼<strong>重構</strong>，讓他足以被大眾理解</p>
<p>而我寫程式的目標是希望在交接的時候被人輕易理解，所以在撰寫的過程中會不斷反思這些程式碼寫在這裡的意義是甚麼，<mark>如果自己都無法解釋的程式，就不用期待他人能夠理解了</mark></p>
<hr>
<h2 class="h-nomark" id="5-好的註解">5. 好的註解<a class="h-anchor" href="#5-%e5%a5%bd%e7%9a%84%e8%a8%bb%e8%a7%a3" aria-label="這個段落的連結"></a></h2>
<p>雖然有神人說過：最好的註解就是程式碼本身</p>
<p>但我想<mark>絕大多數的人都難以到達這個境界，所以要乖乖地寫註解</mark></p>
<ul>
<li><strong>註解的好處</strong>
<ul>
<li>交代前因後果：為什麼這樣寫?遇到了什麼困難?解決了什麼問題?</li>
<li>作為文件說明：有些技術是需要被學習後才能夠看得懂的(ex:引入的模組、套件)，你的註解能讓他快速理解這些工具怎麼使用</li>
</ul>
</li>
<li><strong>請不要有註解如下</strong>
<ul>
<li>毫無意義的牢騷(ex:我好崩潰啊，這段程式我寫了一個禮拜&hellip;)</li>
<li>把註解當成版本控制(ex:2020/08/23完成此函式)</li>
<li>說明這段程式是誰寫的(簽名檔)</li>
<li>把舊的程式碼註解起來怕以後會用到(但通常再也不會用到，而且這個問題用版控就能解決)</li>
</ul>
</li>
</ul>
<hr>
<h2 class="h-nomark" id="6-錯誤處理--日誌log">6. 錯誤處理 &amp; 日誌(log)<a class="h-anchor" href="#6-%e9%8c%af%e8%aa%a4%e8%99%95%e7%90%86--%e6%97%a5%e8%aa%8clog" aria-label="這個段落的連結"></a></h2>
<p>寫的再好的程式都會有漏洞，而完善的錯誤處理 &amp; 明確的日誌紀錄可以協助你更快速的除錯(debug)</p>
<ul>
<li><strong>錯誤處理</strong>：通常使用 try-catch 的方式來處理，這個部分在後面的章節會更詳細介紹</li>
<li><strong>日誌(log)</strong>：記錄程式執行時重要的節點
<ul>
<li>程式執行到哪個步驟</li>
<li>資料是否取得</li>
<li>如果發生錯誤時式在哪個環節</li>
</ul>
</li>
</ul>
<p>以上是我對 Clean Code 的個人感想，如果大家對於文章的內容有任何想法歡迎討論～</p>
<hr>
<h3 id="參考資源">參考資源<a class="h-anchor" href="#%e5%8f%83%e8%80%83%e8%b3%87%e6%ba%90" aria-label="這個段落的連結"></a></h3>
<ol>
<li><a href="https://medium.com/%E6%89%8B%E5%AF%AB%E7%AD%86%E8%A8%98/clean-code-index-51e209cc47db">Clean Code 無瑕的程式碼</a></li>
<li><a href="https://eyesofkids.gitbooks.io/javascript-start-from-es6/content/part3/var_const_naming.html">變數、常數與命名</a></li>
<li><a href="https://medium.com/@totoroLiu/javascript-var-let-const-%E5%B7%AE%E7%95%B0-e3d930521230">var, let, const 差異</a></li>
<li><a href="https://medium.com/@realdennis/%E9%96%92%E8%81%8A-var%E8%88%87let%E7%9A%84%E6%87%B6%E4%BA%BA%E5%8C%85-javascript-b5a3f40ee28d">var 與 let 的主要差別</a></li>
<li><a href="https://pjchender.blogspot.com/2017/01/const.html">JavaScript ES6 中使用 const 宣告常數</a></li>
</ol>
<hr>
<blockquote>
<p><img src="https://deanlin.net/blog/202009/fb-ig-crawler-day-03/images/fb-ig-crawler-day-03-01.webp" width="1024" height="233" alt="參考資源（圖 1）" fetchpriority="high" decoding="async"></p>
<p><strong>在許多人的幫助下，本系列文章已出版成書，並添加了新的篇章與細節補充：</strong></p>
<ul>
<li>加入更多實務經驗，用完整的開發流程讓讀者了解專案每個階段要注意的事項</li>
<li>將爬蟲的步驟與技巧做更詳細的說明，讓讀者可以輕鬆入門</li>
<li>調整專案架構
<ul>
<li>優化爬蟲程式，以更廣的視角來擷取網頁資訊</li>
<li>增加資料驗證、錯誤通知等功能，讓爬蟲執行遇到問題時可以第一時間通知使用者</li>
<li>排程部分改用 node-schedule &amp; pm2 的組合，讓讀者可以輕鬆管理專案程序並獲得更精確的 log 資訊</li>
</ul>
</li>
</ul>
<p><strong>有興趣的朋友可以到天瓏書局選購，感謝大家的支持。</strong></p>
<p><strong>購書連結</strong>：<a href="https://www.tenlong.com.tw/products/9789864348008">https://www.tenlong.com.tw/products/9789864348008</a></p>
</blockquote>
]]></content:encoded>
    </item>
  </channel>
</rss>
