<?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>團隊合作｜林鼎淵 Dean Lin</title>
    <link>https://deanlin.net/tags/%E5%9C%98%E9%9A%8A%E5%90%88%E4%BD%9C/</link>
    <image><url>https://deanlin.net/images/author_hu_aa256fc934e9a932.jpg</url><title>團隊合作｜林鼎淵 Dean Lin</title><link>https://deanlin.net/tags/%E5%9C%98%E9%9A%8A%E5%90%88%E4%BD%9C/</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>Wed, 12 Oct 2022 16:45:00 +0800</lastBuildDate>
    <atom:link href="https://deanlin.net/tags/%E5%9C%98%E9%9A%8A%E5%90%88%E4%BD%9C/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>想讓「專案執行」更加順利？工程師與 PM 間的合作要注意這點！</title>
      <link>https://deanlin.net/blog/202210/engineer-pm-project-execution/</link>
      <pubDate>Wed, 12 Oct 2022 16:45:00 +0800</pubDate>
      <guid>https://deanlin.net/blog/202210/engineer-pm-project-execution/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>團隊合作</category>
      <description>在上篇文章中，筆者介紹了正式開發前的初始任務有哪些。</description>
      <media:content url="https://deanlin.net/blog/202210/engineer-pm-project-execution/images/cover_hu_bab6af5cc4237a8d.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<p><a href="https://deanlin.net/blog/202210/team-workflow-initial-tasks/">在上篇文章中</a>，筆者介紹了正式開發前的初始任務有哪些。</p>
<p>今天就讓我們來聊聊「專案執行」時，如何讓合作的過程更加順利。</p>
<p>以筆者過去的經驗來說，團隊合作免不了要「溝通」，但每個人的溝通能力落差極大，有些人總覺得對方是自己肚子裡的蛔蟲，因此詢問問題、交付任務都沒說明細節，時常需要你來我往的多次確認。</p>
<p>為了減少彼此的衝突，我們可以針對常見的合作情境設計「格式」與「規範」。</p>
<h2 id="工作記錄work-log">工作記錄（Work Log）<a class="h-anchor" href="#%e5%b7%a5%e4%bd%9c%e8%a8%98%e9%8c%84work-log" aria-label="這個段落的連結"></a></h2>
<p>如果團隊有使用專案管理系統，為了日後方便追溯與釐清狀況，建議填寫的內容如下：</p>
<ul>
<li>如果實作的方向是討論出來的，請紀錄「與會人員」與「決議結果」。</li>
<li>如果使用到特別的演算法、技術、套件，請特別附註。</li>
<li>如果該 Ticket 完成後要由其他人接手處理（ex：後端完成 API 後交付給前端），請說明要執行哪些指令（ex：DB Migration、Seeder…），並提供相關文件。</li>
<li>如果發現 Ticket 完成的時間與估計的不同，請與 PM 討論並調整。</li>
</ul>
<h2 id="工程師之間的合作">工程師之間的合作<a class="h-anchor" href="#%e5%b7%a5%e7%a8%8b%e5%b8%ab%e4%b9%8b%e9%96%93%e7%9a%84%e5%90%88%e4%bd%9c" aria-label="這個段落的連結"></a></h2>
<p>律定格式，讓溝通有一定的品質。</p>
<ul>
<li><strong>明定 Ticket 執行順序</strong>：一個 Sprint 中，每個工程師手上有很多的 Ticket，但有些 Ticket 會有所謂的「前置條件」，為了減少等待的空窗期，工程師要在「 Sprint Planning 時溝通好」。</li>
<li><strong>回報 API Bug</strong>：請說明是在「哪個系統」、「哪隻 API」、「什麼參數下」會發生。</li>
<li><strong>回報 Web Bug</strong>：請說明是在「哪個系統」、「哪個畫面（截圖）」、「如何操作」會發生。</li>
<li><strong>遇到自己無法解決的問題</strong>：請說明是在「哪個系統」、「哪個 Ticket」、「你做過哪些嘗試」、「你認為可能的解決方案」。</li>
</ul>
<h2 id="工程師與-pm-的合作">工程師與 PM 的合作<a class="h-anchor" href="#%e5%b7%a5%e7%a8%8b%e5%b8%ab%e8%88%87-pm-%e7%9a%84%e5%90%88%e4%bd%9c" aria-label="這個段落的連結"></a></h2>
<p>工程師與 PM 合作時，千萬不要惜字如金，大家都要把話講清楚；工程師要求 PM 做到的事，自己也要做到。</p>
<ul>
<li><strong>如果 PM 請工程師完成 Sprint 以外的需求</strong>：請說明「任務優先度」、「為什麼會有這個需求」、「可以將哪個 Ticket 排後面一點」。</li>
<li><strong>如果工程師在開發過程中收到其他團隊的需求</strong>：請將對話窗口轉移到「PM」，由他來統一處理。</li>
<li><strong>如果工程師請 PM 開 Ticket</strong>：需描述「哪個系統」、「為什麼會有這個需求」、「需求描述」、「估計時數」。</li>
<li><strong>若 Loading 太重無法負荷</strong>：請說明「原因」，如：掛的 Ticket 數量太多、任務分配不均、某個 Ticket 實作遇到困難。</li>
<li><strong>若多個專案同時發起高優先度的任務</strong>：有些工程師身上會掛多個專案，若不幸有兩個以上的專案同時發起高優先度的任務，就需要請「PM」協助排出優先順序。</li>
</ul>
<h2 id="為什麼都要由pm-來開-ticket">為什麼都要由 PM 來開 Ticket？<a class="h-anchor" href="#%e7%82%ba%e4%bb%80%e9%ba%bc%e9%83%bd%e8%a6%81%e7%94%b1pm-%e4%be%86%e9%96%8b-ticket" aria-label="這個段落的連結"></a></h2>
<p>有些工程師覺得自己開 Ticket 比較快，資訊多轉一手給 PM 根本是浪費時間，但這個制度是有原因的，如果不這樣做就可能導致：</p>
<ul>
<li><strong>PM 對專案的掌握度下降</strong>：如果大家都自己開 Ticket，PM 會無法掌握每個人實際在做的任務，即使有 Tag 到 PM，PM 也未必有辦法看到每一則訊息。</li>
<li><strong>專案進度偏離原定計畫</strong>：很多時候，工程師心中的任務優先順序跟 PM 是不一樣的，這導致最後在核對完成的任務時，會因為彼此的認知落差而產生爭執。</li>
<li><strong>勞逸不均</strong>：有些工程師發現問題就想解，導致身上背了一堆 Ticket 天天加班，而其他工程師閒閒沒事做。</li>
<li><strong>做了徒勞無功的任務</strong>：有些功能從專案的角度來看，可能不重要，甚至是不需要的。</li>
</ul>
<p>為了避免上述的狀況發生，如果有任何想做的需求，請先與 PM 討論，讓 PM 從整體的角度來判斷（ex：如果你的 Loading 太重，PM 就可能將你提出的 Ticket 分配給其他人做）。</p>
<h2 id="結語">結語<a class="h-anchor" href="#%e7%b5%90%e8%aa%9e" aria-label="這個段落的連結"></a></h2>
<p>筆者透過 3 個主題（<a href="https://deanlin.net/blog/202210/team-workflow-project-kickoff/">專案啟動</a>、<a href="https://deanlin.net/blog/202210/team-workflow-initial-tasks/">初始任務</a>、專案執行），與讀者分享制定工作流程的重要性。</p>
<p>制定工作流程是為了讓團隊運作更為順利，所以其中的規範、格式都要與成員充分討論；在彼此有共識的狀態下，工作流程才有存在的價值，否則會變成一種負擔。</p>
<p>最後再次提醒大家，文章的流程未必適用於每個團隊，但可以做為參考方向。</p>
<hr>
]]></content:encoded>
    </item>
    <item>
      <title>讓開發團隊更好協作的方式 — 下班有約系列文</title>
      <link>https://deanlin.net/blog/202202/better-dev-team-collaboration/</link>
      <pubDate>Thu, 24 Feb 2022 13:50:10 +0800</pubDate>
      <guid>https://deanlin.net/blog/202202/better-dev-team-collaboration/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>團隊合作</category>
      <description>前面兩篇文章分享了工程師容易卡住的問題、常犯的錯誤，而這篇文章會聚焦在「協作」這個部分，提供一些方法讓開發團隊發揮更穩定的效能。</description>
      <media:content url="https://deanlin.net/blog/202202/better-dev-team-collaboration/images/better-dev-team-collaboration-og_hu_5d8a0192ac47ec41.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<p>前面兩篇文章分享了工程師容易卡住的問題、常犯的錯誤，而這篇文章會聚焦在「協作」這個部分，提供一些方法讓開發團隊發揮更穩定的效能。</p>
<p><img src="https://deanlin.net/blog/202202/better-dev-team-collaboration/images/better-dev-team-collaboration-01.webp" width="1400" height="745" alt="讓開發團隊更好協作的方式 — 下班有約系列文（圖 1）" fetchpriority="high" decoding="async"></p>
<pre tabindex="0"><code>大綱
➤ 可以一起遵守的 Coding Style
➤ 使用相同的程式碼 Format 工具
➤ 沒有明確 Git Flow 機制會發生什麼事？
➤ 制定團隊 Git Flow 的規則
</code></pre><h2 id="-可以一起遵守的-coding-style">可以一起遵守的 Coding Style<a class="h-anchor" href="#-%e5%8f%af%e4%bb%a5%e4%b8%80%e8%b5%b7%e9%81%b5%e5%ae%88%e7%9a%84-coding-style" aria-label="這個段落的連結"></a></h2>
<p>即使是有經驗的工程師，在同一個專案中也很常不小心有多種命名的風格，下面列出幾個建議：</p>
<ul>
<li><strong>變數與函式：</strong>都用小駝峰式（camelCase）的命名，ex：downloadDoc、deleteDoc。</li>
<li><strong>常數命名：</strong>會建議使用全大寫英文命名，字詞間使用下底線（_）連接，ex：VUE_APP_ROOT_API。</li>
<li><strong>少用簡寫或自己發明縮寫：</strong>就算是本人，幾個月後也會忘記自己當時創造的東西。</li>
<li><strong>不要拼錯英文單字：</strong>當程式結構越來越大，我們會透過搜尋來找答案，如果你拼錯就會造成大家的困惑。</li>
<li><strong>字串單引號、雙引號統一：</strong>儘管在 JavaScript 中兩者皆可運行，但在閱讀體驗上就會有點不舒服。</li>
</ul>
<h2 id="-使用相同的程式碼-format-工具">使用相同的程式碼 Format 工具<a class="h-anchor" href="#-%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%90%8c%e7%9a%84%e7%a8%8b%e5%bc%8f%e7%a2%bc-format-%e5%b7%a5%e5%85%b7" aria-label="這個段落的連結"></a></h2>
<p>其實上面的問題大部分可以透過「工具」來解決，但必須律定團隊使用「統一」的工具。</p>
<p>如果團隊沒有統一的工具，會導致你每次在更新專案時，明明只更新一行，但<strong>因為每個人 Format 工具不同導致在 Merge Branch 時看起來幾乎是重寫</strong>。</p>
<p>這邊推薦使用 VSCode Extensions 的 <a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode">Prettier</a>，他支援大部分程式語言的 Format；當然知名的 <a href="https://eslint.org/">ESLint</a> 也是團隊協作時的好選擇。</p>
<blockquote>
<p>不同 Format 工具的斷行字數、單引號、雙引號、結尾有沒有「;」…的習慣都不一樣，如果大家不統一，你看 diff 時會覺得很崩潰並且浪費時間。</p>
</blockquote>
<h2 id="-沒有明確-git-flow-機制會發生什麼事">沒有明確 Git Flow 機制會發生什麼事？<a class="h-anchor" href="#-%e6%b2%92%e6%9c%89%e6%98%8e%e7%a2%ba-git-flow-%e6%a9%9f%e5%88%b6%e6%9c%83%e7%99%bc%e7%94%9f%e4%bb%80%e9%ba%bc%e4%ba%8b" aria-label="這個段落的連結"></a></h2>
<p>如果沒有一套基礎簡單的規則，你可能會遇到以下障礙：</p>
<ul>
<li><strong>Deploy（部署）沒有基準</strong>：正式機、測試機要用哪個 Branch？如果每次都不一樣，那遲早都會出事。</li>
<li><strong>花很多時間在 Merge Branch（合併分支）上</strong>：如果不是從同一條 Branch 分支出去，那在 Merge 時很容易出現各種衝突需要解決。</li>
<li><strong>難以從 Branch 追蹤作業進度</strong>：有些人會只用一條 Branch 從頭做到尾，造成單純看這個分支無法理解他到底完成了哪些功能。</li>
<li><strong>無法理解的 commit 內容</strong>：每個人都有自己的 commit 風格，導致追溯歷史時很難找到節點。</li>
<li><strong>任務交接時的困擾</strong>：有些人沒有定期 push 的習慣，喜歡累積非常多的 commit 再一次 push；這樣如果他突然請假，或剛好在忙其他事情時，職務代理人並無法協助處理他的任務，甚至重工浪費時間。</li>
</ul>
<h2 id="-制定團隊-git-flow-的規則">制定團隊 Git Flow 的規則<a class="h-anchor" href="#-%e5%88%b6%e5%ae%9a%e5%9c%98%e9%9a%8a-git-flow-%e7%9a%84%e8%a6%8f%e5%89%87" aria-label="這個段落的連結"></a></h2>
<p>下面是筆者團隊在各個 Branch 的規則：</p>
<h3 class="h-nomark" id="-master">🏷️ Master<a class="h-anchor" href="#-master" aria-label="這個段落的連結"></a></h3>
<ul>
<li><strong>功能</strong>：部署到正式機的 branch</li>
<li><strong>Merge request</strong>：由資深工程師或是技術主管審核</li>
</ul>
<h3 class="h-nomark" id="-develop">🏷️ Develop<a class="h-anchor" href="#-develop" aria-label="這個段落的連結"></a></h3>
<ul>
<li><strong>功能</strong>：部署到測試機的 branch</li>
<li><strong>Merge request</strong>：由資深工程師或是技術主管審核</li>
</ul>
<h3 class="h-nomark" id="-feature">🏷️ Feature<a class="h-anchor" href="#-feature" aria-label="這個段落的連結"></a></h3>
<ul>
<li><strong>命名方式</strong>：依功能命名，如果有任務編號的話一同附上，方便日後追蹤</li>
<li><strong>基礎規則</strong>：原則上都是從 Develop 分支出去，每個 Feature 的功能盡量細分到可以在一天內完成</li>
</ul>
<h3 class="h-nomark" id="-hotfix">🏷️ Hotfix<a class="h-anchor" href="#-hotfix" aria-label="這個段落的連結"></a></h3>
<ul>
<li><strong>命名方式</strong>：依功能命名，如果有任務編號的話一同附上，方便日後追蹤</li>
<li><strong>基礎規則</strong>：原則上是為了解決正式機上面的緊急 Bug，因此通常是從 Master 分支出去；完成修改後再合併回 Master、Develop</li>
</ul>
<h3 class="h-nomark" id="-release">🏷️ Release<a class="h-anchor" href="#-release" aria-label="這個段落的連結"></a></h3>
<ul>
<li><strong>命名方式</strong>：依釋出的版本命名</li>
<li><strong>基礎規則</strong>：當有一個大版本準備部署到正式機，為了保證系統穩定性，會先從 Develop 分支 Release 的版本</li>
</ul>
<p>以及其他希望大家一起遵守的細節：</p>
<ul>
<li>完成 Feature 時要 push 一版，並通知協作夥伴確認功能。</li>
<li>如果該 Feature branch 已經 merge 回 develop，且不會再使用該 branch，就需要把它給 delete 掉，避免線上有太多分支，會不清楚哪一個才是有在作用的。</li>
<li>每天下班前至少要 push 一版，讓管理者容易掌握進度。</li>
<li>commit 可以用「新增功能、變更功能、修補 Bug」作為 title 的分類，然後將調整的內容條列式寫入 description，這樣其他人在 Code Review 時可以知道重點，範例如下：</li>
</ul>
<pre tabindex="0"><code>### title
修補 Bug：解決職員列表 issues
### description
1. 解決排序無效 bug
2. 在「異常」欄位增加是否為 null 的判斷，避免字串切割異常
3. 解決 pagination 參數沒有傳送到的問題
</code></pre><blockquote>
<p>筆者認為「簡單、易懂」為第一優先，中英文表達都可以。</p>
</blockquote>
<hr>
<blockquote class="pullquote"><p>相信還有很多可以讓開發團隊協作更愉快的工具與方法，期待大家的留言分享～</p>
</blockquote>
<p><strong>如果你對目前的職涯感到迷茫，想從不同視角檢視自己的選擇，相信《<a href="https://www.tenlong.com.tw/products/9786264142083">工程師下班有約</a>》這本書能為你帶來靈感與啟發：</strong></p>
<figure class="figure"><img src="https://deanlin.net/blog/202202/better-dev-team-collaboration/images/better-dev-team-collaboration-02.webp" width="1400" height="319" alt="林鼎淵著作《工程師下班有約：企業內訓講師帶你認清職涯真相！》" loading="lazy" decoding="async">
  <figcaption><a href="https://www.tenlong.com.tw/products/9786264142083">https://www.tenlong.com.tw/products/9786264142083</a></figcaption>
</figure>

<pre tabindex="0"><code>下班有約系列文
▋ [前端]新手工程師容易卡住的問題
▋ [前端＆後端]工程師常犯的錯誤
▋ 讓開發團隊更好協作的方式(本篇)
▋ 談談 Pair Programing
▋ 談談工程師的話語權
▋ 出社會後，新鮮人要及早知道的 5 件事
▋ 面試的性向測驗竟然準到讓人心裡發寒？
▋ 反其道而行的任務分配
▋ 現在的 Daily Scrum 真的適合團隊嗎？
▋ 用低成本也能請到好員工？資深 HR 不想告訴你的秘密！
</code></pre>]]></content:encoded>
    </item>
    <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>
