CoderClark
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # B0003 易讀程式碼的特性:精準 ## 精簡與準確 **「精準」** 是另一個讓程式碼易讀的重要特性。要注意的是,這裡說的精準,指的是**精簡**與**準確**。必須兩個概念都要具備,才算得上是符合這個特性。 ### 精簡 **精簡**一個容易想像的概念。假設有兩段程式碼可以完成同一件事情,其中一個用了2000行,另一個用了20行,請問哪一個比較易讀呢?在大多數的情況下,**精簡**的20行會比**繁複**的2000行來得更容易掌握、更容易理解。所以說,很多時候使用較少的程式碼可以達成易讀。這真是多麼簡單的概念! ### 準確 不過,只抓住**精簡**的原則是不夠的。當我們只考慮要用較少程式碼完成目標的時候,可能會省略了關鍵程式碼。怎麼說呢?觀察[[B0001 易讀程式碼的特性:白話]]與[[B0002 易讀程式碼的特性:直觀]]提到的例子,不難發現那些完全不白話、完全不直觀的寫法,所需要的程式碼都是比較少的,但他們都是易讀的反指標。所以不能一味地追求精簡,而是在精簡程式碼的過程中,守住一個底線,一個至少能**清楚明白表達行為**的底線,稱作**準確**。 這裡雖然用白話與直觀作為舉例,但**準確**並不是白話與直觀的綜合體。仔細分辨的話,白話與直觀屬於語意上的易讀特性,而準確則是邏輯行為上的易讀特性。有時候程式碼已經白話且直觀了,卻可能邏輯行為讓人難以掌握,變得很**失焦**,也就是**不準確**。 雖說白話且直觀與準確是兩回事,但準確的程式碼通常會需要白話與直觀的支持;換句話說,一個在語意本身不易讀的程式碼,自然無法讓邏輯行為易讀。 ### 精簡與準確並進 前面提到要避免精簡過頭導致不準確,但這不表示他們是敵人似地兩者只能追求一個達成。這兩者其實是兩個不同維度上的概念,一段程式碼可能既精簡又準確,也可能不精簡也不準確。要如何在這兩個概念都做好,是重要的課題。 ## 做到「精準」 試想去聽一場2小時的演講,講者東聊一段爸爸的趣聞、西說一段女兒的經歷,最後用5分鐘講了他工作的心得。請問要如何解讀這場演講呢?如果講題是要聊他的爸爸(或許他爸爸是個名人),似乎不需要談到女兒及工作;如果講題是分享工作心得,這時間的比重也太少,反而覺得他的家人更像是講題;就算講題是介紹自己,也應該多花點心思在自己本身,而不是在家人、工作上。不管講題是什麼,內容是如此**不精準**,讓人很難理解講者所要表達的重點;不管演講的場地有多盛大、門票有多貴、講者多有名,這都不是一個好理解的演講。 程式碼跟演講的概念是一樣的。當一份程式碼**包含太多不需要的概念**、**著墨太多不重要的細節**、或者**保留完全不必要的行為**,肯定是不易讀的吧!必須避開這些問題,才能產出**精準的程式碼**。那要怎麼辦到呢?可以參考下面5個方法:**去蕪存菁、截彎取直、畫地自限、名符其實、換句話說**。 ### 方法1:去蕪存菁 顧名思義,**去蕪存菁**著重在保留重要的、移除不需要的,以盡量做到**精簡**。建議利用下面要點來做到去蕪存菁: * 一段程式碼如果移除掉沒有影響到行為或邏輯表達,就直接移除。 * 如果整段程式碼都難以直接移除,就設法整理成好閱讀的樣子;像是打包程式碼[^1]、或調整程式碼的順序等等。 [^1]: [C0001 不白話的程式碼:文字加密](/tdzMvnrYTrySrC5iokmOtQ)提過的**打包行為**,在這裡可以派上用場。 這看起來不難辦到,但為什麼繁複的程式碼還是很多呢?這可能還是要歸咎於惰性。從上述的要點來看,通常是在程式碼完成了之後才執行,才能比較好判斷哪邊是蕪、哪邊是菁,然後才好做移除或整理;然而因為惰性,當一份程式碼完成了、通過測試了、可以運作了,很多時候都不會再回頭看一眼,自然就停留在不理想的狀態了。 ### 方法2:截彎取直 都說要每個程式碼單位(像是 Function、Class)都是盡量小的好。然而,過度地將權責做小,可能會做出過多的程式碼單位,導致做任何事情都需要透過許多單位來執行,無法簡單地完成。這是一種**過度設計**,即使是一件小事也需要複雜的手段,想當然是不**精簡**的;此外,如果這些單位的關係錯綜複雜,難以一目了然地看懂邏輯行為,也是違背了**準確**概念。 我們可以把這樣的設計稱作是**繞彎**,彷彿是有話不好好說,非要拐彎地說的樣子。要解決彎來彎去的程式碼,就要**截彎取直**,要點如下: * 與去蕪存菁類似,可以移除的單位就移除,不要留戀。 * 尋找邏輯類似、接近的單位,將他們合併成較大的單位。不僅是可以讓使用端變單純,而被合併的單位間,也可能因為合併而簡化交互流程。 ### 方法3:畫地自限 程式碼的組成是很自由的,要怎麼擺程式碼、在什麼邏輯位置完成程式碼,都是自由的。就因為自由,程式碼就容易失焦,讓人摸不清邏輯,導致**不準確**。 什麼樣的程式碼是失焦的?**放任問題產生了之後,再事後解決就是失焦**。比方說,數值不做成常數,卻要在執行的過程檢查數值不變;比方說,呼叫順序不做好限制,卻要在執行的過程檢查是否遺漏呼叫;比方說,Function(或者稱 Method)不隱藏或限制存取,卻要在執行的過程檢查是否被誤用。這些例子都代表著,程式碼顯式地(explicitly)提供了自由使用的空間,但卻隱式地(implicitly)不接受某些使用方式[^2]。 [^2]: 雖然是盡量只讓專有名詞保留用英文,但這裡的**顯式地**、**隱式地**實在難以準確表達,只好分別附註英文explicitly、implicitly。說來有趣,寫文章跟寫程式碼是同一回事,都要講求準確。 如果自由是個問題,那麼就**限制**它吧!這樣的方法稱作**畫地自限**。執行畫地自限的要點只有1項: * 顯式地(explicitly)將**限制**寫進去程式碼。 ### 方法4:名符其實 **準確**的程式碼要注重**名符其實**。所謂的**名**,指的是名稱、命名;所謂的**實**,指的是實作、權責。名與實必須要能對應上,才是準確的程式碼。舉例來說,一個名叫「機車」的程式碼,就不應該有四輪的實作;如果強迫讓機車也能支援四輪,就會失焦。相反地,四輪交通工具的實作就該名叫「汽車」,如果對兩輪、四輪都叫汽車,一樣也是失焦的。這樣的失焦會讓人摸不清邏輯,不容易理解。 要做到名符其實,可以參考以下要點[^3]: * 賦予實作、權責一個名稱時,務必符合實作、權責本身的概念。 * 對一個實作細節命名時,不應該採取遠大於、或遠小於該名稱概念的權責。 * 如果程式碼非得擴展出遠大於或遠小於該名稱概念的權責,可以設法改名稱以符合權責;倘若改名稱是不允許的,可以另起爐灶做另一包程式碼,不要與原本名稱混雜一起。 [^3]: 附帶一提,**名符其實**不只是易讀性的問題,更是**抽象化**的基本原則之一。關於抽象化,未來會有更多介紹。 ### 方法5:換句話說 一個描述方式如果不容易理解,那就換方式來講,就有機會比較**精準**了。這就是**換句話說**的概念。比如行人問路要告訴對方如何到目的地,與其提供哪一條路左轉右轉、哪個地標迴轉等等的說了一堆,不如提供搭某一班直達公車的方法來得簡潔有效。當解決方案拘泥在「步行」上,不管怎麼處理都有一定的複雜度,但如果把「大眾交通工具」納入辦法中,就能找到更精簡與準確的辦法。程式碼也是一樣的,當拘泥在某個假設、前提、設計下,可能會寫得很囉唆,但跳脫出來換個假設、前提、設計,就有機會做得更精準。 這是所有讓程式碼精準的方法中,最難的一個了。因為每一個考慮**換句話說**的程式碼,所處的情境幾乎是不可能一模一樣,或許要改變 Data Structure、或許要調整 Design Pattern、或許要調整行為規格、等等;而且考慮的範圍,可能小至最枝微末節的程式碼,也可能大至整體的軟體架構。也就是說,題目變化可能無限多種,而方法、考量也可能是無限多種,完全不存在一個明確的方法或步驟可以遵循。要**換句話說**得好,只有靠大量的知識與經驗,才能辦到。因此,原則上是沒有要點可以參考的。如果一定要勉強提供一個呢?大概只能這樣說: * 想想有沒有跳脫當前設計的做法吧! ## 言之有物、簡單扼要、不說廢話 回顧讓程式碼白話與直觀,會發現方法是單純的;相較之下,讓程式碼精準的方法更為多元、靈活。所以說,理論上,應該不只有上述提到的觀念與方法才是。我們可以仔細觀察這些方法,歸納出更通用的原則,才不至於拘泥於方法本身;而這個原則就是 **「言之有物、簡單扼要、不說廢話」**。嚴格來說,即使不記得上述方法,只要能掌握這些原則,一樣可以做到精準的程式碼! ## 延伸閱讀 C0006 精準程式碼:去蕪存菁 (撰寫中) C0007 精準程式碼:截彎取直 (撰寫中) C0008 精準程式碼:畫地自限 (撰寫中) C0009 精準程式碼:名符其實 (撰寫中) C0010 精準程式碼:換句話說 (撰寫中)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully