<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://cynthiachuang.github.io/atom.xml" rel="self" type="application/atom+xml" /><link href="https://cynthiachuang.github.io/" rel="alternate" type="text/html" /><updated>2025-02-21T01:32:34+00:00</updated><id>https://cynthiachuang.github.io/atom.xml</id><title type="html">辛西亞的技能樹</title><subtitle>自己整理過才是自己的</subtitle><author><name>辛西亞．Cynthia</name></author><entry><title type="html">從人工智慧到機器學習、深度學習</title><link href="https://cynthiachuang.github.io/From-Artificial-Intelligence-to-Machine-Learning-and-Deep-Learning/" rel="alternate" type="text/html" title="從人工智慧到機器學習、深度學習" /><published>2025-01-16T00:00:00+00:00</published><updated>2025-01-16T00:00:00+00:00</updated><id>https://cynthiachuang.github.io/From-Artificial-Intelligence-to-Machine-Learning-and-Deep-Learning</id><content type="html" xml:base="https://cynthiachuang.github.io/From-Artificial-Intelligence-to-Machine-Learning-and-Deep-Learning/"><![CDATA[<p>之前在整理 <a href="https://cynthiachuang.github.io/Lecture-Notes-Nvidia-GTC-2022/#s42424-deep-learning-demystified-for-the-biopharma-ecosystem">〈GTC 2022 某場演講〉</a>與<a href="https://cynthiachuang.github.io/Hiskio-Codefree-Computer-Science-2/#16-1人工智慧的巨量資料學習法">〈CodeFree｜喝一杯咖啡，輕鬆學電腦科學〉</a>時，我就有打算要整理。不過拖延症又發作，導致這篇文章一度難產 ╮(╯▽╰)╭。</p>

<p>直到最近文組的朋友問了我這個問題，我才想起這篇躺在草稿夾裡的文章，想到好久沒更新的網誌，乾脆把它拿出來寫一寫唄！…雖然距離重寫到現在發表，又過了好一段時間（掩面</p>

<!--more-->

<p class="illustration">
    <img src="https://i.imgur.com/3NNjy42.png" alt="人工智慧是一個總稱，包括機器學習和深度學習" width="300px" />
    人工智慧是一個總稱，包括機器學習和深度學習（圖片來源: <a href="https://www.prowesscorp.com/whats-the-difference-between-artificial-intelligence-ai-machine-learning-and-deep-learning/">Prowess Consulting</a>）
</p>

<p>這張圖可以幫助我們理解三者之間的關係，基本上它們是彼此的子集。<mark>人工智慧是一個總稱，包含了機器學習，而深度學習又是機器學習下的一個分支</mark>。</p>

<p><br class="big" /></p>

<p>是說，我在閱讀時，找到一句很棒的話：</p>
<div class="blockquote-center">
深度學習驅動機器學習，最後實現了人工智慧
</div>

<h2 id="人工智慧artificial-intelligenceai">人工智慧（Artificial Intelligence，AI）</h2>
<p>人工智慧（Artificial Intelligence，AI）其實並不是一個特定的技術，而是一種<mark>通過電腦來展現人類智慧</mark>的概念。這個概念發展至今日，已經廣泛應用於醫療、製造、電子產品、交通、翻譯、金融等領域。</p>

<p>依照這個概念來說，所有模擬人類智慧的技術都可以被視為 AI 的範疇，因此像是 <strong>規則式系統（Rule-based Systems）</strong> 與 <strong>專家系統（Expert Systems）</strong> 也都屬於 AI 的範疇。所以，當許多公司宣稱擁有 AI 時，可能跟你想像中的 AI 有些不同 XDDD。</p>

<p><br class="big" /></p>

<p>現如今，大家對人工智慧的想像，可能更貼近《鋼鐵人》中賈維斯的形象，甚至比它更強大——不僅能像人類一樣進行真正的思考、推理，還能實現自我學習與持續進化。像這類的技術依其智慧能力可劃分在 <strong>通用 AI（Artificial General Intelligence，AGI）</strong> 的階段。</p>

<p>然而，目前通用 AI 仍停留在科幻小說和理論研究階段，尚未真正實現。不過，去年底，據傳 OpenAI 的內部計畫 Q（Q Star）* 在某些關鍵領域取得了突破性進展，這可能標誌著向通用 AI 邁進了一步。</p>

<p class="illustration">
    <img src="https://i.imgur.com/lmHAjCD.png" alt="AI的演進" width="600px" />
    AI的演進（圖片來源: <a href="https://www.eetimes.com/a-path-to-broad-ai-5-challenges/">EE Times</a>）
</p>

<p>若說，通用 AI 是追求像人類般的全面智能，那 <strong>狹義 AI（Narrow AI）</strong> 和 <strong>廣義 AI（Broad AI）</strong>，則代表了處於進行式和未來式的兩個階段：</p>
<ol>
  <li><strong>狹義 AI（Narrow AI）</strong><br />
 這是目前發展較為成熟的 AI 系統，專注於<mark>單一工作任務</mark>，在具備充足資訊的情況下，它們的表現可以達到甚至超越人類。見的應用領域包括電腦視覺、語音識別、語言翻譯、聊天機器人…等。</li>
  <li><strong>廣義 AI（Broad AI）</strong><br />
 廣義 AI 則著眼於<mark>跨領域、多任務的工作執行</mark>，模擬人類在做決策時所需綜合考量的各種情況。這是目前學術機構和大公司積極探索的領域。</li>
</ol>

<p>即便在聊天機器人領域的領頭羊 ChatGPT，目前仍未達到真正的廣義 AI 的程度。所以，IBM 森本典繁先生在 2019 年的一篇文章中提到：</p>
<div class="blockquote-center">
我們目前在狹義 AI 和廣義 AI 之間，只到達 AI 的入口而已！
</div>

<p>在更新這篇文章時，我去問 ChatGPT 他是否覺得自己已經達到廣義 AI 的程度。它回答我，它並未達到真正的廣義 AI 的程度，但在某些方面展現了廣義 AI 的初步特徵，並給了我以下的原因：</p>

<ol>
  <li><strong>跨領域應用的能力</strong><br />
 ChatGPT 確實能夠在多個領域中回答問題，從科學、語言學到生活常識，甚至創意寫作。這表明它具有一定的跨領域知識處理能力，但這是基於大規模語料的訓練結果，而非內在理解。</li>
  <li><strong>上下文處理與適應</strong><br />
 它能記住對話上下文，調整回應風格，對使用者需求進行一定程度的適應。然而，這種適應是基於統計模型，而非真正的推理或長期學習。</li>
  <li><strong>學習與改進</strong><br />
 ChatGPT 無法在與使用者互動中實時學習，也不能主動更新知識。它的能力停留在模型訓練完成的知識點上，而廣義 AI 應具備的自主學習和持續改進特性並不存在。</li>
</ol>

<p><br class="big" /></p>

<p>思考了一下，為什麼 ChatGPT 會這樣回覆我。若從<strong>跨領域整合</strong>與<strong>持續學習</strong>兩方向來思考，它確實展現了狹義 AI的高度成熟，但仍未達到 Broad AI 的核心要求：</p>
<ol>
  <li><strong>跨領域整合</strong><br />
ChatGPT 雖然能模擬或回答跨領域的知識應用，但它這功能是基於語料的訓練結果，無法像人類一樣處理複雜、動態的多任務需求；但理想的廣義 AI 應該能做到多領域知識之間進行真正的整合。</li>
  <li><strong>推理與理解能力</strong><br />
 ChatGPT 的推理能力主要基於訓練語料的模式匹配，難以解決未見問題或生成真正原創的解答；但理想的廣義 AI 應該具備人類般的推理能力，給出創新的解決方案。</li>
</ol>

<p><br class="big" /></p>

<p>題外話，我不太確定 General AI 這個詞該怎麼翻，我看過有文件將 General 這個詞翻譯成普適、通用、一般、廣義…等，最最常見的翻譯是「廣義」一詞。但如果選擇這個翻譯，Broad AI 這個詞反而無法對應，所以我最終採用了<a href="https://event.cw.com.tw/2018ibm/article/index2/article7.html">《天下雜誌》IBM 專欄</a>中所使用的翻譯，將其分別翻譯為通用 AI、狹義 AI、廣義 AI。</p>

<h2 id="機器學習machine-learningml">機器學習（Machine Learning，ML）</h2>
<p>要讓人工智慧從從概念走向現實，機器學習扮演了至關重要的角色。它是<mark>達成人工智慧的一種方法</mark>，旨在<mark>模仿人類如何從經驗中汲取智慧</mark>。</p>

<p>可以說，機器學習是個從<mark>過往的資料和經驗中學習並找到其運行規則</mark>的過程。它通過<strong>輸入資料</strong>，並經由模型（即是演算法）進行分析和學習。通過大量數據和演算法來<strong>訓練</strong>機器，達成判斷或預測的目的。這個過程可以類比於人腦的學習過程：</p>
<p class="illustration">
    <img src="https://i.imgur.com/moxMqme.jpg" alt="機器學習的過程就是仿照人腦的學習過程" />
    機器學習的過程就是仿照人腦的學習過程（圖片來源: <a href="https://codefree.hiskio.com/courses/6">Hiskio Codefree 電腦科學</a>）
</p>

<p>與過往的規則式系統（Rule-based Systems）不同，機器學習無需手動編寫包含特定規則和邏輯的程式來進行判斷或預測；它是從大量樣本中訓練機器辨識規則（即演算法、模型），並利用這些規則進行判斷或預測。</p>

<p><br class="big" /></p>

<p>就像上班族遇到不懂的，會糾結到底是要去問人，直接得到明確答案？還是自己慢慢摸索，得出自己的經驗？在機器學習中，也是有這這樣兩種學習方式：<strong>監督式學習（Supervised Learning）</strong> 與 <strong>非監督式學習（Unsupervised Learning）</strong>，它們是根據資料是否已經標註進行分類：</p>
<ol>
  <li><strong>監督式學習</strong>：資料已經標註正確答案，機器根據這些輸入與預期輸出進行學習</li>
  <li><strong>非監督式學習</strong>：沒有標註預期輸出，機器需要從未標註的資料中探索隱藏模式。</li>
</ol>

<p>兩種方法各有優缺點，監督式學習通常效果較好，但需要大量標註資料，且標註品質會影響訓練結果。因此，後來衍生出了<strong>半監督學習（Semi-supervised Learning）</strong>。</p>

<p>除了常見的監督式和非監督式學習外，還有一種獨特的方法——<strong>強化學習（Reinforcement Learning）</strong>，它不像前兩者需要標註資料，而是通過 <strong>正向回饋（Positive Reward）</strong> 和 <strong>負向回饋（Negative Reward）</strong> 來引導機器調整行為，最終達成預期結果。</p>

<p>我在<a href="https://cynthiachuang.github.io/Machine-Learning-Foundations-Study-Notes-Mathematical-Foundations-Week3/#learning-with-different-data-label">〈【機器學習基石筆記】數學基礎 Week3〉中的 Learning with Different Data Label</a> 一文中曾介紹過這些學習方式，細節就不再贅述，需要了解的可以過去看，麻煩大家幫忙衝下點閱率了（誤</p>

<p class="illustration">
    <img src="https://i.imgur.com/3eJ3vqZ.png" alt="機器學習大致上可以分為監督式學習、非監督式學習與強化學習三類" />
    機器學習大致上可以分為監督式學習、非監督式學習與強化學習三類（圖片來源: <a href="https://ithelp.ithome.com.tw/articles/10217849">iT 邦幫忙</a>）
</p>

<p><br class="big" /></p>

<p>那麼，在實際應用中，該如何選擇最適合的機器學習模型呢？這就需要使用者根據具體問題、資料特性以及可能的挑戰，例如是否會出現過擬合（Overfitting）…等情況進行全面評估。</p>

<p>常見的模型有隨機森林、SVM、決策樹、集群、貝葉斯網路、神經網路（Neural Network，NNs）…等。其中<strong>神經網路</strong>是機器學習的一個重要分支，它模仿人腦中神經元的結構，而<mark>多層隱藏層的神經網路又稱為深度學習</mark>，是目前人工智慧發展中最為關鍵的技術。</p>

<p class="illustration">
    <img src="https://i.imgur.com/zmcAUPA.png" alt="深度神經網路或深度學習網路具有數百萬個連結在一起的人工神經元隱藏層。" />
    深度神經網路或深度學習網路具有數百萬個連結在一起的人工神經元隱藏層。（圖片來源: <a href="https://aws.amazon.com/tw/what-is/neural-network/">AWS</a>）
</p>

<h2 id="深度學習deep-learningdl">深度學習（Deep Learning,，DL）</h2>
<p>雖說機器學習為人工智慧的發展奠定了基礎，但對於處理更複雜的問題，例如影像識別或自然語言處理，傳統方法難以達到實際需求。這時，深度學習提供了一條新路徑，嘗試將需要人類智慧的複雜任務自動化。</p>

<p>深度學習是機器學習的一個重要分支，如前述，其核心是構建多層的神經網路，模仿人類大腦的神經元結構，並從海量數據中學習和提取特徵，你可以將它視為一種<mark>實現機器學習的技術</mark>，甚至可以直接將其視為先進的機器學習技術。</p>

<p><br class="big" /></p>

<p>雖然兩者的工作流程與目標一致，但在演算法的處理上略有不同。以我在 <a href="https://www.quora.com/What-is-the-difference-between-deep-learning-and-usual-machine-learning">Quora</a> 上看到的一張辨識車輛的學習流程為例：</p>

<p class="illustration">
    <img src="https://i.imgur.com/GzdqmOc.png" alt="車輛辨識在機器學習與深度學習的差異" />
     車輛辨識在機器學習與深度學習的差異 （圖片來源: <a href="https://www.quora.com/What-is-the-difference-between-deep-learning-and-usual-machine-learning">Quora</a>）
</p>

<p>在傳統機器學習中，需要進行<strong>特徵擷取（Feature Extraction）</strong>，然後將資料輸入訓練模型，最後得到預期結果。值得注意的是，所擷取的特徵都是由人類所能理解並定義，如：顏色、品牌…等，畢竟這很大機會是工程師肝出來 XDDD</p>

<p>在圖中可以看到，機器學習需要手動進行特徵擷取，而在深度學習中則省略了這一步。只需將資料輸入模型，模型將自動提取特徵並輸出結果。不同於人工擷取的特徵，深度學習所提取的特徵通常更為抽象且難以理解，這也是深度學習之所以被稱為黑盒子的原因。記得之前嘗試過將模型每一層的輸出視覺化，結果出來了一堆奇奇怪怪的幾何或線條，我都不曉得它到底是看了什麼…當然，也不排除我自己印錯了 XDDD</p>

<h2 id="小結">小結</h2>
<p class="illustration">
<img src="https://imgur.com/ML56W2V.png" alt="人工智慧發展史" />
人工智慧發展史（圖片來源: <a href="https://events.rainfocus.com/widget/nvidia/gtcspring2022/sessioncatalog/session/1642417943266001uxhK">NGC 演講</a>）
</p>

<p>雖然人工智慧這幾年火到快燒掉，但其實，從人工智慧的誕生到神經網路的發展，這並非一個全新的領域。</p>

<p>人工智慧的概念早在 1950 年代就已被提出，當時艾倫．圖靈（Alan Mathison Turing）提出了著名的「圖靈測試」，開啟了人類對機器智慧的探索。至於神經網路與用於模型訓練的反向傳播演算法（Back Propagation），則是在 1980 年代問世。儘管早期由於運算能力的限制，相關研究一度陷入低潮，但 2006 年多層神經網路訓練的突破讓這項技術以「深度學習」的姿態強勢回歸，並隨著資<strong>料蒐集效率的提升</strong>與 <strong>GPU 技術的成熟</strong>，深度學習得以迅速崛起，並逐漸成為人工智慧領域的主流方法。</p>

<div class="alert info"> 
<div class="head">補充一下</div>
如果對歷史科普有興趣，我推薦可以去看看腦洞烏托邦推出的<a href="https://youtu.be/ojnO6hrz1FE?si=elo4ND30bSnagLuB">科普影片</a>，還滿有趣的～👍
</div>

<p>近年來，人工智慧領域最火熱的寵兒——<strong>生成式人工智慧（Generative AI）</strong>，特別是 ChatGPT、DALL·E、Stable Diffusion 等應用的誕生，展現了生成式模型在文本、圖像生成等領域的強大能力，而它的基礎也是<strong>深度學習</strong>。</p>

<p>但隨著 AI 能力增強、巨型模型的出現，也帶來了倫理與法律挑戰，包括隱私問題、偏見與歧視、假資訊泛濫等，需要我們多加注意。因此目前推動人工智慧法案（AI Act），以規範 AI 的設計和使用，確保技術發展的同時符合社會利益。可解釋 AI（Explainable AI，XAI）如何讓人類瞭解人工智慧下判斷的理由。</p>

<p>然而，隨著AI能力的增強和巨型模型的出現，也帶來了諸多倫理與法律挑戰，例如隱私問題、偏見與歧視、假資訊泛濫，甚至衍生出 AI 詐騙等議題，這些都需要我們在日常生活多加注意。因此，目前各界積極推動人工智慧法案（AI Act），旨在規範 AI 的設計和使用，確保技術發展與社會利益的和諧。而可解釋 AI（Explainable AI，XAI）的興起，也讓人類能夠更清楚了解人工智慧做出判斷的依據。</p>

<h2 id="參考資料">參考資料</h2>
<ol>
  <li><a href="https://codefree.hiskio.com/courses/6">Codefree - 電腦科學（下）</a>。檢自 Hiskio (2022-10-07)。</li>
  <li>iKala Cloud (2021/11/25)。<a href="https://ikala.cloud/ml-1-ai-ml-deep-learning-intro/">人工智慧、機器學習、深度學習是什麼? – Machine Learning 教學系列 (一)</a>。檢自 技術部落格 (2022-10-07)。</li>
  <li>Michael Copeland (2016-07-29)。<a href="https://blogs.nvidia.com.tw/2016/07/29/whats-difference-artificial-intelligence-machine-learning-deep-learning-ai/">人工智慧、機器學習與深度學習間有什麼區別?</a>。檢自 NVIDIA 台灣官方部落格 (2022-10-07)。</li>
  <li>Samson Tai (2019-03-06)。<a href="https://www.ibm.com/blogs/think/hk-en/2019/03/淺談-ai人工智能發展里程/">淺談 AI人工智能發展里程</a>。檢自 Medium (2022-10-07)。</li>
  <li>阿物科技 (2016-04-19)。<a href="https://www.inside.com.tw/article/6164-detailed-annotations-of-artificial-intelligence-ai">別怕天網成真！關於人工智慧的五個詳解</a>。檢自 INSIDE (2022-10-07)。</li>
  <li>Junko Yoshida (2018-06-29)。<a href="https://www.eettaiwan.com/20180629nt01-path-to-broad-ai-challenges/">邁向廣義AI之路的5大挑戰</a>。檢自 EE Times (2022-10-07)。</li>
  <li><a href="https://event.cw.com.tw/2018ibm/article/index2/article7.html">從 AI 到量子，未來 5 年科技突破力</a>。檢自 IBM藍色觀點｜天下雜誌 (2022-10-07)。</li>
  <li><a href="https://aws.amazon.com/tw/what-is/neural-network/">什麼是神經網路？</a>。檢自 AWS (2024-01-09)。</li>
  <li>YC Liu (2020-07-19)。<a href="https://medium.com/mr-lius-murmur/ai-學習筆記-i-機器學習-vs-深度學習-98b1ce9123a3">AI 學習筆記 #1: 機器學習 vs. 深度學習</a>。檢自 YC Liu’s Notes｜Medium (2024-01-09)。</li>
  <li>Lynn (2019-03-22)。 <a href="https://www.inside.com.tw/feature/ai/9854-ai-history">從人工智慧、機器學習到深度學習，你不容錯過的人工智慧簡史</a>。檢自 INSIDE (2024-01-09)。</li>
</ol>

<h2 id="更新紀錄">更新紀錄</h2>
<details class="update_stamp">
  <summary>最後更新日期：2025-01-16</summary>
  <ul>
    <li>2025-01-16 更新：更新 ChatGPT 現況</li>
    <li>2024-01-09 完稿</li>
    <li>2021-09-14 起稿</li>
  </ul>
</details>]]></content><author><name>辛西亞．Cynthia</name></author><category term="智慧計算 › 人工智慧" /><category term="AI/ML" /><category term="煉丹常識" /><summary type="html"><![CDATA[之前在整理 〈GTC 2022 某場演講〉與〈CodeFree｜喝一杯咖啡，輕鬆學電腦科學〉時，我就有打算要整理。不過拖延症又發作，導致這篇文章一度難產 ╮(╯▽╰)╭。]]></summary></entry><entry><title type="html">CodeFree｜喝一杯咖啡，輕鬆學電腦科學 - 下</title><link href="https://cynthiachuang.github.io/Hiskio-Codefree-Computer-Science-2/" rel="alternate" type="text/html" title="CodeFree｜喝一杯咖啡，輕鬆學電腦科學 - 下" /><published>2024-01-09T00:00:00+00:00</published><updated>2024-01-09T00:00:00+00:00</updated><id>https://cynthiachuang.github.io/Hiskio-Codefree-Computer-Science-2</id><content type="html" xml:base="https://cynthiachuang.github.io/Hiskio-Codefree-Computer-Science-2/"><![CDATA[<p>今天又是喝咖啡學習系列，不過不是學程式，而是學電腦科學。筆記內容包括<a href="https://codefree.hiskio.com/courses/4">上</a>、<a href="https://codefree.hiskio.com/courses/5">中</a>、<a href="https://codefree.hiskio.com/courses/6">下</a>三門課。</p>

<p>這門課看了下內文其實就是計算機概論，有點令人懷念的一門課…想當初算二進制還算到超挫折的 XDDD 不過總感覺這篇不是在寫讀書筆記，而是重寫了一次課程？很多東西它沒提到，是我自己忽然想到其他關鍵字就一併寫進去了 XDDD</p>

<!--more-->

<p class="illustration">
	<img src="https://i.imgur.com/ibijtxL.png" alt="hiskio codefree" />
    codefree time（圖片來源: <a href="https://codefree.hiskio.com/">hiskio codefree</a>）
</p>

<h2 id="ch-9it-讓你跟陌生人之間只隔六個人">CH 9｜IT 讓你跟陌生人之間只隔六個人</h2>
<p><strong>六度分隔理論(Six Degrees of Separation)</strong> 是還滿有名的一個現象，這個現象是在說，世界上的任何人與任何人之間，最多僅隔著 6 個人。</p>

<p>不過隨著社群網路的興起，這網路直徑正在逐漸下降。根據 Facebook 2016 年的研究 <a href="https://research.facebook.com/blog/2016/2/three-and-a-half-degrees-of-separation/">〈Three and a half degrees of separation〉</a>，每個人與其他人間隔約為 4.57 人。</p>

<h3 id="9-1網站的地址ip-位址">9-1｜網站的地址：IP 位址</h3>
<p>IP 位址（Internet Protocol Address，IP Address），可譯為網際協定位址、網際網路協定位址。IP 相當於每戶人家的門牌號，在網際協定中用於<mark>標識傳送或接收資料所示用來帶代表裝置的一串數字</mark>，每個裝置的 IP 都是獨一無二的，不然郵差怎麼把信送到你家？</p>

<p>忽然想到我上次把地址填錯，最後竟然還是送達了 XDDD。不過我那個沒錯得很離譜啦，只是把 Tainan 拼成了 Taiwan 而已，我郵遞區號還是寫對的！</p>

<p><br class="big" /></p>

<p>課程這邊介紹的是 <strong>IPv4</strong>。在 IPv4 中是使用 <strong>32 位元以點區隔的十進位表示法</strong>：簡單來說，就是用 4 個 0 ~ 255 的數字來表示，類似 <code class="language-plaintext highlighter-rouge">172.217.163.36</code>。另外，含有一個正在取代 IPv4 的是 IPv6，它是使用 <strong>128 位元冒號區隔的十六進位表示法</strong>，例如：<code class="language-plaintext highlighter-rouge">2001:0DB8:02de:0000:0000:0000:0000:0e13</code>。</p>

<p>2019 年 11 月 25 日，歐洲網路協調中心宣布 IPv4 地址已告罄，而 <mark>IPv6 的使用就是用來解決 IPv4 數量不夠的問題</mark>。不過台灣分配到的 IP 還夠使用，所以大部分都還是使用 IPv4 的網路通訊協定。</p>

<p class="illustration">
	<img src="https://i.imgur.com/JIG2fRB.png" alt="IPv4 與 IPv6 的比較" />
    IPv4 與 IPv6 的比較（圖片來源: <a href="https://www.ithome.com.tw/tech/92046">iThome</a>）
</p>

<p>IP 根據用途可以分為 <strong>實體 IP（Public IP）</strong> 及 <strong>虛擬 IP（Private IP）</strong> 兩種。實體 IP，代表可在公開網路中被使用，可以用來連線，就像建築物的門牌；虛擬 IP，則是提供給區域網路使用，不過這邊的 IP 封包是出不了路由器直接連網的，這時需要 IP 分享器的 NAT 來幫忙（其實應該是先有 NAT 才有虛擬 IP 才對 XDDD）。不過在家用環境中，數據機相連的那台通常都是路由器、有線分享器與無線分享器的多合一機器。</p>

<p>虛擬 IP 最常應用於企業中，當公司內部多台電腦並用 IP 分享器連接時，會各自被分配到一個虛擬 IP。不過當公司電腦對外連出去後，對外部網路來說卻都是同一個實體 IP 位址。所以有時會發現某個網站如果鎖 IP，幾乎全辦公室都會慘叫 XDDD</p>

<p class="illustration">
	<img src="https://i.imgur.com/zlaeHle.jpg" alt="虛擬 IP 架構" />
    虛擬 IP 架構（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<p>不過實務上，我們在拜訪網站時，並不會輸入 <code class="language-plaintext highlighter-rouge">172.217.163.36</code>，而是直接輸入 <code class="language-plaintext highlighter-rouge">www.google.com</code>。這就托了<strong>網域名稱伺服器（Domain Name Server，DNS）</strong> 的福，它會轉換讓一串數字變成容易識別的英文字串。</p>

<h4 id="單元測驗">單元測驗</h4>
<ol>
  <li><strong>IP 位址就像是網站的地址。針對 IP 位置的敘述，下列何者錯誤？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />虛擬 IP 最常用於企業中，當公司內部有多台電腦並用 IP 分享器連接時，會各被分配到一個虛擬 IP，這些虛擬 IP 都是在同一個內部網路裡面</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />IP 是 Internet Protocol Address 的縮寫，意思是「網際網路協定位址」</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />網站的 IP 位址有可能重覆</li>
    </ul>
  </li>
</ol>

<h3 id="9-2網站的地標名稱網域名稱">9-2｜網站的地標名稱－網域名稱</h3>
<p>課程中有個滿有趣的比喻：<strong>IP 位址像是地址，而網域名稱像是地標名稱</strong>。就像是大家會記得台北101，但沒人會記得它的地址，<del>除了 Google</del>。</p>

<p class="illustration">
	<img src="https://i.imgur.com/AVyJNz4.jpg" alt="網域名稱組成" />
    網域名稱組成（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<p>網域名稱會由幾個部分組成的，每個部分以 <code class="language-plaintext highlighter-rouge">.</code> 做為區隔：</p>
<ol>
  <li>
    <p><strong>https（http）</strong> <br />
 <strong>通訊協定</strong>。這邊採用超文本傳輸協定（HyperText Transfer Protocol），是一種用於分布式、協作式和超媒體訊息系統的應用層協定。HTTP 是全球資訊網的通訊基礎。</p>
  </li>
  <li>
    <p><strong>www</strong> <br />
 www 是可以自行設定的主機名稱，並非註冊域名的主體，或稱子網域及次網域。最常用的主機名稱有 www 及 FTP 等，或是省略不用，它會直接轉向網域名稱。</p>

    <p>子網域的其中一種用法是來規劃網站的不同用途。比如，如果你有一個網站 <code class="language-plaintext highlighter-rouge">yoursite.com</code>，在這個網域你有兩個區塊一個專門用於購物的網站、一個是記錄開發的網誌，那麼就可以使用子網域來區分，例如：<code class="language-plaintext highlighter-rouge">store.yoursite.com</code> 與 <code class="language-plaintext highlighter-rouge">blog.yoursite.com</code>。一個網域名稱最多可設定 500 個子網域，也可以為子網域加入多個階層，如<code class="language-plaintext highlighter-rouge">info.blog.yoursite.com</code>。子網域最長可以設定 255 的字元，但若設定多階層，則每個階層只能使用 63 個字元。</p>
  </li>
  <li>
    <p><strong>104</strong><br />
 這是<strong>次級網域（Second-Level Domain, SLD）</strong>，通常是公司名稱或獨立識別度的文字，如 google、youtube、104…這個名稱會直接影響到使用者識別、搜尋引擎。</p>
  </li>
  <li>
    <p><strong>com</strong><br />
 網址的 <code class="language-plaintext highlighter-rouge">.com</code> 是屬於 <strong>頂級網域（Top-Level Domains, TLDs / Zone）</strong> 的<strong>通用頂級網域 (gTLD, Generic Top-Level Domain)</strong> ，可以標示出網站的性質。常見的有 <code class="language-plaintext highlighter-rouge">.com</code>（公司行號或營利單位）、<code class="language-plaintext highlighter-rouge">.edu</code>（學術機構或教育單位）、<code class="language-plaintext highlighter-rouge">.gov</code>（政府機關）、<code class="language-plaintext highlighter-rouge">.org</code>（財團法人組織）。</p>

    <p>一般常見的 .com / .net / .org / .edu 等結尾，都是屬於通用頂級網名，這類的域名由網際網路名稱與數字地址分配機構（IANA）管理。</p>
  </li>
  <li>
    <p><strong>tw</strong><br />
 <strong>國家頂級域名 (ccTLD, Country-Code Top-Level Domain)</strong>，也是屬於頂級網域的一種，能讓使用者能迅速辨別出網址申請機構所在的區域。通常是由區域名字縮寫組成，常見是由 ISO-3166 的代碼所組成的國家或地區名稱縮寫。</p>

    <p>但 2010 後，IANA 開始分配國際化國家頂級域名之後，就不再遵守這項限制了，除了不再侷限於 2 個字外，還能使用當地文字，例如 <code class="language-plaintext highlighter-rouge">.新加坡</code>、<code class="language-plaintext highlighter-rouge">.台灣</code>、<code class="language-plaintext highlighter-rouge">.الجزائر.</code>（阿爾及利亞）、<code class="language-plaintext highlighter-rouge">.ею</code>（歐盟）等，都屬於國家頂級域名的一種。</p>

    <p>頂級網域跟次級網域合起來就是我們前面提過的<strong>主網域</strong>（Domain）。我另外找了張網域拆得比較清楚的組成，應該會比較容易明白：</p>

    <p class="illustration">
     <img src="https://i.imgur.com/YHg8GDQ.png" alt="網域名稱組成" />
     網域名稱組成（圖片來源: <a href="https://bettywutalk.com/blog/domains/#3_xin_ding_ji_yu_ming_New_gTLD_New_Generic_Top-Level_Domain">矽谷獨角獸學院</a>）
 </p>
  </li>
</ol>

<p>如果我們要拜訪 <code class="language-plaintext highlighter-rouge">www.104.com.tw</code> 這個的網站，電腦會先去找頂級網域 <code class="language-plaintext highlighter-rouge">.tw</code> 的 DNS 伺服器找，再找到 <code class="language-plaintext highlighter-rouge">.com.tw</code> 的次級域 DNS 位置，最後由  <code class="language-plaintext highlighter-rouge">.com.tw</code> 找到 <code class="language-plaintext highlighter-rouge">www.104.com.tw</code> 的正確 IP。</p>

<h4 id="單元測驗-1">單元測驗</h4>
<ol>
  <li><strong>可別搞混 IP 位址與網域名稱搞混了！請選出關於網域名稱的正確敘述。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />IP 位址像是地標名稱，而網域名稱像是網站的地址</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />網域名稱共分為 5 個部分 - 通訊協定、主機名稱、自定義網站名稱、網站性質、申請網址國家機構</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />我們常在網址中看到的 http 就是主機名稱，也稱為子網域或次網域</li>
    </ul>
  </li>
</ol>

<h3 id="9-3網站很懂我耶">9-3｜網站很懂我耶！</h3>
<p>應該有注意過，當你搜尋某項商品後，你就會發現這個商品的廣告就會撲天蓋地的向你襲來，無論打開什麼網頁都會看到這些廣告。這是因為你被<strong>小甜餅</strong>給出賣了！</p>

<p class="illustration">
    <img src="https://i.imgur.com/tJd5itd.png" alt="Cookie" />
    Cookie（圖片來源: <a href="http://lacovadvidre.cat/es/mes-informacio-sobre-les-cookies/">lacovadvidre</a>）
</p>

<p>小甜餅的正式名稱是 Cookie(s)，它是一個「小型文字檔案」。是為了克服 HTTP 協定的無狀態性，所採用的「額外手段」之一，以維護使用者跟伺服器對談中的狀態。它會儲存一些瀏覽資訊、個人偏好、偏好語言與位置、內容定制…等資訊，通常不會存儲有關敏感訊息，例如信用卡、身分證等。</p>

<p><br class="big" /></p>

<p>根據儲存位置，Cookie 可分為<strong>記憶體 Cookie</strong> 和<strong>硬碟 Cookie</strong>。</p>
<ol>
  <li>
    <p><strong>記憶體 Cookie</strong><br />
 由瀏覽器維護，儲存在記憶體中，當瀏覽器被關閉時就消失。存在時間短暫，是臨時的 Cookie。</p>
  </li>
  <li>
    <p><strong>硬碟 Cookie</strong><br />
 當瀏覽器關閉後，尚未到期的 Cookie 會被儲存到硬碟，除非使用者手動清理或過期，否則硬碟 Cookie 不會被刪除。會長期存在，是長期的 Cookie。</p>
  </li>
</ol>

<p><br class="big" /></p>

<p>常見的 Cookie 使用情境有：</p>
<ol>
  <li>
    <p><strong>網路購物</strong> <br />
 當你在選購商品時點選了一瓶飲料，而瀏覽器會在傳送網頁時傳送一段 Cookie 給伺服器，讓伺服器知道你選購了飲料；之後如果繼續選購商品， Cookie 就會不斷追加新的資訊。最後結帳時，伺服器讀取 Cookie 就能得知所有要購買的東西品了！</p>
  </li>
  <li>
    <p><strong>自動登入</strong> <br />
 當登入時勾選「下次自動登入」，再次回到同一個網站時，無須輸入帳密就可以完成登入。這是因為上次登入時伺服器將其 Cookie 傳送到使用者的硬碟上，當下次登入時，若 Cookie 尚未過期，瀏覽器就會傳送這個帳號密碼的 Cookie，就不必再輸入了。</p>
  </li>
  <li>
    <p><strong>廣告投放</strong> <br />
 廣告商會各個網站上投放廣告，而在這些網站上，你連上的每一頁網址都會被 Cookie 所記錄，為第三方 Cookie。因此若把各網站的資料整合，就能追蹤你的網站使用行為。</p>

    <p>說到這個忽然想到，之前我們公司會在 APP 裡面埋廣告，結果過沒多久收到使用者的負評說：『你們可不可以不要一直投放色情廣告阿！』（笑翻了我 XD ）</p>
  </li>
</ol>

<h4 id="單元測驗-2">單元測驗</h4>
<ol>
  <li><strong>現在你終於知道為什麼網站總是知道你的喜好了吧！全都是因為 Cookie！下列關於 Cookie 的敘述，何者正確？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />根據儲存位置的不同，可分為控制 Cookie 和記憶體 Cookie</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />記憶體 Cookie 為非持久 Cookie，由瀏覽器維護，儲存在記憶體中，當瀏覽器被關閉時就消失了，存在時間是很短暫的</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />控制 Cookie 為持久 Cookie，若不是用戶手動清理或到了過期時間，Cookie 不會被刪除，存在時間是長期的</li>
    </ul>
  </li>
</ol>

<h3 id="9-4cookie-出賣了隱私但你可以這樣做">9-4｜Cookie 出賣了隱私，但你可以這樣做！</h3>
<p>基本上，Cookie 不是木馬也不是間諜軟體，網站不可能經由 Cookie 獲得你的其他私人資料，更沒有辦法透過 Cookie 來存取你的電腦。而在 HTTP 中對於 Cookie 的大小有 4 KB 左右的限制，因此也無法儲存複雜資料。但，一旦遭遇惡意的攻擊時，這些資料可能就無法倖免。</p>

<p>如果不想被被盜取 Cookie 可以：</p>
<ol>
  <li>定期清除 Cookie</li>
  <li>選擇關閉 Cookie</li>
</ol>

<h4 id="單元測驗-3">單元測驗</h4>
<ol>
  <li><strong>你擔心你的瀏覽行蹤完全被 Cookie 掌握嗎？其實你可以透過操作來設定 Cookie！關於 Cookie 的特性或設定，何者錯誤呢？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Cookie 能記載的資料有限，且網站不可能經由 Cookie 獲得你的 email 地址或是其他私人資料</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />網站可以透過 Cookie 來存取你的電腦</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />為避免電腦的擁有者或有心人士竊取你使用的軌跡，在離開公共電腦時，你可以清除 Cookie</li>
    </ul>
  </li>
</ol>

<h3 id="9-5小心你的資訊安全">9-5｜小心你的資訊安全</h3>
<p>資訊安全不僅限於網路安全、軟體安全，更明確的說資訊安全是要<mark>保護個人或群體的資料或者資料系統不受到非法的侵入、任意使用，甚至破壞。</mark></p>

<p><strong>CIA 三要素</strong>是資訊安全的鐵三角，任何違反三要素的行為都會降低防護強度，而對公司資產或機密造成威脅。</p>

<p class="illustration">
    <img src="https://i.imgur.com/8Fp0fFu.png" alt="CIA 三要素" />
    CIA 三要素（圖片來源: <a href="https://www.i-scoop.eu/cybersecurity/cia-confidentiality-integrity-availability-security/">i-scoop</a>）
</p>

<ol>
  <li>
    <p><strong>機密性（Confidentiality）</strong><br />
 目的在於確保資料傳遞與儲存的隱密性，<strong>任何機密資料未經授權所都不得被閱覽傳遞</strong>。機密資料包含：正在開發的技術、軍事機密、信用卡資料、醫療紀錄…等，只要是不能或不想公開的資料，就是機密資料。</p>
  </li>
  <li>
    <p><strong>完整性（Integrity）</strong><br />
 目的在於<strong>確保資料在傳輸或儲存的生命週期中，保有其正確性與一致性</strong>。因此需維持資料處理過程是安全合規的，不得遭未經授權者修改。</p>
  </li>
  <li>
    <p><strong>可用性（Availability）</strong><br />
 與機密性相反，資訊可供授權者不間斷地閱覽或存取使用，並能滿足使用需求。如停電、網路斷線或資料遺失，也都違反此原則。</p>
  </li>
</ol>

<p>機密性、完整性、可用性三要素是互相牽制的，例如：機密性高會使可用性的降低；高可用性的系統會導致機密性與完整性的降低。如何在有限資源下，讓三者保持平衡當今資訊安全的重要議題。</p>

<p class="illustration">
    <img src="https://i.imgur.com/J2LWQk6.jpg" alt="CIA 三要素" />
    CIA 三要素（圖片來源: <a href="https://medium.com/hannah-lin/從零開始學資安-什麼是資訊安全-75a7a208e8db">Hannah Lin｜Medium</a>）
</p>

<p><br class="big" /></p>

<p>另外介紹系統安全防護的三個面向（3A，AAA）：</p>

<ol>
  <li>
    <p><strong>認證（Authentication）</strong>  <br />
 <strong>識別資訊使用者的身分</strong>，並記錄資訊被誰所閱覽使用。常見方法是透過密碼、憑證方式驗證使用者身分，也可透過 OTP、指紋等方式進行識別。</p>
  </li>
  <li>
    <p><strong>授權（Authorization）</strong>  <br />
 <strong>依照實際需求授予適當權限</strong>，一般建議採最小權限原則（Least privilege，PoLP），即僅給予執行工作職能所需之最低存取權限，避免過度授權可能造成的資訊洩漏。</p>
  </li>
  <li>
    <p><strong>稽查（Accounting）</strong>  <br />
 <strong>收集使用者與系統之間互動的資料，並留下軌跡紀錄</strong>。紀錄內容包含監控（Monitoring）、報告（Reporting）與日誌(Logging)，以及稽核（Auditing）、計費（Billing）、分析（Analysis）…等資訊提供未來使用。</p>
  </li>
</ol>

<p><br class="big" /></p>

<p>最後，提供了些基本的資安意識。</p>
<ol>
  <li><strong>杜絕盜版</strong>：不接觸不在規範內的違法使用行為，可以大幅降低資安風險。</li>
  <li><strong>強化密碼</strong>：資安原始意義就是加密，不重複、擁有第二憑證等高強度的密碼絕對是必要的。</li>
  <li><strong>隱私控管</strong>：定期清除上網紀錄或 cookie，尤其使用公用電腦。</li>
  <li><strong>軟體更新</strong>：不要小看軟體更新，除了提升穩定度也可以適當防堵安全漏洞。</li>
  <li><strong>HTTPS</strong>：加密版本的 HTTP，可以為網頁瀏覽行為加上一層保障。</li>
</ol>

<h4 id="單元測驗-4">單元測驗</h4>
<ol>
  <li><strong>資安有著 CIA、3A 這幾個特性，現在就來複習一下吧！針對資安的特性，下列敘述何者錯誤？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />3A 分別是認證（Authentication）、授權（Authorization）、稽查（Accounting）</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />C 為機密性（Confidentiality），表示資訊不得向任何人揭露</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />I 為完整性（Integrity），表示資訊不得遭非經授權者更改</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />A 為可用性（Availability），表示資訊可供已授權者使用與存取</li>
    </ul>
  </li>
</ol>

<h3 id="9-6駭客到底是好是壞">9-6｜駭客到底是好是壞？</h3>
<p>這章來介紹在電影中超神秘的駭客（Hacker），在電影中他們可以劃分成正派與反派陣營，還各個能文又能武。在現實生活中，這些駭客們是不是文武雙全我不知道，但他們真的有分陣營，其中有好有壞，也有不成氣候的半調子。</p>

<p class="illustration">
    <img src="https://i.imgur.com/LFOUDFC.jpg" alt="駭客分類" />
    駭客分類（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<ol>
  <li>
    <p><strong>白帽駭客（White Hat）</strong> <br />
 又名為<strong>道德駭客</strong>。他們通常是電腦安全專業人士，會幫助企業找出系統漏洞進而修改，或幫助受害企業移除病毒；或者以個人工作者的身份發現系統漏洞來賺取獎金。但總結來說，白帽駭客的行為是合法的，因為他們在公司的許可下入侵系統。</p>
  </li>
  <li>
    <p><strong>黑帽駭客（Black Hat）</strong> <br />
 也被稱作<strong>劊客或怪客（Cracker）</strong>，是真正的網路犯罪者。會為了金錢或純粹惡意蓄意破壞、攻擊、非法入侵盜取…等。</p>
  </li>
  <li>
    <p><strong>灰帽駭客（Grey Hat）</strong> <br />
 他們是中間的灰色地帶，遊走於正邪之間。他們可能會非法入侵、散播病毒，以竊取金錢或資訊；有時會在事後通知目標企業注意漏洞，並象徵式收取協助修復系統費用；有時則是為了炫耀技術或是宣揚某目標進行攻擊。灰帽駭客通常會有是不道德和非法的行為，但他們不參與犯罪活動，與黑帽駭客專門從事犯罪活動不同。</p>
  </li>
  <li>
    <p><strong>腳本小子（Script Kiddie）</strong>  <br />
 沒有技術的劊客，算是個貶義詞。他不像真正的駭客那樣會發現系統漏洞，通常使用別人開發的程式來惡意破壞他人系統，因而稱之為腳本小子。</p>
  </li>
</ol>

<p><br class="big" /></p>

<p>除了上述的幾個分類外，我還聽過紅帽，知名組織匿名者（Anonymous）記憶中就屬於紅帽。會說記憶中是因為我現在找不到資料出處，不過真的有紅帽這個分類啦，雖然不算主流分類。</p>

<ol>
  <li>
    <p><strong>紅帽駭客（Red Hat）</strong> <br />
 從文字敘述看來紅帽駭客仍然是屬於白帽或灰帽範疇的，或者更偏向灰帽！？</p>

    <p>他們也會像白帽一樣制止黑帽的行動，但卻是採用上載病毒、阻斷服務攻擊（DoS attack）等進攻的方法，以入侵並關閉對方的電腦，也因有手段較為激進，有資料將其稱為激進駭客（Hacktivism）。更多時候他們會利用攻擊來表達政治、意識型態、社會或宗教訊息、或是宣揚某些目的（例如宣傳資訊自由、反戰申明），但這些目的通常都是不是金錢或個人利益。</p>

    <p>著名的紅帽有維基解密（WikiLeaks）和匿名者。</p>
  </li>
  <li>
    <p><strong>藍帽駭客（Blue Hat）</strong><br />
 這是我在查資料時看到的，不過在不同的資料中我看到了不同的定義。</p>

    <p>有一說他們是報復者，僅入侵激怒他們的對象，除非被招惹，否則不會主動攻擊他人，感覺上比較偏向灰帽；另一說則是，軟體公司會將安全性測試委外給外部的藍帽駭客執行，以在軟體發布之前，找軟體的安全性漏洞，若從這個角度看來，他們比較偏向白帽。</p>
  </li>
  <li>
    <p><strong>綠帽駭客（Green Hat）</strong><br />
 這個是個有趣的抬頭，簡單來說這是他們是駭客中的新人，不過可能是那種白目新人，問題多到被其他駭客翻眼的那種。不過總體來說算是個熱衷學習、聽命而為的駭客。</p>
  </li>
</ol>

<p>是說，我在查資料的時候注意到，中國那邊將駭客（Hacker）稱為黑客、將劊客（Cracker）稱為駭客。找資料的時候稍微注意一下。</p>

<h4 id="單元測驗-5">單元測驗</h4>
<ol>
  <li><strong>這個章節是不是打破你對駭客的既定印象呢？你還記得每一種駭客的特性嗎？請你選出錯誤的敘述喔！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />白帽駭客的行為是為了找出系統漏洞進而修改</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />灰帽駭客通常是電腦安全專業人士</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />黑帽駭客的行為是蓄意破壞或攻擊，也是真正的網路犯罪者</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />腳本小子是沒有技術的劊客</li>
    </ul>
  </li>
</ol>

<h2 id="ch-10程式語言中有社會階級嗎">CH 10｜程式語言中有社會階級嗎？</h2>
<p>程式語言之中也有好壞優劣之分？是沒有，但有鄙視鏈，這是個人人都鄙視 PHP 的世界 XDDD</p>

<p class="illustration">
    <img src="https://i.imgur.com/EEs4SSE.png" alt="駭客分類" />
    人人鄙視 PHP（圖片來源: <a href="https://blog.csdn.net/qq470603823/article/details/122204409">Python导师大白的博客｜CSDN博客</a>）
</p>

<h3 id="10-1低階語言low-level-language">10-1｜低階語言（Low-level language）</h3>
<p>高低階語言指的不是程式語言的優劣，而是以<strong>易讀性</strong>做為區分依據。高階語言接近於人類使用的語言，也越容易學習，但執行效率比低階語言差；反之，低階語言較接近電腦執行的動作，執行效率高，但不易學習。</p>

<p class="illustration">
    <img src="https://i.imgur.com/U3omHfK.jpg" alt="高低階語言差別" />
    高低階語言差別（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<p>這章節先介紹<strong>低階語言</strong>。一般來說，低階語言與電腦硬體相依行高，具備<strong>機器依存（Machine Dependent）</strong>、<strong>可攜性（Portability）低</strong>的特性。舉例來說，在 ASUS 上能執行的程式，通常不能在 ACER 的執行，必須經過修改才能在不同電腦正確執行。因它與硬體運作的密切關係，所以設備商多用低階語言來開發設備的驅動程式。</p>

<p>而常見的低階語言有「機器語言」及「組合語言」：</p>

<ol>
  <li>
    <p><strong>機器語言（Machine Language）</strong><br />
 機器語言是以<strong>二進制</strong>，也就是 0 和 1 與電腦直接溝通，不需經過任何翻譯便可以執行，且佔用<strong>記憶體少</strong>，所以<strong>執行速度時間最短</strong>。<mark>它也是電腦唯一懂的語言</mark>。</p>

    <p>但因整份程式碼只用 0 和 1 兩個數字來撰寫，所以撰寫程式碼程式時需要強記每個指令對應的機器碼，難學難懂，且不易發現除錯。</p>

    <p class="illustration">
     <img src="https://i.imgur.com/Ch5zydL.png" alt="二整數相加的機器語言碼" />
     二整數相加的機器語言碼（圖片來源: <a href="https://shopee.tw/【欣明】Foundations-of-computer-science-2e-計算機概論-原文書-i.66892677.8437790606">《計算機概論 2/e》</a>）
 </p>
  </li>
  <li>
    <p><strong>組合語言（Assembly language）</strong><br />
 因二進制符號的難讀難寫，因此衍生出較接近人類符號的助憶碼來取代機器語言，方便撰寫與除錯。但即便如此還是超級難寫…之前寫個加法器的作業就搞掉我快一週時間…。</p>

    <p class="illustration">
     <img src="https://i.imgur.com/PCgqOSW.png" alt="二整數相加的組合語言程式碼" />
     二整數相加的組合語言程式碼（圖片來源: <a href="https://shopee.tw/【欣明】Foundations-of-computer-science-2e-計算機概論-原文書-i.66892677.8437790606">《計算機概論 2/e》</a>）
 </p>

    <p>此外組合語言無法電腦直接溝通，因此必須通過<strong>組譯器</strong>（Assembler）將助憶碼轉譯成為機器碼。</p>

    <p class="illustration">
 <img src="https://i.imgur.com/Z6x3mB5.jpg" alt="組合語言需通過組譯器轉譯" />
 組合語言需通過組譯器轉譯（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
 </p>
  </li>
</ol>

<h4 id="單元測驗-6">單元測驗</h4>
<ol>
  <li><strong>低階語言可不是比高階語言低下的語言喔！請從選項中選出關於低階語言的正確敘述吧！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />低階語言又分為機器語言、組合語言</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />低階語言與高階語言相比，較貼近人類使用的語言，因此較容易理解</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />相較於高階語言，低階語言在程式撰寫、維護方面都較為容易</li>
    </ul>
  </li>
</ol>

<h3 id="10-2高階語言high-level-language">10-2｜高階語言（High-level language）</h3>
<p>相較低階語言，高階語言會<strong>更接近人類英文語法</strong>，因此容易學習也易於維護；此外高階語言不受電腦的限制，可使用在不同的電腦系統執行，<strong>可攜性高</strong>，…當然前提是你寫的好，不然還是得改程式。</p>

<p>而高階語言也具組合語言的特徵，一樣必須透過<strong>直譯或編譯</strong>將高階語言轉譯成機器語言。也因為這樣的轉譯處理，執行效率會比低階語言差。</p>

<p>高階語言主要分為「程序導向語言」及「物件導向語言」：</p>

<ol>
  <li>
    <p><strong>程序導向語言（Procedure-Oriented Programming，POP）</strong><br />
 指的是一般結構化的高階程式語言，這些程式語言都是<strong>依照程式敘述的「先後指令及邏輯順序」</strong>，一步一步向下執行。</p>

    <p>常見的程序導向語言有 Basic、Fortran、Cobol 及 C 語言..等。</p>
  </li>
  <li>
    <p><strong>物件導向語言（Object-Oriented Programming，OOP）</strong><br />
 而物件導向語言則是先設計類別與物件，再利用多個物件組合出程式。物件導向語言具備 3 大特性：</p>
    <ol>
      <li><strong>封裝（Encapsulation）</strong><br />
將特定功能的處理程序及資料包裝在物件裡面，使用者不需要了解內部設計就可以使用。</li>
      <li><strong>繼承（Inheritance）</strong><br />
新類別物件可以承襲既有類別的功能及屬性，可以省去撰寫相同程式碼的時間。</li>
      <li><strong>多型（Polymorphism）</strong> <br />
不同物件對於同樣的事件，可以有不同的表示法。</li>
    </ol>

    <p>目前較知名且流行的程式語言，大多都是物件導向語言，像是 Python、C++、Objective-C、Swift、Java、Ruby 及 PHP 等。</p>
  </li>
</ol>

<p class="illustration">
    <img src="https://i.imgur.com/XqUi0yL.jpg" alt="機器語言、組合語言與高階語言的比較" />
    機器語言、組合語言與高階語言的比較（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<h4 id="單元測驗-7">單元測驗</h4>
<ol>
  <li><strong>可別搞混低階語言、高階語言的特性了喔！請問關於「高階語言」的敘述，何者錯誤？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />高階語言又分為「程序導向語言」及「物件導向語言」</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />程序導向語言是依照程式敘述的「先後順序及流程」來告知電腦需要完成什麼工作及它的流程，而 Python、Java 都屬於此種語言</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />高階語言的執行速度較低階語言慢</li>
    </ul>
  </li>
</ol>

<h3 id="10-3高階語言的內建翻譯機">10-3｜高階語言的內建翻譯機</h3>
<p>前面提過，機器語言是電腦唯一懂的語言，連同為低階語言的組合語言都需透過組譯器將其轉譯成機器語言，而高階語言更是此。在標題中所提到的內建翻譯機，指得就是前面所提過的<strong>直譯</strong>、<strong>編譯</strong>以及<strong>即時編譯</strong>。</p>

<ol>
  <li>
    <p><strong>編譯語言（Compiled language）</strong></p>

    <p class="illustration">
 <img src="https://i.imgur.com/PDAhI9u.jpg" alt="編譯流程" />
 編譯流程（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
 </p>

    <p>這種程式語言，會在程式執行前先透過編譯器（compiler）將程式碼編譯成機器語言（machine language）。而這些機器語言會再透過連結器（linker）將一個或多個目的檔（.obj）與靜態函式庫（.lib）連結，產生可執行檔（.exe）。最終要執行程式時，只需要透過載入器（loader）將可執行檔載入記憶體，並與動態函式庫（.dll）連結，不需重新翻譯。</p>

    <p>編譯式語言多半以 <strong>靜態語言（static language）</strong> 為主，如：C、C++、bjective-C、Visual Basic …等等。它們會事先定義的型別、型別檢查，能夠在程式編譯時期檢查中型別錯誤。此語言的優點因已經先預先編譯，因此具備較高的執行速度，反之程式語法繁瑣、彈性不足，因此在執行前只能出檢查的簡單錯誤，程式開發、除錯速度會較慢。</p>
  </li>
  <li>
    <p><strong>直譯語言（Interpreted language）</strong></p>

    <p class="illustration">
 <img src="https://imgur.com/rgNeUZd.jpg" alt="直譯流程" />
 直譯流程（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
 </p>

    <p>不同於編譯語言，直譯語言在執行時會一行一行的動態將程式碼直譯成機器語言；直譯器在此擔任的角色就像一位「中間人」，它會邊轉譯邊執行。直譯語言多半以<strong>動態語言</strong>為主，包含：JavaScript、Python、Ruby…等等，具有靈活的型別處理，動態生成與程式彈性，但執行速度會比編譯式語言要慢一些。</p>

    <p>使用直譯器的好處是，它不需要在每次程式更新後重新編譯整個程式，程式開發與除錯速度比較快，較適合新手。而缺點在於動態語言的型別錯誤要到執行時期才會呈現出來，效能較不理想。此外不同於編譯語言的可執行檔可獨立執行；直譯語言則是必須依賴一個執行環境，語言可用的功能由這個執行環境提供，例如 JavaScript 只能使用瀏覽器提供的功能、Python 必須安裝相關 Package。</p>

    <p class="illustration">
 <img src="https://i.imgur.com/3VfMp0x.png" alt="編譯與直譯語言比較" />
 編譯與直譯語言比較（圖片來源: <a href="https://cg2010studio.com/2021/01/25/圖解-編譯-vs-直譯/">逍遙文工作室</a>）
 </p>
  </li>
  <li>
    <p><strong>即時編譯（just-in-time compilation，JIT）</strong></p>

    <p class="illustration">
 <img src="https://i.imgur.com/Q9r28tA.jpg" alt="即時編譯" />
 即時編譯（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
 </p>

    <p>為了改善編譯語言以及直譯語言的缺點，因而發展出即時編譯的技術，混合了兩者的優點。如同編譯語言，會一句一句編譯原始碼，但翻譯過的程式碼會快取起來成為中介碼（Bytecode）。到執行期時，再將中介碼直譯，之後執行。使用即時編譯技術的語言會比純編譯語言來的慢一些，但是卻又擁有直譯語言的特性。此類語言的代表語言有 Java、C#。</p>
  </li>
</ol>

<h4 id="單元測驗-8">單元測驗</h4>
<ol>
  <li><strong>高階語言的翻譯機分為「編譯」、「直譯」、「即時編譯」，下列關於其敘述，何者錯誤？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />編譯語言有 C、C++ 等，優點是有高效能的執行速度，但缺點是程式語法繁瑣、彈性不足，也只能檢查出執行前的簡單錯誤</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />直譯式語言有 Objective-C，其語法簡潔且有較高的彈性，且在初期嘗試的階段可以立即執行並除錯</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />即時編譯是為了改善編譯語言及直譯語言的缺點，所以其混合了兩者的優點</li>
    </ul>
  </li>
</ol>

<h2 id="ch-11成為軟體工程師第一步選擇一個語言並練熟">CH 11｜成為軟體工程師第一步：選擇一個語言並練熟</h2>
<p>這個章節是從學習目標分析挑選的入門語言。</p>

<p class="illustration">
<img src="https://i.imgur.com/JczesKA.png" alt="程式語言合集雲" />
</p>

<h3 id="11-1初學者可以從網頁開發開始">11-1｜初學者可以從網頁開發開始</h3>
<p>沒啥特定目標的話，可以考慮從開發網頁開始，因為相較其他程式，網頁不但能立即看到成果，更能直接開始使用；如果再搭配線上編輯器，更可以即時看到效果。對於初學者來說，可以即時看到成果，能得到較高成就感。</p>

<p>其他原因如<strong>簡單易懂，資源龐大</strong>，在網路上，網頁學習相關資源既多又廣，可以說整個網路世界都是你的老師。</p>
<ul>
  <li><strong>相關工具</strong>
    <ul>
      <li><a href="https://www.w3schools.com/">w3schools</a>：網頁開發的字典</li>
      <li><a href="https://coolors.co/">coolors</a>：網頁設計的調色盤/配色寶典</li>
      <li><a href="https://www.awwwards.com/">awwwards</a>：各種免費的現成優秀案例可以</li>
    </ul>
  </li>
  <li><strong>線上課程網站</strong>
    <ul>
      <li><a href="https://zh-tw.coursera.org/">Coursera</a></li>
      <li><a href="https://www.udemy.com/?utm=3ba75b10bfa8ef986d88743c19573aab&amp;track=1&amp;pt=2">Udemy</a></li>
      <li><a href="https://hahow.in/">Hahow</a></li>
      <li><a href="https://www.yottau.com.tw/home">Yotta</a></li>
      <li><a href="https://www.theodinproject.com/">The Odin Project</a></li>
      <li>程式相關社團，如：<a href="https://www.hexschool.com/?utm_source=google&amp;utm_medium=ads&amp;utm_campaign=hexschool-course-web-searchads220425&amp;gclid=Cj0KCQjwpeaYBhDXARIsAEzItbE39xzr7wFi2HjcR6OBgnv6og2-Gv_eJB7z8aojYe7-nivC0iNUQ50aAj3KEALw_wcB">六角學院</a></li>
    </ul>
  </li>
  <li><strong>線上編譯器</strong>
    <ul>
      <li><a href="https://codepen.io/">CodePen</a></li>
      <li><a href="https://jsfiddle.net/">JSFiddle</a></li>
    </ul>
  </li>
</ul>

<p><br class="big" /></p>

<p>嗚，課程中還有稍微提了下網頁三巨頭 － HTML、CSS、JavaScript，不過我這邊就不提了，有需要的話去看看 <a href="https://cynthiachuang.github.io/Hiskio-Codefree-HTML">〈CodeFree｜喝一杯咖啡，輕鬆學 HTML〉</a>這篇。</p>

<h4 id="單元測驗-9">單元測驗</h4>
<ol>
  <li>如果你想學程式，但還沒有方向，那麼建議你可以從網頁開始。關於「網頁三巨頭」－HTML、CSS、JavaScript 的敘述何者錯誤？
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />HTML 負責管理使用者的操作行為</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />CSS 負責改變網頁外觀</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />JavaScript 負責網頁的動態效果</li>
    </ul>
  </li>
</ol>

<h3 id="11-2網頁通通交給我">11-2｜網頁通通交給我！</h3>
<p>這邊介紹的是除了 HTML 與 CSS 外的語言。</p>

<ol>
  <li><strong>JavaScript</strong>
    <p class="illustration">
 <img src="https://imgur.com/fcO9N7r.png" alt="JavaScript" />
 JavaScript（圖片來源: <a href="https://papan01.com/archives/2020-01-01-you-dont-know-js-yet-1">Papan01's Blog</a>）
 </p>

    <p>JavaScript 與 HTML 及 CSS 並稱為網頁前端的三大巨頭，主要是網頁前端的程式語言，負責決定網頁與使用者的互動及瀏覽器的行為。除應用於網頁前端外，也會用後端的資料庫系統。</p>

    <p>JavaScript 屬於物件導向及直譯式語言，對於新手而言上手較為容易，雖然…我學的第一門語言不是這個，這好像是我第七還八個學得語言！？</p>

    <p>相關學習資源有 <a href="https://developer.mozilla.org/zh-TW/docs/Learn/JavaScript">MDN的JS手冊</a> 與 <a href="https://www.w3schools.com/js/default.asp">w3schools</a>。</p>
  </li>
  <li><strong>Go（又稱 Golang）</strong>
    <p class="illustration">
 <img src="https://imgur.com/KzbF7OA.png" alt="Golang" />
 Golang（圖片來源: <a href="https://www.kevinwu0904.top/blogs/golang-error/">极客熊生</a>）
 </p>

    <p>Golang 是由 Google 所開發出來的程式語言，以語法靈活、簡潔、清晰、高效為特徵，最特別的是它有垃圾回收功能。</p>

    <p>Golang 常應用伺服器端，用來開發大型軟體；除此之外，也廣泛應用在網路上，Google、Facebook、騰訊及百度等，都是 Go 的使用者。這個語言還滿容易學習的，雖然我沒學完 XDDD，學到一半跑去學前端 Vue。</p>

    <p>相關學習資源有 <a href="http://www.golang-book.com/books/intro">Go技術手冊</a> 與 <a href="https://tour.golang.org/welcome/1">Go練功好所在</a>。</p>
  </li>
  <li><strong>PHP</strong>
    <p class="illustration">
 <img src="https://imgur.com/97CkgB7.png" alt="PHP" />
 PHP（圖片來源: <a href="https://laravel-news.com/php-releases-on-hold-for-two-weeks">Laravel News</a>）
 </p>

    <p>對，就是人人鄙視、位於鄙視鏈最末端的 PHP XDDD</p>

    <p>PHP 多用在網頁後端開發，對新手來說上手快，但因沒有清晰的設計哲學而遭人詬病，且地雷較多，讓人又愛又恨 XDDD 話雖如此，在後端語言蓬勃崛起之際，PHP 仍佔穩市場的第一，諸如：Facebook、 WordPress 與市面上超過 27 % 的部落格（CMS）也是以 PHP 為架構。</p>

    <p>相關學習資源有 <a href="http://www.imooc.com/learn/54">PHP慕課網</a>。</p>

    <p class="illustration">
 <img src="https://i.imgur.com/NHnWQ0D.png" alt="即時更新的後端排名" />
 即時更新的後端排名（圖片來源: <a href="https://w3techs.com/technologies/overview/programming_language/all">w3techs</a>）
 </p>
  </li>
  <li><strong>Ruby</strong>
    <p class="illustration">
 <img src="https://imgur.com/kpQbWY9.png" alt="Ruby" />
 Ruby（圖片來源: <a href="https://www.geeksforgeeks.org/interesting-facts-about-ruby-programming-language/">GeeksforGeeks</a>）
 </p>

    <p>Ruby 是個靈巧且方便又實用的程式語言，而專攻網頁後端 Ruby on Rails 正是 Ruby 爆發成長的催化劑。使用 Ruby on rails 的著名例子有 Github、Airbnb…等。</p>

    <p>相關學習資源有 <a href="http://lrthw.github.io/">笨方法學Ruby</a>。</p>
  </li>
</ol>

<h4 id="單元測驗-10">單元測驗</h4>
<ol>
  <li><strong>想必你應該了解哪些是常見的製作網站的程式語言了吧！請選出下列不是常用來製作網頁的語言喔！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Swift</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />JavaScript</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />PHP</li>
    </ul>
  </li>
</ol>

<h3 id="11-3想學-c-語言請找我">11-3｜想學 C 語言請找我！</h3>
<p>必須說 C 語言幾乎是所有語言的實現基礎，如果精通了，再去學其他的語言也很容易上手，這也是資工系第一個學會的語言。</p>

<p class="illustration">
    <img src="https://i.imgur.com/HDwg1qB.jpg" alt="C語言家族" />
    C語言家族（圖片來源: <a href="https://www.pcschool.com.tw/blog/it/c-cplusplus-csharp">巨匠電腦</a>）
</p>

<ol>
  <li>
    <p><strong>C 語言</strong><br />
 C 語言是非常強大且重要的程式語言，其編碼方式和邏輯運影響了後來的眾多程式語言，例如 C++、C#、Objective-C、Java、JavaScript…等。因此有人說：「學程式就從 C 語言開始」，從它開始學習可以打好基礎，並使其它程式語言的學習會更輕鬆！</p>

    <p>它最常被用在作業系統的編譯器中，擅長處理低階語言，例如 Microsoft Windows、macOS、Linux、Unix 等。</p>

    <p>相關學習資源有 <a href="https://openhome.cc/Gossip/CGossip/index.html">C語言技術</a>、<a href="http://dhcp.tcgs.tc.edu.tw/c/index.htm">美麗C世界</a>。</p>
  </li>
  <li>
    <p><strong>C++</strong><br />
 C++ 和 C 語言一樣都是我們資工系必修課，它承襲 C 語言的優點及特性，並導入了 C 語言所沒有的物件導向特性。C++ 可用於軟體開發、搜尋引擎及操作系統上，常見的 Office 系列軟體與 Google 就是以 C++ 撰而寫成的。</p>

    <p>相關學習資源有 <a href="http://ocw.aca.ntu.edu.tw/ntu-ocw/index.php/ocw/cou/101S112">C++台大開放式課程</a>、<a href="https://codingsimplifylife.blogspot.com/2016/04/c.html">給新手的C++練習</a>。</p>
  </li>
  <li>
    <p><strong>C# （發音為 C sharp）</strong><br />
 C# 則是微軟開發的程式語言，採用全物件導向設計的高階語言。C# 多用於開發網頁、服務平台及 Windows 應用上，如 Evernote。除此之外，C# 還能夠在 Unity 裡面寫遊戲！</p>

    <p>相關學習資源有 <a href="https://www.microsoft.com/net/tutorials/csharp/getting-started">微軟C#學習</a>。</p>
  </li>
</ol>

<h4 id="單元測驗-11">單元測驗</h4>
<ol>
  <li><strong>你掌握 C 語言這個大家族的特性了嗎？請選出錯誤的敘述喔！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />C ++ 語言是低階語言</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />C 最常使用在作業系統的編譯器中，它擅長處理低階語言</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />C# 多用於開發網頁</li>
    </ul>
  </li>
</ol>

<h3 id="11-4寫-app-選我就對了">11-4｜寫 APP 選我就對了！</h3>
<p>基本上分成兩大支派 - Android 跟 IPhone 系列，不同的開發方向會選擇不同的程式語言。</p>

<p class="illustration">
	<img src="https://i.imgur.com/uAXfZdj.png?1" alt="Android vs Mac" />
    Android vs Mac（圖片來源: <a href="https://news.xfastest.com/apple/96118/ios-android/">XFastest News</a>）
</p>

<ol>
  <li>
    <p><strong>Objective-C</strong><br />
 Objective-C 是 C 語言家族的延伸，也是物件導向的程式語言。</p>

    <p>Objective-C 在實務上就是用來寫 IOS 和 Mac 應用程式的程式語言，不太適合做為通用型語言來學。如果真要學習程式設計，不建議從 Objective-C 入手，建議先學過一門通用型語言後再來學習，除非真要專門開發 Mac 相關程式。但若要針對 Mac 開發，我會建議先學 Swift。</p>

    <p>相關學習資源有 <a href="https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html">Objective-C官方文件</a>。</p>
  </li>
  <li>
    <p><strong>Swift</strong><br />
 Swift 也是由 Apple 發布的，根據 Apple 聲稱 Swift 的效能優於 Objective-C，並具備快速、現代、安全及互動特點，且相較於 Objective-C 它的語法清晰度高，也更加簡單，更多<a href="https://www.pcschool.com.tw/blog/it/ios-app-engineer">學習Swift的理由</a>。</p>

    <p>目前 Apple 有意讓 Swift 和 Objective-C 共存於公司的作業系統上。因我不開發 Mac 不太確定它的開發現況，但根據課程所說，目前的 iOS APP 仍多以 Objective-C 開發，且工作職缺仍以 Objective-C 為主；不過就看到一些排名與報導，Swift 的排名似乎在 Objective-C 之上？</p>

    <p>相關學習資源有 <a href="https://numbbbbb.gitbooks.io/-the-swift-programming-language-/">Swift技術手冊</a>。</p>
  </li>
  <li>
    <p><strong>Java</strong><br />
 Java 好像是我學的第三個語言？它屬於即時編譯語言，並具備跨平台及物件導向的特性，是一個應用廣泛的程式語言。它可以用來開發 Andorid 的 APP、跨平台的桌面應用程式及遊戲開發，知名的案例有 Gmail 及 Minecraft。</p>

    <p>相關學習資源有 <a href="https://caterpillar.gitbooks.io/javase6tutorial/content/c1.html">Java技術手冊</a> 與 <a href="https://openhome.cc/Gossip/Java/">Java語言技術</a>。</p>
  </li>
</ol>

<h4 id="單元測驗-12">單元測驗</h4>
<ol>
  <li><strong>可以製作 APP 的程式語言是不是比你想像中的多呢？針對製作 APP 常用的程式語言，請選出錯誤的敘述。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Swift、Objective-C 都是常用來開發 iOS APP 的程式語言</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Objective-C 也是程序導向語言的程式語言</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Objective-C 只能用來開發 Apple 相關產品</li>
    </ul>
  </li>
</ol>

<h3 id="11-5資料分析請找我">11-5｜資料分析請找我！</h3>
<ol>
  <li>
    <p><strong>R</strong><br />
 R 是資料科學界的巨星，市佔率高達 61%。它簡單易上手，可以將複雜的資料做出數據分析、統計和圖形模型…等資料視覺化呈現。</p>

    <p>相關學習資源有 <a href="https://liao961120.github.io/2018/01/31/RlearningPath.html">R的學習歷程</a>。</p>
  </li>
  <li>
    <p><strong>Python</strong><br />
 Python 是近年來最流行的程式語言，還被譽為「最容易學習的程式語言」。Python 除了廣為人知的資料分析外，還能夠應用於網頁、遊戲及應用程式開發。Instagram、Youtube、Spotify 都是用 Python 所寫的；不過要我說最熱門的用法莫過於機器學習。</p>

    <p>若是沒有明確目標的初學者，也可以將 Python 列入第一考量，它的易懂性高，能快速入門！相關學習資源有 <a href="http://www.runoob.com/python/python-tutorial.html">Python基礎教程</a> 與 <a href="https://pala.tw/begin-to-learn-python/#resources">Python新手學習</a>。</p>
  </li>
</ol>

<p class="illustration">
	<img src="https://i.imgur.com/V4WLoex.png" alt="Python 與 R 語言比較" />
    Python 與 R 語言比較（圖片來源: <a href="https://medium.com/marketingdatascience/python與r語言-行銷資料科學家必備技能之一-40878e0a5de9">Marketingdatascience｜Medium</a>）
</p>

<h4 id="單元測驗-13">單元測驗</h4>
<ol>
  <li><strong>原來分析資料不只可以用 Excel！針對常見的資料分析語言，請選出正確的敘述。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Python、R 都是常用來分析資料的程式語言</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Swift 是最近竄起的分析資料的程式語言，可以用來做出數據分析、統計和圖形模型</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />JavaScript 不只可以應用於資料分析，還能用於網頁、遊戲及應用程式開發</li>
    </ul>
  </li>
</ol>

<h3 id="11-6如果你還不知道要選什麼或許你可以參考這篇">11-6｜如果你還不知道要選什麼，或許你可以參考這篇</h3>
<p>從前面看下來可以發現程式語言的面向不盡相同，這邊將面向大致分成了五大類：<strong>網頁（Web）</strong>、<strong>行動裝置（Mobile）</strong>、<strong>電腦（PC）</strong>、<strong>積體電路（IC）</strong>及<strong>資料分析（Data Analytics）</strong>，並依面向整理出相關的語言建議：</p>

<p class="illustration">
    <img src="https://i.imgur.com/yTq4GWT.jpg" alt="即時編譯" />
    即時編譯（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<p>如果完全沒目標，只是想寫寫看程式，會見從從 Python 或是網頁前端開始入手；如果要專業學習，可以考慮從 C/C++ 開始打好基礎。另外課中推薦了一篇文章以供參考：<a href="https://blog.hiskio.com/the-problems-for-freshman-of-coding/">〈新手學程式－我該學哪種語言？新手常見毛病我中招了嗎？〉</a></p>

<h4 id="單元測驗-14">單元測驗</h4>
<ol>
  <li><strong>認識那麼多程式語言，你是不是快搞混了呢？現在就讓我們來釐清一下！請選出正確的敘述。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />PHP 除了可以開發網站，也可以用來分析數據</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Java 應用面向廣泛，可以開發網站、APP，也可以開發桌面應用程式</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />JavaScript 應用面向也非常廣泛，可以開發網站、APP還能分析數據</li>
    </ul>
  </li>
</ol>

<h2 id="ch-12程式技術放眼未來">CH 12｜程式技術，放眼未來</h2>
<p>這個章節有點雜，從前端談到了 APP。</p>

<h3 id="12-1cms-跟-cvs-一樣好方便">12-1｜CMS 跟 CVS 一樣好方便</h3>
<p>內容管理系統（Content Management System，CMS），是一種網站<strong>後台管理系統</strong>，會將網站內的資訊組織並加以整合。</p>

<p>CMS 的使用更偏向管理者，而非開發者。它通常會提供一特定網址，使用者毋需撰寫任何程式，僅需登入管理網站，並準備好欲發布的文字與圖片就能把資料更新到網站。這項技術可使使用者將精力專注在內容上，著名的 WordPress 其本質上就是一款內容管理系統。</p>

<p>一般來說內容管理系統會具備下列優點：</p>
<ol>
  <li><strong>有效管理文章</strong> <br />
 通常有個視覺化界面的後台，讓使用者可以更輕鬆的利用套件來完成，不需要時也能將它關閉。</li>
  <li><strong>輕鬆更新外觀</strong><br />
 通常是外觀與內容分離的模式，就像紙娃娃一樣，可以很能容易地為它換上新衣服。</li>
  <li><strong>活躍社群支援</strong><br />
 是開源程式碼，當使用者越多時，便擁有越多的相關程式可以使用，更不用害怕委託的工程師跑了或公司倒了！</li>
</ol>

<p class="illustration">
    <img src="https://i.imgur.com/aDShZHU.jpg" alt="CMS" />
    CMS（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<h4 id="單元測驗-15">單元測驗</h4>
<ol>
  <li><strong>想要迅速架設網站，記得先搞懂 CMS！下列哪些不是 CMS 的特性呢？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />中文為內容管理系統，是一種網站後台管理系統，會將網站內的資訊組織並加以整合</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />通常有一個後台可以登入，只要利用瀏覽器便能輕鬆編輯網站，但需要撰寫程式語言</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />CMS 是開源程式碼，當使用者越多時，你便擁有越多的相關程式可以使用</li>
    </ul>
  </li>
</ol>

<h3 id="12-2熱門的-3-大-cms">12-2｜熱門的 3 大 CMS</h3>
<p>承前節，這邊介紹 3 個家喻戶曉的 CMS 。</p>

<ol>
  <li>
    <p><strong>Wordpress</strong><br />
 Wordpress 是其中最知名的 CMS 工具，目前全球有三成的網站都是使用 WordPress 製作的，且在 CMS 系統的市佔率更接近六成。</p>

    <p>WordPress 的優勢在於其學習曲線的平緩與多語系的支援；另外 WordPress 為開源免費的，得益於此發展出龐大的社群，而衍生許多主題、外掛、網站架構版型可供選擇。</p>

    <p>是說，我當初有想說用 WordPress 來放置這些筆記，但它需要額外負擔<strong>個人網址</strong>和<strong>虛擬主機費用</strong>，我承認我懶得管這些，所以後來才選擇依附在平台的 Github Pages。</p>
  </li>
  <li>
    <p><strong>Joomla!</strong><br />
 雖說是市佔率第二名，但其市占率僅有 6 %，與 WordPress 的 60 % 相比只能是望塵莫及。</p>

    <p>Joomla! 學習曲線相對平緩，上手難度僅次於 WordPress。而其特色在於具備與多特別商業布景，適用於中小型企業的場域，此外它的操作後台，可將常用的功能做成下拉式及按鈕，畫面漂亮且易理解。</p>
  </li>
  <li>
    <p><strong>Drupal</strong><br />
 市占率有近 4 %。相較於上面兩者來說，它的學習曲線較陡，需要學習大量的知識，像是 HTML、PHP 及物件導向…等。</p>

    <p>但它的優勢則在於它是一個功能特殊又可以無限擴充的網站，常被用來架設大型、多用戶的網站像是競選網站、交友網站及共筆媒體…等。</p>
  </li>
</ol>

<p class="illustration">
    <img src="https://i.imgur.com/Tvv7GbD.jpg" alt="熱門的 3 大 CMS" />
    熱門的 3 大 CMS（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<h4 id="單元測驗-16">單元測驗</h4>
<ol>
  <li><strong>你了解熱門 CMS 的特性嗎？請選出它們錯誤的敘述喔！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Wordpress 最初是設計為部落格架站的工具，現在慢慢變成 CMS</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />使用 Drupal 需要學習大量的知識，像是 HTML、PHP 及物件導向等，學習曲線較陡</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />WordPress 不適開源的程式碼，這也是其相關資源稀少的原因之一</li>
    </ul>
  </li>
</ol>

<h3 id="12-3軟體工程師也有分前後嗎">12-3｜軟體工程師也有分前後嗎？</h3>
<p>這邊簡單介紹下，<strong>前端（front-end）</strong>、 <strong>後端（back-end）</strong> 與 <strong>全端（full-stack）</strong> 工程師，三者間各自負責的工作內容：</p>

<ol>
  <li>
    <p><strong>前端</strong><br />
 前端工程師負責<strong>造房子</strong>，<mark>負責整體網頁畫面的呈現與點擊按鈕或區塊的互動</mark>，要熟悉 HTML、CSS/Sass、JavaScript 以及其他相關開發框架等。</p>

    <p>簡單來說，在使用上<strong>看得到</strong>的部分通常就是由前端開發者負責。</p>
  </li>
</ol>

<ul>
  <li>
    <p><strong>後端</strong><br />
  <mark>後端工程師則是負責資料傳遞與網站的溝通層面</mark>，也就是負責<strong>打地基</strong>的，它會將前端的動作傳遞到後端並從資料庫撈取相對應的資料，最後呈現在頁面上。除了熟悉後端程式語言與演算法，也要了解前端相關知識、網路通訊協定、大資料處理，甚至是伺服器的設定…等。</p>

    <p>簡單來說，使用上<strong>看不見</strong>的部分通常是由後端開發者負責。</p>
  </li>
  <li>
    <p><strong>全端</strong><br />
  簡單來說就是<strong>前、後端都要會</strong>！說好聽一點是<strong>通才</strong>的概念，更形象點的說明就是工具人啦 XDDD 它需要工程師必須兼具網站的的多項知識，包含伺服器、資料庫系統維護、版面調整、使用者介面與體驗、客戶與商業需求…等，根據不同任務性質投入前或後端的開發與維護。</p>

    <p>至於全端這個概念，出自 2012 年開源技術大會（open source convention，OSCON）上一位 Facebook 員工說出「他們只雇用全端開發者」。在場的軟體工程師 Laurence Gellert，因而寫下 <a href="http://goo.gl/EVMa32">〈What is a Full Stack developer?〉</a>一文，提及一位全端開發者應該具備的條件。</p>

    <p>課程中建議全端工程師可在進一步掌握資訊安全方面的知識。</p>
  </li>
</ul>

<p class="illustration">
    <img src="https://i.imgur.com/tiGrDK2.png" alt="三種軟體工程師工作內容與職務比較" />
    三種軟體工程師工作內容與職務比較（圖片來源: <a href="https://www.worker360.com.tw/blog/developer">窩課360</a>）
</p>

<h4 id="單元測驗-17">單元測驗</h4>
<ol>
  <li><strong>前端與後端工程師的職責可是天差地遠，別搞錯囉！請選出正確的工程師職位與其相對應的職責。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />前端工程師：負責「打地基」，包含伺服器與資料庫的應用，例如儲存使用者登入的資料與行為記錄</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />前端工程師：負責整體畫面的呈現與點擊按鈕、區塊的互動行為</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />後端工程師：負責「造房子」，包含軟體（應用程式或網頁等）架構、樣貌與互動功能</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />後端工程師：負責改變網頁外觀，如：顏色、排列等視覺元素</li>
    </ul>
  </li>
</ol>

<h3 id="12-4什麼還有全端設計師">12-4｜什麼？還有全端設計師？</h3>
<p>全端設計師並不是在說全端工程師，而是在說<strong>寫程式的設計師</strong>。這…就別斜槓來跟我們搶飯碗了，拜託…</p>

<p>目前多數公司會分成 UI/UX 跟前端工程師兩種職務，但為精簡人力、省下溝通成本、或是為了增加團隊的合作性…等原因，而衍生出全端設計師一職。設計師除了原先 UI/UX 的設計外，還會參與甚至包辦前端開發，有時還會身兼 PM 並參與行銷…等，協助整個專案的執行。</p>

<p>在這邊的全端偏向，<strong>具備且熟悉多樣技能，來解決更多問題</strong>的意義，而不是一開始前後兼顧的意思。不過說實話無論是全端工程師或是全端設計師，在職場上的定位較為模糊，這職位可能會是領導者、顧問，不過更有可能是工具人，哪裡有需要就去哪裡支援 XDDD</p>

<p class="illustration">
    <img src="https://i.imgur.com/WM2AvfE.jpg" alt="全端設計師職能範圍" />
    全端設計師職能範圍（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<h4 id="單元測驗-18">單元測驗</h4>
<ol>
  <li><strong>沒想到設計師也有「全端」的吧！下列關於全端設計，何者正確呢？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />全端設計師需要會「前端工程師」、「後端工程師」、「UI、UX 設計師」的工作內容</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />當一個設計師學會程式，開始可以參與甚至包辦前端開發，協助整個專案的執行，就稱作「全端設計師」</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />能包辦「UI 設計」、「UX 設計」的設計師稱作「全端設計師」</li>
    </ul>
  </li>
</ol>

<h3 id="12-5響應式設計">12-5｜響應式設計</h3>
<p>響應式設計（Responsive web design，RWD），又稱適應性網頁、響應式網頁設計、回應式網頁設計、多螢幕網頁設計，為一種網頁設計技術。</p>

<p>最大特色在於：<mark>在不同解析度下改變網頁頁面的布局排版</mark>，讓同一個網站在不同裝置上自動調整，無論電腦、平板或手機，都能呈現最好閱讀的畫面，是因應移動裝置的使用者數量大增而發展出的方法。</p>

<p class="illustration">
    <img src="https://i.imgur.com/CcBEaFa.jpg" alt="在不同解析度下改變網頁頁面的布局排版" />
    在不同解析度下改變網頁頁面的布局排版（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<p>RWD 是目前最受歡迎的網頁設計之一，其優點如下：</p>

<ol>
  <li>
    <p><strong>方便閱讀，提升使用者體驗</strong><br />
 這是 RWD 最大的優點，也是它的最重要目的。隨著移動裝置使用的興起，其尺寸與規格如雨後春筍般大量地涌現出來，而RWD 採用液態排版技術（Liquid Layout）可克服這問題。</p>

    <p>液態排版技術（Liquid Layout），可讓網站內容，包含圖片、LOGO、主選單、文字內容、網頁標尾…等，自動隨螢幕的尺寸來進行縮放、移動…等重新排列，以找到最合適的呈現方式。如：在電腦寬螢幕上圖片、文字內容以橫向水平排列、遇到手機螢幕圖片改以縱向垂直呈現，以避免呈現過於密麻的字、或避免需要縮放，方便使用者可以輕鬆瀏覽。</p>
  </li>
  <li>
    <p><strong>輕鬆管理，大幅節省成本</strong> <br />
 對管理者來說，僅維護單一版本，會是更加輕鬆，能節省不少時間和人力成本！此外僅製作單一版本，當然能節省開發費用。</p>
  </li>
  <li>
    <p><strong>提升排名，有效加速行銷</strong><br />
 如果行動版具有獨立版的網址，那麼就很有可能會分散網站在搜尋排名上的力道，因為同樣的內容卻存在著兩個網址，那麼搜尋排名計分也就被分攤掉了。</p>

    <p>因此會推薦採用 RWD 整合成單一網址，使瀏覽次數不分散，能直接優化排名（SEO）、帶動行銷效益。針對這一點，Google 在官方網誌<a href="https://developers.google.com/search/blog/2012/06/recommendations-for-building-smartphone">〈Recommendations for building smartphone-optimized websites〉</a>一文中也推薦此用法：</p>

    <blockquote>
      <p>Sites that use responsive web design, that is, sites that serve all devices on the same set of URLs, with each URL serving the same HTML to all devices and using just CSS to change how the page is rendered on the device. <strong>This is Google’s recommended configuration.</strong></p>
    </blockquote>
  </li>
</ol>

<p class="illustration">
    <img src="https://i.imgur.com/cZaIVoH.png" alt="圖解傳統網頁與RWD網頁製作方式" />
    圖解傳統網頁與RWD網頁製作方式（圖片來源: <a href="https://www.ibest.tw/page01.php">愛貝斯</a>）
</p>

<h4 id="單元測驗-19">單元測驗</h4>
<ol>
  <li><strong>原來同一個畫面可以在手機、電腦等裝置都完美呈現全都靠 RWD！請選出錯誤的敘述。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />RWD 中文為響應式設計，它可以讓同一個網站在不同裝置上自動調整畫面</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />RWD 雖然方便，但採用 C 語言的技術，所以製作門檻較高</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />RWD 提升了行動友善度，而且採用單一網址，瀏覽次數不分散，因此能直接優化網頁排名（SEO）</li>
    </ul>
  </li>
</ol>

<h3 id="12-6來認識-app-吧">12-6｜來認識 APP 吧！</h3>
<p>應用程式（application, App）廣義上來說電腦上的各種軟體都算；但由於行動裝置普及，現在提到 App 多半是指行動裝置的應用程式，也就是 Mobile App。</p>

<p>課程這邊針對 Mobile App 進行分類：</p>
<ol>
  <li>
    <p><strong>原生型 Native App</strong><br />
 目前最常見的應用程式，就像是在電腦上安裝使用的軟體一樣。原生 App 是為特定作業系統所開發的應用程式，因此無法跨平台操作，例如同為 Facebook Android 版本的就無法在 iOS 上使用，必須針對不同的作業系統開發相應的 App，因此開發與維護都比較麻煩。</p>
  </li>
  <li>
    <p><strong>網頁型 （Mobile）Web App</strong><br />
 基本上就是 RWD 的網頁，因透過瀏覽器開啟應用程式，故具備跨平台操作的特性，也不需在意更新問題，但也因要透過需瀏覽器才能使用，運行速度與整體效能比較受限。</p>

    <p class="illustration">
     <img src="https://i.imgur.com/NnCpWxg.jpg" alt="原生型與網頁型 Facebook App 畫面比較" />
     原生型與網頁型 Facebook App 畫面比較（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
 </p>

    <p>撇除使用體驗與運行速度，原生型與網頁型兩者的差異在於<mark>原生型「不依賴瀏覽器運作」</mark>，所以最上面不會出現網址列。</p>
  </li>
  <li>
    <p><strong>混合型 Hybrid App</strong><br />
 混合型 App 是前兩者的綜合發展體，結合原生型與網頁型的優點，可以用 HTML5 技術方便開發，又不用依賴瀏覽器使用，跨平台開發特性也方便維護，運行流暢度與成本則介於 Native App 和 Web App 之間。</p>

    <p>開發者可以降低開發成本，又能透過審核上架至 App 商店，觀察使用者下載情形與偏好，可以說是同時也具備方便開發與商業考量的意義。</p>
  </li>
</ol>

<p class="illustration">
    <img src="https://i.imgur.com/ksBCuCN.jpg" alt="原生型與網頁型 Facebook App 畫面比較" />
    原生型與網頁型 Facebook App 畫面比較（圖片來源: <a href="https://codefree.hiskio.com/courses/5">課程</a>）
</p>

<h4 id="單元測驗-20">單元測驗</h4>
<ol>
  <li><strong>那麼多種 APP，千萬別搞混了！請選出下列正確的選項。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />網頁型 App 是目前最常見的應用程式，是專為特定作業系統（手機目前以 iOS、Android 為主）所開發的應用程式</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />原生型 App 與電腦上的網頁並沒有太大的區別，只不過到了行動裝置上多了 RWD</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />混和型 APP 結合了原生、網頁型 APP 的優點，且可以用 HTML5 技術開發，又不用依賴瀏覽器使用</li>
    </ul>
  </li>
</ol>

<h3 id="12-7認識結對程式設計">12-7｜認識結對程式設計</h3>
<p>結對程式設計（Pair programming），是一種敏捷開發的方式。</p>

<p>望文生義，就是開發者兩兩「結對」，他們會從設計構想到執行的過程都在同台電腦上共同工作。兩人中一人負責輸入程式碼，稱之為<strong>駕駛員（driver）</strong>，另一人則負責審查駕駛員所輸入的每一行程式碼，稱之為<strong>觀察員（observer）</strong> 或 <strong>領航員（navigator）</strong>，兩者可隨時互換角色。如此兩兩交互討論、切磋並共事，再相互交換角色的工作模式，就稱之為結對程式設計。</p>

<p class="illustration">
    <img src="https://i.imgur.com/lNfkNpS.png" alt="結對程式設計" />
    結對程式設計（圖片來源: <a href="https://zh.wikipedia.org/zh-tw/结对编程">維基百科</a>）
</p>

<p>這種工作模式我看過我前主管跟另外一位組員做過幾次，不過他們不會整個專案都這們幹，因為太耗時了！通常都是在開發新功能或重構才會這麼做 XDDD</p>

<p><br class="big" /></p>

<p>它這邊提了 3 個結對程式設計的優點，有點懶直接把課程內容整個貼過來：</p>

<ol>
  <li>
    <p><strong>知識傳播</strong><br />
 結對程式設計是一個<strong>很直接的技術和經驗傳授管道</strong>，類似一對一家教，能對實作上的進行意見反饋。透過這樣的方式，是經驗共享和知識共享的效果最大化。</p>

    <p>因此，有些公司會採取這樣的模式，例如建立自己的培訓系統，或是聘請專家來培育新生代。</p>
  </li>
  <li>
    <p><strong>個人提升</strong><br />
 在擔任不同角色時，能夠<strong>透過不同的思考層面與角度去衡量程式的不同設計面向</strong>。</p>
  </li>
  <li>
    <p><strong>產出質量</strong><br />
 因結對時，會有觀察員負責審查所輸入的程式碼。因此錯漏與 bug 能在第一時間及時修正，如此便能在成果初次呈現之時就提升其質量並且省去最後 debug 步驟的精力和時間。</p>
  </li>
</ol>

<p><br class="big" /></p>

<p>至於結對程式設計的效率則與結對的人選有關：</p>

<ol>
  <li>
    <p><strong>若是強強組合</strong><br />
 在雙方都是有經驗有技術的前提之下，都各自固有寫程式習慣與思維，其實也沒有什麼討論的必要。如此一來，便形成人才閒置，如果拆開來工作，便能獨自完成兩個項目，提升了產出效率。</p>
  </li>
  <li>
    <p><strong>若是弱弱搭配</strong><br />
 確實能夠達到討論互助及增進團體凝聚力的效果，但比較難要求短時間的生產效率。</p>
  </li>
  <li>
    <p><strong>若是強弱搭配</strong><br />
 普遍來說，經驗和能力上較缺乏的初級工程師搭配一個資深工程師，經合作後能夠培養獨當一面的能力。不僅能提升技術，更能精進從不同角度的問題思考與架構。</p>

    <p>但這種模式對於初學者來說獲益匪淺，但對於資深開發者卻只是付出遠大於收穫，難免出現失衡的。因此，對於結對程式設計一直以來都有著兩極的評價和看法。</p>
  </li>
</ol>

<p>對於結對程式設計究竟適不適用，須考量到的層面包含每個人的個性、習慣與工作模式，甚至是環境和產出內容的難易程度和所預設的目標都會影響到運作效果！</p>

<h4 id="單元測驗-21">單元測驗</h4>
<ol>
  <li><strong>下列關於結對程式設計，何者敘述錯誤呢？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />工作模式為程式開發者兩兩「結對」，使用同一台電腦工作，從設計構想一路到執行編碼的過程中都是共同合作</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />兩人會先分配誰要開發哪一部分，接著分頭撰寫程式</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />其中一人負責輸入程式碼，另外一人則負責審查輸入的每一行程式碼</li>
    </ul>
  </li>
</ol>

<h3 id="12-8雲端的-3-大服務">12-8｜雲端的 3 大服務</h3>
<p>雲端運算（cloud computing），是一種基於網際網路的運算方式，通過這種方式，將共享的軟硬體資源與資訊可以按需求提供給各種終端和裝置，使用服務商提供的基礎設施進行運算。雲端運算最終的目標：讓資源透過網路變得像是日常生活的水、電一樣唾手可得。</p>

<p>課程接下來介紹了，3大服務模式：<strong>IaaS、PaaS、SaaS</strong>，我這邊就偷懶不做筆記了，要看的話就參考之前的筆記：<a href="https://cynthiachuang.github.io/Difference-between-IaaS-PaaS-SaaS-and-FaaS">〈雲端計算 IaaS、PaaS、SaaS 與 FaaS〉</a>。</p>

<h4 id="單元測驗-22">單元測驗</h4>
<ol>
  <li><strong>原來平常使用的雲端有分那麼多種服務模式！請選出下列正確的敘述喔！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />雲端共有 IaaS、PaaS、SaaS 這 3 種服務模式</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />我們常用的 Google 雲端硬碟屬於 PaaS</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />SaaS 將硬體資源虛擬化，提供虛擬伺服器、虛擬主機等。它可以大幅省去硬體採購投資、部署設備的成本</li>
    </ul>
  </li>
</ol>

<h3 id="12-9雲端的-4-種部署方式">12-9｜雲端的 4 種部署方式</h3>
<p>上一節提過雲端運算提供運算資源的 3 種服務型式，而這節則介紹 4 種雲端運算部署模式：</p>

<ol>
  <li>
    <p><strong>公有雲（Public Cloud）</strong><br />
 簡而言之，公有雲是由銷售雲端服務的廠商所成立，針對大眾提供的雲端運算服務，一般用戶或企業都能使用。一般耳熟能詳的雲端運算服務，絕大多數都屬於公有雲的模式，例如針對企業用戶的 AWS、 Azure、 Salesforce.com…等，或是針對個人的 Dropbox、 Evernote…等，都是公有雲服務。</p>

    <p>公有雲使取得運算資源的門檻降低，使任何人都可以輕易取得龐大的運算資源。但這系統通常以帳號密碼登入作為存取控制機制，安全疑慮較高，容易衍生出其他的安全問題。</p>
  </li>
  <li>
    <p><strong>私有雲（Private Cloud）</strong><br />
 與公用雲相反，只服務企業內部或受信任的人員，可以是由該組織自己管理，或由第三方廠商管理，它可以部署在企業內，也可部署在企業外。</p>

    <p>由於私有雲主要是建立在企業管控的網路，可以擁有絕對的網路控制權，比起公有雲的安全性高；但也因是企業自建，經濟效益與規模比較受限，運算資源較難快速地擴張。</p>
  </li>
  <li>
    <p><strong>社群雲（Community Cloud）</strong><br />
 這種架構是由目標或利益相仿的組織，例如有共同的任務、安全要求、政策與法規，共同成立，以服務擁有相同需求的群體，例如電子病歷交換雲端平臺。</p>
  </li>
  <li>
    <p><strong>混合雲（Hybrid Cloud）</strong><br />
 此種架構架構，是結合多個獨立的雲端運算架，藉由結合公、私兩端的優點，以彈性利用不同架構間安全、規模等優勢。混合雲是一種較新的概念，主要是為了因應單一架構無法滿足人們需求。舉例來說，企業會建立私有雲，但受限於規模可能會將較無安全疑慮的服務交由公有雲。</p>
  </li>
</ol>

<p class="illustration">
    <img src="https://i.imgur.com/rSjme8l.png" alt="雲端的 4 種部署方式" />
    雲端的 4 種部署方式（圖片來源: <a href="https://www.ithome.com.tw/article/93013">iThome</a>）
</p>

<h4 id="單元測驗-23">單元測驗</h4>
<ol>
  <li><strong>下列雲端部署方式與其敘述，何者有誤？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />私有雲是最常見的部署方式，使用上彈性空間大但安全疑慮較高</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />混合雲結合公、私兩端的優點</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />公用雲一般用戶或企業都能使用，但通常僅以帳號密碼登入作為存取控制機制</li>
    </ul>
  </li>
</ol>

<h3 id="12-10雲端的-5-種運算特徵">12-10｜雲端的 5 種運算特徵</h3>
<p>雲端運算除了有 3 種服務模式、 4 種部署模式外，還有 5 種運算特徵：</p>

<ol>
  <li>
    <p><strong>隨選所需自助服務（On-gemand self-service）</strong><br />
 我覺得有點類似之前<a href="https://cynthiachuang.github.io/Serverless-Use-Cases-Study-Notes-01/">講師介紹 Serverless 架構</a>所提到─<strong>按需執行</strong>。</p>

    <p>使用者無須經由供應商，可以直接按照需求（如：伺服器運作時間、網路儲存空間、計算資源…等）取得服務以執行。此特點能滿足<strong>隨用隨付（Pay-As-You-Go,PAYG）模型</strong>中資源配置的需求。</p>
  </li>
  <li>
    <p><strong>網路存取方式多樣化（Broad network access）</strong><br />
 因為網路資源變得容易取得，使用者隨時都可以透過各種裝置（如電腦、平板、手機等）隨時隨地存取資訊。</p>
  </li>
  <li>
    <p><strong>共用資源池（Resource pooling）</strong>  <br />
 這個特徵是在說明雲端運算的<strong>共享性</strong>，它會將運算資源整合為一個共用資源池，並能根據使用量自動調配虛擬與實體主機的資源，以提供給多位使用者。</p>
  </li>
  <li>
    <p><strong>快速、彈性地調整服務（Rapid elasticity）</strong>  <br />
 就是<strong>按需擴展</strong>的概念，這是指雲端運算服務可以快速、彈性部署及釋出運算資源。</p>
  </li>
  <li>
    <p><strong>可行量與計價的服務（Measured service）</strong><br />
 就是<strong>按使用來計費</strong>的概念。使用者或服務供應商能夠直接取得、管理資源的使用情況，並按照使用資源計費。</p>
  </li>
</ol>

<h4 id="單元測驗-24">單元測驗</h4>
<ol>
  <li><strong>針對雲端的運算特徵，下列敘述何者錯誤？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />用戶能在不需要供應商介入的情況下自行配置像是伺服器運作時間、網路儲存空間等運算資源</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />配置運算資源時，架構既可快速擴增，亦可快速縮小，在一些情況下甚至能夠自動化運作</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />無法自動控制運算資源的使用（儲存空間、處理器、頻寬與使用人數等）但能使資源最佳化</li>
    </ul>
  </li>
</ol>

<h2 id="ch-13換一顆軟體工程師的邏輯腦演算法">CH 13｜換一顆軟體工程師的邏輯腦：演算法</h2>

<h3 id="13-1演算法是什麼如何演算">13-1｜演算法是什麼？如何演算？</h3>
<p>演算法是<strong>一連串解決問題的邏輯步驟</strong>。當我們將邏輯步驟用程式撰寫後，電腦就會計算給出答案，從輸入到輸出結果的過程，就是演算法的範圍。而過程會是：輸入（input）→ 演算（algorithm）→ 輸出（output）。</p>

<p class="illustration">
<img src="https://i.imgur.com/b192fuE.png" alt="演算法基本概念" />
演算法基本概念（圖片來源: <a href="https://www.eisland.com.tw/Main.php?stat=a_yg2Y8Hs">英語島</a>）
</p>

<p>舉例來說，當上班肚子餓時（輸入 input），我們依序確認時間點，以及適不適合出門（演算法 algorithm），再根據結果，決定要如何解決（輸出 output），這中間的起承轉合，就是演算法的過程。</p>

<p class="illustration">
<img src="https://i.imgur.com/vp4PAhZ.jpg" alt="演算法與流程圖" />
演算法與流程圖（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<p>演算法必須完全滿足下列 5 項特性：</p>
<ol>
  <li><strong>輸入（input）</strong><br />
 <strong>0 個或多個輸入資料</strong>，這些輸入必須有清楚的描述或定義。</li>
  <li><strong>輸出（output）</strong><br />
 <strong>至少會有一個輸出結果</strong>，不可以沒有輸出結果。</li>
  <li><strong>明確（definiteness）</strong><br />
 每個指令或步驟必須是<strong>明確的指令</strong>。</li>
  <li><strong>有限（finiteness）</strong><br />
 必須在<strong>有限</strong>步驟後必產生結果，不然會產生無窮迴圈。</li>
  <li><strong>有效（effectiveness）</strong><br />
 步驟清楚可行，阿不然要怎麼算？</li>
</ol>

<h4 id="單元測驗-25">單元測驗</h4>
<ol>
  <li><strong>經過圖解後，你是不是更了解演算法了呢？請選出下列關於演算法錯誤的特性吧！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />演算法有 5 種特性，分別是輸入、輸出、時效性、有限、有效</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />必須完全滿足演算法 5 種特性，才稱得上邏輯運算</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />演算法的運作過程為輸入→ 演算→ 輸出</li>
    </ul>
  </li>
</ol>

<h3 id="13-2常用的演算法表示法">13-2｜常用的演算法表示法</h3>
<p>常用來表示演算法的方法有兩種，簡單來說不是畫出來就是寫出來：</p>

<p class="illustration">
<img src="https://i.imgur.com/8PELm5K.png" alt="構思演算法" />
構思演算法（圖片來源: <a href="http://ms2.ctjh.ntpc.edu.tw/~luti/107-2week04_1.htm">初探演算法</a>）
</p>

<ol>
  <li>
    <p><strong>畫出來：流程圖（flow chart）表示法</strong><br />
 流程圖會運用各種方塊、圖形、線條和箭頭，精簡表達演算的順序和步驟。且圖示本身，就表達資料性質、處理方式…等等。常用的流程圖符號如下：</p>

    <p class="illustration">
 <img src="https://i.imgur.com/vBFQ1wX.jpg" alt="常用的流程圖符號" />
 常用的流程圖符號（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
 </p>
  </li>
  <li>
    <p><strong>寫出來：虛擬碼（pseudo code）</strong><br />
另一個常用的方法就是透過虛擬碼。它是介於自然語言與程式語言之間的描述語言，結構上與程式接近，但並無嚴格的語法規則，一般只要結構清晰、方便閱讀，就可視為虛擬碼。</p>
  </li>
</ol>

<p>恩，我找到了個範例：輸入一個正整數N，判定是否能被 2 整除，如果 N 能被 2 整除是偶數，否則 N 是奇數。將這敘述分別使用兩種方法撰寫：</p>

<p class="illustration">
<img src="https://i.imgur.com/kAZGb6q.jpg" alt="流程圖與虛擬碼" />
流程圖與虛擬碼（圖片來源: <a href="https://sites.google.com/cycu.org.tw/python">Python 程式設計與邏輯思維</a>）
</p>

<h4 id="單元測驗-26">單元測驗</h4>
<ol>
  <li><strong>原來演算法的標示方法不只有一種！你了解這些標示方法了嗎？請選出正確的敘述吧！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />常見的標示法有「流程圖標示法」、「文字敘述表示法」兩種</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />流程圖運用各種方塊、圖形、線條和箭頭，精簡表達演算的順序和步驟。例如：菱形就表示起訖符號</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />文字敘述法透過圖案本身，就能表達出資料性質、處理方式</li>
    </ul>
  </li>
</ol>

<h3 id="13-3打造演算法的鋼筋水泥">13-3｜打造演算法的鋼筋水泥</h3>
<p>程式語言，或說演算法的控制結構共分為：<strong>循序</strong>、<strong>條件</strong>及<strong>重複結構</strong>。是說，之前在寫 <a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#ch-4流程控制">Python 的流程控制</a>時好像提過類似的事情？</p>

<h4 id="循序結構sequence-structure">循序結構（sequence structure）</h4>
<p><strong>依其先後順序逐一完成執行</strong>。最常見的結構，一般程式撰寫時沒有特別設定，多是這個結構。例如：</p>
<pre><code class="language-python=">使用自動販賣機，選好飲料 → 選擇付款方式 → 付錢 → 獲得飲料
</code></pre>

<p class="illustration">
<img src="https://i.imgur.com/5eDB3FV.jpg" alt="循序結構" />
循序結構（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<h4 id="條件結構conditional-structure">條件結構（conditional structure）</h4>
<p><strong>依條件是否成立</strong>，來決定執行的動作。</p>

<p class="illustration">
<img src="https://i.imgur.com/1kZuSKd.jpg" alt="條件結構" />
條件結構（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<h4 id="重複結構repetition-structure">重複結構（repetition structure）</h4>
<p><strong>在條件成立時，會反覆執行動作</strong>。例如：</p>

<p class="illustration">
<img src="https://i.imgur.com/6IdDqDI.jpg" alt="重複結構" />
重複結構（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<h4 id="單元測驗-27">單元測驗</h4>
<ol>
  <li><strong>演算法有「循序、條件、重複」三種基本結構，請選出下列正確的配對。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />循序結構：由上至下依序執行，用於需要依序執行多個動作時。結構為：指令 1 → 指令 2 → 指令 3 →……</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />條件結構：依條件是否成立，來決定執行的動作，例如：while….則執行某動作</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />重複條件：在條件成立時，會反覆執行動作。例如：if…then…else</li>
    </ul>
  </li>
</ol>

<h2 id="ch-14認識軟體工程師的開發工具">CH 14｜認識軟體工程師的開發工具</h2>

<h3 id="14-1一應俱全的整合開發環境-ide">14-1｜一應俱全的整合開發環境 IDE</h3>
<p>整合開發環境（Integrated Development Environment，IDE），不過習慣上大家都直接稱呼 IDE。</p>

<p>IDE 是一種輔助程式開發人員開發軟體的應用軟體。通常包含程式語言編輯器、編譯器/直譯器、除錯器、還有使用者圖形界面…等，IDE 會將各自獨立的工具集結在一起，方便一站式使用（課程說像是三合一咖啡 XDDD）。</p>

<p>過往的 IDE 會針對特定的程式語言量身打造（如：Visual Basic），但現今的 IDE 往支持多種語言的方向在推動（如：Eclipse 及 Microsoft Visual Studio）。 All-In-One 的設計雖然方便，但並非所有工具的使用都能遂心如願，所以有些開源的 IDE，可以讓工程師混搭，以創造更合適的 IDE。</p>

<p class="illustration">
<img src="https://i.imgur.com/GfC5mzr.jpg" alt="IDE 整合開發環境" />
IDE 整合開發環境（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<ul>
  <li><strong>IDE 的優點</strong>
    <ol>
      <li><strong>適合新手</strong>：不需在終端機下安裝及設定各種前置作業，能節省建立開發環境的成本，並加速對開發環境的了解。</li>
      <li><strong>執行程式碼</strong>：可以在 IDE 內直接執行一段程式碼，不需離開編輯器。</li>
      <li><strong>高亮程式碼</strong>：將原始碼以不同顏色顯現，讓我們閱讀更方便。</li>
      <li><strong>自動排版</strong>：當輸入 if 或 while 時，編輯器知道下一行要縮進。</li>
    </ol>
  </li>
</ul>

<h4 id="單元測驗-28">單元測驗</h4>
<ol>
  <li><strong>如果你平常有在接觸程式領域，那麼你一定很常聽到 IDE 吧？相信經過我們的講解，你應該有了初步的了解。請選出下列正確的敘述吧！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />IDE 中文為整合開發環境，它將程式開發所需的軟體工具集結在一起，通常包含程式語言編輯器、編譯器 / 直譯器、除錯器、還有圖形使用者界面</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />它最大的缺點就是不能在 IDE 內直接執行一段程式碼，而是需要離開編輯器</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />IDE 的 ALL IN ONE 設計相當方便，完全沒有任何缺點</li>
    </ul>
  </li>
</ol>

<h3 id="14-2熱門的整合開發環境">14-2｜熱門的整合開發環境</h3>
<p>這節介紹些熱門的 IDE：</p>

<ol>
  <li><strong>Visual Studio</strong>
    <blockquote>
      <p>完整的 <a href="https://visualstudio.microsoft.com/zh-hant/vs/">Visual Studio介紹及載點</a></p>
    </blockquote>

    <p>簡稱 VS，是由微軟開發的 IDE，是目前應用廣泛的 IDE 之一。它同時能在 Windows、Linux 和 macOS 作業系統上執行，還能支援 C++、C#、.NET、F#、JavaScript、Ruby、Go 及 Python 等程式。</p>

    <p>我記得這是我大學教授指定的 IDE，不過我大學之後就再也沒用過了 XDDD 不過需要注意的是，這邊介紹的 Visual Studio 而不是 Visual Studio Code，兩者的定位並不一樣。VS 是 IDE，而 VS Code 則僅是單純的程式碼編輯器，不過說真的，最新的 VS Code 加上龐大的擴充套件，幾乎可以取代 IDE 使用。</p>
  </li>
  <li><strong>Eclipse</strong>
    <blockquote>
      <p><a href="https://www.kjnotes.com/devtools/80">Eclipse 下載教學</a></p>
    </blockquote>

    <p>Eclipse 由 IBM 開發，本身是一個框架平台，但因為外掛程式的支援，因此許多軟體開發商以 Eclipse 為框架，開發自己的 IDE。它最初是用來開發 Java，後來也有人透過外掛程式，來開發 C/C++、PHP、Ruby、JavaScript、R 及 Python。</p>

    <p>這個是我曾經最愛的 IDE :heart_decoration: ，我通常拿它來開發 Java，不過我讀完研究所後就在也沒裝過它了 XDDD</p>
  </li>
  <li><strong>Xcode</strong>
    <blockquote>
      <p><a href="https://medium.com/彼得潘的-swift-ios-app-開發問題解答集/安裝xcode-8需要macos-10-11-5以上-2e0f2d5557f3">Xcode 下載教學</a></p>
    </blockquote>

    <p>這個我就沒有用過了。它只能運行在 Mac OS X 作業系統上，是提供開發人員用來開發蘋果的相關應用程式的 IDE，能支援 C、C++、Fortran、Objective-C、Java、Python、Ruby 和 Swift 等程式語言。</p>
  </li>
  <li><strong>IntelliJ</strong>
    <blockquote>
      <p><a href="https://www.jetbrains.com/idea/download/#section=linux">IntelliJ 下載</a></p>
    </blockquote>

    <p>這是我目前慣用的 IDE，是由 JetBrains 所釋出。它有提供社區版本以及商業版本，像是 Android Studio，就是 Google 基於 IntelliJ IDEA 的社區版本發展而來。IntelliJ 本身主要是針對 Java 的 IDE，但針對其他語言，如： JavaScript、TypeScript、Ruby、Go 及 Python…等，可由外掛程式載入 IntelliJ 使用。</p>
  </li>
  <li><strong>雲端開發環境</strong><br />
 另外一種我常用的開發方式，是用 SaaS，也就是<a href="https://www.inside.com.tw/article/4177-best-online-ides-let-you-code-anywhere">雲端開發環境</a>，它可以免除繁瑣複雜的前置作業。不過也因為它是 SaaS，所以程式碼會儲存在供應商的儲存服務中，所以我通常是用來快速驗證，或是臨時寫程式時才會用。</li>
</ol>

<p><br class="big" /></p>

<p class="illustration">
<img src="https://i.imgur.com/RP7vuw2.png" alt="IDE 整合開發環境" />
熱門的 IDE 比較（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<p>是說看到這些 IDE 害我又想到傳說中的<strong>鄙視鍊</strong>，Vim 或 text editor 的鄙視用 IDE 的工程師、 Android Studio 或 IntelliJ IDEA 的鄙視用 Eclipse 的工程師…等。這些各式各樣的鄙視鍊還滿有趣的，有興趣的可以去查查。</p>

<p class="illustration">
<img src="https://i.imgur.com/FES6dqv.png" alt="工具版鄙視鍊" />
工具版鄙視鍊（圖片來源: <a href="https://segmentfault.com/a/1190000012510841">SegmentFault 思否</a>）
</p>

<h4 id="單元測驗-29">單元測驗</h4>
<ol>
  <li><strong>關於下列熱門的 IDE，請選出錯誤的敘述。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />Xcode 是 Windows 開發人員所提供的 IDE，用來開發微軟的相關應用程式，且僅能運行於 Windows 作業系統上</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />Visual Studio 簡稱 VS，是一款全功能整合開發平台，不過僅相容 Windows 和 macOS X 系統</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />elipse 由 IBM 開發，本身是一個框架平台，但因為外掛程式支援，所以許多軟體開發商以 Eclipse 為框架，開發自己的 IDE</li>
    </ul>
  </li>
</ol>

<h3 id="14-3程式語言的框架">14-3｜程式語言的框架</h3>
<p>課程說的有點文言，先別管它，我用自己的理解寫一次好了。</p>

<p>框架，也就是 Framework，它像是個積木，開發者已經建構出大多數的元件了，甚至建築好大致的骨架後，一旦你有應用需求（Application）就只需在框架之上，依照需求去做修改與實踐，以實現客製化。如：PyTroch 跟 Tensorflow，就是機器學習中兩大框架，他們有撰寫公開的骨幹網路模型、損失函數、優化函數及衡量指標，當你要實做你的網路架構時，你只需要從中挑選並組成所需網路即可。</p>

<p class="illustration">
<img src="https://i.imgur.com/sSJvh5p.png" alt="程式語言的框架" />
程式語言的框架（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<p>現階段框架為程式領域中公認前瞻性的技術，並且因應 IT 轉型的需求，成為近年來技術潮流的新秀。框架的出現產生了最主要提供了以下的便利性：</p>

<ol>
  <li>讓開發者省去初始編寫架構的時間和精力，得以專注於核心開發上。</li>
  <li>透過自動化系統矯正錯誤，不再需要為繁雜的語法費心力。</li>
</ol>

<h4 id="單元測驗-30">單元測驗</h4>
<ol>
  <li><strong>其實不是所有的語法都要一個個字輸入，而是有更快的方法及工具－框架，來提升效率喔！針對框架的特性，請選出錯誤的敘述。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />它可以讓開發者省去編寫架構的時間與精力</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />由一連串代碼庫所組成，功用為簡化特定輸入的程式語言語法</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />無法透過系統自動化矯正錯誤</li>
    </ul>
  </li>
</ol>

<h3 id="14-4javascript-的網頁開發框架">14-4｜JavaScript 的網頁開發框架</h3>
<p>可能之前提到前端，因此在這章介紹網頁前端開發的框架。</p>

<p>這邊介紹的前端框架，多基於 JavaScript 所開發的，因 JavaScript 的開發痛點在於各瀏覽器的相容性，而透過 JavaScript 框架除了具備上述框架的優點外，還能輕鬆地克服跨瀏覽器問題。</p>

<p>框架跟程式語言的發展史一樣，都會依照開發用途、使用者體驗…等因素，逐漸進行迭代，發展至今 JavaScript 框架大多皆已發展地相當完整且成熟。下列介紹幾個普遍使用的 JavaScript 框架：</p>

<ol>
  <li><strong>JQUERY UI</strong><br />
 這是是一套 JavaScript 函式庫，它提供抽象化、可自訂主題的 GUI 控制項與動畫效果。課程提到了幾個特點：
    <ol>
      <li>現今各大主流跨瀏覽兼容</li>
      <li>鏈式操作及選擇器使用方便，語法更簡潔</li>
      <li>前端網頁的基本插件種類豐富
 不過鏈式操作應該不算是 JQUERY UI 的特點？而是 JQUERY 本身的特點？</li>
    </ol>
  </li>
  <li><strong>Vue.js</strong><br />
 我之前學過得一套框架，可以去翻翻之前的<a href="https://cynthiachuang.github.io/Vue-Study-Notes-Contents/">筆記</a>。它具備：
    <ol>
      <li>學習容易，可快速上手</li>
      <li>加入 Laravel 中，可支援些許項目</li>
      <li>快速啟動便利性高的命令列介面（CLI）工具</li>
    </ol>
  </li>
  <li><strong>React</strong><br />
 React 主要是在做前端的渲染的，課程介紹它優點包含：
    <ol>
      <li>使用者滿意度最高的 Javascript 框架</li>
      <li>充分學習 React.js 後，可轉移至 React Native 開發客戶端</li>
      <li>可支援 JSX 的新語法</li>
    </ol>

    <p>這邊有個問題，雖然習慣上在介紹前端框架時候都會提到 React，但它其實並<strong>不是框架而是函式庫</strong>。 嚴格說來，React 和 react-router、react-redux、redux-saga 等結合起來才是個框架，React 本身只一個前端渲染的函式庫而已。</p>

    <p class="illustration">
 <img src="https://i.imgur.com/wKcjkLv.png" alt="React 是函式庫不是框架" />
 React 是函式庫不是框架（圖片來源: <a href="https://zh-hant.reactjs.org/">React 官網</a>）
 </p>
  </li>
</ol>

<p>在未來的趨勢裡，框架扮演著規範和定義的角色，它能以更為簡潔的語法取代許多繁瑣的步驟，避免錯誤設定，讓開發者投入更核心、更重要的開發工作。</p>

<h4 id="單元測驗-31">單元測驗</h4>
<ol>
  <li><strong>使用 JavaScript 開發最大的困難點在於各個瀏覽器的相容性，而使用框架就能輕鬆解決跨瀏覽器的相容問題。請選出下列關於 React 的正確描述</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />可加入 Laravel 中，支援些許項目</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />充分學習 React.js 後，可轉移至 React Native 開發客戶端</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />現今各大主流跨瀏覽器兼容，且前端網頁的基本插件種類豐富</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />不可支援JSX的新語法</li>
    </ul>
  </li>
</ol>

<h3 id="14-5認識函式庫動態與靜態函式庫">14-5｜認識函式庫－動態與靜態函式庫</h3>
<p>這邊開始介紹函式庫 library，它是一個由許多程式碼集結而成的程式碼集合體，負責幫助程式設計實現各種不同的功能，就像是名副其實圖書館一樣，它內建豐富典藏以供查詢取用。</p>

<p><a href="#10-3高階語言的內建翻譯機">之前在編譯語言</a>的時後有提過：</p>
<blockquote>
  <p>編譯語言會透過連結器將一個或多個目的檔與<strong>靜態函式庫</strong>連結，產生可執行檔。最終要執行程式時，只需要透過載入器將可執行檔載入記憶體，並與<strong>動態函式庫</strong>連結，不需重新翻譯。</p>
</blockquote>

<p>其中所提到的靜態函式庫與動態函式庫，就是本節所要介紹，它們依<mark>協助運行程式的方式</mark>不同而有不同的特性：</p>

<ol>
  <li>
    <p><strong>靜態函式庫（Static library）</strong><br />
 又稱靜態連結函式庫（Statically-linked library），在編譯期間由編譯器與連結器將它整合至應用程式內，並製作成目的檔以及可以獨立運作的執行檔，因此執行檔毋須考慮電腦上函式庫檔案是否存在及版本問題。</p>

    <p>但在編譯階段載入多個函式庫，會導致執行檔肥大，而且需要更新時要整個重新編譯再重新連結，會大量消耗記憶體與系統資源。</p>
  </li>
  <li>
    <p><strong>動態函式庫</strong><br />
 這東西在 Windows 上稱為動態連結函式庫（Dynamic-link library，DLL），而在 UNIX 或 Linux 上則稱為共享函式庫（Shared Library）。函式庫會獨立於執行檔之外，只有當執行程式時才被統載入使用，可以節省記憶體資源、提升開發效率；但有能遇到執行端所存在的函式庫與程式要求版本不相容的狀況，導致程式無法正常執行，也就是所謂的 DLL 地獄。</p>
  </li>
</ol>

<p class="illustration">
<img src="https://i.imgur.com/8T1oDFa.jpg" alt="兩種函式庫比較" />
兩種函式庫比較（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<h4 id="單元測驗-32">單元測驗</h4>
<ol>
  <li><strong>若依協助運行程式的方式區分，可分為動態、靜態函式庫，可別搞混它們的特性了！請選出下列哪些為靜態函式庫的特性</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />即使在不同環境下無需函式庫也可以執行檔案</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />在 UNIX 或 Linux 系統上則是稱作共享函式庫</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />載入多個函式庫時，執行檔會很小，且需更新程式時，要整個重新編譯再重新連結，只會稍微消耗記憶體與系統資源</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />函式庫檔獨立於執行檔，在執行程式時才被作業系統載入使用，可以節省記憶體資源</li>
    </ul>
  </li>
</ol>

<h3 id="14-6認識函式庫標準與第三方函式庫">14-6｜認識函式庫－標準與第三方函式庫</h3>
<p>函式庫除了依照協助運行程式來區分函式庫外，還可以依<mark>輔助程式語言相關使用</mark>來區分：</p>

<ol>
  <li>
    <p><strong>標準函式庫（Standard Library）</strong><br />
 像是<mark>程式語言基本補充包</mark>，在某些情況下，程式語言規格說明中會直接提及該函式庫；通常與程式語言一起合稱為「ＯＯＯ標準函式庫」，例如：Ｃ標準函式庫、Ｃ++標準函式庫等。</p>
  </li>
  <li>
    <p><strong>第三方函式庫（Third-party Library）</strong><br />
 可以想像成是<mark>程式語言進階擴充包</mark>，含許多可以實現其他延伸功能的外部函式的庫。例如：jQuery 是 JavaScript 非常受歡迎的第三方函式庫。</p>
  </li>
</ol>

<h4 id="單元測驗-33">單元測驗</h4>
<ol>
  <li><strong>若依輔助程式語言相關使用區分，可分為標準、第三方函式庫！請選出下列哪些為第三方函式庫的特性</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />像是「程式語言基本補充包」，通常與程式語言一起合稱為「ＯＯＯ標準函式庫」，例如：Ｃ標準函式庫</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />像是「程式語言進階擴充包」，含許多可以實現其他延伸功能的外部函式的庫</li>
    </ul>
  </li>
</ol>

<h3 id="14-7帶來無限便利的-api">14-7｜帶來無限便利的 API</h3>
<p>之前，寫過一篇關於 <a href="https://cynthiachuang.github.io/Android-SDK-and-API/#api-application-programming-interface應用程式介面">API 的網誌</a>可以先去看看。</p>

<p>在課程中則是用了餐廳點餐的過程為例：</p>
<ol>
  <li>進入餐廳看菜單</li>
  <li>向服務生點餐（提出需求）</li>
  <li>服務生向廚房點餐（要求）</li>
  <li>服務生送餐點過來（回應）</li>
</ol>

<p>當你點完餐，服務生會到後台傳遞這個訊息，餐點製作完成後，再由服務生送上餐點。在這個過程中，服務生的角色，既非生產者，也非需求方，而是在於傳達，好比 API 傳遞訊息、回傳資料的概念。</p>

<p class="illustration">
<img src="https://i.imgur.com/qufvInY.jpg" alt="兩種函式庫比較" />
兩種函式庫比較（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<p>由於 API 經濟的興起，越來越多的企業通過 API 將自己企業的功能和數據開放提供第三方人員有償或是無償使用，這樣的開放可以直接對企業利潤帶來引響，或是擴大自身在生態圈影響力，並且很快的完成創新。</p>

<p>舉例來說，在 Facebook 可以看 Youtube 影片、在部落格可以嵌入 Google map，都是拜 API 之賜。因為 Youtube、Google map 提供 API 服務，所以工程師不必自己架設影音網站，也不用自己創造全新地圖，就能串接 API 擴充，享用對方的服務。</p>

<h4 id="單元測驗-34">單元測驗</h4>
<ol>
  <li><strong>身為工程師，你一定得認識 API！請選出關於 API 正確的敘述吧！</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />為 application programming interface 的縮寫，中文為「應用程式介面」</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />主要功用，在於對外獲得雙方的資訊</li>
    </ul>
  </li>
</ol>

<h2 id="ch-15程式語言的資料型態">CH 15｜程式語言的資料型態</h2>

<h3 id="15-1python-的資料型態">15-1｜Python 的資料型態</h3>
<p>這章我整個跳過，因為在<a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#ch-3資料型態">〈CodeFree｜喝一杯咖啡，輕鬆學 Python〉</a>一節中已經做過相同的筆記了…我不想在做一次 Orz</p>

<h4 id="單元測驗-35">單元測驗</h4>
<ol>
  <li><strong>如果你想學習程式，那麼你一定要懂資料型態。下列哪些是正確的配對呢？</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />bool：分為 True、False、and、or</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />float：指有小數點的數值</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />int：字串</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />tuple：整數</li>
    </ul>
  </li>
</ol>

<h3 id="15-2資料運算">15-2｜資料運算</h3>
<p>這節就講<strong>算術運算子</strong>、<strong>邏輯運算子</strong>、<strong>賦值運算子</strong>，不過多東西我在〈CodeFree｜喝一杯咖啡，輕鬆學 Python〉那篇有整理過了，所以就跳過一部分囉～</p>

<blockquote>
  <p>想了解算術運算子，點<a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#3-3資料型態數字">這裡</a>；想了解邏輯運算子，點<a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#4-6符號-and-與-or">這裡</a></p>
</blockquote>

<p><br class="big" /></p>

<p>而 <strong>賦值運算子（Assignment operators）</strong> 之前沒有專門整理過，這邊在稍微整理下。</p>

<p>賦值運算子是種比較特別的運算子，通常是用來將已存在物件賦予給其他相同類別的物件。在大多數的程式語言中，賦值運算子是以<strong>等號（=）</strong> 來表示。不過雖說是等於，但跟數學上的等於略有不同，在計算時他們會將右邊的運算完成後，賦值給左邊的變數，左右邊跟數學上是相反過來的。除了基礎的賦值外，還有衍生出複合的賦值運算子：</p>

<p class="illustration">
<img src="https://i.imgur.com/00eqHzx.jpg" alt="兩種函式庫比較" />
兩種函式庫比較（圖片來源: <a href="https://codefree.hiskio.com/courses/6">課程</a>）
</p>

<h4 id="單元測驗-36">單元測驗</h4>
<ol>
  <li><strong>運算元與運算子在寫程式時也非常常用。請選出下列正確的配對與敘述。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />邏輯判斷運算子：用於計算加減乘除</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />賦值運算子：又稱為比較運算子，用於比較大小關係</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />計算運算子：用於賦與運算元數值</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />運算元（Operant）就是運算資料，可以是數字或算式</li>
    </ul>
  </li>
</ol>

<h3 id="15-3流程控制條件判斷控制">15-3｜流程控制－條件判斷控制</h3>
<p>在章節 <a href="https://cynthiachuang.github.io/Hiskio-Codefree-Computer-Science-2/#13-3打造演算法的鋼筋水泥">13-3</a> 時，提過演算法的控制結構共分為：循序、條件及重複結構。</p>

<p>在這節會來說明條件判斷控制…恩，我又要來跳過…有需要的還是去看看〈CodeFree｜喝一杯咖啡，輕鬆學 Python〉那篇，我把兩邊對應的章節給列在下面了：</p>
<ol>
  <li>單向選擇 if &gt; <a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#4-2if-流程控制">傳送門</a></li>
  <li>雙向選擇 if···else &gt; <a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#4-3else-例外處理">傳送門</a></li>
  <li>多向選擇 if···elif···else &gt; <a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#4-4elif-多重流程控制判斷">傳送門</a></li>
  <li>巢狀 if &gt; <a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#4-5巢狀-if-流程控制">傳送門</a></li>
</ol>

<h4 id="單元測驗-37">單元測驗</h4>
<ol>
  <li><strong>請選出錯誤的配對。</strong>　
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />單向選擇 if：當判斷式成立時即執行該程式區塊</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />雙向選擇 if···else：當條件成立時可以執行 if 下的程式區塊，而當不成立時就執行 else 下的程式區塊</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />巢狀 if：當第一個條件成立時可以執行 if 下的程式區塊，不然就看第二個條件是否成立，成立時就執行該 elif 下的程式區塊</li>
    </ul>
  </li>
</ol>

<h3 id="15-4流程控制迴圈控制">15-4｜流程控制－迴圈控制</h3>
<p>繼續跳過，還是上對照連結：</p>
<ol>
  <li>for 迴圈 &gt; <a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#ch-5for-迴圈">傳送門</a></li>
  <li>while 迴圈 &gt; <a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python/#ch-6while-迴圈">傳送門</a></li>
</ol>

<h4 id="單元測驗-38">單元測驗</h4>
<ol>
  <li><strong>請選出正確的配對。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />for 迴圈：以「for」這個字組成，在兩字之間會放入我們自訂的變數</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />巢狀for迴圈：巢狀迴圈也就是迴圈裡又包著迴圈，外層迴圈每動作一次，內層迴圈就會把自身的整個迴圈執行一遍，執行完畢後才跳回外層迴圈</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />break：不會讓迴圈結束，只跳過迴圈內 continue 後面的剩餘敘述，再回到迴圈的判斷式</li>
    </ul>
  </li>
</ol>

<h3 id="15-5函式">15-5｜函式</h3>
<p>還是跳過，直接上<a href="https://cynthiachuang.github.io/Hiskio-Codefree-Python#ch-9函數-function">傳送門</a>。</p>

<h4 id="單元測驗-39">單元測驗</h4>
<ol>
  <li><strong>為了避免落落長的程式碼，你就會使用到函式！請選出下列正確的敘述。</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />宣告函式：函式在使用前不需要宣告，但會先定義出函式的名稱、參數及它要做的事情</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />呼叫函式：在寫完函式後，我們要使用函式時必須「呼叫（call）」函式，才能讓函式開始運作</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />函式可以避免不同的東西一直複製貼上在你的程式碼</li>
    </ul>
  </li>
</ol>

<h2 id="ch-16過去三十年人工智慧剛起步-vs-未來三十年人工智慧-iq-10000">CH 16｜過去三十年人工智慧剛起步 v.s. 未來三十年人工智慧 IQ 10000</h2>

<h3 id="16-1人工智慧的巨量資料學習法">16-1｜人工智慧的巨量資料學習法</h3>
<p>害我想到我的草稿夾，有一篇關於人工智慧、機器學習與深度學習之間的網誌，我決定等那邊篇寫完再來給連結…恩…希望有吧 XDDD</p>

<p>:::info
:information_source: <strong>關於人工智慧、機器學習與深度學習之間的網誌</strong></p>

<p>我竟然寫完（感動</p>
<ul>
  <li><a href="https://cynthiachuang.github.io/From-Artificial-Intelligence-to-Machine-Learning-and-Deep-Learning/">從人工智慧到機器學習、深度學習</a>
:::</li>
</ul>

<h4 id="單元測驗-40">單元測驗</h4>
<ol>
  <li><strong>現在你終於搞懂人工智慧、機器學習、深度學習之間的關係了！讓我們來複習一下吧！請選出下列正確的選項</strong>
    <ul class="task-list">
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />人工智慧：機器學習的分支，目標在於以電腦解決問題，發展至今日，舉凡醫療、交通等領域，都已經廣泛運用</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />機器學習：簡稱 ML，人工智慧的一個分支，它能讓電腦從海量的資料中自行學習，並且自己逐步精進</li>
      <li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />深度學習：人工智慧的分支。以人工神經網路為架構，讓機器朝人類更進一步發展，把機器學習推向實際運用</li>
    </ul>
  </li>
</ol>

<h3 id="16-2生活中的人工智慧">16-2｜生活中的人工智慧</h3>
<p>這節在介紹目前人工智慧的應用範疇，並提人工智慧是未來科技的趨勢：「未來只剩兩種人，告訴電腦該怎麼做的人，以及被電腦告知該怎麼做的人」。是說，我這邊偷懶幾乎是用課程原文：</p>

<h4 id="專家系統expert-system">專家系統（Expert System）</h4>
<p>專家系統採用事前做足應對措施的方式，也可以說是人工智慧系統中的知識庫。以針對性的問題作為出發，進而發想出他的解決方法。不過一個很大的缺點是，只限制於專家有預先設想過的答案或應對，侷限性相較比較大，有尚未考慮過的問題是專家系統中的一個缺漏。</p>

<h4 id="電腦視覺computer-vision">電腦視覺（Computer Vision）</h4>
<p>電腦視覺以開啟電腦及攝影機的視覺為目的，也就是讓電腦學會「看」，以便進行資料的圖像化。並且在人工智慧系統中，期望以電腦視覺去取得圖像中的更多資訊。常見的應用有：無人駕駛、圖像監測、工業機器人和圖像資料庫等。</p>

<h4 id="語音辨識speech-understanding">語音辨識（Speech Understanding）</h4>
<p>語音辨識，也可稱做自動語音辨識（Automatic Speech Recognition，簡稱 ASR），以人類所釋出的語音轉為對應文字的系統，生活中常見的手機語音輸入法就是一個應用的例子。其他應用包含：語音撥號、語音導航、室內裝置控制及語音文件檢索…等。近期更是出現了語音轉語音的翻譯系統，也是仰賴語音辨識的智慧系統。</p>

<h4 id="機器人應用robotic-application">機器人應用（Robotic Application）</h4>
<p>機器人取代人力的運作模式從數十年前就已開啟。目前機器人的應用在許多工業領域中發光發熱，包含倉儲物流、航太產業、汽車製造，以及木工與建築…等。許多搬運及組裝的工作透過機器人組成的自動化流程，不但能省時省力，更能使得流程穩定且順暢。</p>

<h4 id="類神經網路artificial-neural-network">類神經網路（Artificial Neural Network）</h4>
<p>自 2010 年代後興起的人工智慧浪潮中，其中一個就是機器學習（Machine Learning）的模式。透過深度學習後，電腦以創造了數學及計算模型來處理人工智慧種種複雜行為。類神經網路系統架構就如同人類的神經元和受器的建構關係，在接收指令與執行指令之間完成行為模式。而電腦最基本的數學運算及統計系統就是建構在類神經網路的應用上。</p>

<h4 id="智慧型代理人intelligent-agent">智慧型代理人（Intelligent Agent）</h4>
<p>人工智慧中的智慧型代理能利用快速且精確的運算能力達成目標。同時具有三大特性：自主能力（autonomous）、反應能力（reactivity）和交互作用能力（interactive）。智慧型代理人藉由他的自主主體性在進行決策時，能針對事項進行反應，並且各個代理人之間得以溝通、合作來達成最終目的。常見的例子像是蘋果手機的 Siri、聊天機器人 Chatbox 都是智慧型代理人的一種。</p>

<h4 id="自然語言處理natural-language-understanding">自然語言處理（Natural Language Understanding）</h4>
<p>所謂的自然語言相對應程式語言，是人類為了溝通所形成具結構性語法的語言。而自然語言的處理主要透過演算法讓電腦理解自然語言，並實際執行指令。運作方式是將語法架構拆解以便理解並生成語言。從簡單普遍的拼字檢查、關鍵字搜尋，到複雜的機器翻譯和語意分析都是依賴自然語言處理的功能達成的。</p>

<h2 id="其他連結">其他連結</h2>
<ol>
  <li>課程內容：
    <ol>
      <li><a href="https://codefree.hiskio.com/courses/4">Codefree - 電腦科學（上）</a></li>
      <li><a href="https://codefree.hiskio.com/courses/5">Codefree - 電腦科學（中）</a></li>
      <li><a href="https://codefree.hiskio.com/courses/6">Codefree - 電腦科學（下）</a></li>
    </ol>
  </li>
  <li>課程筆記：
    <ol>
      <li><a href="https://cynthiachuang.github.io/Hiskio-Codefree-Computer-Science-1">CodeFree｜喝一杯咖啡，輕鬆學電腦科學 - 上</a></li>
      <li><a href="https://cynthiachuang.github.io/Hiskio-Codefree-Computer-Science-2">CodeFree｜喝一杯咖啡，輕鬆學電腦科學 - 下</a></li>
    </ol>
  </li>
</ol>

<h2 id="參考資料">參考資料</h2>
<ol>
  <li>卞哲琛, Et al.。<a href="https://sites.google.com/site/nutncsie11037/home">煞氣a精靈部隊之期末 ALL PASS 版本計算機概論重點整理</a>。檢自 nutncsie11037 (2022-07-12)。</li>
  <li>陳思翰 (2011-03-04)。<a href="https://www.ithome.com.tw/tech/92046">認識IPv4與IPv6的差異</a>。檢自 iThome (2022-07-29)。</li>
  <li>協同撰寫。<a href="https://zh.wikipedia.org/zh-tw/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE">超文本傳輸協定</a> 。檢自 維基百科 (2022-07-29)。</li>
  <li>bettywutalk。<a href="https://bettywutalk.com/blog/domains/#3_xin_ding_ji_yu_ming_New_gTLD_New_Generic_Top-Level_Domain">主網域、子網域、網域寄放和附加網域是什麼？對SEO有何影響？</a>。檢自 矽谷獨角獸學院 (2022-07-29)。</li>
  <li><a href="https://tw.godaddy.com/help/what-is-a-subdomain-296">什麼是子網域？</a>。檢自 GoDaddy TW (2022-07-29)。</li>
  <li>Hannah Lin (2021-05-22)。<a href="https://medium.com/hannah-lin/從零開始學資安-什麼是資訊安全-75a7a208e8db">從零開始學資安 — 什麼是資訊安全?. 網路上的資訊安全文章普遍深澀所以想寫簡單易懂的一系列文章。</a>。檢自 Medium (2022-08-02)。</li>
  <li>Ugnė Mikalajūnaitė (2020-10-25)。<a href="https://nordvpn.com/zh-tw/blog/heike-shi-shenme/">駭客是什麼</a>。檢自 NordVPN (2022-08-02)。</li>
  <li>Po-Ching Liu (2017-12-28)。<a href="https://totoroliu.medium.com/編譯語言-vs-直譯語言-5f34e6bae051">編譯語言 VS 直譯語言</a>。檢自 Medium (2022-09-02)。</li>
  <li>吳其勳 (2011-06-21)。<a href="https://www.ithome.com.tw/article/93013">徹底了解Cloud Computing｜部署模式</a>。檢自 iThome (2022-09-16)。</li>
  <li>呂同塵 (2018-11)。<a href="https://www.eisland.com.tw/Main.php?stat=a_yg2Y8Hs">圖解演算法：演算法是什麼？</a>。檢自 英語島 (2022-09-20)。</li>
  <li>莊泉福, 黃慶福 (2018-11)。<a href="https://sites.google.com/cycu.org.tw/python/ch-5-演算法虛擬碼與流程圖">Python 程式設計與邏輯思維</a>。檢自 自然組 (2022-09-22)。</li>
</ol>

<h2 id="更新紀錄">更新紀錄</h2>
<details class="update_stamp">
  <summary>最後更新日期：2024-01-09</summary>
  <ul>
    <li>2024-01-09 更新：新增人工智慧介紹網誌連結。</li>
    <li>2022-10-07 發布</li>
    <li>2022-09-29 完稿</li>
    <li>2022-07-29 起稿</li>
  </ul>
</details>]]></content><author><name>辛西亞．Cynthia</name></author><category term="硬體系統 › 計算機系統" /><category term="計算機概論" /><category term="讀書筆記" /><category term="Hiskio" /><summary type="html"><![CDATA[今天又是喝咖啡學習系列，不過不是學程式，而是學電腦科學。筆記內容包括上、中、下三門課。 這門課看了下內文其實就是計算機概論，有點令人懷念的一門課…想當初算二進制還算到超挫折的 XDDD 不過總感覺這篇不是在寫讀書筆記，而是重寫了一次課程？很多東西它沒提到，是我自己忽然想到其他關鍵字就一併寫進去了 XDDD]]></summary></entry><entry><title type="html">ID驗證系列｜公司統一編號驗</title><link href="https://cynthiachuang.github.io/Check-Tax-ID-Number/" rel="alternate" type="text/html" title="ID驗證系列｜公司統一編號驗" /><published>2023-12-20T00:07:00+00:00</published><updated>2023-12-20T00:07:00+00:00</updated><id>https://cynthiachuang.github.io/Check-Tax-ID-Number</id><content type="html" xml:base="https://cynthiachuang.github.io/Check-Tax-ID-Number/"><![CDATA[<p>又是不務正業的一篇 XDDD  <br />
不過統編的資料有點少，所有的資料看來都出自同一個地方。</p>

<!--more-->
<p class="illustration">
    <img src="https://i.imgur.com/GPyBBgm.jpg?1" alt="公司統一編號" />
    公司統一編號
</p>

<div class="alert warning">
<div class="head">公司統一編號驗證檢查碼邏輯修正說明</div>
1. 統一編號預估空號將於 2024 年用罄，故擴增統一編號。<br />
2. 為相容新舊統一編號，檢查邏輯由可被『10』整除改為可被『5』整除。<br />
   `Sum%10=0` -&gt; `Sum%5=0` <br />
3. 預計 <b>2023 年 4 月</b>以後，逐步釋出新統一編號。<br />
4. 不過是說 2023 年才釋出的編號，我改這麼快幹嘛啦 XD<br />
</div>

<h2 id="編號規則">編號規則</h2>
<p>目前現行的統編是 <strong>8 個數字</strong>。在驗證時，會將其乘上相對應的權重分別得到每個位元乘積的十位與個位數的：</p>

<table>
  <thead>
    <tr>
      <th>Index</th>
      <th>$n_0$</th>
      <th>$n_1$</th>
      <th>$n_2$</th>
      <th>$n_3$</th>
      <th>$n_4$</th>
      <th>$n_5$</th>
      <th>$n_6$</th>
      <th>$n_7$</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>權重</td>
      <td>1</td>
      <td>2</td>
      <td>1</td>
      <td>2</td>
      <td>1</td>
      <td>2</td>
      <td>4</td>
      <td>1</td>
    </tr>
    <tr>
      <td>乘積十位數</td>
      <td>$t_0$</td>
      <td>$t_1$</td>
      <td>$t_2$</td>
      <td>$t_3$</td>
      <td>$t_4$</td>
      <td>$t_5$</td>
      <td>$t_6$</td>
      <td>$t_7$</td>
    </tr>
    <tr>
      <td>乘積個位數</td>
      <td>$d_0$</td>
      <td>$d_1$</td>
      <td>$d_2$</td>
      <td>$d_3$</td>
      <td>$d_4$</td>
      <td>$d_5$</td>
      <td>$d_6$</td>
      <td>$d_7$</td>
    </tr>
  </tbody>
</table>

<p>再將每個位元的乘積的十位與個位數兩兩相加，得到一新的 8 碼數字 $s_0s_1s_2s_3s_4s_5s_6s_7$：</p>

\[s_i = t_i + d_i，\text{ where }  0 \le i \le 7 \text{ and } 0 \le s_i &lt; 10\]

<p><br class="big" /></p>

<p>最後新的 8 碼數字總和若為 <strong>10 的倍數</strong>，即為有效的驗證碼。</p>

\[Sum\%10=0，\text{ where }  Sum = \sum_{i=0}^{7}s_i\]

<p>不過在 <strong>2023 年 4 月</strong>逐步釋出新的統一編號後，若為相容新舊統一編號，則應檢查數字總和是否為 <strong>5 的倍數</strong>：</p>

\[Sum\%5=0，\text{ where }  Sum = \sum_{i=0}^{7}s_i\]

<h3 id="例外n_6--7">例外：$n_6 = 7$</h3>
<p>不過上述的計算過程中，會有一個例外情況，就是當 $n_6 = 7$ 時，當其乘上對應權重 $4$ 後，會得到：</p>

\[t_6 = 2 , d_6 = 8\]

<p>但，兩者相加後，其值會大於 10：</p>

\[s_6 = t_6 + d_6 = 2 + 8 = 10\]

<p><br class="big" /></p>

<p>當遇到這情況時，會採用一個折衷的方法，將 $10$ 的兩個位數分別當成：</p>

\[s_6 = 1, s_6' = 0\]

<p><br class="big" /></p>

<p>把這兩個數分別計算總和，得到 $Sum$ 與 $Sum’$ ：</p>

\[Sum = \sum_{i=0}^{7}s_i \text{ , }
Sum' = \sum_{i=0, i \not = 6}^{7}s_i + s_6'\]

<p><br class="big" /></p>

<p>若其中一個和為 <strong>10 的倍數</strong>，即為有效的驗證碼。</p>

\[Sum\%10=0 \text{ or } Sum'\%10=0\]

<p>一樣若在新版統編釋出後，為相容兩者檢查邏輯則改為：其中一個和為 <strong>5 的倍數</strong></p>

\[Sum\%5=0 \text{ or } Sum'\%5=0\]

<h2 id="程式碼">程式碼</h2>
<p>這次驗證規則有點瑣碎，regexp 只能用來驗證是否為數字與長度。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>^\d{8}$
</code></pre></div></div>

<p><br class="big" /></p>

<p>至於其他的驗證只能靠程式了，regexp 派不上用場，對了這次是 C++。偷個懶直接把 checkNumber 拉成變數並設置為 5，就自己視需求要用 10 或 5。</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;regex&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="kt">bool</span> <span class="nf">checkTaxId</span><span class="p">(</span><span class="n">string</span> <span class="n">taxId</span><span class="p">);</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[]){</span>
    <span class="kt">int</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> 
    <span class="k">while</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="o">++</span><span class="n">count</span><span class="p">]);</span>

    <span class="k">if</span><span class="p">(</span><span class="n">count</span><span class="o">!=</span><span class="mi">2</span><span class="p">){</span>
        <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Give me an Tax-ID-Number!!!!"</span><span class="p">;</span>
        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="n">string</span> <span class="n">taxId</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> 
 
    <span class="kt">bool</span> <span class="n">verification</span> <span class="o">=</span> <span class="n">checkTaxId</span><span class="p">(</span><span class="n">taxId</span><span class="p">);</span>	
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">boolalpha</span> <span class="o">&lt;&lt;</span> <span class="n">verification</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">bool</span> <span class="n">checkTaxId</span><span class="p">(</span><span class="n">string</span> <span class="n">idStr</span><span class="p">){</span>
    <span class="n">regex</span> <span class="n">reg</span><span class="p">(</span><span class="s">"^</span><span class="se">\\</span><span class="s">d{8}$"</span><span class="p">);</span>
    <span class="n">smatch</span> <span class="n">m</span><span class="p">;</span>
    <span class="n">ssub_match</span> <span class="n">sm</span><span class="p">;</span>
    
    <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">regex_match</span><span class="p">(</span><span class="n">idStr</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="n">reg</span><span class="p">)){</span>
        <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Fail, 長度錯誤"</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>
        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="mi">8</span>  <span class="p">;</span>
    <span class="kt">int</span> <span class="n">idArray</span><span class="p">[</span><span class="n">len</span><span class="p">];</span>
    <span class="kt">int</span> <span class="n">weight</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">1</span><span class="p">};</span>

    <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
         <span class="c1">// conver char to int </span>
        <span class="n">idArray</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">idStr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">-</span> <span class="sc">'0'</span> <span class="p">;</span>
        <span class="kt">int</span> <span class="n">p</span> <span class="o">=</span> <span class="n">idArray</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">weight</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
        <span class="kt">int</span> <span class="n">s</span> <span class="o">=</span> <span class="n">p</span><span class="o">/</span><span class="mi">10</span> <span class="o">+</span> <span class="n">p</span><span class="o">%</span><span class="mi">10</span><span class="p">;</span>
        <span class="n">s</span> <span class="o">=</span> <span class="n">s</span><span class="o">==</span><span class="mi">10</span><span class="o">?</span><span class="mi">0</span><span class="o">:</span><span class="n">s</span><span class="p">;</span>
        <span class="n">sum</span> <span class="o">+=</span> <span class="n">s</span> <span class="p">;</span>  
    <span class="p">}</span>

    <span class="c1">// when s[6]==7, after adding the two, its value will be equal to 10, in this case, 1 or 0 should be used to calculate the sum. But here 10 is used directly to calculate the sum, because if 0 and 10 are used to take the remainder, both are 0; if 1 is taken to take the remainder as 0, it can be reversed that the remainder should be 9.  </span>
    <span class="kt">int</span> <span class="n">checkNumber</span> <span class="o">=</span> <span class="mi">5</span> <span class="p">;</span>
    <span class="kt">bool</span> <span class="n">isLegal</span> <span class="o">=</span> <span class="n">sum</span><span class="o">%</span><span class="n">checkNumber</span><span class="o">==</span><span class="mi">0</span> <span class="o">||</span> <span class="p">((</span><span class="n">sum</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">%</span><span class="n">checkNumber</span><span class="o">==</span><span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">idArray</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span><span class="o">==</span><span class="mi">7</span><span class="p">);</span>

    <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">isLegal</span><span class="p">){</span>
        <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"Fail, 不合法的統編驗證"</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span>   
    <span class="p">}</span>

    <span class="k">return</span> <span class="n">isLegal</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="參考資料">參考資料</h2>
<ol>
  <li>林壽山 (2013-03-17)。<a href="https://superlevin.ifengyuan.tw/%E7%87%9F%E5%88%A9%E4%BA%8B%E6%A5%AD%E7%B5%B1%E4%B8%80%E7%B7%A8%E8%99%9F%E9%82%8F%E8%BC%AF%E6%AA%A2%E6%9F%A5%E6%96%B9%E6%B3%95/">營利事業統一編號邏輯檢查方法</a> 。檢自 Levin’s Blog-林壽山 (2020-10-23)。</li>
  <li>hero (2018-11-07)。<a href="http://herolin.webhop.me/entry/is-valid-TW-company-ID/">營利事業統一編號驗證完全手冊(Javascript,Java,C#,PHP)</a> 。檢自 Hero Think~用手摀住我的嘴 (2020-10-23)。</li>
  <li>beethobear (2006-10-30)。<a href="http://phorum.study-area.org/index.php/topic,11397.html">[商用軟體]統一編號檢查碼規則</a> 。檢自 酷!學園 (2020-10-23)。</li>
  <li>電子發票組 (2021-12-22)。<a href="https://www.fia.gov.tw/singlehtml/3?cntId=c4d9cff38c8642ef8872774ee9987283">營利事業統一編號檢查碼邏輯修正說明</a> 。檢自 財政部財政資訊中心 (2022-05-01)。</li>
</ol>

<h2 id="更新紀錄">更新紀錄</h2>
<details class="update_stamp">
  <summary>最後更新日期：2023-12-20</summary>
  <ul>
    <li>2023-12-20 更新：使計算過程與文件相符，但不影響判別是否為合法統編</li>
    <li>2022-05-01 更新：檢查碼邏輯修正說明</li>
    <li>2022-05-01 更新：檢查碼判別式錯誤修正</li>
    <li>2020-12-31 發布</li>
    <li>2020-10-24 完稿</li>
    <li>2020-10-23 起稿</li>
  </ul>
</details>]]></content><author><name>辛西亞．Cynthia</name></author><category term="先備知識" /><category term="編碼規則" /><category term="C/C++" /><category term="regexp" /><category term="臺灣ID驗證系列" /><summary type="html"><![CDATA[又是不務正業的一篇 XDDD 不過統編的資料有點少，所有的資料看來都出自同一個地方。]]></summary></entry><entry><title type="html">Survey｜Label Studio</title><link href="https://cynthiachuang.github.io/Survey-Label-Studio/" rel="alternate" type="text/html" title="Survey｜Label Studio" /><published>2023-12-20T00:00:00+00:00</published><updated>2023-12-20T00:00:00+00:00</updated><id>https://cynthiachuang.github.io/Survey-Label-Studio</id><content type="html" xml:base="https://cynthiachuang.github.io/Survey-Label-Studio/"><![CDATA[<p>我竟然還是從草稿夾中把這篇給翻出來填坑…。上次搞這個都是一年前了，但最近又被重新 assign 了這個 project，也只能重新去把記憶給找回來了。嘖…要回想一年多前做了什麼事情真是難倒我了＝＝</p>

<p>上次看的時候時候版本還是 1.0，現在都 1.6 啦…不過筆記應該沒有差多少？應該…</p>

<!--more-->
<p class="illustration">
    <img src="https://i.imgur.com/rlEl5Z6.png" alt="Label Studio" />
    Label Studio（圖片來源: <a href="https://github.com/heartexlabs/label-studio">GitHub</a>）
</p>

<h2 id="overview">Overview</h2>
<p>故事的開始好像是從 CVAT 開始，它是套是開源的影像標注工具，功能雖然完善但主要專注於影像方面，界面也稍嫌複雜。如果要標注文本或是 NLP 就需要另尋它法…雖然我拿 excel 也能標啦 XDDD</p>

<p>在找標注工具時，大概考慮了幾個點：</p>
<ol>
  <li><strong>開源</strong>：<del>大概是因為老闆不想多付錢 XDDD</del></li>
  <li><strong>友好界面，有 UI 支援更加</strong>：都得標文字資料，再不來點 UI 洗洗眼睛，應該很快就膩了。</li>
  <li><strong>協作功能</strong>：相信我不會想要一個人標完整個資料集。</li>
  <li><strong>管理機制</strong>：主要是看訪控權限跟 project 管理機制，免得有天兵砍我資料（也不是沒發生過＝＝。</li>
</ol>

<p>我是有看到一套我還滿喜歡的 <a href="https://demo.prodi.gy/?=null&amp;view_id=ner_manual">Prodigy</a>，不過它看起來只能標注文本，重點是它不是開源的。Survey 到最後上位的就是 Label Studio 啦～！</p>

<p class="illustration">
    <img src="https://i.imgur.com/toUwkBX.png" alt="What is Label Studio?" />
    What is Label Studio?（圖片來源: <a href="https://labelstud.io/">Label Studio 官網</a>）
</p>

<p>忽然意識到他們有換配色耶，尾巴的顏色也不太一樣了…不過好像舊版的顏色比較合我胃口？</p>

<h3 id="labeling-workflow">Labeling Workflow</h3>
<p>開始看 Label Studio 之前，先看下標注流程，因為無論是要進行人工標注（Human Labeling）或是半監督學習（Semi-supervised Labeling），第一步都是資料標注。</p>

<p>其中人機協作是常見的資料標注流程：</p>
<ol>
  <li><strong>資料收集</strong>：<br />
 通過爬蟲、程式或者其它工具，將資料保存到資料庫中。</li>
  <li><strong>資料前處理/資料標注</strong>：<br />
 因為收集回來的資料多是雜亂無章的，若要標注、甚至進行訓練前，都必需先將資料進行清洗。清洗完的資料可以直接用於無監督學習（Unsupervised Labeling）做預訓練模型，也可以將整理後的資料進行標注，變成有標籤資料。<br /><br />	
 標注的方式與目標，會依照訓練目的而有所不同。例如對於文本的標注有：文本分類、命名實體識別、文本摘要…等；對於音訊可以做講者分類、情緒識別或轉錄…等；對於圖片則可能有圖像分類、物件檢測、語義分割…等。<br /><br />	
 是說，如果是多人協作標注資料，最好在開始前確定標注原則…至少…確定要使用的標籤，別出現一人標貓、一人標 cat。</li>
  <li><strong>模型訓練</strong>：<br />
 有了標注完成的資料後，即可將資料導入，從無到有進行訓練；或者選擇在該領域或是其他領域的模型進行 Fine-Tune 或遷移學習（Transfer Learning）。</li>
  <li><strong>模型評估</strong>：<br />
 當訓練完成後，使用測試集或是新收集的資料進行檢驗，若是訓練結果無法有良好的表現，可能需要調整參數重新訓練。</li>
  <li><strong>重新訓練 or 模型部署</strong>：<br />
 	不斷重複前 1～4 步，以優化模型和資料，提高模型性能。一旦取得合乎預期的表現後，就可將模型進一步部署在設備端或伺服器上。
    <p class="illustration">
     <img src="https://i.imgur.com/V7KOD9m.png" alt="Usually Labeling Workflow" />
     Usually Labeling Workflow（圖片來源: <a href="https://towardsdatascience.com/introducing-label-studio-a-swiss-army-knife-of-data-labeling-140c1be92881">Towards Data Science</a>）
 </p>
  </li>
</ol>

<h3 id="what-is-label-studio">What is Label Studio?</h3>
<p>通常完成上述的步驟需耗時數週到數月的時間，所以 Heartex 的首席技術官希望能整合相關功能到自動化的平台，從而減少技術團隊的產品、機器學習的開發、實驗時間學習生命週期。</p>

<p><br class="big" /></p>

<p>Heartex 就是推出 Label Studio 的公司，而 Label Studio 是一套開源的標注工具，它可應用範圍很廣，包含圖片、音訊、文字、影片…等格式的資料。此外它還提供簡明 UI 可快速配置多種資料，能在 10 分鐘內準備好工具，用以標注文本、音訊或圖像…等資料格式。</p>

<p>它另外一個宣傳點則是可將 Label Studio 與機器學習模型進行集成。機器學習可以用來協助標注，以提供標籤預測（預標籤），並可執行持續的主動學習。</p>

<p>不過有些我希望的功能，例如：訪控權限，並不是在開源版本中，不過我這還能接受 XDDD</p>

<p class="illustration">
	<img src="https://i.imgur.com/CzmobYV.png" alt="Usually Labeling Workflow" />
	Usually Labeling Workflow（圖片來源: <a href="https://towardsdatascience.com/introducing-label-studio-a-swiss-army-knife-of-data-labeling-140c1be92881">Towards Data Science</a>）
</p>

<h3 id="components-and-architecture">Components and Architecture</h3>
<p>根據 Label Studio 的軟體架構圖，系統可以大致分成：<strong>Frontend</strong>、<strong>Backend</strong>、<strong>Task</strong>、<strong>ML Backend</strong> 4 個部份：</p>

<p class="illustration">
	<img src="https://i.imgur.com/sE306vT.png" alt="Label Studio Architecture" />
Label Studio Architecture（圖片來源: <a href="https://labelstud.io/guide/index.html#Components-and-architecture">Label Studio Documentation</a>）
</p>

<p>顧名思義，各元件負責前端、執行標注、標籤資料與任務管理、以及串接 ML Backend 的部份。各個元件基本都有提供 <a href="https://labelstud.io/guide/index.html#Components-and-architecture">Source Code</a>，方便開發者自行客製化。</p>

<p>從表中也可以看到各元件的實做方法中，其中大概除了 <a href="https://github.com/mobxjs/mobx-state-tree">MST</a> 我可能找不到替罪同事外，其他應該都可以？而且授權看來都是 <strong>Apache 2.0 LICENSE</strong>，所以可以放心改 XDDD</p>

<p class="illustration">
	<img src="https://i.imgur.com/wZU025g.png" alt="Label Studio Components" />
	Label Studio Components（圖片來源: <a href="https://labelstud.io/guide/index.html#Components-and-architecture">Label Studio Documentation</a>）
</p>

<h4 id="label-studio-backend">Label Studio Backend</h4>
<ul>
  <li><a href="https://github.com/heartexlabs/label-studio/">heartexlabs/label-studio</a></li>
</ul>

<p>基本上，Backend 是它主體了 XDDD 在這份 Source Code 中，你可以找到 frontend 跟 data_manager。安裝所用的 docker 與 docker-compose 都出自於這一份。</p>

<h4 id="label-studio-frontend">Label Studio Frontend</h4>
<ul>
  <li>A. <a href="https://github.com/heartexlabs/label-studio/tree/master/label_studio/frontend">heartexlabs / label_studio/frontend</a></li>
  <li>B. <a href="https://github.com/heartexlabs/label-studio-frontend">heartexlabs / label-studio-frontend</a></li>
</ul>

<p>A 混在 Backend 的 project 內，安裝 Backend 時會順便起起來，如果要直接起則是 B。但目前從 commit 看來兩邊專案似乎不齊頭？</p>

<p>這個專案所使用到的技術，就是我們在上表看到的 React 跟 MST（mobx-state-tree）。</p>

<h4 id="data-manager">Data Manager</h4>
<ul>
  <li><a href="https://github.com/heartexlabs/dm2">heartexlabs/dm2</a></li>
</ul>

<p class="illustration">
	<img src="https://i.imgur.com/tTP9yoD.png" alt="Data exploration tool for Label Studio." />
	Data exploration tool for Label Studio.（圖片來源: <a href="https://github.com/heartexlabs/dm2">GitHub</a>）
</p>

<p>這專案可讓使用者輕鬆探索資料集，可以選擇如何查看與顯示的資料，如：網格和列表視圖…等。當然這個專案必須跟前端集成，因為 DataManager 使用 LabelStudio API 進行操作。</p>

<p class="illustration">
	<img src="https://i.imgur.com/mIWHD8y.png" alt="LabelStudio API Workflow" />
	LabelStudio API Workflow（圖片來源: <a href="https://github.com/HumanSignal/dm2/blob/master/docs/dm_architecture_diagram.pdf">dm2｜GitHub</a>）
</p>

<h4 id="machine-learning-backends">Machine Learning Backends</h4>
<ul>
  <li><a href="https://github.com/heartexlabs/label-studio-ml-backend">heartexlabs/label-studio-ml-backend</a></li>
</ul>

<p>Machine Learning Backends 是一個 SDK，可讓使用者封裝機器學習程式碼並將其變成換為 Web 服務器。最後將該服務器連接到 Label Studio Instance 以執行 2 個任務：</p>

<ol>
  <li>基於模型推理結果動態預標注資料</li>
  <li>根據最近注釋的資料重新訓練或微調模型</li>
</ol>

<h4 id="label-studio-enterprise-edition">Label Studio Enterprise Edition</h4>
<p>官網是建議，在客製化之前先參考下 Label Studio Enterprise Edition 咩，有了它就可以不用自己造輪子了呦～！不過我沒研究過他的<a href="https://labelstud.io/guide/billing.html">收費標準</a>，有考慮的可能得查一下。</p>

<p class="illustration">
	<img src="https://i.imgur.com/MqJnisw.png" alt="Label Studio Features" />
	Label Studio Features（圖片來源: <a href="https://labelstud.io/guide/index.html#Components-and-architecture">Label Studio Documentation</a>）
</p>

<p>是說…那個訪控權限跟標注 review 的功能，看起來就很棒！</p>

<h3 id="data-type">Data Type</h3>
<p>它們能支援的格式或說標注動作還不少，以資料類型來說大致包含了 <mark>Images、 Audio、 Text、 Time Series、 Multi-Domain、 Video</mark>：</p>

<ol>
  <li><strong>Images</strong>
    <ul>
      <li>支援圖片分類、物體檢測、語義分割。</li>
    </ul>
  </li>
  <li><strong>Audio</strong>
    <ul>
      <li>支援音源分類、講者分類、情緒識別、轉錄。</li>
    </ul>
  </li>
  <li><strong>Text</strong>
    <ul>
      <li>支援文檔分類、NER、問答、情緒分析。</li>
    </ul>
  </li>
  <li><strong>Time Series</strong>
    <ul>
      <li>支援時間序列分類、分割、事件識別。</li>
    </ul>
  </li>
  <li><strong>Multi-Domain</strong>
    <ul>
      <li>支援對話處理（呼叫中心錄音可以同時轉錄和處理為文本）、OCR、將影像或音檔分割時間序列數。</li>
    </ul>
  </li>
  <li><strong>Video</strong>
    <ul>
      <li>支援影像分類、物件追蹤、輔助標記。</li>
    </ul>
  </li>
</ol>

<p class="illustration">
	<img src="https://i.imgur.com/1re3sxj.gif" alt="Label every data type." />
	Label every data type.（圖片來源: <a href="https://labelstud.io/">Label Studio</a>）
</p>

<p>各資料所能接受的資料格式如下，不過我好像沒看到 video 的資料格式？是還沒更新上去嗎（video 是 1.6 版新增的）？</p>

<p class="illustration">
	<img src="https://i.imgur.com/ALRMGe9.png" alt="Types of data you can import" />
	Types of data you can import（圖片來源: <a href="https://labelstud.io/guide/tasks.html#Types-of-data-you-can-import-into-Label-Studio">Label Studio Documentation</a>）
</p>

<h3 id="pros-and-cons">Pros and Cons</h3>
<p>稍微玩了下這套工具，簡單列些優缺點。不過在開始前先看看官方給的優點：</p>
<ol>
  <li>
    <p><strong>簡單</strong>：<br />
 沒有複雜的配置，並且易於集成到機器學習管道中。</p>
  </li>
  <li>
    <p><strong>可針對多種資料類型快速配置</strong>：<br />
 可在 10 分鐘內準備好工具，以在標記文本、音源與圖像之間切換。甚至可以同時標注三種類型，不過這種複合式的用法得自製 template 才可用。</p>

    <p class="illustration">
 <img src="https://i.imgur.com/lvZrPku.png" alt="同時標注三種類型" />
 同時標注三種類型
 </p>
  </li>
  <li>
    <p><strong>機器學習集成</strong> <br />
 它能與所有眾多的機器學習框架和模型集成。ML 有許多不同的約束條件應用程序，Label Studio 必須足夠靈活以處理它們並提供幫助，而不是使其複雜化。</p>
  </li>
</ol>

<p><br class="big" /></p>

<p>玩完後，它確實可以稱得上它所宣稱的優點：</p>
<ol>
  <li><strong>界面相對漂亮</strong><br />
 這套算是我玩過工具中，界面比較漂亮的。</li>
  <li><strong>部署方便</strong><br />
 它提供了 2～3 種的部署方式，且每種方式的部署也都還滿簡單的。</li>
  <li><strong>配置方便，且有多種內置模板與支持多種資料類型</strong><br />
 這前面說過了，就不再提了。</li>
  <li><strong>機器學習集成</strong><br />
 可以串接訓練好的推論服務，達到輔助標注的目的。</li>
</ol>

<p>至於缺點的部份，除了權限機制跟 plug-in 的部份（好吧，這其實也不太算是缺點，是閹割的結果）外，我覺得比較麻煩的是的是它的<strong>錯誤訊息難以閱讀</strong>，這蟲要抓會很麻煩 XDDD</p>

<p class="illustration">
<img src="https://i.imgur.com/rmaUE5O.png" alt="Label Studio 界面" />
Label Studio 界面（圖片來源: <a href="https://labelstud.io/guide/tasks.html#Types-of-data-you-can-import-into-Label-Studio">Label Studio Documentation</a>）
</p>

<h2 id="quick-start">Quick start</h2>
<p>OK，來試著安裝它吧！先貼傳送門，等等應該用的上：</p>
<ul>
  <li><a href="https://labelstud.io/guide/install.html">Install and upgrade Label Studio</a></li>
  <li><a href="https://labelstud.io/guide/start.html">Start Label Studio</a></li>
  <li><a href="https://labelstud.io/guide/storedata.html">Database setup</a></li>
</ul>

<h3 id="system-requirements">System requirements</h3>
<p>安裝前先確定下安裝環境，主要是儲存空間的部份，特別是如果是要作為 production 那空間需要特別注意：</p>

<ol>
  <li><strong>軟體要求</strong>
    <ul>
      <li>Python 3.6 +（不過我覺得應該要 <strong>Python 3.7</strong> + 才對？）</li>
      <li>Linux、Windows or MacOSX</li>
      <li>PostgreSQL 11.5 版 or  SQLite 3.35 +</li>
    </ul>
  </li>
  <li><strong>空間</strong>
    <ul>
      <li>使用 SQLite 資料庫時，100 萬筆的標注任務佔用大約 2.3GB 的硬碟空間。若是要作為 production，建議使用 <strong>50GB</strong> 的硬碟空間。</li>
      <li>至於記憶體的部份至少使用 8GB RAM，但<strong>建議使用 16GB RAM</strong>。</li>
    </ul>
  </li>
</ol>

<h3 id="install-label-studio--start-label-studio">Install Label Studio &amp; Start Label Studio</h3>
<p>他的安裝方式有 4 種，可以依照需要的方式來安裝：</p>

<ol>
  <li>
    <p><strong>pip</strong><br />
 這大概是最簡單的安裝方式，不過需要注意下 Python 版本，文件中有說需要 <strong>Python 3.7 +</strong> 的版本：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>pip <span class="nb">install</span> <span class="nt">-U</span> label-studio
 <span class="nv">$ </span>label-studio
</code></pre></div>    </div>

    <p><br class="big" /></p>

    <p>啟動時，默認 Web 瀏覽器會在 <code class="language-plaintext highlighter-rouge">http://localhost:8080</code>。 這個方式在啟動時是資料庫是使用 SQLite，如果要用 PostgreSQL 可以在啟動時設定：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>label-studio start my_project <span class="nt">--init</span> <span class="nt">-db</span> postgresql
</code></pre></div>    </div>

    <p>不過還需要設定點環境變數：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">DJANGO_DB</span><span class="o">=</span>default
 <span class="nv">POSTGRE_NAME</span><span class="o">=</span>postgres
 <span class="nv">POSTGRE_USER</span><span class="o">=</span>postgres
 <span class="nv">POSTGRE_PASSWORD</span><span class="o">=</span>
 <span class="nv">POSTGRE_PORT</span><span class="o">=</span>5432
 <span class="nv">POSTGRE_HOST</span><span class="o">=</span>db
</code></pre></div>    </div>

    <p><br class="big" /></p>

    <p>另外，還有個參數我覺得應該也能派上用場： <code class="language-plaintext highlighter-rouge">LABEL_STUDIO_BASE_DATA_DIR</code> / <code class="language-plaintext highlighter-rouge">--data-dir</code>，前者用在環境變數、後者用在命令列，不過目的是一樣，從文件中看來這個值應該可以讓每次啟動都讀到相同的資料庫…不然每次啟動都要重標資料？怎麼可能啦 XDDD</p>
  </li>
  <li><strong>Docker</strong><br />
 	這個大概是我比較常用的方法：
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>docker run <span class="nt">-it</span> <span class="nt">-p</span> 8080:8080 <span class="nt">-v</span> <span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span>/mydata:/label-studio/data heartexlabs/label-studio:latest
</code></pre></div>    </div>

    <p>在 mount 進去的 mydata 資料夾後，會看到存放資料的資料夾 media 跟與標籤存放的 <code class="language-plaintext highlighter-rouge">label_studio.sqlite3</code>。若要換成 PostgreSQL 或是指定資料庫的話可以用 <code class="language-plaintext highlighter-rouge">-e</code> 的參數搭配 <code class="language-plaintext highlighter-rouge">LABEL_STUDIO_DATABASE</code>、<code class="language-plaintext highlighter-rouge">LABEL_STUDIO_BASE_DATA_DIR</code> 這兩個環境變數使用。</p>

    <p><br class="big" /></p>

    <p>不過我這次在玩 1.6 時候會遇到，一連串 <code class="language-plaintext highlighter-rouge">OpenBLAS blas_thread_init</code> 的 error：</p>

    <p class="illustration">
 <img src="https://i.imgur.com/qUsoNyU.png" alt="Label Studio 界面" />
 Label Studio 界面（圖片來源: <a href="https://labelstud.io/guide/tasks.html#Types-of-data-you-can-import-into-Label-Studio">Label Studio Documentation</a>）
 </p>

    <p>對於這個我有點莫名奇妙，想想看當你上一秒用 1.0 跑得很愉快的時候，下一秒發現有更新，就順手換到 1.6 版，然後就 GG 了…你能想像這有多崩潰阿 XDDD</p>

    <p>而且最悲劇的是，我在 <a href="https://labelstud.io/guide/index.html">Label Studio Documentation</a> 找不到相關的訊息，還好最後 <a href="https://github.com/heartexlabs/label-studio/blob/6efe3b21aad7ba69ed04c28aa68314174c78bfdf/docs/source/guide/install.md#openblas-blas_thread_init-pthread_create-failed-for-thread-x-of-y-operation-not-permitted">git 的 docs</a> 有找到，謝天謝地！</p>

    <p>簡而言之，就是 Docker Engine 的版本太低了，文件中要求 Docker Engine 需要 &gt;= <code class="language-plaintext highlighter-rouge">20.10.12</code>。不過我實驗用的環境是 Ubuntu 16.04，Docker Engine 升不上 <code class="language-plaintext highlighter-rouge">20.10.12</code>  (艹皿艹 )</p>
  </li>
  <li>
    <p><strong>Docker Compose</strong> <br />
是說如果真要部署 production ，應該用 Docker Compose 比較適合</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git clone https://github.com/heartexlabs/label-studio.git
<span class="nv">$ </span><span class="nb">cd </span>label-studio
<span class="nv">$ </span>docker-compose up <span class="nt">-d</span>
Creating network <span class="s2">"label-studio_default"</span> with the default driver
Creating volume <span class="s2">"label-studio_static"</span> with default driver
...
Creating label-studio_db_1 ... <span class="k">done 
</span>Creating label-studio_app_1 ... <span class="k">done
</span>Creating label-studio_nginx_1 ... <span class="k">done</span>
</code></pre></div>    </div>

    <p>完成後可以看到有 3 容器被啟動：</p>
    <ul>
      <li><strong>Label Studio</strong>：就是本體阿。</li>
      <li><strong>Nginx</strong>：proxy web server 是用於加載各種靜態資料，包括上傳的音檔、圖像…等。</li>
      <li><strong>PostgreSQL</strong>：這邊是用於替代性能較低的 SQLite3。</li>
    </ul>

    <p>各容器的詳細設定就直接看看 <a href="https://github.com/heartexlabs/label-studio/blob/develop/docker-compose.yml">docker-compose.yml</a> 吧。</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>docker ps
CONTAINER ID        IMAGE                                         COMMAND                  CREATED              STATUS              PORTS                    NAMES
fdd6ea6bb8b8        nginx:latest                                  <span class="s2">"/docker-entrypoint.…"</span>   About a minute ago   Up About a minute   0.0.0.0:8080-&gt;80/tcp     label-studio_nginx_1
de66bb2f5bfc        heartexlabs/label-studio:latest               <span class="s2">"./deploy/docker-ent…"</span>   About a minute ago   Up About a minute   8080/tcp                 label-studio_app_1
b4108f4d947f        postgres:11.5                                 <span class="s2">"docker-entrypoint.s…"</span>   About a minute ago   Up About a minute   5432/tcp                 label-studio_db_1
</code></pre></div>    </div>
  </li>
  <li>
    <p><strong>Source Code</strong><br />
這邊通常用有需要改動程式碼的時候會用到。例如若要更改前端，可以進入修改 <code class="language-plaintext highlighter-rouge">frontend/</code> 文件夾，不過改完後後，記得重 build：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>label_studio/frontend/
npm ci
npx webpack
<span class="nb">cd</span> ../..
python label_studio/manage.py collectstatic <span class="nt">--no-input</span>
</code></pre></div>    </div>

    <p>是說，如果文件建議改這份前端的話，所以前端是以這份為主？</p>

    <p><br class="big" /></p>

    <p>改完後有兩種用法：</p>
    <ol>
      <li><strong>直接運行</strong>：
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> git clone https://github.com/heartexlabs/label-studio.git
 <span class="nb">cd </span>label-studio
 <span class="c"># Install all package dependencies</span>
 pip <span class="nb">install</span> <span class="nt">-e</span> <span class="nb">.</span>
 <span class="c"># Run database migrations</span>
 python label_studio/manage.py migrate
 <span class="c"># Start the server in development mode at http://localhost:8080</span>
 python label_studio/manage.py runserver
</code></pre></div>        </div>
      </li>
      <li><strong>包成 Docker image</strong>：<br />
 因為我要部署上伺服器，所以我傾向會把它包成 image。在 source code 中有現成的 dockerfile，所以可以直接 build 了，不過需要注意的是，跟 Docker 一樣 Docker Engine 太低會 build 不起來，不然你<a href="https://stackoverflow.com/questions/71941032/why-i-cannot-run-apt-update-inside-a-fresh-ubuntu22-04">會發現它 apt update 會一直 fail</a>。</li>
    </ol>
  </li>
</ol>

<p><br class="big" /></p>

<p>啟動完成後就可以看倒吊的…老鼠（！？）</p>

<p class="illustration">
<img src="https://i.imgur.com/6GL45uv.png" alt="Label Studio 界面" />
Label Studio 界面（圖片來源: <a href="https://labelstud.io/guide/tasks.html#Types-of-data-you-can-import-into-Label-Studio">Label Studio Documentation</a>）
</p>

<p><br class="big" /></p>

<p>喔，<a href="https://labelstud.io/blog/what-s-with-the-label-studio-opossums/">查了一下</a>原來牠是負鼠（opossums），而且人家是女孩子，名叫海蒂（Heidi）XDDD</p>

<p class="illustration">
<img src="https://i.imgur.com/5myGKmv.png" alt="Hi, Heidi" />
Hi, Heidi（圖片來源: <a href="https://labelstud.io/blog/what-s-with-the-label-studio-opossums/">Label Studio</a>）
</p>

<h3 id="labeling-workflow-1">Labeling workflow</h3>
<p>安裝完成並啟動 Label Studio 後，就可以開始嘗試標注：</p>

<h4 id="step1-create-accounts-for-label-studio"><strong>Step1: Create accounts for Label Studio.</strong></h4>
<ul>
  <li><a href="https://labelstud.io/guide/signup.html">Set up user accounts</a></li>
</ul>

<p>開始前須先註冊並建立一個帳戶，以開始標記資料和設置專案。目前有兩種方式可以註冊：</p>
<ol>
  <li>
    <p><strong>UI</strong><br />
 就會看到剛剛那隻爬爬走的負鼠，在頁面中有一個 sing up 的選項。</p>
  </li>
  <li>
    <p><strong>terminal</strong><br />
 另一種是在啟動 Label Studio 時在指令順便建立一個帳號：</p>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>label-studio start <span class="nt">--username</span> &lt;username&gt; <span class="nt">--password</span> &lt;password&gt; <span class="o">[</span><span class="nt">--user-token</span> &lt;token-at-least-5-chars&gt;]
</code></pre></div>    </div>

    <p>如果是用 docker 則是加上 <code class="language-plaintext highlighter-rouge">LABEL_STUDIO_USERNAME</code> 與 <code class="language-plaintext highlighter-rouge">LABEL_STUDIO_PASSWORD</code> 兩個環境變數：</p>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>docker run <span class="nt">-it</span> <span class="nt">-p</span> 8080:8080 <span class="nt">-v</span> <span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span>/mydata:/label-studio/data <span class="nt">-e</span> <span class="nv">LABEL_STUDIO_USERNAME</span><span class="o">=</span>&lt;my-email&gt;  <span class="nt">-e</span> <span class="nv">LABEL_STUDIO_PASSWORD</span><span class="o">=</span>&lt;my-password&gt; heartexlabs/label-studio:latest
</code></pre></div>    </div>

    <p><br class="big" /></p>

    <p>如果要禁用註冊頁面，讓僅有人使用邀請鏈接人使用，在啟動 Label Studio 前加上環境變數：</p>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">export </span><span class="nv">LABEL_STUDIO_DISABLE_SIGNUP_WITHOUT_LINK</span><span class="o">=</span><span class="nb">true</span>
</code></pre></div>    </div>

    <p>再用指令啟動並建立一個基礎帳戶，以用於登入 Label Studio：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>label-studio start <span class="nt">--username</span> &lt;username&gt; <span class="nt">--password</span> &lt;password&gt; <span class="o">[</span><span class="nt">--user-token</span> &lt;token-at-least-5-chars&gt;]
</code></pre></div>    </div>

    <p>或是直接在 docker 啟動指令上加上環境變數：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>docker run <span class="nt">-it</span> <span class="nt">-p</span> 8080:8080 <span class="nt">-v</span> <span class="sb">`</span><span class="nb">pwd</span><span class="sb">`</span>/mydata:/label-studio/data <span class="nt">-e</span> <span class="nv">LABEL_STUDIO_DISABLE_SIGNUP_WITHOUT_LINK</span><span class="o">=</span><span class="nb">true</span> <span class="nt">-e</span> <span class="nv">LABEL_STUDIO_USERNAME</span><span class="o">=</span>&lt;my-email&gt;  <span class="nt">-e</span> <span class="nv">LABEL_STUDIO_PASSWORD</span><span class="o">=</span>&lt;my-password&gt; heartexlabs/label-studio:latest
</code></pre></div>    </div>

    <p>登入 Label Studio 後，再邀請協作者。</p>
  </li>
</ol>

<h4 id="step2-set-up-the-labeling-projectset-up-the-labeling-interface"><strong>Step2: Set up the labeling project/Set up the labeling interface.</strong></h4>
<ul>
  <li><a href="https://labelstud.io/guide/setup_project.html">Set up your labeling project</a></li>
  <li><a href="https://labelstud.io/guide/setup.html">Set up your labeling interface</a></li>
  <li><a href="https://labelstud.io/guide/tasks.html">Get data into Label Studio</a></li>
  <li><a href="https://labelstud.io/guide/labeling.html">Label and annotate data</a></li>
</ul>

<p>先針對要標記的資料，定義標記類型並配置專案設置：</p>
<ol>
  <li>建立專案：
    <p class="illustration">
 <img src="https://i.imgur.com/a0Ox5mG.png" alt="建立專案" />
 </p>
  </li>
  <li>導入資料以進行標注任務：
    <ul>
      <li><a href="https://labelstud.io/guide/storage.html">Sync data from external storage</a></li>
    </ul>

    <p>從文件看來資料來源可以是：<strong>雲端儲存體</strong>，如：Amazon S3、 Google Cloud Storage、 Microsoft Azure Blob storage…等， <strong>Redis database</strong>、 <strong>URL</strong> 與 <strong>Local storage</strong>。</p>

    <p>其中從 Local 端上傳資料是比較簡單的做法：</p>

    <p class="illustration">
 <img src="https://i.imgur.com/GOniSBJ.png" alt="從 Local 端上傳資料" />

 <img src="https://i.imgur.com/NkS4Dwf.png" alt="從 Local 端上傳資料" />
 </p>
  </li>
  <li>labeling interface
    <ul>
      <li><a href="https://labelstud.io/templates/">Templates</a></li>
    </ul>

    <p>上傳完資料後，就可以開始配置標注模板，制定模板的方式有兩種。一是使用現成的模板，能選擇的方式還頗多，基本上就是參考 <a href="#Data-Type">Data Type</a> 的支援。</p>

    <p>因為我手邊的是貓狗資料集，所以我這邊選擇影像分類：</p>

    <p class="illustration">
 <img src="https://i.imgur.com/HsEWU5w.png" alt="labeling interface" />
 </p>

    <p class="illustration">
 <img src="https://i.imgur.com/GXYAQd4.png" alt="labeling interface" />
 </p>

    <p><br class="big" /></p>

    <p>另一種起相同標注模板的方式是使用 Template 撰寫：</p>

    <p class="illustration">
 <img src="https://i.imgur.com/aLyHdLH.png" alt="labeling interface" />	
 </p>

    <p class="illustration">
 <img src="https://i.imgur.com/45uZECY.png" alt="labeling interface" />
 </p>

    <p><br class="big" /></p>

    <p>如果現有的標注模板不符合使用需求，可以<a href="https://labelstud.io/guide/setup.html#Customize-a-template">自定義符合需求的 template</a>，像是之前提過的標注三種類型的 template：</p>

    <details class="details-2">
 <summary>自定義 template：</summary>
 <pre>
 <span>&lt;<span>View</span>&gt;</span>
 <span class="hljs-comment">&lt;!-- Image with Polygons --&gt;</span>
 <span>&lt;<span>View</span> <span>style</span>=<span>"padding: 25px;
             box-shadow: 2px 2px 8px #AAA"</span>&gt;</span>
 <span>&lt;<span>Header</span> <span>value</span>=<span>"Label the image with polygons"</span>/&gt;</span>
 <span>&lt;<span>Image</span> <span>name</span>=<span>"img"</span> <span>value</span>=<span>"$image"</span>/&gt;</span>
 <span>&lt;<span>Text</span> <span>name</span>=<span>"text1"</span>
         <span>value</span>=<span>"Select label, start to click on image"</span>/&gt;</span>

 <span>&lt;<span>PolygonLabels</span> <span>name</span>=<span>"tag"</span> <span>toName</span>=<span>"img"</span>&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Airbus"</span> <span>background</span>=<span>"blue"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Boeing"</span> <span>background</span>=<span>"red"</span>/&gt;</span>
 <span>&lt;/<span>PolygonLabels</span>&gt;</span>
 <span>&lt;/<span>View</span>&gt;</span>
 <span class="hljs-comment">&lt;!-- Text with multi-choices --&gt;</span>
 <span>&lt;<span>View</span> <span>style</span>=<span>"margin-top: 20px; padding: 25px;
             box-shadow: 2px 2px 8px #AAA;"</span>&gt;</span>
 <span>&lt;<span>Header</span> <span>value</span>=<span>"Classify the text"</span>/&gt;</span>
 <span>&lt;<span>Text</span> <span>name</span>=<span>"text2"</span> <span>value</span>=<span>"$text"</span>/&gt;</span>
 <span>&lt;<span>Choices</span> <span>name</span>=<span>"choices1"</span> <span>toName</span>=<span>"img"</span> <span>choice</span>=<span>"multiple"</span>&gt;</span>
     <span>&lt;<span>Choice</span> <span>alias</span>=<span>"wisdom"</span> <span>value</span>=<span>"Wisdom"</span>/&gt;</span>
     <span>&lt;<span>Choice</span> <span>alias</span>=<span>"long"</span> <span>value</span>=<span>"Long"</span>/&gt;</span>
 <span>&lt;/<span>Choices</span>&gt;</span>
 <span>&lt;/<span>View</span>&gt;</span>

 <span>&lt;<span>View</span> <span>style</span>=<span>"margin-top: 20px; padding: 25px;
             box-shadow: 2px 2px 8px #AAA;"</span>&gt;</span>
 <span>&lt;<span>Header</span> <span>value</span>=<span>"Named entity"</span>/&gt;</span>
 <span>&lt;<span>Labels</span> <span>name</span>=<span>"label"</span> <span>toName</span>=<span>"text"</span>&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Person"</span> <span>background</span>=<span>"red"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Organization"</span> <span>background</span>=<span>"darkorange"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Fact"</span> <span>background</span>=<span>"orange"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Money"</span> <span>background</span>=<span>"green"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Date"</span> <span>background</span>=<span>"darkblue"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Time"</span> <span>background</span>=<span>"blue"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Ordinal"</span> <span>background</span>=<span>"purple"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Percent"</span> <span>background</span>=<span>"#842"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Product"</span> <span>background</span>=<span>"#428"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Language"</span> <span>background</span>=<span>"#482"</span>/&gt;</span>
     <span>&lt;<span>Label</span> <span>value</span>=<span>"Location"</span> <span>background</span>=<span>"rgba(0,0,0,0.8)"</span>/&gt;</span>
 <span>&lt;/<span>Labels</span>&gt;</span>

 <span>&lt;<span>Text</span> <span>name</span>=<span>"text"</span> <span>value</span>=<span>"$text"</span>/&gt;</span>
 <span>&lt;/<span>View</span>&gt;</span>
 <span>&lt;/<span>View</span>&gt;</span>
 </pre>
 </details>

    <p class="illustration">
 <img src="https://i.imgur.com/lvZrPku.png" alt="同時標注三種類型" />
 同時標注三種類型
 </p>
  </li>
  <li>Label and annotate the data.  <br />
 設定完後就可以嚕貓了 XDDD
    <p class="illustration">
 <img src="https://i.imgur.com/nIFNsm8.png" alt="貓狗影像分類" />
 </p>

    <p><br class="big" /></p>

    <p>順便試試物件偵測：</p>

    <p class="illustration">
 <img src="https://i.imgur.com/UKbrhZp.png" alt="物件偵測" />
 </p>

    <p><br class="big" /></p>

    <p>跟車牌標注：</p>
    <p class="illustration">
 <img src="https://i.imgur.com/anuaKtP.png" alt="貓狗影像分類" />
 </p>
  </li>
  <li>Export the labeled data or the annotations
    <ul>
      <li><a href="https://labelstud.io/guide/export.html">Export annotations and data from Label Studio</a></li>
    </ul>

    <p>因為只有企業版本才能從 UI 會出標注結果，所以我們只能用指令來匯出：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$label</span><span class="nt">-studio</span> <span class="nb">export</span> &lt;project-id&gt; &lt;export-format&gt; <span class="nt">--path</span><span class="o">=</span>&lt;output-path&gt;
</code></pre></div>    </div>
  </li>
</ol>

<h3 id="machine-learning-backends-1">Machine Learning Backends</h3>
<p>這邊試著設置 ML Backends。<a href="https://labelstud.io/guide/ml.html">文件中</a>提供了兩種安裝方法：<code class="language-plaintext highlighter-rouge">docker-compose</code> 或是指令。</p>

<p>我這邊使用指令方式安裝：</p>

<ol>
  <li>首先先 Clone the repo
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>git clone https://github.com/heartexlabs/label-studio-ml-backend  
</code></pre></div>    </div>
  </li>
  <li>Setup environment。建議使用venv，不過我在 label studio 的容器內執行，所以我就沒管它了。
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">cd </span>label-studio-ml-backend
 <span class="nv">$ </span>pip <span class="nb">install</span> <span class="nt">-U</span> <span class="nt">-e</span> <span class="nb">.</span>
 <span class="nv">$ </span>pip <span class="nb">install</span> <span class="nt">-r</span> label_studio_ml/examples/requirements.txt
</code></pre></div>    </div>
  </li>
  <li>根據範例腳本初始化 ML 後端。
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>label-studio-ml init my_ml_backend <span class="nt">--script</span> label_studio_ml/examples/simple_text_classifier.py
</code></pre></div>    </div>
    <p>此 ML 後端是 Label Studio 提供的 <a href="https://github.com/heartexlabs/label-studio-ml-backend/blob/master/label_studio_ml/examples/simple_text_classifier/simple_text_classifier.py">example</a>。</p>
  </li>
  <li>Start ML 後端 server
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>label-studio-ml start my_ml_backend
</code></pre></div>    </div>
  </li>
  <li>最後啟動 Label Studio 後，前往在專案設置頁面的機器學習部分，添加指向 <code class="language-plaintext highlighter-rouge">http://localhost:9090</code> 機器學習模型後端的連結。
    <p class="illustration">
 <img src="https://i.imgur.com/R7QpvJl.png" alt="連接 ML 後端" />
 </p>
  </li>
</ol>

<h3 id="demo-畫面">Demo 畫面</h3>
<p>最後附上幾張看起來超級酷的 demo 畫面。</p>

<p class="illustration">
<img src="https://i.imgur.com/LW3JD4E.gif" alt="Demo1" />
</p>

<p class="illustration">
<img src="https://i.imgur.com/cPPynxt.gif" alt="Demo1" />
</p>

<p class="illustration">
<img src="https://i.imgur.com/MV1naEb.gif" alt="Demo1" />
</p>

<p class="illustration">
<img src="https://i.imgur.com/drT44AA.gif" alt="Demo1" />
</p>

<h2 id="題外話">題外話</h2>
<p>是說…我真的覺得綠色那隻比較好看欸？你們覺得呢？</p>

<p class="illustration">
<img src="https://i.imgur.com/rLSg2Ef.gif" alt="題外話" />
</p>

<p><br class="big" /></p>

<p>海蒂小姐真的還滿可愛的 XDDD</p>

<p class="illustration">
<img src="https://i.imgur.com/xtFkeBt.png" alt="題外話" />
</p>

<h2 id="參考資料">參考資料</h2>
<ol>
  <li>secsilm (2020-11-10)。<a href="https://blog.csdn.net/u010099080/article/details/104881167">试用开源标注平台 Label Studio_Alan Lee</a>。檢自 CSDN博客 (2021-08-04)。</li>
  <li>協同撰寫 (2021-07-28)。<a href="https://github.com/heartexlabs/label-studio">heartexlabs/label-studio</a>。檢自 GitHub (2021-08-04)。</li>
  <li>Nikolai Liubimov (2020-01-28)。<a href="https://towardsdatascience.com/introducing-label-studio-a-swiss-army-knife-of-data-labeling-140c1be92881">Introducing Label Studio, a swiss army knife of data labeling</a>。檢自 Towards Data Science (2021-08-04)。</li>
  <li>Johnson7788 (2020-12-28)。<a href="https://zhuanlan.zhihu.com/p/339567115">安利一个开源的好工具Label Studio, 闭环数据标注和模型训练</a>。檢自 知乎 (2021-08-04)。</li>
  <li><a href="https://labelstud.io/guide/index.html#Components-and-architecture">Components and Architecture</a>。檢自 Label Studio Documentation (2022-12-09)。</li>
  <li><a href="https://labelstud.io/guide/label_studio_compare.html">Label Studio features</a>。檢自 Label Studio Documentation (2022-12-09)。</li>
</ol>

<h2 id="更新紀錄">更新紀錄</h2>
<details class="update_stamp">
  <summary>最後更新日期：2023-12-20</summary>
  <ul>
    <li>2023-12-20 更新：更新 API Workflow 圖片來源。</li>
    <li>2023-02-16 發布</li>
    <li>2022-12-14 完稿</li>
    <li>2021-08-04 起稿</li>
  </ul>
</details>

<style>
.details-2 summary {
	padding: 5px;
	background-color: #f0f0f0;
}
.details-2 content {
	display: block;
	padding: 5px;
	background-color: #f5f7f7;
}

.details-2 summary::after {
	content: '';
	position: absolute;
	width: 1em; height: 1em;
	margin: .2em 0 0 .5ch;
	background: "^"
	background-size: 100% 100%;
	transition: transform .2s;
}
.details-2:not([open]) summary::after {
	margin-top: .25em;
	transform: rotate(90deg);    
}

.details-2 ::-webkit-details-marker {
	display: none;
}
.details-2 ::-moz-list-bullet {
	font-size: 0;
}
</style>]]></content><author><name>辛西亞．Cynthia</name></author><category term="資訊科技 › 開發與輔助工具" /><category term="工具安裝與部署" /><category term="工具介紹與操作" /><category term="Label Studio" /><summary type="html"><![CDATA[我竟然還是從草稿夾中把這篇給翻出來填坑…。上次搞這個都是一年前了，但最近又被重新 assign 了這個 project，也只能重新去把記憶給找回來了。嘖…要回想一年多前做了什麼事情真是難倒我了＝＝ 上次看的時候時候版本還是 1.0，現在都 1.6 啦…不過筆記應該沒有差多少？應該…]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://i.imgur.com/rlEl5Z6.png" /><media:content medium="image" url="https://i.imgur.com/rlEl5Z6.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">URI、URL 與 URN</title><link href="https://cynthiachuang.github.io/URI-URL-and-URN/" rel="alternate" type="text/html" title="URI、URL 與 URN" /><published>2023-12-06T00:00:00+00:00</published><updated>2023-12-06T00:00:00+00:00</updated><id>https://cynthiachuang.github.io/URI-URL-and-URN</id><content type="html" xml:base="https://cynthiachuang.github.io/URI-URL-and-URN/"><![CDATA[<p>在學習網路相關知識的過程中，URI、URL 和 URN 這三個術語會反覆出現。好吧，主要是 URI 和 URL 使用得比較多，反而是 URN 比較少被提及。這篇網誌就簡單整理這三個術語的定義與差異。</p>

<p>是說，寫完後一直沒發出來，導致我都有點忘了當初我為啥會寫這篇筆記了。好像是命名變數時，經常在 URI、URL 和 URN 之間拿不定主意吧？🤔但如果你也對這些術語感到困惑，這篇可以賞光一下~</p>

<!--more-->

<p class="illustration">
    <img src="https://i.imgur.com/LOUwjvI.png" alt="URI 可以是 URL 或 URN，甚至同時具備兩者的特性。" width="450px" />
    URI 可以是 URL 或 URN，甚至同時具備兩者的特性。（圖片來源: <a href="https://zh.wikipedia.org/zh-tw/统一资源名称">維基百科</a>）
</p>

<h2 id="uri-uniform-resource-identifier統一資源標識符">URI （Uniform Resource Identifier，統一資源標識符）</h2>
<p>URI，即統一資源標識符，呃…算了，先別管這個拗口詞，反正我平時也沒怎麼用這個詞。我們還是來看看它的英文定義好了，在 <a href="https://datatracker.ietf.org/doc/html/rfc2396">RFC2396</a> 這份文件中，對 <a href="https://datatracker.ietf.org/doc/html/rfc2396#section-1.1">URI 的定義是</a>：</p>

<ul>
  <li>
    <p><strong>Uniform</strong><br />
  允許在同一上下文中使用不同類型的資源標識符，並統一解釋常見的語法規則。這樣可以讓協議方案的增擴變得更加容易。</p>
  </li>
  <li>
    <p><strong>Resource</strong>    <br />
  資源指的是可以被識別的任何事物，像是文件、圖像、服務…等，不僅限於具體物理實體，也可以是虛擬資源，甚至是一組實體的集合。</p>
  </li>
  <li>
    <p><strong>Identifier</strong><br />
 標識符，用來表明可識別的資源。</p>
  </li>
</ul>

<p>寫的超複雜的有沒有！！其實只要記住，<mark>URI 就是用來標示資源的字串，無論是抽象的還是實體的都可以</mark> 就好，像是網路上的各種資源（HTML 文件、圖像、音檔、影片、程序等）都可以用 URI 來定位。</p>

<p>換句話說，<strong>URI 是資源的抽象定義</strong>，而要進行實際定位，通常有兩種方法：</p>
<ol>
  <li>URL （Uniform Resource Locator，統一資源定位符）</li>
  <li>URN （Uniform Resource Name，統一資源名稱）</li>
</ol>

<p class="illustration">
    <img src="https://i.imgur.com/JdMhaCu.png" alt="URI 是資源的抽象定義，其中包含了兩種實際定位方式 URL 與 URN" width="400px" />
   URI 是資源的抽象定義，其中包含了兩種實際定位方式 URL 與 URN（圖片來源: <a href="https://www.readfog.com/a/1660187374166052864">閱坊</a>）
</p>

<h2 id="url-uniform-resource-locator統一資源定位符">URL （Uniform Resource Locator，統一資源定位符）</h2>
<p>URL 就是我們常說的<strong>網址</strong>，用來描述是網際網路上資源的位址，它是<mark>具體的定位方法，告訴我們如何到達資源</mark>。有點像是網路上的<strong>門牌號碼</strong>，可以直接把你導航到網站的特定頁面。</p>

<p>例如，定位 HTML 資源的 URL 可能是：</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code>https://www.example.com.tw
https://www.example.com/index.html
</code></pre></div></div>

<p>然而，並非所有的 URL 都是以 HTTP/HTTPS 開頭，還有許多其他協議可用，比如：ftp、mailto、telnet、file…等。</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ftp://user:password@ftp.gitee.com:21/code/chat/chat.py
file://localhost/code/chat/chat.py
</code></pre></div></div>

<p><br class="big" /></p>

<p>一般來說，URL 由三個部分組成：</p>
<ol>
  <li>協議（或稱服務方式）</li>
  <li>資源所在伺服器的名稱或 IP 地址（有時也包括埠號）</li>
  <li>主機資源的具體地址，如目錄和檔名等。</li>
</ol>

<p class="illustration">
    <img src="https://i.imgur.com/BBzwTm1.png" alt="URL 是由協議、伺服器地址、檔名地址所組成" />
    URL 是由協議、伺服器地址、檔名地址所組成
</p>

<h2 id="urn-uniform-resource-name統一資源名稱">URN （Uniform Resource Name，統一資源名稱）</h2>
<p>接下來，我們來看看最後一個術語 URN。說個有趣的插曲，我在查資料時，Google 搜尋結果的第一項居然是骨灰罈…不過在這邊 URN 是指<mark>某個特定資源的名稱</mark>，它不關心資源在何處，只關心資源是誰。</p>

<p>跟 URL 一樣，URN 也是由三個部份組成：</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;URN&gt; ::<span class="o">=</span> <span class="s2">"urn:"</span> &lt;NID&gt; <span class="s2">":"</span> &lt;NSS&gt;
</code></pre></div></div>

<ol>
  <li>URN：表示這是一個 URN 方案標識。</li>
  <li>NID： 註冊於 <a href="https://www.iana.org/">IANA</a>的命名空間標識符。</li>
  <li>NSS：具體的命名空間字串。</li>
</ol>

<p><br class="big" /></p>

<p><strong>ISBN（國際標準書號）</strong> 是一個常見的 URN 例子，ISBN 可以用來表示特定書籍，即便我把書本從書局帶回我家，它的 ISBN 依然能唯一識別這本書，就像是牛被牽到北京，它還是牛。</p>

<p>如果將書籍的 ISBN <code class="language-plaintext highlighter-rouge">ISBN 10 :9780132350884</code>，寫成 URN 的格式，就是：</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>URN:ISSN:9780132350884
</code></pre></div></div>

<p><br class="big" /></p>

<p>最後舉個例子，如果今天要在台灣找到某個具體的人（URI），比如用地址來描述：例如臺北市中正區龍福里重慶南路二段永和寓所的主人，那就是 URL。如果用身份證號碼加上姓名（例如：賴清德），那就是 URN 了。</p>

<p>簡而言之，<mark>URI 是對資源的定義，它既可以是抽象的描述，也可以是具體的表達</mark>。這些描述方式可以通過 URN 來標識某個事物的身份，或通過 URL 來提供尋找該事物的具體方法。簡單來說，URI、URL 和 URN 在網路資源定位中各自扮演著不同的角色，彼此協作，幫助我們準確地找到所需的資源。</p>

<h2 id="參考資料">參考資料</h2>
<ol>
  <li>GreedIsGood (2021-09-20)。<a href="https://ithelp.ithome.com.tw/articles/10266610?sc=pt">URL / URN / URI 的定義</a>。檢自 iT 邦幫忙 (2023-07-05)。</li>
  <li>蜗牛蒲哥 (2022-07-30)。<a href="https://zhuanlan.zhihu.com/p/38120321">URL与URI，有联系有区别？</a>。檢自 知乎 (2023-07-05)。</li>
  <li><a href="https://www.readfog.com/a/1660187374166052864">一文帶你理解 URI 和 URL 有什麼區別？</a>。檢自 閱坊 (2023-07-05)。</li>
  <li>刘Java (2021-08-04)。<a href="https://juejin.cn/post/6992383657340551204">URI和URL的概念和区别</a>。檢自 掘金 (2023-07-05)。</li>
  <li>協同撰寫。<a href="https://zh.wikipedia.org/zh-tw/统一资源标志符">統一資源標識符</a>。檢自 維基百科 (2023-07-05)。</li>
  <li>協同撰寫。<a href="https://zh.wikipedia.org/zh-tw/统一资源定位符">統一資源定位符</a>。檢自 維基百科 (2023-07-05)。</li>
  <li>協同撰寫。<a href="https://zh.wikipedia.org/zh-tw/统一资源名称">統一資源名稱</a>。檢自 維基百科 (2023-07-05)。</li>
  <li><a href="https://www.issn.org/zh-hans/services-et-prestations/services-en-ligne/urn/">URN</a>。檢自 ISSN (2023-07-05)。</li>
</ol>

<h2 id="更新紀錄">更新紀錄</h2>
<details class="update_stamp">
  <summary>最後更新日期：2023-12-06</summary>
  <ul>
    <li>2023-12-06 發布</li>
    <li>2023-07-06 完稿</li>
    <li>2023-07-05 起稿</li>
  </ul>
</details>]]></content><author><name>辛西亞．Cynthia</name></author><category term="硬體系統 › 計算機系統" /><category term="計算機概論" /><summary type="html"><![CDATA[在學習網路相關知識的過程中，URI、URL 和 URN 這三個術語會反覆出現。好吧，主要是 URI 和 URL 使用得比較多，反而是 URN 比較少被提及。這篇網誌就簡單整理這三個術語的定義與差異。 是說，寫完後一直沒發出來，導致我都有點忘了當初我為啥會寫這篇筆記了。好像是命名變數時，經常在 URI、URL 和 URN 之間拿不定主意吧？🤔但如果你也對這些術語感到困惑，這篇可以賞光一下~]]></summary></entry><entry><title type="html">Scale-Up Vs Scale-Out</title><link href="https://cynthiachuang.github.io/What-Is-Scale-Up-Vs-Scale-Out/" rel="alternate" type="text/html" title="Scale-Up Vs Scale-Out" /><published>2023-12-05T00:00:00+00:00</published><updated>2023-12-05T00:00:00+00:00</updated><id>https://cynthiachuang.github.io/What-Is-Scale-Up-Vs-Scale-Out</id><content type="html" xml:base="https://cynthiachuang.github.io/What-Is-Scale-Up-Vs-Scale-Out/"><![CDATA[<p>呃…說實話，其實我對這兩種擴展方式沒啥問題啦，但每次在寫到他們的介系詞卻總是遲遲下不了手 🤯。為此，我特地畫了張圖來幫助記憶！既然已經畫好了，不順勢整理成一篇網誌，騙一篇，好像有點對不起自己。當然，還是偏資工領域的觀點啦～至於我的英文嘛，就先別太計較了 XDDD。</p>

<p>是說，這篇網誌的分類好像有點隨性？但懶得再開新類別了，先這樣湊合吧！😅</p>

<!--more-->
<p><br /></p>

<p class="illustration">
    <img src="https://i.imgur.com/VKaKPZq.png" alt="Scale up vs Scale out" />
    Scale up vs Scale out（圖片來源: <a href="https://www.lightbitslabs.com/blog/scale-up-vs-scale-out/">Lightbits</a>）
</p>

<h2 id="先來從字典了解-scale-up">先來從字典了解 Scale-Up</h2>
<p>在劍橋詞典中，可以發現在 <a href="https://dictionary.cambridge.org/zht/詞典/英語-漢語-繁體/scale?q=Scale">Scale</a> 的定義之一是：</p>
<blockquote>
  <p>the size or level of something, especially when this is large<br />
大小；規模；範圍</p>
</blockquote>

<p>這部份看來沒啥問題，可是有趣的是，當查片語時，我只能找到「Scale Up/Down」，卻找不到「Scale Out/In」。難道這是資工領域的專用語？🤔</p>

<p><br class="big" /></p>

<p>既然只查到 Scale Up/Down。那麼我們就先先來看看 <a href="https://dictionary.cambridge.org/zht/詞典/英語-漢語-繁體/scale-sth-up">Scale sth up</a> 的定義：</p>
<blockquote>
  <p>to increase the size, amount, or importance of something, usually an organization or process</p>
</blockquote>

<p>順便也查了<a href="https://www.collinsdictionary.com/dictionary/english/scale-up">柯林斯字典</a>是怎麼說的：</p>
<blockquote>
  <p>If you scale up something, you make it greater in size, amount, or extent than it used to be.</p>
</blockquote>

<p>乍看之下，這兩個解釋沒什麼區別，都是把<mark>東西弄大</mark>的意思，這個東西可以是<strong>尺寸</strong>、<strong>數量</strong>或<strong>涵蓋範圍</strong>。但很顯然，這樣的字面定義無法說明「Scale-Up」和「Scale-Out」的區別嘛！</p>

<p><br class="big" /></p>

<p>當然有增必有減，查了一下 <a href="https://dictionary.cambridge.org/zht/詞典/英語-漢語-繁體/scale-sth-down">Scale Down</a> 的定義：</p>
<blockquote>
  <p>to make something smaller than it was or smaller than it was planned to be</p>
</blockquote>

<p>這解釋根本是直接把 increase 換成 smaller、up 換成 down 而已咩 XDDD，唯一的收穫是，我發現它還有個同義詞 <a href="https://www.collinsdictionary.com/dictionary/english/scale-back">Scale Back</a>。</p>

<p><br class="big" /></p>

<p>在片語表中，有一個看起來跟 Scale Out 相似的字是 <a href="https://www.collinsdictionary.com/dictionary/english/out-of-scale">out of scale</a>，但它跟增加、擴增無關，而是指<strong>不合比例</strong>。</p>

<h2 id="資工領域中的-scale-up">資工領域中的 Scale Up</h2>
<p>字典的定義能幫助我們理解詞語的本義，…雖然這些解釋好像沒啥用，因此我們還是得回頭看看，來聊聊資工界對 Scale Up/Down 和 Scale Out/In 的理解吧！</p>

<p>在資工領域中，Scale 這個詞常用來表示擴展設施的規模，使其能夠應對持續增長的需求。尤其在伺服器管理中，最常提到的就是<strong>可擴充性（Scalability）</strong>。簡單來說，可擴充性指的是伺服器在面對不同壓力時的應變能力。當需求上升時，適度增加伺服器規模以確保服務的穩定和可用；反之，若需求減少，則縮減規模以節省成本。</p>

<p>至於<strong>如何增加規模</strong>這件事，主流有兩種方法，也就是我們一直提到的 <strong>Scale Up</strong> 和 <strong>Scale Out</strong>。雖然從使用者的角度來看，這兩種方式似乎都能達到相同目的，但事實上，它們背後代表的是<mark>截然不同的系統架構</mark>，且各自適用於不同的場景需求。</p>

<p class="illustration">
    <img src="https://imgur.com/EKSlkz3.png" alt="Scale up vs Scale out" />
    Scale up vs Scale out
</p>

<p>首先是 Scale Up，也被稱為<strong>向上擴展</strong>或<strong>垂直擴展（Scaling Vertically）</strong>。它的做法是升級單一節點的硬體資源，例如提升 CPU 性能、增加記憶體容量、或擴展儲存空間。透過這種擴展，單一節點的計算或儲存能力能變得更為強大，從而應對更高的需求負載。</p>

<p>至於 Scale Out 則被稱為<strong>向外擴展</strong>或<strong>水平擴展（Scaling Horizontally）</strong>。這種方式透過增加節點數量，也就是通過添加更多的伺服器或機器，將工作負載分散到多個節點上來共同承擔。可以將這種方法比喻為「人海戰術」：與其讓一個人做更多事，不如找更多人一起分工合作。</p>

<p><br class="big" /></p>

<p>舉例來說，假設你家有一台雙槽烤麵包機，一次可以同時烤兩片吐司。但如果現在需要同時烤八片吐司，就得想辦法升級設備。這時候你有兩個選擇：第一種方式，直接買一台八槽烤麵包機，這就相當於 Scale Up（向上擴展），在單一設備上增加容量；第二種方式，添購三台雙槽烤麵包機，這就是 Scale Out（向外擴展），透過增加設備數量來解決需求。</p>

<p>雖然我忘記這個例子是哪裡看到的，但不得不說，真的超貼切啊！</p>

<p>所以該選哪個方案呢？如果你的錢包鼓鼓的話，直接去訂做八槽烤麵包機，換裝備吧；但如果只是偶爾需要烤八片吐司，平時還是兩片，那麼購買三台雙槽烤麵包機或許會更划算。</p>

<h2 id="scale-up-or-scale-out到底該選哪個">Scale Up or Scale Out：到底該選哪個？</h2>
<p>以目前雲端趨勢來看，Scale-Out 似乎是當前顯學，因為它更能應對現代分散式架構的需求。但隨著技術進步，平台中的節點運算能力也不斷增強，因此在某些情況下，這也可以視為一種形式的 Scale Up。因此，Scale Up 和 Scale Out 是可以並行發展的！</p>

<p>但相較於可以選擇並行擴展的田僑仔，我們這些口袋不太鼓的窮小子來說，如何選擇適合的擴展策略就變得至關重要了。</p>

<p>如果你選擇 Scale Up，操作會比較簡單，升級也比較快速，能夠短時間內解決問題。然而，當計算與儲存需求逐步攀升時，硬體升級的成本也會水漲船高，但效益卻會逐漸遞減。此外，瘋狂升級單一節點不僅成本高，還會讓維護成本居高不下，還可能引發單點故障的風險。</p>

<p>相比之下，Scale Out 的優勢在於每新增一個節點的成本相對較低，且可以更靈活地分擔負載。不過，這種擴展方式初期的挑戰不容小覷：分散式架構對技術和管理的要求都更高，部署和維護的難度也隨之增加。但長期來看，隨著技術成熟，這些挑戰會被逐漸克服，最終呈現出比 Scale Up 更低的管理難度。</p>

<p><br class="big" /></p>

<p>窮小子既然無法兩手都抓，只能從<strong>成本</strong>、<strong>複雜度</strong>、<strong>未來成長</strong>等方面來權衡選擇 XDDD。畢竟，不同的擴展方式對應不同的需求和限制，找到適合自身的解決方案才是關鍵。</p>

<p>如果你的專案特性符合以下情況，那麼 <strong>Scale Up</strong> 可能是更適合的選擇：</p>
<ol>
  <li><strong>有限的可擴展性</strong><br />
 如果你的應用並不需要大規模的擴展，僅透過硬體升級就能輕鬆滿足需求，那麼選擇 Scale Up 更為簡單，且不會增加額外的複雜性。</li>
  <li><strong>高耦合的系統架構</strong><br />
 當元件之間高度耦合且難以分離時，將負載分配到多台伺服器會變得非常困難，這時提升單一節點的性能是更實際的解法。</li>
  <li><strong>低延遲需求</strong><br />
 如果應用對於延遲有極高需求，導致節點間的通訊開銷會成為瓶頸，那麼集中處理的 Scale Up 是更適合的選擇。</li>
</ol>

<p>而如果你的專案需求與以下情況相符，那麼選擇 <strong>Scale Out</strong> 會更為有利：</p>
<ol>
  <li><strong>快速成長或變動的應用場景</strong><br />
 當你的流量或需求呈現快速增長或變動時，Scale Out 能夠靈活應對不斷增長的需求，而無需頻繁升級硬體。</li>
  <li><strong>災難復原</strong><br />
 如果應用需要高可用性並希望從錯誤中快速恢復，Scale Out 通過分散負載來提高可用性，確保即便某些節點故障，系統仍能正常運行。</li>
  <li><strong>易於分發的架構</strong><br />
如果你的應用支持分佈式部署，且能輕鬆分配至多台伺服器上，那麼 Scale Out 無疑是最合適的選擇。</li>
</ol>

<p>無論是選擇 Scale Up 還是 Scale Out，最重要的是要充分了解自己應用的需求和限制。初期階段，選擇單一節點升級可能是最佳選擇；然而，隨著需求的增長，向外擴展的靈活性便成為不可或缺的關鍵。就像烤吐司一樣，最終的選擇還是要根據你的「肚子容量」和「預算」，來決定最合適的方式。</p>

<h2 id="參考資料">參考資料</h2>
<ol>
  <li>Collins Ayuya (2022-03-21)。<a href="https://www.serverwatch.com/storage/scale-up-vs-scale-out/">Scale Up vs Scale Out: Data Center Infrastructure</a>。檢自 ServerWatch (2023-02-17)。</li>
  <li>Justin Stoltzfus (2020-12-15)。<a href="https://www.techopedia.com/7/31151/technology-trends/what-is-the-difference-between-scale-out-versus-scale-up-architecture-applications-etc">What is the difference between scale-out versus scale-up?</a>。檢自 techopedia (2023-02-17)。</li>
  <li>Paul Kirvan (2022-08-02)。<a href="https://www.techtarget.com/searchstorage/tip/Differences-in-scale-up-vs-scale-out-storage">Differences in scale-up vs. scale-out storage</a>。檢自 TechTarget (2023-02-17)。</li>
  <li>Carol Platz (2022-02-16)。<a href="https://www.lightbitslabs.com/blog/scale-up-vs-scale-out/">What is Scale-up vs Scale-out?</a> 。檢自 Lightbits (2023-02-17)。</li>
  <li>Omnigeeker (2018-12-05)。<a href="https://zhuanlan.zhihu.com/p/51625766">云存储的未来：Scale Up还是Scale Out？</a>。檢自 知乎 (2023-07-05)。</li>
</ol>

<h2 id="更新紀錄">更新紀錄</h2>
<details class="update_stamp">
  <summary>最後更新日期：2023-12-05</summary>
  <ul>
    <li>2023-12-05 發布</li>
    <li>2023-07-05 完稿</li>
    <li>2023-02-17 起稿</li>
  </ul>
</details>]]></content><author><name>辛西亞．Cynthia</name></author><category term="雲端網路 › 雲端運算" /><category term="語言學習" /><category term="英文進修" /><category term="K8S" /><summary type="html"><![CDATA[呃…說實話，其實我對這兩種擴展方式沒啥問題啦，但每次在寫到他們的介系詞卻總是遲遲下不了手 🤯。為此，我特地畫了張圖來幫助記憶！既然已經畫好了，不順勢整理成一篇網誌，騙一篇，好像有點對不起自己。當然，還是偏資工領域的觀點啦～至於我的英文嘛，就先別太計較了 XDDD。]]></summary></entry><entry><title type="html">Survey｜Source-To-Image</title><link href="https://cynthiachuang.github.io/Survey-Source-to-Image/" rel="alternate" type="text/html" title="Survey｜Source-To-Image" /><published>2023-02-16T00:00:00+00:00</published><updated>2023-02-16T00:00:00+00:00</updated><id>https://cynthiachuang.github.io/Survey-Source-to-Image</id><content type="html" xml:base="https://cynthiachuang.github.io/Survey-Source-to-Image/"><![CDATA[<p>過年大掃除，又掃出一篇之前 Survey 過且寫到一半的草稿 XDDD 這應該是去年（2021）年 12 月份筆記，我這次只是把筆記整理到能見人的程度，如果後續有更新，麻煩告知我一下，我有空再來看看 <del>（雖然很有可能會一直沒空下去）</del></p>

<p>這篇的 Servey 目標是玩玩 S2I，順便看看 <mark>Openshift 利用 S2I 提供了哪些 image builder 相關功能</mark>。</p>

<!--more-->

<p class="illustration">
    <img src="https://i.imgur.com/ZVTUloI.png" alt="openshift/source-to-image" />
    openshift/source-to-image（圖片來源: <a href="https://github.com/openshift/source-to-image">GitHub</a>）
</p>

<h2 id="overview">Overview</h2>
<p>雖然我習慣使用 Dockerfile 從頭構建一個 image。但若你的應用不複雜，則可以考慮下 Image Builder 這些更快捷的方法。Image Builder 通常可藉由指定基礎 image 及提供要安裝工具、函式庫與自定義程式…等，為使用者提供客製化 image。</p>

<h3 id="source-to-images2i">Source-To-Image，S2I</h3>
<p>Source-To-Image（S2I），就是套由 <strong>OpenShift</strong> 所提供的 Image Builder Framework，它可以將你的程式碼編譯後，注入 Builder Image 中以產生新的 image。</p>

<p>這樣的開發方式，是為了方便軟體開發人員對程式碼進行改動，他們毋需了解 Dockerfile 的撰寫與構建，只需要專注在軟體的開發即可， <del>（當然還要學會用 S2I）</del>。其工作流程如下：</p>

<p class="illustration">
    <img src="https://imgur.com/dE1zcpi.png" alt="S2I Developer Workflow" />
    S2I Developer Workflow（圖片來源: <a href="https://cloud.redhat.com/blog/source-image-s2i-deep-dive-ben-parees-openshift-commons-briefing-43">Red Hat Blog</a>）
</p>

<p>SI2 是套相當便捷的工具，也是 OpenShift 生態系中相當重要的一個工具。我在網路上看到一個<a href="https://www.jianshu.com/p/c06b8ec92ed3">論點</a>，他認為 <mark>OpenShift 之所以能區別於 K8S 成為一個 PaaS 平台，其中一個主要環節就是 SI2</mark>。透過這套工具，在使用時僅需提供程式碼，就能生成 image，並利用 OpenShift 現有的體系架構（Deployment config，DC 和 Build config，BC）直接部署，完成所有的應用的生命週期管理。</p>

<h3 id="pros">Pros</h3>
<p>S2I 除可以讓開發者關注程式碼本身外，亦有以下好處：</p>

<ul>
  <li>
    <p><strong>關注點分離 SoC</strong><br />
  這點有點贅述了，它的意思就是程式碼和 Docker image 是清楚的分離開的，簡而言之就是讓<mark>開發者關注程式碼本身</mark>，不過我覺得這小標看起來很厲害的樣子，所以我還是再貼了一次 XDDD</p>
  </li>
  <li>
    <p><strong>速度 Speed</strong> <br />
  這可以想像，依照前面所說的，不需要從 Dockerfile 從頭 build 起，改利用現有 image 的話確實會比較快。</p>

    <p>是說我有個疑問，我習慣把程式碼的部份放在 Dockerfile 的最後面，好像也就重 build 最後一層？這樣的話，重 build 最後一層跟編譯注入程式碼會是哪個快？ 🤔</p>

    <p>嗯…好像少算了寫 Dockerfile 的時間，算了這先別管它好了。</p>
  </li>
  <li>
    <p><strong>可修補性 Patchability</strong><br />
  如果 Builder Image 基於安全問題需要修補，可以協助不斷 rebuild 應用的 image。</p>
  </li>
  <li>
    <p><strong>操作安全性 Operational Safety</strong> <br />
  這優點在 PaaS 平台上比較能展現。透過 S2I 進而對構建 image 的過程進行限制，可以避免意外或故意濫用構建系統。 
  <br /><br />
  此外，讓使用者直接用 Dockerfile 構建 image，可能主機系統暴露於 root 特權提升的風險中，透過 S2I 限制可以 root 使用者的操作。</p>
  </li>
  <li>
    <p><strong>使用者效率 User efficiency</strong> <br />
  其實這跟上一條有點像，不過這是從使用者的角度出發。它可以阻止使用者員在應用構建期間執行任意的 yum 安裝類型操作，避免過度安裝太多的套件導致 image 太過肥大，拖慢開發迭代的效率。</p>
  </li>
  <li>
    <p><strong>生態性 Ecosystem</strong> <br />
  鼓勵共享 image 的生態系統，找到並利用最佳實踐的方式來為應用構建映像檔。</p>
  </li>
</ul>

<p>上面我直接當搬運工，直接從這篇 <a href="https://access.redhat.com/documentation/zh-cn/openshift_container_platform/4.4/pdf/builds/OpenShift_Container_Platform-4.4-Builds-zh-CN.pdf">〈OpenShift Container Platform 4.4 构建（build）〉</a> 搬過來的 XDDD</p>

<h2 id="required-image-contents">Required Image Contents</h2>

<p class="illustration">
    <img src="https://i.imgur.com/TeduiMV.png" height="450px" alt="S2I Developer Workflow" />
    S2I Developer Workflow（圖片來源: <a href="https://cloudpak.info/openshift/что-такое-source-2-image/4811">Cloudpak Service</a>）
</p>

<p>在 S2I 中，image 的建構主要是由<strong>三個元素</strong>互動所構成，分別是：<mark>builder image、s2i scripts、source code</mark>。</p>

<h3 id="builder-image">Builder Image</h3>
<p>就是拿來當基底的 image，我在 <a href="https://github.com/sclorg?q=s2i&amp;type=all&amp;language=&amp;sort=">Software Collections</a> 有找到一些支援 S2I framework 的 image，它是有含 Pyhton 的 container 啦，不過像是我們比較常用的 Jupyter、 Tensorfolw、 Pytorch 之類好像都沒有，所以還要來研究下怎麼自定義 S2I framework image。</p>

<p><br class="br" /></p>

<p><a href="https://github.com/openshift/source-to-image/blob/master/examples/nginx-centos7/README.md">研究</a>了下，感覺自定義 S2I framework image 不難，只是必須包含特定文件，也就是我們的第二個元素 <strong>s2i scripts</strong>：</p>

<table>
  <thead>
    <tr>
      <th>File</th>
      <th>Required?</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Dockerfile</td>
      <td><strong>Yes</strong></td>
      <td>Defines the base builder image</td>
    </tr>
    <tr>
      <td>s2i/bin/assemble</td>
      <td><strong>Yes</strong></td>
      <td>Script that builds the application</td>
    </tr>
    <tr>
      <td>s2i/bin/usage</td>
      <td>No</td>
      <td>Script that prints the usage of the builder</td>
    </tr>
    <tr>
      <td>s2i/bin/run</td>
      <td><strong>Yes</strong></td>
      <td>Script that runs the application</td>
    </tr>
    <tr>
      <td>s2i/bin/save-artifacts</td>
      <td>No</td>
      <td>Script for incremental builds that saves the built artifacts</td>
    </tr>
    <tr>
      <td>test/run</td>
      <td>No</td>
      <td>Test script for the builder image</td>
    </tr>
    <tr>
      <td>test/test-app</td>
      <td>No</td>
      <td>Test application source code</td>
    </tr>
  </tbody>
</table>

<p>這些<a href="https://github.com/openshift/source-to-image/blob/master/docs/cli.md#sti-create">結構</a>不用特別去記憶，可以直接用相對應的指令產生目錄結構：</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>s2i create &lt;imageName&gt; &lt;destination&gt; <span class="o">[</span>flags]
</code></pre></div></div>
<p>其中 <code class="language-plaintext highlighter-rouge">&lt;imageName&gt;</code> 就是 image 的名字，<code class="language-plaintext highlighter-rouge">&lt;destination&gt;</code> 則是要產生目錄的資料夾名稱。詳細的狀況稍後等我們實際玩指令時再來試試。</p>

<h3 id="s2i-scripts">S2I Scripts</h3>
<p>焦點在回到前面提到的 s2i scripts。在前述的表格中，除了 Dockerfile 外還有幾項必備的文件就都是屬於 s2i scripts：</p>
<ul>
  <li><strong>[Required] assemble</strong><br />
  它會涉及原始碼的編譯、構建。我們會建立一個 assemble scripts 來 build 我們的程式，如：build modules、
  bundle install gems、設置應用程式 configuration…之類的。
  <br />
  預設情況下，build 時程式碼會放在 <code class="language-plaintext highlighter-rouge">/tmp/s2i/src</code> 下，你可依照需求搬移至指定位置。你也可以透過 <code class="language-plaintext highlighter-rouge">io.openshift.s2i.destination label</code>，或傳入 <code class="language-plaintext highlighter-rouge">--destination</code> 參數修改。</li>
  <li><strong>[Required] run</strong><br />
  生成的最終 image 將以這個 script 作為容器的啟動命令。</li>
  <li><strong>[Optional] usage</strong><br />
  印出協助資訊，以告知使用者 image 的用法，我理解就是我們平常看到 <code class="language-plaintext highlighter-rouge">--help</code> 所看到的資訊。</li>
  <li><strong>[Optional] save-artifacts</strong> <br />
  為了實現增量構建，在構建過程中會執行此腳本保存中間構建產物，以節省時間。(待會再詳細介紹)</li>
</ul>

<h3 id="source-code">Source Code</h3>
<p>Source code 顧名思義就是我們要放入 image 中的原始碼。原始碼的來源已有二：</p>
<ol>
  <li><strong>遠端 Git Repository</strong> <br />
 你可以從遠端的 Git Repository 抓取原始碼來構建映像檔，甚至可以從指定 repo 中的特定資料夾來建構映像檔。</li>
  <li><strong>本地端</strong><br />
 另一個可以取得原始碼的方法就是從本地端啦 XDDD</li>
</ol>

<h3 id="build-flow">Build Flow</h3>
<p>大概知道三個元素在構建過程中所扮演的角色後，我們可以來綜觀整個構建過程。</p>

<p>S2I 會將 sources 和 scripts 壓成 tar，並將其放入 builder image 中。在執行 assemble scripts 之前，S2I 會將壓縮檔解壓並放置指定位置，然後執行 S2I。完整的構建流程如下：</p>

<p class="illustration">
    <img src="https://i.imgur.com/RIbvZ6i.png" alt="Build Workflow" />
    Build Workflow（圖片來源: <a href="https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md">GitHub｜source-to-image</a>）
</p>

<p>其中會按照下面的順序與位置搜索 scripts ：</p>
<ol>
  <li>at the <code class="language-plaintext highlighter-rouge">--scripts-url</code> URL</li>
  <li>in the application source <code class="language-plaintext highlighter-rouge">.s2i/bin</code> directory（<code class="language-plaintext highlighter-rouge">/usr/libexec/s2i</code>）</li>
  <li>at the default image URL（<code class="language-plaintext highlighter-rouge">io.openshift.s2i.scripts-url</code> label）</li>
</ol>

<p>並以下列形式提供位置資訊：</p>
<ol>
  <li>image 內的絕對路徑：<code class="language-plaintext highlighter-rouge">image://path_to_scripts_dir</code></li>
  <li>主機上的相對或絕對路徑：<code class="language-plaintext highlighter-rouge">file://path_to_scripts_dir</code></li>
  <li>URL：<code class="language-plaintext highlighter-rouge">http(s)://path_to_scripts_dir</code></li>
</ol>

<p><br class="big" /></p>

<p>換個較簡單的方法來表示，基本上將 copying、 assemble 與 run 這三個步驟，對應回 Dockerfile 中，可以比較清楚這三個步驟對應的的執行時間。</p>

<p class="illustration">
    <img src="https://i.imgur.com/pZrbq3x.png" alt="Build Workflow" />    
</p>

<h3 id="save-artifacts">Save Artifacts</h3>
<p>不過像這樣的建構方式，一旦稍有有變動相依性就被打破，導致 assemble script 中相關安裝必須重來。</p>

<p>所以為了使用增量，我們需傳遞 <code class="language-plaintext highlighter-rouge">--incremental=true</code> 參數，並提供一個已構建好的 image 作為 cash，以獲取中間產物：</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>./s2i build &lt;<span class="nb">source </span>code&gt; &lt;Builder Image&gt; &lt;New Image&gt; <span class="nt">--incremental</span><span class="o">=</span><span class="nb">true</span>
</code></pre></div></div>

<p><br class="big" /></p>

<p>引入增量後，流程會變成這樣：</p>

<p class="illustration">
    <img src="https://i.imgur.com/ieSfMSA.png" alt="Build Workflow" />    
</p>

<h2 id="installation-and-operation">Installation and Operation</h2>
<p>好了，還是來看看怎麼使用這套軟體吧。</p>

<h3 id="installation">Installation</h3>
<p>首先，當然必須先將它安裝起來 XDDD</p>

<ol>
  <li><strong>安裝 s2i</strong><br />
 首先先建立一個資料夾，並目前目錄切換置資料夾：
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">mkdir </span>s2i
 <span class="nv">$ </span><span class="nb">cd </span>s2i
</code></pre></div>    </div>

    <p>前往 <a href="https://github.com/openshift/source-to-image/releases">releases 頁面</a>，挑選合適的發行版本並解壓縮：</p>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>wget https://github.com/openshift/source-to-image/releases/download/v1.3.1/source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz
 <span class="nv">$ </span><span class="nb">tar </span>zxvf source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz 
</code></pre></div>    </div>

    <p><br class="big" /></p>

    <p>解壓完成後，會多出兩個資料夾 <code class="language-plaintext highlighter-rouge">sti</code> 與 <code class="language-plaintext highlighter-rouge">s2i</code>：</p>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">ls 
 </span>s2i  source-to-image-v1.3.1-a5a77147-linux-amd64.tar.gz  sti
</code></pre></div>    </div>

    <p>將其中的 s2i 添加到 PATH 環境變數中，或移動到 PATH 的目錄中：</p>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">cp </span>s2i /usr/local/bin
 <span class="nv">$ </span>./s2i version
 s2i v1.3.1
</code></pre></div>    </div>
  </li>
</ol>

<h3 id="operation">Operation</h3>
<p>我們從自定義 S2I builder image 開始，並以 builder image 為底構建新的 image。</p>

<h4 id="自定義-s2i-builder-image">自定義 S2I builder image</h4>
<ol>
  <li><strong>建立一個 builder image</strong><br />
 前面提過不用特別去<a href="https://github.com/openshift/source-to-image/blob/master/docs/cli.md#sti-create">記 builder image 的結構</a>，可以直接用相指令產生目錄結構：
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>s2i create &lt;imageName&gt; &lt;destination&gt; <span class="o">[</span>flags]
</code></pre></div>    </div>

    <p><br class="big" /></p>

    <p>實際試試指令的執行效果，將 <code class="language-plaintext highlighter-rouge">&lt;imageName&gt;</code> 命名為 test-imag、要產生的目錄資料夾 <code class="language-plaintext highlighter-rouge">&lt;destination&gt;</code> 則命名為 test-image-content：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>./s2i create test-image test-image-content
</code></pre></div>    </div>

    <p>建立目錄後，可以切進目錄以觀察目錄結構。基本上與先前介紹過得相呼應（廢話 XDDD）：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">cd </span>test-image-content/
 <span class="nv">$ </span>tree 
 <span class="nb">.</span>
 ├── Dockerfile
 ├── Makefile
 ├── README.md
 ├── s2i
 │   └── bin
 │      ├── assemble
 │      ├── run
 │      ├── save-artifacts
 │      └── usage
 └── <span class="nb">test</span>
     ├── run，可以看到先前介紹過得內容：

 4 directories, 9 files
</code></pre></div>    </div>
  </li>
  <li>
    <p><strong>修改 Dockerfile</strong><br />
 這邊開始撰寫所需要 Dockerfile。在這份文件中會有許多提示，依照這些提示填入需要的安裝。</p>
  </li>
  <li><strong>修改 assemble / run</strong>
    <ul>
      <li>建立一個 assemble，主要是配置文件和靜態內容複製到目標容器中。<br />
不過這邊我沒做 XDDD</li>
      <li>再稍微修改下 run
        <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="nb">exec</span> ./app.sh  
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
  <li><strong>建立 base image</strong>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>docker build <span class="nt">-t</span> test-image-base test-image-content/.
</code></pre></div>    </div>
  </li>
</ol>

<h4 id="構建-app-image">構建 app image</h4>
<ol>
  <li><strong>撰寫個人程式</strong>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">mkdir </span>myproject 
 <span class="nv">$ </span><span class="nb">echo</span> <span class="s2">"echo 'Hello Word' "</span> <span class="o">&gt;</span> myproject/app.sh
</code></pre></div>    </div>
  </li>
  <li><strong>構建 app image</strong>
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>s2i build  myproject/ test-image-base hello-world-app
</code></pre></div>    </div>

    <p>如果順利，就會做出新的 image。但若你的 builder image 不符合 s2i 架構，在構建 app image 時就會出現錯誤訊息：</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> warning: Image sha256:37e4715d22fd3c00d8b51379e9e0eb556e842d4796d4c582fd4ff814e3d55edd does not contain a value <span class="k">for </span>the io.openshift.s2i.scripts-url label
 Build failed
 ERROR: An error occurred: failed to <span class="nb">install</span> <span class="o">[</span>assemble run]
 ERROR: Suggested solution: <span class="nb">set </span>the scripts URL parameter with the location of the S2I scripts, or check <span class="k">if </span>the image has the <span class="s2">"io.openshift.s2i.scripts-url"</span> label <span class="nb">set
 </span>ERROR: If the problem persists consult the docs at https://github.com/openshift/source-to-image/tree/master/docs. Eventually reach us on freenode <span class="c">#openshift or file an issue at https://github.com/openshift/source-to-image/issues providing us with a log from your build using log output level 3.</span>
</code></pre></div>    </div>
  </li>
</ol>

<p><br class="big" /></p>

<p>是說，我這邊偷懶用了比較簡單的例子。另外這邊有一個範例演示如何構建包含 Nginx 服務的 image builder：</p>
<ul>
  <li><a href="https://kubesphere.io/zh/docs/v3.3/project-user-guide/image-builder/s2i-templates/">〈自定义 S2I 模板〉</a></li>
  <li><a href="https://www.twblogs.net/a/5c4c35cebd9eee6e7e06f186">〈Openshift S2I構建流程〉</a></li>
</ul>

<h4 id="從-git-repository-抓取原始碼">從 Git Repository 抓取原始碼</h4>
<p>之前說過除了從本地端抓取原始碼外，也可以從遠端抓取原始碼。</p>

<ol>
  <li>從遠端 Git Repository 抓取原始碼來構建 image
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>s2i build &lt;git-repo&gt; &lt;S2I Builder Image Repository&gt; &lt;imageName&gt;
</code></pre></div>    </div>
  </li>
  <li>或是從指定 repo 中的特定資料夾抓取原始碼
    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span>s2i build &lt;git-repo&gt; <span class="nt">--context-dir</span><span class="o">=</span>&lt;Path/To/Context&gt; &lt;S2I Builder Image Repository&gt; &lt;imageName&gt;
</code></pre></div>    </div>
  </li>
</ol>

<h2 id="openshift-s2i">OpenShift S2I</h2>
<p>阿，這篇一開始的目的是要看 OpenShift 利用 S2I 提供了哪些 image builder 相關功能。不過，我完全忘了截 OpenShift 的圖，只能附上幾篇有 UI 的 XDDD</p>

<ul>
  <li><a href="https://programmersought.com/article/70153639307/">〈Get s2i image on Openshift〉</a></li>
  <li><a href="https://www.cnblogs.com/ericnie/p/9677719.html">〈OpenShift应用镜像构建(1) S2I tomcat 镜像定制〉</a></li>
</ul>

<h2 id="epilogue-and-supplement">Epilogue and Supplement</h2>
<p>好吧，我承認我這篇寫的爛透了 XDDD 畢竟這篇是好久前的事情，希望下一篇不會這麼糟糕 Orz</p>

<p class="illustration">
    <img src="https://i.imgur.com/cPqnoom.png" alt="爛透了" />
    爛透了（圖片來源: <a href="https://memes.tw/">Meme 梗圖倉庫</a>）
</p>

<p><br class="big" /></p>

<p>手邊還有幾張在文中用不到的圖，但我覺得圖還不錯，所以我就把圖放在這邊提供大家參考了：</p>

<p class="illustration">
    <img src="https://i.imgur.com/4sVwCth.png" alt="s2i flow" />
    s2i flow（圖片來源: <a href="https://andyyoung01.github.io/2016/08/24/Source-to-image构建代码">Andy's Techblog</a>）
</p>

<p class="illustration">
    <img src="https://i.imgur.com/b9Y8tjr.png" alt="s2i flow" />
    s2i flow（圖片來源: <a href="https://osninja.io/source-to-image-getting-started-with-s2i-4554dc9daa68">The OpenShift Ninja｜Medium </a>）
</p>

<h2 id="參考資料">參考資料</h2>
<ol>
  <li><a href="https://v2-1.docs.kubesphere.io/docs/developer/s2i-introduction/">Introduction to S2I</a>。檢自 KubeSphere Documents (2022-12-31)。</li>
  <li><a href="https://docs.openshift.com/container-platform/3.11/creating_images/s2i.html">S2I Requirements｜OpenShift Container Platform 3.11</a>。檢自 Red Hat OpenShift (2022-12-31)。</li>
  <li>Maciej Szulik (2015-07-21)。<a href="https://cloud.redhat.com/blog/create-s2i-builder-image">How to Create an S2I Builder Image</a>。檢自 Red Hat Hybrid Cloud (2022-12-31)。</li>
  <li>Diane Mueller (2016-07-08)。<a href="https://cloud.redhat.com/blog/source-image-s2i-deep-dive-ben-parees-openshift-commons-briefing-43">Source-to-Image (S2I) Deep Dive with Ben Parees - OpenShift Commons Briefing #43</a>。檢自 Red Hat Hybrid Cloud (2022-12-31)。</li>
  <li>(2021-03-11)。<a href="https://access.redhat.com/documentation/zh-cn/openshift_container_platform/4.4/pdf/builds/OpenShift_Container_Platform-4.4-Builds-zh-CN.pdf">OpenShift Container Platform 4.4 构建（build）</a>。檢自 Red Hat (2022-12-31)。</li>
  <li>coreydaley et al. (2022-07-09)。<a href="https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md">s2i builder image requirements</a>。檢自 source-to-image｜GitHub (2023-01-12)。</li>
  <li>Nautilu, coreydaley (2021-10-18)。<a href="https://github.com/openshift/source-to-image/blob/master/examples/nginx-centos7/README.md">Creating a basic S2I builder imag</a>。檢自 source-to-image｜GitHub (202-01-12)。</li>
  <li>Vidyasagar Machupalli (2021-10-18)。<a href="https://www.ibm.com/cloud/blog/build-a-container-image-from-source-code-using-s2i">Build a Container Image from Source Code Using S2I and Push It to a Private Registry</a>。檢自 IBM (202-01-12)。</li>
  <li>The OpenShift Ninja (2018-07-03)。<a href="https://osninja.io/source-to-image-getting-started-with-s2i-4554dc9daa68">Source-To-Image: Getting Started With s2i</a>。檢自 Medium (2022-12-31)。</li>
  <li>elef (2018-11-08)。<a href="https://www.jianshu.com/p/c06b8ec92ed3">第5章 5.2 OpenShift Origin下快速部署JAVA应用</a>。檢自 简书 (2022-12-31)。</li>
  <li>brandontsai (2020-09-26)。<a href="https://ithelp.ithome.com.tw/articles/10244344">免 Dockerfile 就可建構 Image 神器 - Source-To-Image (S2I)</a>。檢自 iT 邦幫忙 (2022-12-31)。</li>
  <li>张雷 (2018-01-16)。<a href="https://zhuanlan.zhihu.com/p/33046277">Source to Image 工具介绍 - </a>。檢自 知乎 (2022-12-31)。</li>
  <li>杨冬 (2016-08-24)。<a href="https://andyyoung01.github.io/2016/08/24/Source-to-image构建代码/">使用Source-to-image（S2I）构建镜像</a>。檢自 Andy’s Techblog (2022-12-31)。</li>
  <li>我是读书人 (2020-06-15)。<a href="https://segmentfault.com/a/1190000022936004">使用S2I从源码构建镜像</a>。檢自 SegmentFault 思否 (2022-12-31)。</li>
  <li>shenhonglei (2020-07-16)。<a href="https://blog.csdn.net/shenhonglei1234/article/details/107396708">快速学习Source-to-Image (S2I) (一)</a>。檢自 shenhonglei 的博客｜CSDN博客 (2022-12-31)。</li>
  <li>胡了了 (2017-09-27)。<a href="https://blog.csdn.net/huqigang/article/details/78110233?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=openshift/origin学习记录（9）——S2I镜像&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-78110233.142^v70^js_top,201^v4^add_ask&amp;spm=1018.2226.3001.4187">openshift/origin学习记录（9）——S2I镜像定制(基于Git)</a>。檢自 胡了了的博客｜CSDN博客 (2022-12-31)。</li>
  <li>胡了了 (2017-10-25)。<a href="https://blog.csdn.net/huqigang/article/details/78338376?ops_request_misc=&amp;request_id=&amp;biz_id=102&amp;utm_term=openshift/origin工作记录（1）——S2I镜像&amp;utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-78338376.142^v70^js_top,201^v4^add_ask&amp;spm=1018.2226.3001.4187">openshift/origin工作记录（1）——S2I镜像定制(基于SVN)</a>。檢自 胡了了的博客｜CSDN博客 (2022-12-31)。</li>
  <li>echochio (2017-05-07)。<a href="https://echochio.pixnet.net/blog/post/44754745-source-to-image（s2i）測試一下">Source-to-image（S2I）測試一下</a>。檢自 echochio｜痞客邦 (2022-12-31)。</li>
  <li>qq_dao (2019-01-26)。<a href="https://www.twblogs.net/a/5c4c35cebd9eee6e7e06f186">Openshift S2I構建流程</a>。檢自 台部落 (2022-12-31)。</li>
  <li><a href="https://programmersought.com/article/70153639307/">Get s2i image on Openshift</a>。檢自 Programmer Sought (2022-12-31)。</li>
</ol>

<h2 id="更新紀錄">更新紀錄</h2>
<details class="update_stamp">
  <summary>最後更新日期：2023-02-16</summary>
  <ul>
    <li>2023-02-16 發布</li>
    <li>2023-01-08 完稿</li>
    <li>2022-12-29 起稿</li>
  </ul>
</details>]]></content><author><name>辛西亞．Cynthia</name></author><category term="資訊科技 › 開發與輔助工具" /><category term="Docker" /><category term="工具安裝與部署" /><category term="工具介紹與操作" /><summary type="html"><![CDATA[過年大掃除，又掃出一篇之前 Survey 過且寫到一半的草稿 XDDD 這應該是去年（2021）年 12 月份筆記，我這次只是把筆記整理到能見人的程度，如果後續有更新，麻煩告知我一下，我有空再來看看 （雖然很有可能會一直沒空下去） 這篇的 Servey 目標是玩玩 S2I，順便看看 Openshift 利用 S2I 提供了哪些 image builder 相關功能。]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://i.imgur.com/ZVTUloI.png" /><media:content medium="image" url="https://i.imgur.com/ZVTUloI.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">CSS 漸層背景</title><link href="https://cynthiachuang.github.io/CSS-Gradient-Backgrounds/" rel="alternate" type="text/html" title="CSS 漸層背景" /><published>2023-02-15T16:46:00+00:00</published><updated>2023-02-15T16:46:00+00:00</updated><id>https://cynthiachuang.github.io/CSS-Gradient-Backgrounds</id><content type="html" xml:base="https://cynthiachuang.github.io/CSS-Gradient-Backgrounds/"><![CDATA[<p>我還以為我這篇已經寫完了，結果一切都是我幻想 XDDD</p>

<p>這主要是我當初用在用 <a href="/Mark-Element-is-Used-to-Highlight-Content/">Mark Tag 實作細螢光筆</a>的技術，這邊稍微整理一下相關資料。</p>

<!--more-->
<p class="illustration">
	<img src="https://i.imgur.com/ehVOu8l.png" alt="Basic gradients" />
	Basic gradients（範例來源: <a href="https://easylogic.medium.com/gradient-tool-conic-gradient-e9dd198921cc">easylogic｜Medium</a>）
</p>

<h2 id="gradient">Gradient</h2>
<p>漸層基本上就是一個顏色的漸變過程。既然是漸變，那至少需具備<strong>兩種顏色</strong>，或者說<mark>需要兩種以上的顏色</mark>，並從其中挑出兩種顏色分別設置為是起始色與終點色。</p>

<p>設定完成後，瀏覽器會計算出中間漸變的過程，進而產生一種流動感。除了顏色設定外，還可設定漸變角度、方向與尺寸…等，形成不同的流動感。</p>

<p>不過漸層這東西，如果顏色挑選的好的話，這顏色會非常漂亮，但…如果挑選的不好那會是場災難 XDDD</p>

<p>在 CSS 裡有 6 種漸層，分別是：</p>
<ol>
  <li>linear-gradient：線性漸層</li>
  <li>radial-gradient：徑向漸層</li>
  <li>conic-gradient：錐形漸層</li>
  <li>repeating-linear-gradient：線性重複漸層</li>
  <li>repeating-radial-gradient：放射重複漸層</li>
  <li>repeating-conic-gradient：重複錐形漸層</li>
</ol>

<h2 id="linear-gradient-線性漸層">Linear Gradient 線性漸層</h2>
<p>線性漸層大概是大家第一印象會浮出的樣式。線性漸層的特色就是沿著指定角度上放置數個顏色，並以直線的方式依照此角度逐漸漸變：</p>

<p class="illustration">
    <img src="https://i.imgur.com/HEvHg0w.png" alt="紫色和黃色之間呈 45 度角的線性漸變。" />
    紫色和黃色之間呈 45 度角的線性漸變。（圖片來源: <a href="https://www.quackit.com/css/functions/css_linear-gradient_function.cfm">Quackit</a>）
</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="nd">:linear-gradient</span><span class="o">(</span><span class="nt">direction</span><span class="o">,</span> <span class="nt">color-stop1</span><span class="o">,</span> <span class="nt">color-stop2</span><span class="o">,</span> <span class="o">...);</span>  
</code></pre></div></div>

<ol>
  <li><strong>direction</strong><br />
 漸變的方向或角度，如果沒有設定，預設會是由上至下進行漸層；若是設定角度，則是以左下角為圓心，與正 y 軸的夾角作為角度的來設定。這細節我們等等來實驗會比較清楚。</li>
  <li><strong>color-stop</strong><br />
 它會依照依方向使用 color 1 → color 2 → … 依序漸變過去。在 color 後方會僅跟著定位參數，將每個顏色放置在漸層線上的特定位置。若沒有指定定位參數，則預設為將第一個顏色放置在 0%、最後一個顏色放置在 100%，其餘顏色則會自動等比例分配。其中 0% 表示起始邊界，100% 表示結束邊界。</li>
</ol>

<h3 id="用關鍵字設置漸變方向">用關鍵字設置漸變方向</h3>
<p>接下來我們就漸變方向的設置方式的不同來實驗。</p>

<p>若想用關鍵字設置漸變方向，這邊有八組關鍵字可用，剛好對應八個方位：<strong>上、下、左、右、上左、下左、上右、下右</strong>，分別為 <strong>to top、to bottom、to left、to right、to top left、to bottom left、to top right、to bottom right</strong>。需特別注意的是 <mark>to</mark> 是必須的，別省略了。</p>

<p>這邊設置柔紫色 <code class="language-plaintext highlighter-rouge">#c5d5fa</code> 為起始色、柔綠色 <code class="language-plaintext highlighter-rouge">#c3dc99</code> 為終點色，並依序設置漸層方向為上、下、左、右，其效果如下：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">to</span> <span class="nt">top</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">to</span> <span class="nt">bottom</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">to</span> <span class="nt">left</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">to</span> <span class="nt">right</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);;</span>
</code></pre></div></div>

<p class="illustration">
    <img src="https://i.imgur.com/KRyoNCw.png" alt="漸層方向依序為上、下、左、右" />
    漸層方向依序為上、下、左、右
</p>

<p>若依序設置漸層方向為上左、下左、上右、下右，其效果如下：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">to</span> <span class="nt">top</span> <span class="nt">left</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">to</span> <span class="nt">bottom</span> <span class="nt">left</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">to</span> <span class="nt">top</span> <span class="nt">right</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">to</span> <span class="nt">bottom</span> <span class="nt">right</span> <span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>
<p class="illustration">
    <img src="https://i.imgur.com/TDOTHk5.png" alt="漸層方向依序為上左、下左、上右、下右" />
    漸層方向依序為上左、下左、上右、下右
</p>

<h3 id="用度數設置漸變方向">用度數設置漸變方向</h3>
<p>不過因為用關鍵字只能設定特定方向，若想設置其他角度只能用度數來設定。設定時是<strong>以左下角為圓心，夾角以 12 點鐘方向順時鐘轉動來表示</strong>。</p>

<p>這邊一樣設置柔紫色 <code class="language-plaintext highlighter-rouge">#c5d5fa</code> 為起始色、柔綠色 <code class="language-plaintext highlighter-rouge">#c3dc99</code> 為終點色，並依序設置漸層不同的度數，其效果如下：</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="err">0</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="err">30</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="err">45</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="err">60</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="err">90</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
    <img src="https://i.imgur.com/e911Iad.png" alt="漸層方向依序為0度、30度、45度、60度、90度" />
    漸層方向依序為0度、30度、45度、60度、90度
</p>

<p>仔細觀察，可以看到漸層依順時鐘的方向在轉動。其中 45 倍數角度的渲染效果基本就跟關鍵字的渲染效果一致。這邊試著依每 30 度為一步旋轉 360 度，其效果如下：</p>

<p class="illustration">
    <img src="https://i.imgur.com/125pGOh.png" alt="漸層方向依順時鐘旋轉一圈的效果" />
    漸層方向依順時鐘旋轉一圈的效果
</p>

<h3 id="多種顏色漸層">多種顏色漸層</h3>
<p>除了兩色外，漸層的顏色還可以使用多色漸層。以三色為例 <code class="language-plaintext highlighter-rouge">#c5d5fa</code>、<code class="language-plaintext highlighter-rouge">#fcdef4</code>、<code class="language-plaintext highlighter-rouge">#c3dc99</code> ，因為沒有設定定位參數，所以三種顏色平均分配漸層位置，分別是 0%、50%、100%。</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span>  <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>
<p class="illustration">
    <img src="https://imgur.com/2cWDQex.png" alt="預設分配位置的三色漸層" />
    預設分配位置的三色漸層
</p>

<p>這邊試著把粉紅色 <code class="language-plaintext highlighter-rouge">#fcdef4</code> 的位置由預設的 50%，上提到 15% 的位置。可以看到因為粉紅色 <code class="language-plaintext highlighter-rouge">#fcdef4</code> 的位置上提，導致柔紫色 <code class="language-plaintext highlighter-rouge">#c5d5fa</code> 的位置被壓縮。</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nf">#c5d5fa</span> <span class="err">0</span><span class="o">%,</span> <span class="nf">#fcdef4</span> <span class="err">15</span><span class="o">%,</span> <span class="nf">#c3dc99</span> <span class="err">100</span><span class="o">%);</span>
</code></pre></div></div>
<p class="illustration">
    <img src="https://i.imgur.com/jx2ihat.png" alt="自訂分配位置的三色漸層" />
    自訂分配位置的三色漸層
</p>

<p><br class="big" /></p>

<p>如果多一點顏色，還能做出彩虹的效果，就是出來的效果有點傷眼睛 XDDD</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">red</span><span class="o">,</span> <span class="nt">orange</span><span class="o">,</span> <span class="nt">yellow</span><span class="o">,</span> <span class="nt">green</span><span class="o">,</span> 
                            <span class="nt">blue</span><span class="o">,</span> <span class="nt">indigo</span><span class="o">,</span> <span class="nt">purple</span><span class="o">);</span>
</code></pre></div></div>
<p class="illustration">
    <img src="https://i.imgur.com/EkYuUvI.png" alt="彩虹漸層" />
    彩虹漸層
</p>

<p>這時可以搭配定位參數的使用，畫出銳利的直線：</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">red</span> <span class="err">0</span><span class="o">%,</span> <span class="nt">red</span> <span class="err">15</span><span class="o">%,</span> 
                            <span class="nt">orange</span> <span class="err">15</span><span class="o">%,</span> <span class="nt">orange</span> <span class="err">30</span><span class="o">%,</span>
                            <span class="nt">yellow</span> <span class="err">30</span><span class="o">%,</span> <span class="nt">yellow</span> <span class="err">45</span><span class="o">%,</span>
                            <span class="nt">green</span> <span class="err">45</span><span class="o">%,</span> <span class="nt">green</span> <span class="err">60</span><span class="o">%,</span>
                            <span class="nt">blue</span> <span class="err">60</span><span class="o">%,</span> <span class="nt">blue</span> <span class="err">75</span><span class="o">%,</span>
                            <span class="nt">indigo</span> <span class="err">75</span><span class="o">%,</span> <span class="nt">indigo</span> <span class="err">90</span><span class="o">%,</span>
                            <span class="nt">purple</span> <span class="err">90</span><span class="o">%,</span> <span class="nt">purple</span> <span class="err">100</span><span class="o">%);</span>
</code></pre></div></div>

<p class="illustration">
    <img src="https://i.imgur.com/wOh7IbF.png" alt="彩虹" />
    彩虹
</p>

<p>這效果主要是藉由將兩種顏色位置重疊，最終會直接畫出一條壁壘分明直線：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">linear-gradient</span><span class="o">(</span><span class="nf">#c5d5fa</span> <span class="err">50</span><span class="o">%</span> <span class="o">,</span><span class="nf">#c3dc99</span> <span class="err">50</span><span class="o">%);</span>
</code></pre></div></div>
<p class="illustration">
    <img src="https://i.imgur.com/wtIhDIB.png" alt="壁壘分明直線" />
    壁壘分明直線
</p>

<h3 id="patterns-with-gradients">Patterns with Gradients</h3>
<p>如果能熟練的使用線性漸層能拼出一些有趣的花樣。像是在 <a href="https://www.oxxostudio.tw/articles/202008/css-gradient.html">oxxo</a> 就弄出了個拼磚：</p>

<p class="illustration">
    <img src="https://i.imgur.com/ZvmN70e.png" alt="彩色拼磚" />
    彩色拼磚（範例來源: <a href="https://www.oxxostudio.tw/articles/202008/css-gradient.html">OXXO.STUDIO</a>）
</p>

<p>不過這個需要按照尺寸客製化去調整。使用上有點小麻煩。</p>

<p><br class="big" /></p>

<p>到是在 <a href="https://www.quackit.com/css/codes/patterns/">Quackitn</a> 跟 <a href="https://www.casper.tw/css/2013/09/24/css-background/">卡斯伯</a> 這邊找到些有趣的花樣：</p>

<p class="illustration">
    <img src="https://i.imgur.com/D2yeUdU.png" alt="grid Patterns" />	
    <img src="https://i.imgur.com/BubAmOp.png" alt="grid Patterns" />		
	<img src="https://i.imgur.com/uTdE9Wu.png" alt="Zig-Zag Patterns" />
    <img src="https://i.imgur.com/1aQ6wSG.png" alt="Box Patterns" />
    <img src="https://i.imgur.com/xlHu2L0.png" alt="Zig-Zag Patterns" />
	<img src="https://i.imgur.com/FodellA.png" alt="Pyramid" />	
	<img src="https://i.imgur.com/7TUeJIm.png" alt="Half-Rombes" />	
    <img src="https://i.imgur.com/7ABhKhK.png" alt="Zig-Zag Patterns" />
	Box and Zig-Zag Background Patterns（範例來源: <a href="https://www.quackit.com/css/codes/patterns/">Quackitn</a>、<a href="https://www.casper.tw/css/2013/09/24/css-background/">卡斯伯 Blog</a>、<a href="https://medium.com/@lavanyaratnabala/css-patterns-870d65192f40">Medium</a>、<a href="https://css-tricks.com/background-patterns-simplified-by-conic-gradients/">CSS-Tricks</a>）
	
	
</p>

<p>分享個我比較喜歡樣式，也就是上面第一張圖的 CSS：</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> 
    <span class="nt">linear-gradient</span><span class="o">(</span><span class="err">135</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#ccc</span> <span class="err">25</span><span class="o">%,</span> <span class="nt">transparent</span> <span class="err">25</span><span class="o">%)</span> <span class="nt">-50px</span> <span class="err">0</span><span class="o">,</span>
    <span class="nt">linear-gradient</span><span class="o">(</span><span class="err">225</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#eee</span> <span class="err">25</span><span class="o">%,</span> <span class="nt">transparent</span> <span class="err">25</span><span class="o">%)</span> <span class="nt">-50px</span> <span class="err">0</span><span class="o">,</span>
    <span class="nt">linear-gradient</span><span class="o">(</span><span class="err">315</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#ccc</span> <span class="err">25</span><span class="o">%,</span> <span class="nt">transparent</span> <span class="err">25</span><span class="o">%),</span>
    <span class="nt">linear-gradient</span><span class="o">(</span><span class="err">45</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#eee</span> <span class="err">25</span><span class="o">%,</span> <span class="nt">transparent</span> <span class="err">25</span><span class="o">%);</span>	
<span class="nt">background-size</span><span class="o">:</span> <span class="err">100</span><span class="nt">px</span> <span class="err">100</span><span class="nt">px</span><span class="o">;</span>
</code></pre></div></div>

<h2 id="radial-gradient-徑向漸層">Radial Gradient 徑向漸層</h2>
<p>除了基礎的線性漸層，另一個常見的漸層方式徑向漸層。它與線性漸層一樣，會用設定的顏色填滿整個區域，但與之不同的是，徑向漸層是從單點為顏色起始點，並依圓形或橢圓的方式向外放射延伸。</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">shape</span> <span class="nt">size</span> <span class="nt">at</span> <span class="nt">position</span><span class="o">,</span> <span class="nt">color-stop1</span><span class="o">,</span> <span class="nt">color-stop2</span><span class="o">,</span> <span class="o">...);</span>  
</code></pre></div></div>

<ol>
  <li><strong>shape size at position</strong><br />
 其實這邊有三個參數 shape、size 與 position。
    <ul>
      <li><strong>shape</strong> <br />
  指的是向外放射延伸的形狀，<strong>預設是橢圓（ellipse）</strong>，另一個選項則是圓形（circle）。</li>
      <li><strong>size</strong><br />
  指的是橢圓/圓形的半徑，<strong>預設是以圓心到最遠角（farthest-corner）</strong> 為半徑進行漸變，其餘的值有最近邊（closest-side）、最近角（closest-corner）、最遠邊（farthest-side）。這邊一樣等等來做實驗。</li>
      <li><strong>position</strong><br />
  預設會將圓心設在中心點（center）。</li>
    </ul>
  </li>
  <li><strong>color-stop</strong><br />
 跟線性漸層一樣，有顏色與定位參數兩個參數，寫在前的顏色越接近圓心。</li>
</ol>

<h3 id="設置放射延伸形狀">設置放射延伸形狀</h3>
<p>剛剛提過延伸的形狀有兩種：<mark>橢圓（ellipse）與圓形（circle）兩種</mark>。這邊一樣柔紫色 <code class="language-plaintext highlighter-rouge">#c5d5fa</code> 為起始色、柔綠色 <code class="language-plaintext highlighter-rouge">#c3dc99</code> 為終點色，來觀察兩種形狀的漸層效果：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">circle</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">ellipse</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
    <img src="https://i.imgur.com/xvr87iW.png" alt="觀察圓形與橢圓的漸層效果" />
    觀察圓形與橢圓的漸層效果
</p>

<p>一樣可以透過定位參數來調整它的渲染效果：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">circle</span><span class="o">,</span> <span class="nf">#c5d5fa</span> <span class="err">25</span><span class="o">%,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">circle</span><span class="o">,</span> <span class="nf">#c5d5fa</span> <span class="err">70</span><span class="o">%,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
    <img src="https://i.imgur.com/orkcNCD.png" alt="不同定位參數的圓形漸層效果" />
    不同定位參數的圓形漸層效果
</p>

<h3 id="設置放射中心">設置放射中心</h3>
<p>無論是橢圓還是圓形其放射中心，都是預設在區域中心。如果想更改放射中心位置有 3 種方式：</p>
<ol>
  <li><strong>絕對位置</strong>：直接使用長度值來定義位置（如：10px）</li>
  <li><strong>百分比值</strong>：使用百分比（例：10%）來定義位置</li>
  <li><strong>關鍵字</strong>：使用 top、 bottom、 left、 right、 center 關鍵字來指明位置，也可將關鍵字使用，就是前面提到的 top left、 top right…等。</li>
</ol>

<p>對了關鍵字 <strong>at</strong> 別忘了：</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">circle</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">circle</span> <span class="nt">at</span> <span class="err">30</span><span class="nt">px</span> <span class="err">50</span><span class="nt">px</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">circle</span> <span class="nt">at</span> <span class="err">80</span><span class="o">%</span> <span class="err">20</span><span class="o">%,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">circle</span> <span class="nt">at</span> <span class="nt">left</span> <span class="nt">bottom</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
    <img src="https://i.imgur.com/niOVS4G.png" alt="不同放射中心的圓形漸層效果" />
    不同放射中心的圓形漸層效果
</p>

<h3 id="設置放射半徑">設置放射半徑</h3>
<p>若依照參數順序，這小節應該放在設置放射延伸形狀與設置放射中心的中間章節比較合適，不過因為效果圖必須搭配放射中心的調整來看會比較清楚，所以我把它移到這邊來看效果。</p>

<p>這邊總共有 4 個值可選最遠角（farthest-corner）、最近邊（closest-side）、最近角（closest-corner）、最遠邊（farthest-side）：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="nd">:radial-gradient</span><span class="o">(</span><span class="nt">circle</span> <span class="nt">closest-side</span> <span class="nt">at</span> <span class="nt">center</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="nd">:radial-gradient</span><span class="o">(</span><span class="nt">circle</span> <span class="nt">farthest-side</span> <span class="nt">at</span> <span class="nt">center</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="nd">:radial-gradient</span><span class="o">(</span><span class="nt">circle</span> <span class="nt">closest-corner</span> <span class="nt">at</span> <span class="nt">left</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="nd">:radial-gradient</span><span class="o">(</span><span class="nt">circle</span> <span class="nt">farthest-corner</span> <span class="nt">at</span> <span class="nt">left</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/zeLzbT8.png" alt="不同放射半徑的圓形漸層效果" />
	不同放射半徑的圓形漸層效果
</p>

<h3 id="多種顏色漸層-1">多種顏色漸層</h3>
<p>至於多種顏色的設置跟線性漸層的一致，如果沒有設置定位參數，所有顏色會平均分配：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="nd">:radial-gradient</span><span class="o">(</span><span class="nt">circle</span><span class="o">,</span> <span class="nt">red</span><span class="o">,</span> <span class="nt">orange</span><span class="o">,</span> <span class="nt">yellow</span><span class="o">,</span> 
                           <span class="nt">green</span><span class="o">,</span> <span class="nt">blue</span><span class="o">,</span> <span class="nt">indigo</span><span class="o">,</span> <span class="nt">purple</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/GrePbTF.png" alt="徑向彩虹漸層" />
	徑向彩虹漸層
</p>

<p>一樣透過設置定位參數，可以調整顏色的分配狀況，若直接將顏色重疊，會做出同心圓效果…雖然我的圖被截掉…不過應該還看得出是同心圓啦 XDDD</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="nd">:radial-gradient</span><span class="o">(</span><span class="nt">circle</span><span class="o">,</span> 
                            <span class="nt">red</span> <span class="err">0</span><span class="o">%,</span> <span class="nt">red</span> <span class="err">15</span><span class="o">%,</span> 
                            <span class="nt">orange</span> <span class="err">15</span><span class="o">%,</span> <span class="nt">orange</span> <span class="err">30</span><span class="o">%,</span>
                            <span class="nt">yellow</span> <span class="err">30</span><span class="o">%,</span> <span class="nt">yellow</span> <span class="err">45</span><span class="o">%,</span>
                            <span class="nt">green</span> <span class="err">45</span><span class="o">%,</span> <span class="nt">green</span> <span class="err">60</span><span class="o">%,</span>
                            <span class="nt">blue</span> <span class="err">60</span><span class="o">%,</span> <span class="nt">blue</span> <span class="err">75</span><span class="o">%,</span>
                            <span class="nt">indigo</span> <span class="err">75</span><span class="o">%,</span> <span class="nt">indigo</span> <span class="err">90</span><span class="o">%,</span>
                            <span class="nt">purple</span> <span class="err">90</span><span class="o">%,</span> <span class="nt">purple</span> <span class="err">100</span><span class="o">%);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/nPp3Pv2.png" alt="徑向彩虹漸層" />
	彩虹同心圓
</p>

<h3 id="patterns-with-gradients-1">Patterns with Gradients</h3>
<p>每次看人家的範例，就覺得就覺得人家真超厲害，一個簡單的漸層都可以完出個花來：</p>

<p class="illustration">
	<img src="https://i.imgur.com/asXOzkV.png" alt="圓圈背景" />
	<img src="https://i.imgur.com/RmT8uXv.png" alt="圓圈背景" />
	<img src="https://i.imgur.com/F5Lxk7c.png" alt="圓圈背景" />
	<img src="https://i.imgur.com/xSpvlTa.png" alt="圓圈背景" />
	圓圈背景（範例來源: <a href="https://www.quackit.com/css/codes/patterns/">Quackitn</a>、<a href="https://www.casper.tw/css/2013/09/24/css-background/">卡斯伯 Blog</a>、<a href="https://medium.com/@lavanyaratnabala/css-patterns-870d65192f40">Medium</a>）
</p>

<p><a href="https://www.oxxostudio.tw/articles/202008/css-gradient.html">oxxo</a> 還能畫出個球體：</p>
<p class="illustration">
	<img src="https://i.imgur.com/nzHhNQy.png" alt="球體" />
	球體（範例來源: <a href="https://www.oxxostudio.tw/articles/202008/css-gradient.html">OXXO.STUDIO</a>）
</p>

<p>橘黃色點點那個還滿漂亮的，留一下 CSS 好了：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background-color</span><span class="o">:</span> <span class="nt">orange</span><span class="o">;</span>
<span class="nt">background-image</span><span class="o">:</span> 
    <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">gold</span> <span class="err">15</span><span class="o">%,</span> <span class="nt">transparent</span> <span class="err">15</span><span class="o">%),</span>
    <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">gold</span> <span class="err">40</span><span class="o">%,</span> <span class="nt">transparent</span> <span class="err">40</span><span class="o">%);</span>
<span class="nt">background-size</span><span class="o">:</span> <span class="err">60</span><span class="nt">px</span> <span class="err">60</span><span class="nt">px</span><span class="o">;</span>
<span class="nt">background-position</span><span class="o">:</span> <span class="err">0</span> <span class="err">0</span><span class="o">,</span> <span class="err">30</span><span class="nt">px</span> <span class="err">30</span><span class="nt">px</span><span class="o">;</span>
</code></pre></div></div>

<h2 id="conic-gradient-錐形漸層">Conic Gradient 錐形漸層</h2>
<p>錐形漸層語法有點類似徑向漸層，但漸變的方向確不太一樣。徑向漸層是由圓心向外漸變，而錐形漸層則是<mark>順時針繞圓心漸變</mark>：</p>

<p class="illustration">
	<img src="https://i.imgur.com/FZQT7D8.png" alt="線性漸層、徑向漸層與錐形漸層的漸變差異" />
	線性漸層、徑向漸層與錐形漸層的漸變差異（範例來源: <a href="https://followandrew.dev/css-conic-gradient-effects-tutorial/">FollowAndrew</a>）
</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background-image</span><span class="o">:</span> 
    <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">from</span> <span class="nt">angle</span> <span class="nt">at</span> <span class="nt">position</span><span class="o">,</span> <span class="nt">color-stop1</span><span class="o">,</span> <span class="nt">color-stop2</span><span class="o">,</span> <span class="o">...);</span> 
</code></pre></div></div>

<ol>
  <li><strong>from angle</strong><br />
 開始旋轉的角度，預設是從 <strong>0 度</strong> 開始順時鐘漸變。</li>
  <li><strong>at position</strong><br />
 錐形漸層的圓心，預設圓心是在圖片中心。</li>
</ol>

<p><br class="big" /></p>

<p>自己上點顏色來看看，</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">radial-gradient</span><span class="o">(</span><span class="nt">circle</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>
<p class="illustration">
	<img src="https://i.imgur.com/3zlx7Bq.png" alt="徑向漸層與錐形漸層的漸變差異" />
	徑向漸層與錐形漸層的漸變差異
</p>

<h3 id="設置起始旋轉的角度">設置起始旋轉的角度</h3>
<p>這邊要特別注意的大概就是關鍵字 <mark>from</mark> 別丟了？</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">from</span> <span class="err">0</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">from</span> <span class="err">90</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">from</span> <span class="err">180</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">from</span> <span class="err">270</span><span class="nt">deg</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/fEyVauI.png" alt="不同起始旋轉的角度的錐形漸層效果" />
	不同起始旋轉的角度的錐形漸層效果
</p>

<h3 id="設置錐形的圓心">設置錐形的圓心</h3>
<p>跟徑向漸層的放射中心設置方式一樣，可以透過設置<strong>絕對位置</strong>、<strong>百分比值</strong>與<strong>關鍵字</strong>的 3 種方式，一樣 <mark>at</mark> 別忘了：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">at</span> <span class="err">30</span><span class="nt">px</span> <span class="err">50</span><span class="nt">px</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">at</span> <span class="err">80</span><span class="o">%</span> <span class="err">20</span><span class="o">%,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">at</span> <span class="nt">left</span> <span class="nt">bottom</span><span class="o">,</span> <span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#fcdef4</span><span class="o">,</span> <span class="nf">#c3dc99</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/2tpVgCd.png" alt="不同圓心的錐形漸層效果" />
	不同圓心的錐形漸層效果
</p>

<h3 id="多種顏色漸層-2">多種顏色漸層</h3>
<p>其實我前面已經用了三個顏色了，但…我想畫彩虹 :rainbow: 所以我畫了兩版，一版是漸層變色，一版是色塊版：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">width</span><span class="o">:</span><span class="err">200</span><span class="nt">px</span><span class="o">;</span>
<span class="nt">height</span><span class="o">:</span><span class="err">200</span><span class="nt">px</span><span class="o">;</span>
<span class="nt">border-radius</span><span class="o">:</span><span class="err">50</span><span class="o">%;</span>     
<span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">red</span><span class="o">,</span> <span class="nt">orange</span><span class="o">,</span> <span class="nt">yellow</span><span class="o">,</span> <span class="nt">green</span><span class="o">,</span> <span class="nt">blue</span><span class="o">,</span> <span class="nt">indigo</span><span class="o">,</span> <span class="nt">purple</span><span class="o">,</span> <span class="nt">red</span><span class="o">);</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">conic-gradient</span><span class="o">(</span><span class="nt">red</span> <span class="err">0</span><span class="o">,</span> <span class="nt">red</span> <span class="err">25</span><span class="nt">deg</span><span class="o">,</span> 
                           <span class="nt">orange</span> <span class="err">25</span><span class="nt">deg</span><span class="o">,</span> <span class="nt">orange</span> <span class="err">75</span><span class="nt">deg</span> <span class="o">,</span> 
                           <span class="nt">yellow</span> <span class="err">75</span><span class="nt">deg</span><span class="o">,</span> <span class="nt">yellow</span> <span class="err">125</span><span class="nt">deg</span><span class="o">,</span>
                           <span class="nt">green</span> <span class="err">125</span><span class="nt">deg</span><span class="o">,</span> <span class="nt">green</span> <span class="err">175</span><span class="nt">deg</span><span class="o">,</span> 
                           <span class="nt">blue</span> <span class="err">175</span><span class="nt">deg</span><span class="o">,</span> <span class="nt">blue</span> <span class="err">225</span><span class="nt">deg</span><span class="o">,</span> 
                           <span class="nt">indigo</span> <span class="err">225</span><span class="nt">deg</span><span class="o">,</span> <span class="nt">indigo</span> <span class="err">275</span><span class="nt">deg</span><span class="o">,</span> 
                           <span class="nt">purple</span> <span class="err">275</span><span class="nt">deg</span><span class="o">,</span> <span class="nt">purple</span> <span class="err">325</span><span class="nt">deg</span><span class="o">,</span> 
                           <span class="nt">red</span> <span class="err">325</span><span class="nt">deg</span><span class="o">,</span> <span class="nt">red</span> <span class="err">360</span><span class="nt">deg</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/uvHHuaL.png" alt="彩虹錐形漸變" />
	彩虹錐形漸變
</p>

<h3 id="patterns-with-gradients-2">Patterns with Gradients</h3>
<p>錐形好像比較少見到各種花裡胡哨的圖案，到是比較常見各種圓餅圖：</p>
<p class="illustration">
	<img src="https://i.imgur.com/gnT6EZJ.png" alt="圓餅圖" />
	圓餅圖（範例來源: <a href="https://lenadesign.org/2021/05/15/css-conic-gradient/">Lena Design</a>）
</p>

<p>另一種比較常見的則是這種環形色票：</p>

<p class="illustration">
	<img src="https://i.imgur.com/hXxMXQv.png" alt="色票" />
	色票（範例來源: <a href="https://lenadesign.org/2021/05/15/css-conic-gradient/">Lena Design</a>）
</p>

<h2 id="repeating-linear-gradients-重複線性漸層">Repeating Linear Gradients 重複線性漸層</h2>
<p>前面的範例中，如果要做出重複的漸層效果，都會透過 <code class="language-plaintext highlighter-rouge">background-size</code> 與 <code class="language-plaintext highlighter-rouge">background-repeat</code> 來實現。但除此之外，還可以透過 <code class="language-plaintext highlighter-rouge">repeating-linear-gradient</code> 輕鬆實現重複效果：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="nd">:repeating-linear-gradient</span><span class="o">(</span><span class="nt">direction</span><span class="o">,</span> <span class="nt">color-stop1</span><span class="o">,</span> <span class="nt">color-stop2</span><span class="o">,</span> <span class="o">...);</span>  
</code></pre></div></div>

<p>基本使用方法，與 <code class="language-plaintext highlighter-rouge">linear-gradient</code> 基本一致，但需要指定定位參數，瀏覽器會將需要重複的顏色放置在指定位置，其餘部份會自動計算補滿：</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="nd">:repeating-linear-gradient</span><span class="o">(</span><span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span>  <span class="err">15</span><span class="o">%);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/O2uC0Yl.png" alt="repeating-linear-gradient 漸層效果" />
	repeating-linear-gradient 漸層效果
</p>

<p>以這個例子為例，會將 <code class="language-plaintext highlighter-rouge">#c5d5fa</code> 與 <code class="language-plaintext highlighter-rouge">#c3dc99</code> 分別擺放在 0% 和 15%，其餘部份就會重複填滿了。不過我發現這個重複的交界處的過渡太過明顯，所以我在 30% 的地方加上起始色 <code class="language-plaintext highlighter-rouge">#c5d5fa</code>，讓它的產生平滑過渡的效果：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="nd">:repeating-linear-gradient</span><span class="o">(</span><span class="nf">#c5d5fa</span><span class="o">,</span> <span class="nf">#c3dc99</span>  <span class="err">15</span><span class="o">%,</span> <span class="nf">#c5d5fa</span> <span class="err">30</span><span class="o">%);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/Uka8hxp.png" alt="repeating-linear-gradient 漸層效果" />
	repeating-linear-gradient 漸層效果
</p>

<p>若沒有指定定位參數，使用起來的效果基本跟 <code class="language-plaintext highlighter-rouge">linear-gradient</code> 相同：</p>
<p class="illustration">
	<img src="https://i.imgur.com/ZTFefJ9.png" alt="不給定定位參數的 repeating-linear-gradient 漸層效果" />
	不給定定位參數的 repeating-linear-gradient 漸層效果
</p>

<h3 id="patterns-with-gradients-3">Patterns with Gradients</h3>
<p>一樣找了些有趣花樣：</p>

<p class="illustration">
	<img src="https://i.imgur.com/SdRNmr2.png" alt="網狀線" />
	<img src="https://i.imgur.com/xEVPr40.png" alt="斑馬線" />
	<img src="https://i.imgur.com/Duhv4Zt.png" alt="警戒線" />
	網格與線狀（範例來源: <a href="https://www.quackit.com/css/codes/patterns/">Quackitn</a>、<a href="https://www.casper.tw/css/2013/09/24/css-background/">卡斯伯 Blog</a>、<a href="https://medium.com/@lavanyaratnabala/css-patterns-870d65192f40">Medium</a>）
</p>

<p>那個橘黑色的配色，有點像道路工程的警示色 XDDD</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">repeating-linear-gradient</span><span class="o">(</span><span class="err">45</span><span class="nt">deg</span><span class="o">,</span> 
                                      <span class="nt">black</span> <span class="err">0</span><span class="o">,</span> <span class="nt">black</span> <span class="err">5</span><span class="o">%,</span> 
                                      <span class="nt">orange</span> <span class="err">5</span><span class="o">%,</span> <span class="nt">orange</span> <span class="err">10</span><span class="o">%);</span>
</code></pre></div></div>

<h2 id="repeating-radial-gradient-重複徑向漸層">Repeating Radial Gradient 重複徑向漸層</h2>
<p>除線性漸層有重複效果外，徑向漸層也有：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="nd">:repeating-radial-gradient</span><span class="o">(</span><span class="nt">direction</span><span class="o">,</span> <span class="nt">color-stop1</span><span class="o">,</span> <span class="nt">color-stop2</span><span class="o">,</span> <span class="o">...);</span>  
</code></pre></div></div>

<p>基本使用方法，與 radial-gradient 基本一致，但需要指定定位參數，剩下交由瀏覽器自動補滿：</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">repeating-radial-gradient</span><span class="o">(</span><span class="nt">circle</span><span class="o">,</span> <span class="nf">#c5d5fa</span> <span class="err">5</span><span class="o">%,</span> <span class="nf">#c3dc99</span> <span class="err">10</span><span class="o">%);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/KHL7UqV.png" alt="重複徑向漸層" />
	重複徑向漸層
</p>

<p>不曉得為啥，好像出現類似陰影的效果，我換個顏色感覺會更明顯：</p>
<p class="illustration">
	<img src="https://i.imgur.com/Ukz4lEF.png" alt="重複徑向漸層有自帶陰影效果" />
	重複徑向漸層有自帶陰影效果
</p>

<p>一樣若想讓過渡效果平滑點，可將起始色設為新的終點色，就是眼睛看起來有點花：</p>
<p class="illustration">
	<img src="https://i.imgur.com/rbu1CdL.png" alt="平滑過渡效果的重複徑向漸層" />
	平滑過渡效果的重複徑向漸層
</p>

<h3 id="patterns-with-gradients-4">Patterns with Gradients</h3>
<p>這個我就不找太多範例了，我眼睛好花阿 @@</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">repeating-radial-gradient</span><span class="o">(</span><span class="nt">closest-side</span> <span class="nt">at</span> <span class="err">25</span><span class="nt">px</span> <span class="err">35</span><span class="nt">px</span><span class="o">,</span> <span class="nt">orange</span> <span class="err">15</span><span class="o">%,</span> <span class="nt">gold</span> <span class="err">40</span><span class="o">%);</span>
<span class="nt">background-size</span><span class="o">:</span><span class="err">60</span><span class="nt">px</span> <span class="err">60</span><span class="nt">px</span><span class="o">;</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/iS4ABKV.png" alt="圈圈" />
	圈圈（範例來源: <a href="https://www.quackit.com/css/codes/patterns/">Quackitn</a>）
</p>

<h2 id="repeating-conic-gradient-重複錐形漸層">Repeating Conic Gradient 重複錐形漸層</h2>
<p>如果用重複錐形漸層則可做出放射線的背景效果：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">repeating-conic-gradient</span><span class="o">(</span><span class="nt">from</span> <span class="nt">angle</span> <span class="nt">at</span> <span class="nt">position</span><span class="o">,</span> <span class="nt">color-stop1</span><span class="o">,</span> <span class="nt">color-stop2</span><span class="o">,</span> <span class="o">...);</span>  
</code></pre></div></div>

<p>基本使用方法，與 conic-gradient 基本一致，一樣別忘了定位參數：</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background</span><span class="o">:</span> <span class="nt">repeating-conic-gradient</span><span class="o">(</span><span class="nt">red</span> <span class="err">0</span><span class="o">,</span> <span class="nt">yellow</span> <span class="err">15</span><span class="nt">deg</span><span class="o">);</span>      
<span class="nt">background</span><span class="o">:</span> <span class="nt">repeating-conic-gradient</span><span class="o">(</span><span class="nt">red</span> <span class="err">0</span><span class="o">,</span> <span class="nt">red</span> <span class="err">15</span><span class="nt">deg</span><span class="o">,</span> <span class="nt">yellow</span> <span class="err">15</span><span class="nt">deg</span><span class="o">,</span>  <span class="nt">yellow</span> <span class="err">30</span><span class="nt">deg</span><span class="o">);</span>     
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/v5mf4wi.png" alt="重複錐形漸層" />
	重複錐形漸層
</p>

<h3 id="patterns-with-gradients-5">Patterns with Gradients</h3>
<p>如果能熟練是用漸層的話，可以試著疊加不同的漸層效果，例如漸淡融入的效果；也能取代之前一些像是棋盤實做，它的程式碼會更加的簡短。</p>

<p class="illustration">
	<img src="https://i.imgur.com/j0H2hRP.png" alt="重複錐形漸層花樣" />
	重複錐形漸層花樣（範例來源: <a href="https://www.oxxostudio.tw/articles/202008/css-gradient.html">OXXO.STUDIO</a>、<a href="https://css-tricks.com/background-patterns-simplified-by-conic-gradients/">CSS-Tricks</a>）
</p>

<p>最後記錄下棋盤的 CSS</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">border</span><span class="o">:</span><span class="err">7</span><span class="nt">px</span> <span class="nt">solid</span> <span class="err">#000</span><span class="o">;</span>
<span class="nt">background</span><span class="o">:</span> <span class="nt">repeating-conic-gradient</span><span class="o">(</span><span class="nt">black</span> <span class="err">0</span><span class="o">%</span> <span class="err">25</span><span class="o">%,</span> <span class="nt">white</span> <span class="err">0</span><span class="o">%</span> <span class="err">50</span><span class="o">%)</span> <span class="err">43</span><span class="o">%/</span><span class="err">45</span><span class="nt">px</span> <span class="err">50</span><span class="nt">px</span><span class="o">;</span> 
</code></pre></div></div>

<h2 id="combine-background-image-with-gradient-overlay">Combine background image with gradient overlay</h2>
<p>原本我以為圖片也有漸層屬性可用，不過看來我多想了，它也是利用漸層效果疊加做出來的：</p>

<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">background-image</span><span class="o">:</span>
    <span class="nt">linear-gradient</span><span class="o">(</span><span class="nt">to</span> <span class="nt">bottom</span><span class="o">,</span> <span class="nt">rgba</span><span class="o">(</span><span class="err">195</span><span class="o">,</span> <span class="err">220</span><span class="o">,</span> <span class="err">153</span><span class="o">,</span> <span class="err">0</span><span class="o">.</span><span class="err">32</span><span class="o">),</span> <span class="nt">rgba</span><span class="o">(</span><span class="err">255</span><span class="o">,</span> <span class="err">255</span><span class="o">,</span> <span class="err">255</span><span class="o">,</span> <span class="err">0</span><span class="o">.</span><span class="err">73</span><span class="o">)</span> <span class="err">80</span><span class="o">%),</span>
    <span class="nt">url</span><span class="o">(</span><span class="s2">'https://i.imgur.com/OzTiFeI.png'</span><span class="o">);</span>
</code></pre></div></div>

<p class="illustration">
	<img src="https://i.imgur.com/b9FkiTd.png" alt="圖片漸層效果" />
	圖片漸層效果（原圖片來源: <a href="https://699pic.com/tupian-401782443.html">摄图网</a>）
</p>

<h2 id="color-palettes-generator-and-color-gradient-tool">Color Palettes Generator and Color Gradient Tool</h2>
<p>這部份跟 CSS 比較沒關係，純粹就是給配色苦手用的參考資料。這些網站有現成的配色方案，能配出許多還不錯的視覺效果 XDDD</p>

<ol>
  <li><a href="https://webgradients.com/">Fresh Background Gradients</a> <strong>推</strong> :star2:</li>
  <li><a href="https://uigradients.com/">UI Gradients</a></li>
  <li><a href="http://www.colorzilla.com/gradient-editor/">Colorzilla Gradients</a></li>
  <li><a href="https://mycolor.space/">ColorSpace</a></li>
  <li><a href="http://grabient.com">Grabient</a></li>
  <li><a href="http://webkul.github.io/coolhue">coolhue</a></li>
  <li><a href="https://gradients.cssgears.com/">CSS GEARS</a></li>
</ol>

<h2 id="參考資料">參考資料</h2>
<ol>
  <li>卡斯伯 (2013-09-24)。<a href="https://www.casper.tw/css/2013/09/24/css-background/">CSS沒有極限 - CSS3的漸層</a>。檢自 卡斯伯 Blog (2022-12-22)。</li>
  <li>oxxo (2022-08-30)。<a href="https://www.oxxostudio.tw/articles/202008/css-gradient.html">深入理解 CSS 漸層 ( CSS Gradient ) </a>。檢自 OXXO.STUDIO (2022-12-22)。</li>
  <li>小艾 (2018-01-14)。<a href="https://ithelp.ithome.com.tw/articles/10197136">Day26：小事之 多重背景與漸層背景 CSS3 Gradients</a>。檢自 iT 邦幫忙 (2022-12-22)。</li>
  <li>bdp (2017-12-07)。<a href="https://ithelp.ithome.com.tw/articles/10190867">CSS：background 雙色漸層</a>。檢自 iT 邦幫忙 (2022-12-22)。</li>
  <li>逗點人 (2017-10-27)。<a href="https://blog.7netic.com/2017/10/27/三種絕美css-背景漸層語法產生器fresh-background-gradients）-適用firefox、ie/">三種絕美CSS 背景漸層語法產生器(FRESH BACKGROUND GRADIENTS）-適用FIREFOX、IE</a>。檢自 逗點人7netic設計插畫誌 (2022-12-22)。</li>
  <li><a href="https://www.quackit.com/css/functions/css_linear-gradient_function.cfm">CSS linear-gradient() Function</a>。檢自 Quackit (2022-12-22)。</li>
  <li><a href="https://www.w3schools.com/cssref/func_radial-gradient.php">CSS radial-gradient() function</a>。檢自 W3schools (2022-12-22)。</li>
  <li>Lena Stanley (2021-05-15)。<a href="https://lenadesign.org/2021/05/15/css-conic-gradient/">CSS Conic-Gradient</a>。檢自 Lena Design (2022-12-22)。</li>
  <li>Ana Tudor (May 28, 2020-05-28)。<a href="https://css-tricks.com/background-patterns-simplified-by-conic-gradients/">Background Patterns, Simplified by Conic Gradients</a>。檢自 CSS-Tricks (2022-12-26)。</li>
  <li>(2021-06-16)。<a href="https://webdevetc.com/blog/how-to-add-a-gradient-overlay-to-a-background-image-using-just-css-and-html/">How to add a gradient overlay to a background image using just CSS and HTML</a>。檢自 Web dev etc (2022-12-26)。</li>
  <li>沾醬油(2018-04-19)。<a href="https://spencer581026.pixnet.net/blog/post/402900452-色票-好用的9個漸層配色網站">色票-好用的9個漸層配色網站</a>。檢自 沾醬油的部落格｜痞客邦 (2022-12-26)。</li>
</ol>

<h2 id="更新紀錄">更新紀錄</h2>
<details class="update_stamp">
  <summary>最後更新日期：2023-02-15</summary>
  <ul>  
    <li>2023-02-15 發布</li>
    <li>2022-12-26 完稿</li>
    <li>2022-12-22 起稿</li>
  </ul>
</details>]]></content><author><name>辛西亞．Cynthia</name></author><category term="程式設計 › 程式語言與架構" /><category term="CSS/SCSS" /><category term="前端" /><summary type="html"><![CDATA[我還以為我這篇已經寫完了，結果一切都是我幻想 XDDD 這主要是我當初用在用 Mark Tag 實作細螢光筆的技術，這邊稍微整理一下相關資料。]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://i.imgur.com/ehVOu8l.png" /><media:content medium="image" url="https://i.imgur.com/ehVOu8l.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">【LeetCode】0000. 解題目錄</title><link href="https://cynthiachuang.github.io/LeetCode-0000-Contents/" rel="alternate" type="text/html" title="【LeetCode】0000. 解題目錄" /><published>2023-02-15T00:00:00+00:00</published><updated>2023-02-15T00:00:00+00:00</updated><id>https://cynthiachuang.github.io/LeetCode-0000-Contents</id><content type="html" xml:base="https://cynthiachuang.github.io/LeetCode-0000-Contents/"><![CDATA[<p>最近開始刷 LeetCode，但雖然有些題目解了出來，但還是存在很多似懂非懂的模糊空間，因此想透過記錄的方式記下這些經驗與領略，並用自己的方式表達出來，以釐清這些模糊的空間。</p>

<p>是說才剛開始刷題，長路漫漫阿…
<!--more--></p>

<p><br class="big" /></p>

<table>
  <thead>
    <tr>
      <th>NO.</th>
      <th>題目</th>
      <th>難度</th>
      <th>備註</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0771.</td>
      <td><a href="/LeetCode-0771-Jewels-and-Stones/">Jewels and Stones</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0226.</td>
      <td><a href="/LeetCode-0226-Invert-Binary-Tree/">Invert Binary Tree</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0208.</td>
      <td><a href="/problemset/2018/12/21/LeetCode-0208-Implement-Trie/">Implement Trie (Prefix Tree) </a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0189.</td>
      <td><a href="/LeetCode-0189-Rotate-Array/">Rotate Array</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0175.</td>
      <td><a href="/LeetCode-0175-Combine-Two-Tables/">Combine Two Tables</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0140.</td>
      <td><a href="/LeetCode-0140-Word-Break-II/">Word Break II</a></td>
      <td>H</td>
      <td> </td>
    </tr>
    <tr>
      <td>0139.</td>
      <td><a href="/LeetCode-0139-Word-Break/">Word Break</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0071.</td>
      <td><a href="/LeetCode-0071-Simplify-Path/">Simplify Path</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0066.</td>
      <td><a href="/LeetCode-0066-Plus-One/">Plus One</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0065.</td>
      <td><a href="/LeetCode-0065-Valid-Number/">Valid Number</a></td>
      <td>H</td>
      <td> </td>
    </tr>
    <tr>
      <td>0044.</td>
      <td><a href="/LeetCode-0044-Wildcard-Matching/">Wildcard Matching*</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0043.</td>
      <td><a href="/LeetCode-0043-Multiply-Strings/">Multiply Strings</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0036.</td>
      <td>Valid Sudoku</td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0035.</td>
      <td>Search Insert Position</td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0034.</td>
      <td>Find First and Last Position of Element in Sorted Array</td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0033.</td>
      <td>Search in Rotated Sorted Array</td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0032.</td>
      <td><a href="/LeetCode-0032-Longest-Valid-Parentheses/">Longest Valid Parentheses*</a></td>
      <td>H</td>
      <td> </td>
    </tr>
    <tr>
      <td>0031.</td>
      <td><a href="/LeetCode-0031-Next-Permutation/">Next Permutation</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0030.</td>
      <td>Substring with Concatenation of All Words</td>
      <td>H</td>
      <td> </td>
    </tr>
    <tr>
      <td>0029.</td>
      <td>Divide Two Integers</td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0028.</td>
      <td><a href="/LeetCode-0028-Find-the-Index-of-the-First-Occurrence-in-a-String">Find the Index of the First Occurrence in a String</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0027.</td>
      <td><a href="/LeetCode-0027-Remove-Element">Remove Element</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0026.</td>
      <td><a href="/LeetCode-0026-Remove-Duplicates-from-Sorted-Array">Remove Duplicates from Sorted Array</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0025.</td>
      <td><a href="/LeetCode-0025-Reverse-Nodes-in-k-Group/">Reverse Nodes in k-Group</a></td>
      <td>H</td>
      <td> </td>
    </tr>
    <tr>
      <td>0024.</td>
      <td><a href="/LeetCode-0024-Swap-Nodes-in-Pairs/">Swap Nodes in Pairs</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0023.</td>
      <td><a href="/LeetCode-0023-Merge-k-Sorted-Lists">Merge k Sorted Lists</a></td>
      <td>H</td>
      <td> </td>
    </tr>
    <tr>
      <td>0022.</td>
      <td><a href="/LeetCode-0022-Generate-Parentheses">Generate Parentheses</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0021.</td>
      <td><a href="/LeetCode-0021-Merge-Two-Sorted-Lists/">Merge Two Sorted Lists</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0020.</td>
      <td><a href="/LeetCode-0020-Valid-Parentheses/">Valid Parentheses</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0019.</td>
      <td><a href="/LeetCode-0019-Remove-Nth-Node-From-End-of-List/">Remove Nth Node From End of List</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0018.</td>
      <td><a href="/LeetCode-0018-4Sum/">4Sum*</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0017.</td>
      <td><a href="/LeetCode-0017-Letter-Combinations-of-a-Phone-Number/">Letter Combinations of a Phone Number</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0016.</td>
      <td><a href="/LeetCode-0016-3Sum-Closest/">3Sum Closest</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0015.</td>
      <td><a href="/LeetCode-0015-3Sum/">3Sum</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0014.</td>
      <td><a href="/LeetCode-0014-Longest-Common-Prefix/">Longest Common Prefix</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0013.</td>
      <td><a href="/LeetCode-0013-Roman-to-Integer/">Roman to Integer</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0012.</td>
      <td><a href="/LeetCode-0012-Integer-to-Roman/">Integer to Roman</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0011.</td>
      <td><a href="/LeetCode-0011-Container-With-Most-Water/">Container With Most Water</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0010.</td>
      <td><a href="/LeetCode-0010-Regular-Expression-Matching/">Regular Expression Matching</a></td>
      <td>H</td>
      <td> </td>
    </tr>
    <tr>
      <td>0009.</td>
      <td><a href="/LeetCode-0009-Palindrome-Number/">Palindrome Number</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0008.</td>
      <td><a href="/LeetCode-0008-String-to-Integer-atoi/">String to Integer (atoi)</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0007.</td>
      <td><a href="/LeetCode-0007-Reverse-Integer/">Reverse Integer</a></td>
      <td>E</td>
      <td> </td>
    </tr>
    <tr>
      <td>0006.</td>
      <td><a href="/LeetCode-0006-ZigZag-Conversion/">ZigZag Conversion</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0005.</td>
      <td><a href="/LeetCode-0005-Longest-Palindromic-Substring/">Longest Palindromic Substring</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0003.</td>
      <td><a href="/LeetCode-0003-Longest-Substring-Without-Repeating-Characters">Longest Substring Without Repeating Characters</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0002.</td>
      <td><a href="/LeetCode-0002-Add-Two-Numbers/">Add Two Numbers</a></td>
      <td>M</td>
      <td> </td>
    </tr>
    <tr>
      <td>0001.</td>
      <td><a href="/LeetCode-0001-Two-Sum/">Two Sum</a></td>
      <td>E</td>
      <td> </td>
    </tr>
  </tbody>
</table>]]></content><author><name>辛西亞．Cynthia</name></author><category term="面試刷題" /><category term="LeetCode" /><category term="目錄" /><summary type="html"><![CDATA[最近開始刷 LeetCode，但雖然有些題目解了出來，但還是存在很多似懂非懂的模糊空間，因此想透過記錄的方式記下這些經驗與領略，並用自己的方式表達出來，以釐清這些模糊的空間。]]></summary></entry><entry><title type="html">【LeetCode】0022.Generate Parentheses</title><link href="https://cynthiachuang.github.io/LeetCode-0022-Generate-Parentheses/" rel="alternate" type="text/html" title="【LeetCode】0022.Generate Parentheses" /><published>2023-02-15T00:00:00+00:00</published><updated>2023-02-15T00:00:00+00:00</updated><id>https://cynthiachuang.github.io/LeetCode-0022-Generate-Parentheses</id><content type="html" xml:base="https://cynthiachuang.github.io/LeetCode-0022-Generate-Parentheses/"><![CDATA[<p>Given <code class="language-plaintext highlighter-rouge">n</code> pairs of parentheses, write a function to generate all combinations of well-formed parentheses.</p>

<!--more-->
<p><br /></p>

<p><strong>Example 1:</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Input: n = 3
Output: ["((()))","(()())","(())()","()(())","()()()"]
</code></pre></div></div>

<p><br /></p>

<p><strong>Example 2:</strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Input: n = 1
Output: ["()"]
</code></pre></div></div>

<p><br /></p>

<p><strong>Constraints</strong>:</p>
<ul>
  <li>1 &lt;= n &lt;= 8</li>
</ul>

<p><br /></p>

<p><strong>Related Topics:</strong> <code class="language-plaintext highlighter-rouge">String</code> <code class="language-plaintext highlighter-rouge">Dynamic Programming</code> <code class="language-plaintext highlighter-rouge">Backtracking</code></p>

<h2 id="解題邏輯與實作">解題邏輯與實作</h2>
<p>好久沒刷 LeetCode，所以先拿之前寫過，但還沒打成網誌的題目來練練手。</p>

<p>這題會給定一個數字 n，以生成包含 n 個括號的所有正確形式。若要列出所有結果，我第一個想到的會是用遞迴，幾個中止條件也在第一時間就浮出來了：</p>
<ol>
  <li>
    <p><strong>長度為 2n，且左括號（open parenthesis）個數等於右括號（close parenthesis）個數</strong><br />
 這個條件應該是可以輸出正確形式的中止條件，所以這個終止時需要回傳正確的形式。但實作時，我不想多傳入常數 n（因為這個數在遞迴過程中不會變），所以我把條件給反過來使用倒數的方式：「當左括號剩餘個數為零，且右括號剩餘個數亦為零」時終止。</p>
  </li>
  <li>
    <p><strong>右括號剩餘個數少於左括號剩餘個數</strong><br />
 假設 n = 3，若目前字串為 <code class="language-plaintext highlighter-rouge">())</code> ，則左括號剩餘個數則為 2、右括號剩餘個數為 1，遇到這樣的非法形式就直接返回不處理了。</p>
  </li>
</ol>

<p>如果兩種終止條件都不滿足就繼續往下走：</p>
<ol>
  <li>若左括號個數仍有剩餘，即不為 0，則輸出一左括號後繼續向下遞迴。</li>
  <li>若右括號剩餘個數大於左括號剩餘個數，則輸出一右括號後繼續向下遞迴。</li>
</ol>

<p>有這些基本條件後就能開始寫 code 了，完整程式碼如下：</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">generateParenthesis</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
        <span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">cur_str</span> <span class="o">=</span> <span class="s">""</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">generate</span><span class="p">(</span><span class="n">cur_str</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">results</span>


    <span class="k">def</span> <span class="nf">generate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cur_str</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">open_remaining</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">close_remaining</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">results</span><span class="p">:</span><span class="nb">list</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">open_remaining</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">close_remaining</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">results</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">cur_str</span><span class="p">)</span>
            <span class="k">return</span>         
        <span class="k">if</span> <span class="n">close_remaining</span> <span class="o">&lt;</span> <span class="n">open_remaining</span><span class="p">:</span>
            <span class="k">return</span>

        <span class="k">if</span> <span class="n">open_remaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">generate</span><span class="p">(</span><span class="n">cur_str</span> <span class="o">+</span> <span class="s">"("</span><span class="p">,</span> <span class="n">open_remaining</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">close_remaining</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">close_remaining</span> <span class="o">&gt;</span> <span class="n">open_remaining</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">generate</span><span class="p">(</span><span class="n">cur_str</span> <span class="o">+</span> <span class="s">")"</span><span class="p">,</span> <span class="n">open_remaining</span><span class="p">,</span> <span class="n">close_remaining</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span>            
</code></pre></div></div>

<p>Runtime 大約 38 ms，約在 78.88% 左右，我再多加個終止條件試試應該可以加快速度：</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">generateParenthesis</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
        <span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">cur_str</span> <span class="o">=</span> <span class="s">""</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">generate</span><span class="p">(</span><span class="n">cur_str</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">n</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">results</span>

    <span class="k">def</span> <span class="nf">generate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cur_str</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">open_remaining</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">close_remaining</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">results</span><span class="p">:</span><span class="nb">list</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">open_remaining</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">close_remaining</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">results</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">cur_str</span><span class="p">)</span>
            <span class="k">return</span>         
        <span class="k">if</span> <span class="n">open_remaining</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">close_remaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">cur_str</span> <span class="o">+=</span> <span class="s">')'</span><span class="o">*</span><span class="n">close_remaining</span>
            <span class="n">results</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">cur_str</span><span class="p">)</span>
            <span class="k">return</span>   
        <span class="k">if</span> <span class="n">close_remaining</span> <span class="o">&lt;</span> <span class="n">open_remaining</span><span class="p">:</span>
            <span class="k">return</span>  
        <span class="k">if</span> <span class="n">close_remaining</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">open_remaining</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span>        
        
        <span class="k">if</span> <span class="n">open_remaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">generate</span><span class="p">(</span><span class="n">cur_str</span> <span class="o">+</span> <span class="s">"("</span><span class="p">,</span> <span class="n">open_remaining</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">close_remaining</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">close_remaining</span> <span class="o">&gt;</span> <span class="n">open_remaining</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">generate</span><span class="p">(</span><span class="n">cur_str</span> <span class="o">+</span> <span class="s">")"</span><span class="p">,</span> <span class="n">open_remaining</span><span class="p">,</span> <span class="n">close_remaining</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">results</span><span class="p">)</span>            
</code></pre></div></div>
<p>Runtime 有稍微提升來到了 31 ms，約在 95.25% 左右。</p>

<h2 id="其他連結">其他連結</h2>
<ol>
  <li><a href="/LeetCode-0000-Contents/">【LeetCode】0000. 解題目錄</a></li>
</ol>

<h2 id="更新紀錄">更新紀錄</h2>
<details class="update_stamp">
  <summary>最後更新日期：2023-02-15</summary>
  <ul>
    <li>2023-02-15 發布</li>
    <li>2023-01-09 完稿</li>
    <li>2023-01-09 起稿</li>
  </ul>
</details>]]></content><author><name>辛西亞．Cynthia</name></author><category term="面試刷題" /><category term="LeetCode" /><summary type="html"><![CDATA[Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.]]></summary></entry></feed>