CarryFront
      • 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
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners 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 No publishing access yet

      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.

      Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

      Explore these features while you wait
      Complete general settings
      Bookmark and like published notes
      Write a few more notes
      Complete general settings
      Write a few more notes
      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 New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Help
Menu
Options
Engagement control Make a copy 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
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners 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 No publishing access yet

    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.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    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
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Topic 22 - 24 ###### tags: `The Pragmatic Programmer` ## Topic 22 Engineering Daybooks :::spoiler story Dave once worked for a small computer manufacturer, which meant working alongside electronic and sometimes mechanical engineers. Many of them walked around with a paper notebook, normally with a pen stuffed down the spine. Every now and then when we were talking, they’d pop the notebook open and scribble something. Eventually Dave asked the obvious question. It turned out that they’d been trained to keep an engineering daybook, ==a kind of journal in which they recorded what they did, things they’d learned, sketches of ideas, readings from meters: basically anything to do with their work.== When the notebook became full, they’d write the date range on the spine, then stick it on the shelf next to previous daybooks. There may have been a gentle competition going on for whose set of books took the most shelf space. ::: use daybooks to take notes in meetings, to jot down what we’re working on, to note variable values when debugging, to leave reminders where we put things, to record wild ideas, and sometimes just to doodle. The daybook has three main benefits: - It is more reliable than memory. - It gives you a place to store ideas that aren’t immediately relevant to the task at hand. - It acts as a kind of rubber duck (described here). > 試著用紙筆筆記本,寫工程日誌一個月! # chapter 4 Pragmatic Paranoia 務實的偏執 :::warning **You Can’t Write Perfect Software** Accept it as an axiom of life. Embrace it. Celebrate it. Because perfect software doesn’t exist. ::: - Everyone knows that they personally are the only good driver on Earth.(其他人都是三寶,都不好遵守規則XD),So we drive defensively(防禦性駕駛). - 撰寫程式碼也是如此。we are taught to code defensively. assertions( to detect bad data), check for consistency(put constraints on database columns) and ==feel pretty good about ourselves.== But Pragmatic Programmers take this a step further.... :::info They don’t trust themselves, either. ::: ## Topic 23 Design by Contract 合約式設計 One of the best solutions for ensuring plain dealing is the contract. ### DBC(Design by Contract) Bertrand Meyer (Object-Oriented Software Construction [Mey97]) developed the concept of Design by Contract for the language Eiffel. documenting the rights and responsibilities of software modules to ensure program correctness. > What is a correct program? One that does no more and no less than it claims to do. :::info Documenting and verifying that claim is the heart of DBC。 ::: 1. Preconditions 前置條件 What must be true in order for the routine to be called; 當前置條件被違反,他就不應該被呼叫。 2. Postconditions 後置條件 函式保證要做的事。 What the routine is guaranteed to do; the state of the world when the routine is done. (會得出結論,infinite loops aren’t allowed.) 3. Class invariants 類別不變量 類別必須確保不變量條件始終成立 A class ensures that this condition is always true from the perspective of a caller. 當函式退出並控制傳給呼叫者時,不變量必須成立。 The contract between a routine and any potential caller can thus be read as: :::warning If all the routine’s preconditions are met by the caller, the routine shall guarantee that all postconditions and invariants will be true when it completes. 如果呼叫者滿足了前置條件,則函式應該在完成時保證所有後置條件與不變量都成立 ::: 如果有任何一方未能履行合約,就會呼叫補救措施。 (exception is raised, or the program terminates.) 不管怎樣,不能履行合約都是一個錯誤,不應該發生~ 有些語言更能支援這個概念,例如 ### Clojure:範例:存款函式 :pre => 前置條件 1. amount is greater than zero 2. account is open and valid :post => 後置條件 1. the function guarantees that the new transaction can be found among the transactions for this account. ```=Clojure (defn accept-deposit [account-id amount] { :pre [ (> amount 0.00) (account-open? account-id) ] :post [ (contains? (account-transactions account-id) %) ] } "Accept a deposit and return the new transaction id" ;; Some other processing goes here... ;; Return the newly created transaction: (create-transaction account-id :deposit amount)) ``` if there’s a bug in the program and you somehow passed in a negative amount for the deposit, you’ll get a runtime exception: >Exception in thread "main"... Caused by: java.lang.AssertionError: Assert failed: (> amount 0.0) >Exception in thread "main"... Caused by: java.lang.AssertionError: Assert failed: (account-open? account- id) ### Elixir:guard clause ```=Elixir defmodule Deposits do def accept_deposit(account_id, amount) when (amount > 100000) do # Call the manager! end def accept_deposit(account_id, amount) when (amount > 10000) do # Extra Federal requirements for reporting # Some processing... end def accept_deposit(account_id, amount) when (amount > 0) do # Some processing... end end ``` 若不符合將丟出例外: >** (FunctionClauseError) no function clause matching in Deposits.accept_deposit/2 :::info This is a better approach than simply checking your inputs; in this case, you simply can not call this function if your arguments are out of range. ::: ### Design with Contracts #### Class Invariants and Functional Languages What this idea really refers to is state. 其實就是狀態 state ![](https://i.imgur.com/dC4zFLg.png) #### DBC and Test-Driven Development > is DBC needed in a world where developers practice unit testing, test- driven development (TDD), property-based testing, or defensive programming? **YES,DBC and testing are different approaches** They both have value and both have uses in different situations. DBC offers several advantages over specific testing approaches: 1. DBC doesn’t require any setup or mocking 2. DBC defines the parameters for success or failure in all cases, whereas testing can only target one specific case at a time 3. TDD and other testing happens only at “test time” within the build cycle. But DBC and assertions are forever: during design, development, deployment, and maintenance 4. TDD does not focus on checking internal invariants within the code under test,it’s more black-box style to check the public interface. 5. DBC is more efficient (and DRY-er) than defensive programming, where everyone has to validate data in case no one else does. TDD is a great technique, but as with many techniques, it might invite you to concentrate on the “happy path,” and not the real world full of bad data, bad actors, bad versions, and bad specifications. Is it 🤔❓ #### IMPLEMENTING DBC Simply enumerating what the input domain range is, what the boundary conditions are, and what the routine promises to deliver—or, more importantly, what it doesn’t promise to deliver. In languages that do not support DBC in the code, this might be as far as you can go—and that’s not too bad. ==DBC is, after all, a design technique. Even without automatic checking, you can put the contract in the code as comments or in the unit tests and still get a very real benefit. 合約式設計是一種設計技術== #### Assertions(斷言) 檢查一些不應該發生的事情,當你覺得“當然這是不可能發生的”,加入程式碼來檢查他! https://caterpillar.gitbooks.io/javase6tutorial/content/c10_5.html #### DBC AND CRASHING EARLY 早期崩壞 By using an assert or DBC mechanism to validate the preconditions, postconditions, and invariants, you can crash early and report more accurate information about the problem. exmaple: 計算平方根的方法 * 前置條件,input 限制為正數 In languages that support DBC, if you pass sqrt a negative parameter, you’ll get an informative error such as `sqrt_arg_must_be_positive,` along with a stack trace. 那在其他語言呢?將複數傳給計算平方根的方法,回傳NaN, ...後續根據回傳做更多操作.. * 傳遞正確資料是誰的責任?是呼叫者還是被呼叫的函示? :::spoiler ANSWE 當一種語言把檢查前置條件實作為一部份, 答案是兩者都不該負責, 因為在呼叫此函式之後,但在進入韓式之前,前置條件會在背景被測試。 針對有支援的語言=>如果要執行任何的手動的參數檢查,必須在 呼叫者端做,因為被呼叫函式本身永遠不會看到違反其前置條件的參數 針對沒有支援的語言=> 需要在 被呼叫的函式 加上一組前綴/後綴 來做 ssertion 檢查 ::: 有一支函式,從console 讀取一個數字, 計算平方根(呼叫sqrt),印出結果。sqrt 有一個前置條件,參數不能是負數。 假設使用者在console 輸入了一個負數,呼叫端程式碼要確保這個負數不會傳給sqrt。 sqrt 前置條件表達了可接受的值,將正確性的負擔轉移到呼叫程式,這樣可以放心的設計 sqrt 函式,因為他拿到的輸入將會在範圍內。 #### SEMANTIC INVARIANTS 語意不變量,表達不可違背的需求,a kind of “philosophical contract.''哲學合約 * invariants—it must be central to the very meaning of a thing, and not subject to the whims of policy。一個東西的重要意義,請不會受到政策的影響。 Err in favor of the consumer. This is a clear, concise, unambiguous statement that’s applicable in many different areas of the system. It is our contract with all users of the system, our guarantee of behavior. #### CHALLENGES Points to ponder: If DBC is so powerful, why isn’t it used more widely? Is it hard to come up with the contract? Does it make you think about issues you’d rather ignore for now? Does it force you to THINK!? Clearly, this is a dangerous tool! #### 14 * Design an interface to a kitchen blender. It will eventually be a web-based, IoT-enabled blender, but for now we just need the interface to control it. It has ten speed settings (0 means off). You can’t operate it empty, and you can change the speed only one unit at a time (that is, from 0 to 1, and from 1 to 2, not from 0 to 2). ``` Here are the methods. Add appropriate pre- and postconditions and an invariant. int getSpeed() void setSpeed(int x) boolean isFull() void fill() void empty() ``` :::spoiler answer ```=java //1. You can’t operate it empty //2. change the speed only one unit at a time // 類別的不變數: @invaraint getSpeed() > 0 implies isFull() // 空無一物的時候不運轉 @invaraint getSpeed() >= 0 && getSpeed() < 10 // 轉速段位檢查 // 前置 後置 條件 @pre Math.abs(getSpeed()-x)<=1 // 一次只能切換一段 @pre x >= 0 && x < 10 // 轉速段位檢查 @post getSpeed() == x // 施行要求的轉速段位 public void setSpeed(final int x) @pre !isFull() //不能填充兩次東西 @post isFull // 確保有填充東西 void fill() @pre isFull() // 不能清空兩次 @post !isFull() // 確保已執行清空 void empty() ``` ::: #### 15 * How many numbers are in the series 0, 5, 10, 15, ..., 100? :::spoiler answer 21 ::: ## Topic 24 Dead Programs Tell No Lies Have you noticed that sometimes other people can detect that things aren’t well with you before you’re aware of the problem yourself? It’s the same with other people’s code. we want to know when the “impossible” has happened. **It’s easy to fall into the “it can’t happen” mentality.** * All errors give you information. :::info Pragmatic Programmers tell themselves that if there is an error, something very, very bad has happened. Don’t forget to Read the Damn Error Message. ::: ### CATCH AND RELEASE IS FOR FISH Some developers feel that is it good style to catch or rescue all exceptions: ``` try do add_score_to_board(score); rescue InvalidScore Logger.error("Can't add invalid score. Exiting"); raise rescue BoardServerDown Logger.error("Can't add score: board is down. Exiting"); raise rescue StaleTransaction Logger.error("Can't add score: stale transaction. Exiting"); raise end ``` Pragmatic Programmers would write this: ``` add_score_to_board(score); ``` 1. the application code isn’t eclipsed by the error handling. 2. the code is less coupled Tip 38: Crash Early ### CRASH, DON’T TRASH One of the benefits of detecting problems as soon as you can is that you can crash earlier. The Erlang and Elixir languages embrace this philosophy. > Joe Armstrong, is often quoted as saying, “Defensive programming is a waste of time. Let it crash!” #### In these environments, programs are designed to fail, but that failure is managed with supervisors. :::spoiler supervisors? 主管負責啟動、停止和監視其子進程。 當一個進程崩潰是,它能夠快速重啟該進程,並根據不同的策略做出不同的行為。 https://blog.csdn.net/fbher/article/details/93209407 https://www.erlang.org/doc/design_principles/sup_princ.html ::: #### In other environments it may be inappropriate simply to exit a running program. 有可能有已經要求使用但未被釋放的資源...互動等等 <br> However, the basic principle stays the same—when your code discovers that something that was supposed to be impossible just happened, your program is no longer viable. ==Anything it does from this point forward becomes suspect, so terminate it as soon as possible.== :::info A dead program normally does a lot less damage than a crippled one. :::

    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
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    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