CloudMosa 面試心得

這篇文章分享 CloudMosa (美商雲端科技) 的面試心得。會投這間公司主要是他們的 Puffin Browser 與創辦人,所以就試著應徵 SDET 看看,以自己的能力來說是沒機會的,但還是硬著頭皮去試試,感謝 CloudMosa 面試官的寶貴時間,還讓我問了一堆問題 (感覺反而是採訪)。

CloudMosa 面試據說有二階段,我只有去第一階段,第二階段說是用 Skype 跟創辦人面試。第一階段面試大約要 4 小時,我 13:00 去到 19:00 才離開,總共有 4 位面試官輪流面試,各自獨立進行,所以可能要自我介紹 4 次。中間沒有特別休息,只去了一次洗手間,面試結束感覺非常疲累,20:00 回到家吃飯洗澡弄一弄就睡了。

面試流程大該分成 3 個部分。第一是自我介紹,說說過去你做了什麼偉大的事情,第二是面試官提問,第三是自己的提問。面試官的面試時間不一定,每位大概是 1 至 2 小時。 4 位面試官據說是從資歷淺到深來進行,但因為我當天面試官有兩位住在桃園和新竹,導致順序有些調整。

面試過程感覺是一關比一關困難,大概在第三關的時候就覺得沒機會了,最後第四關反而比較輕鬆自在,像是在跟同事討論事情的感覺。

過程

由於自己是軟體開發人員 (SDE),第一關和第四關的面試官是 SDET,專業領域比較沒有辦法深入的討論,面試過程比較像是討論產品測試的一些想法與問題。

第二關的面試官是 SDE ,這部分的面試就硬了。有個簡短的 pseudocode 程式撰寫,考題是 LRU 快取演算法,寫完和面試官討論了程式邏輯和複雜度。事後回想覺得當時太緊張了,面試官的訊息有些沒有抓到,可能回答錯誤。另外,也從我過去的工作經驗問了 SQL 和 NoSQL 的差異與應用情境,這題也沒有回答的很好,覺得「知道是一回事,能夠妥善回答又是另一回事」。

當天第三關的面試官是 VP ,主要是問人格特質的部分,技術的問題偏少。這邊我覺得被過去的工作思維給限制住了,像是面試官問了一個要如何規劃設計 Puffin Browser 的測試,當時回答是看看手邊有多少資源才能做多少事,但事後回想這樣應該不正確,必須「以終為始」來規劃設計。要做大事情,要想著可以找到和創造那些資源,而不是被資源限制住。

VP 最後問了兩個問題,(1) 如果有一百萬美金從事資訊領域創業,不求任何營收,在兩至三年的時間內,你要做什麼? (2) 如果有一百萬美金從事資訊領域創業,在兩至三年的時間內需要回收賺錢,你要做什麼?

因為第一個問題我沒有答案, VP 才又提出第二個問題,當時覺得第二個問題比較難。但現在我反而認為第一個問題才難,問題的困難其實在於「做什麼去創業」的想法,有營收限制條件的第二題反而比較容易一些。

心得總結

  • 感謝 CloudMosa 的面試機會。 年紀稍大,越覺得時間寶貴,別人願意給面試機會就是對能力的一種肯定。
  • CloudMosa 的面試是專業的,過程中面試者是受到尊重的。據說面試官結束要寫報告,不是隨隨便便的。
  • 面試時的自我介紹要練習,因為可能要說 4 遍,不應該太長。
  • 第一階段面試很久,大約 4 小時,要吃飽才去啊!中間可以去洗手間,面試官還會問說要不要喝飲料呢。
  • 公司距離不是問題,新竹以北的高手可以試試看。
  • 根據面試官表示
    • 他們要找高手中的高手,厲害的人做事可以減少一堆問題 。
    • 自主管理,工作目標自己找 。
    • 彈性上下班,一週有一次和創辦人一起開會。
    • 6 個月至 1 年的試用期,不適任資遣 。
  • 面試紀念品: Puffin Browser 馬克杯。

Software Testing

這篇文章將介紹什麼是軟體測試 (software testing)。以下列出一些常見的定義:

Glenford Myers

Software testing is the process of executing a program or system with the intent of finding errors.

據說 Glenford Myers 寫的書《The Art of Software Testing》是軟體測試領域的聖經本,裡面提到:軟體測試就是為了發現錯誤而執行程序或系統的過程。

ANSI/IEEE Std 729-1983

The process of exercising or evaluating a system or system component by manual or automated means to verify that it satisfies specified requirements or to identify differences between expected and actual results.

這是《IEEE Standard Glossary of Software Engineering Terminology》裡面的定義,軟體測試是透過手動或自動方式執行或評估系統或系統元件的過程,以驗證其是否滿足指定的要求,或確定預期結果與實際結果之間的差異。

Bill Hetzel

It involves any activity aimed at evaluating an attribute or capability of a program or system and determining that it meets its required results.

Bill Hetzel 的著作《The Complete Guide to Software Testing》裡面提到:軟體測試是涉及評估程序或系統的屬性或功能,並確定其滿足要求的結果的任何活動。

題外話,書籍《Software Quality Assurance: A Self-Teaching Introduction》誤將 IEEE 729 的定義寫成 IEEE 83a,利用 Google 搜尋確認後發現沒有 IEEE 83a 的文件,但有不少書籍文獻都寫上 IEEE 83a 這樣的參考資料,這樣的錯誤不知道是從哪裡開始,盡信書不如無書啊!下面補充正確對應的文獻來源。

  • IEEE 83a
    The Institute of Electrical and Electronics Engineers, Inc. IEEE Standard Glossary’ of Software Engineering Terminology. The Institute of Electrical and Electronics Engineers, Inc., New York, NY, 1983.
    (就是 IEEE 729 啦!)
  • IEEE 83b
    IEEE Computer Society, Konover Hotel, Miami Beach, Florida. IEEE Computer Society Workshop on Software Engineering Technology Transfer, April 25-27, 1983.

軟體測試

前面寫了那麼難懂的定義文字,如同法律文件一般,有沒有比較好懂的解釋?《Software Quality Assurance: A Self-Teaching Introduction》書上寫到一個比較受歡迎的定義:

Software Testing = Software Verification + Software Validation

軟體驗證 (software verification) 加上軟體確認 (software validation) 等於軟體測試。驗證和確認 (verification and validation, V&V) 兩者是互補的,關注的問題不太一樣,用白話一點的解釋:

  • 驗證 (verification):我們是否做對的軟體。(We build the right thing.)
  • 確認 (validation):我們是否把軟體做對。(We build it right.)

術語

以下列出軟體測試領域的(英文)專業術語與其說明。(看不懂沒關係,不要被文字描述所限制,所謂的專業領域就是把事情越搞越複雜、定義越來越多的名詞術語XD)

  • Error / Mistake / Bugs
    錯誤,把原本正確的事情做錯。錯誤是會擴散與放大的,規格的錯誤會讓設計和寫程式 (coding) 都會有錯。
  • Fault / Defect
    缺陷,因為 error 造成軟體執行不正確的結果。
  • Failure
    失效,當執行 fault 後發生的結果。
  • Incident
    事件,提醒用戶發生 failure 的症狀。
  • Test
    測試,測試是關於 error, fault, failure, incident 的活動,依據 test case 執行軟體,測試是為了找出軟體的 failure,並證明軟體是正確的。
  • Test case
    測試案例,test case 與軟體的行為有關,具有 input 與預期的 output,input 有實際輸入與先決條件 (precondition) 兩種,output 則有實際輸出與後置條件 (postcondition) 兩種。另外,test case 通常包含其他資訊,例如:ID、名稱、描述、目的、歷史記錄… 等。
  • Test suite
    測試套件,test suite 包含多個 test case 或 test script,為了確認 bug fixes 或是找出 bugs。
  • Test script
    測試腳本,一步一步的指令描述 test case 如何執行。
  • Test ware
    測試製品,在測試過程中產生的所有文件。例如測試腳本、測試案例、測試資料…等。
  • Test oracle
    測試準則,預測測試結果的任何方法。test oracle 是用來判斷測試是否通過的「神諭 (oracle)」。
  • Test log
    測試記錄,依據時間先後紀錄的測試結果。
  • Test report
    測試報告,描述執行測試的實施與成果。

提問

誰應該做測試?

是測試人員、開發人員,還是使用者,大部分的書會寫團隊的每個人,實際上不太一定 (看你怎麼訂 KPI,誰就會去做) 。 測試的目的是為了確認是否有做對的事,以及驗證是否把事情做對,因此跟整個軟體開發都有關係,流程當中涉及不同的工作與人員,所以團隊的每個人都必須做「測試」這件事。

測試會花多少時間?

根據《Software Quality Assurance: A Self-Teaching Introduction》書上,測試佔了軟體開發生命週期 (Software Development Life Cycle, SDLC) 的 70%。實際上呢?測試會依據你給多少時間和資源而決定做多少測試案例 (天啊!怎麼會這樣)。由於帕金森定律(Parkinson’s Law):「無論配置多少工作時間,該工作都會把配置的時間耗光。」比較務實的提問,這個問題應該要改成「你願意給測試多少時間執行?」

軟體要做多少測試?

這個問題要問「要做多少測試才足夠?」軟體系統可能會有無限的執行組合,要每個數值都測試不太實際,例如加法計算,若要測試所有數值那會做不完。正確的做法是設計好的 test case,盡可能讓測試包含所有情境。

參考書籍

Rajiv Chopra, Software Quality Assurance: A Self-Teaching Introduction, Mercury Learning & Information, 2018

Remote Browser

這裡紀錄《How the Puffin Browser Works》的閱讀心得。《How the Puffin Browser Works》這篇文章簡介瀏覽器的基本原理和架構,說明瀏覽器效能的瓶頸,並解釋 Puffin Browser 運行如此之快的原因,最後列出效能測試結果。

遠端瀏覽器

Puffin Browser 是一種遠端瀏覽器 (remote browser),是 CloudMosa Inc. 公司的產品。「遠端瀏覽器」是指利用遠端的(另一台主機上的)瀏覽器去瀏覽網站,不同於我們現在一般使用 Chrome, Firefox, IE, Edge, Safari 的「本地瀏覽器 (local browser)」這種方式。

使用遠端瀏覽器有什麼優點?(1) 安全 (2) 效能。

安全是因為透過遠端的瀏覽器去瀏覽網站,本機與網站因此有了「隔離」,這種隔離不是瀏覽器本身沙箱的隔離,而是實體機器的隔離,保護本機不受惡意軟體 (malware) 和零時差漏洞 (zero-day) 的攻擊。

效能是因為遠端機器的伺服器比使用者裝置還要好的關係,不管是 CPU 、記憶體、硬碟和網路速度,伺服器的效能通常都會好很多,當然執行速度也會快很多。

架構

先講結論,細節請參考《How the Puffin Browser Works》。Puffin Browser 把瀏覽器絕大部分的事情放在遠端伺服器上執行,僅把最後畫面配置結果 (即 layout tree) 傳回使用者的用戶端程式。

遠端伺服器執行的稱為 Puffin browser engine,而用戶端程式則稱為 Puffin browser client ,架構上主要分成這兩個部分。這樣的架構設計有幾個優點:

  1. 執行速度可以提升。由於伺服器的效能比較好,瀏覽器解析 HTML, CSS 與計算網頁排版的速度會很快。
  2. 下載資料的時間縮短。伺服器與資料中心之間的網路很快,於是 HTTP 通訊的往返時間 (round-trip time, RTT) 會很短,傳輸資料的時間也會很短,結果是擷取網頁的 HTML, CSS, JavaScript 與圖片媒體的速度會很快,加上一個網頁通常會有多個 HTTP 請求,縮短的時間讓網頁能有突破性地提升。
  3. 節省資料的傳輸量。由於僅把最後畫面配置結果傳回用戶端,可以將資料壓縮以減少資料量,在低頻寬的網路上也能提高網頁載入的速度。
  4. 提高安全性。遠端瀏覽器的架構可避免使用者受到惡意軟體和零時差漏洞的攻擊。

因此, Puffin Browser 瀏覽網頁的速度將不受使用者裝置效能的影響,我想這才是 Puffin Browser 建造遠端瀏覽器的原因,以達到「打破貧富之間的數位落差 (digital divide)」的目標。

缺點呢?在這樣的架構之下,使用者還是必須和遠端瀏覽器溝通,當網頁應用需要頻繁地與網頁互動,上述效能的優點會比較不顯著。另外,由於遠端瀏覽器的關係,像是需要安裝第三方程式的應用 (例如ActiveX, Java Applet),架構上也難以支援。不過 第三方程式的 Flash 是個例外,這是 Puffin Browser 的產品功能之一,也許當未來各瀏覽器都不支援 Flash 的時候,我們僅能使用 Puffin Browser 瀏覽 Flash 網頁!

文章中提到 CloudMosa 以水果當作產品的綽號,這點滿有趣的,應該是溝通上的需要吧。以下是 CloudMosa 所販售的水果:

  • Remote browser engine: 芒果 (Mango)
  • Browser client
    • Android: 檸檬 (Lemon)
    • iOS: 櫻桃 (Cherry)
    • Windows: 木瓜 (Papaya)
    • Linux: 樹莓 (Raspberry)
    • macOS: ?
    • Android TV: ?
    • Puffin OS: ?

提問

  1. 為何 Puffin Browser 取名為 Puffin ?
    (Puffin 是一種叫「海鸚」的海鳥,不知道瀏覽器和海鸚有什麼關係。)
  2. 為何 Puffin Browser 是基於 Chromium 基礎開發?
    (是否和授權條款有關)
  3. Puffin Browser 如何處理 JavaScript 這個部分?
    從架構上來看,JavaScript 應該是由 Puffin browser engine 全部下載完成後,再送給 Puffin browser client 執行,與畫面配置結果 (layout tree) 分開處理。
  4. Puffin Browser 如何顯示 Flash 這個部分?
    既然 Puffin browser client 知道畫面配置結果,可以將 Flash 的畫面繪製在所屬的畫面位置上, Flash 的畫面則由伺服器上的 Puffin browser engine 送出。
  5. Puffin Browser 如何處理 Video 與 Audio 呢?
    Video 與 Audio 應該是 Puffin browser client 直接連到原本的 Web 主機讀取,沒有必要透過 Puffin browser engine 讀取再轉送給 Puffin browser client。

CloudMosa

這裡整理有關 CloudMosa 這間公司的資訊。從 Ben 以前所說的故事中得知,他提到:「在台大的一場演講中,沈修平提到了李琳山教授當年的期許『西天取經,志在中土』。」因此,我才會知道 CloudMosa 公司與創辦人沈修平博士。

CloudMosa 主要產品是 Puffin Browser (就是一種網頁瀏覽器),早期產品只有行動裝置 iOS 和 Android 的 app 可以安裝,當時 Puffin Browser 的特色之一就是可以在 iOS 上看 Flash 的網頁,然而 Flash 看不到也還好,換到桌上型電腦看網頁就行了,所以對 Puffin Browser 沒有特別強烈需要。另外一個 Puffin Browser 的特點其實是速度,但這個特色對我感受不大,可能是裝置與網路都用不錯的關係。

在 2017 年底的時候推出 Windows 平台的 Puffin Browser,我安裝使用發現和 Chrome 沒什麼差異,當時是 Beta 版還不需要付費使用,現在是需要輸入基本資訊註冊才能試用。就因為用起來和 Chrome 沒什麼差別,爾後一陣子就沒繼續使用,不過一直有持續關注 CloudMosa 會有什麼新東西出來。

CloudMosa 在 2018 年 6 月正式推出 Windows 的 Puffin Browser,在 2019 年 3 月也 正式推出 macOS 的 Puffin Browser,Windows 和 macOS 的桌面應用程式稱為 Puffin Secure Browser。到此,各大作業系統平台 (除了 Linux ) 都有 Puffin Browser 可以使用了。

在 2018 年底, CloudMosa 推出 Raspberry Pi 使用的 Puffin Internet Terminal,而且在 2019 年 6 月推出 Puffin OS 作業系統的手機,於 Kickstarter 上募資。現在 2019 年也是 CloudMosa 創立的第 10 年。

#BadApple

起因於這件事:It’s Time to Call Out the #BadApple

相關報導:大鯨魚欺負小蝦米?Puffin 瀏覽器驚傳遭 App Store 駁回更新|數位時代

因為 Apple 認為 Puffin Browser 違反 App Store Review Guidelines 的 「2.5.6 Apps that browse the web must use the appropriate WebKit framework and WebKit Javascript.」規範,Puffin Browser 使用的是基於 Chromium 的瀏覽器引擎,因此 Apple 拒絕 Puffin Browser 的更新申請。背後所代表的意義是什麼?

引述數位時代的報導內容:

CloudMosa 認為 Apple 駁回其所提出的更新申請理由已經違反了美國的反托拉斯法,消費者有自身選擇其所倚賴瀏覽器技術的選擇權,無論是伺服器端或客戶端技術都是。就算 20 年前微軟在其 Windows 作業系統綑綁預設搭載 Internet Explorer 瀏覽器最終判決違反反托拉斯法,都還沒有出現如 Apple 今日禁止其他第三方瀏覽器裝載或更新這樣不公平行為。

在別人家的 App Store 平台上架軟體就是會有被拒絕的風險,不論理由是否正當。但這邊也有個疑問,為何 Google Chrome 可以在 App Store 上呢?同樣都是網頁瀏覽器,難道 Chrome 沒有違反 App Store Review Guidelines 2.5.6 的規範。

CloudMosa 公司文化

每間公司的文化都不一樣,除非員工出來分享或是進入公司才會知道,目前網路上介紹 CloudMosa 的公司文化大概就這篇最詳細:這個暑假我在 CloudMosa 所見所聞

《這個暑假我在 CloudMosa 所見所聞》的作者是曾經在 CloudMosa 擔任實習生,對於辦公室環境、組織架構、產品線等都有初步的介紹,滿有參考價值。感謝 Liu, An-Chi (@tigercosmos) 的分享。

文化是由人所形成,建立在每個人的價值觀和觀念上,除上述文章外,想了解 CloudMosa 的公司文化也可以搜尋創辦人的相關文章。像是《臺灣團隊打造世界級瀏覽器,維運萬臺伺服器靠Docker》報導當中提到:

沒有任何觀念永遠正確、永遠適用

CloudMosa的IT架構之旅,一路從純公有雲、混合雲到開始使用Docker容器技術,「沒有任何東西技術、觀念永遠正確,能解決問題才是最重要。」沈修平笑著說,無論是最新的Kubernetes、Swarm等容器調度技術,CloudMosa也都有進行研究,不過他仍再次強調,解決問題才是重點,「不要為了追趕潮流而用,把技術視為炫耀財。」

同時,沈修平也在CloudMosa倡導,每個員工都得具備獨立思考能力,「對任何外來資訊都要存疑」,接觸外界資訊的重要性,在於擴大視野,重點仍是靠自己消化資訊,「找出一條最適合自己的路。」

還有《 20 人台灣軟體公司,在全世界烙下印記——專訪 CloudMosa 創辦人沈修平 》 這篇也提到 CloudMosa 的文化和理想:

沈修平說,自己只「管理」公司文化。

「我一直在 Push 的事情是,每個員工都能夠找到一件很重要的事情做,不是一件證明他自己很重要的事情,而是證明他正在做的那件事情很重要」

「一個 engineer 最重要的就是眼光,能夠自己判斷重要性,絕大多數時候都是我在問問題,而不是提供 guideline:你要能說服我,為什麼你要這樣做?為什麼這件事是有意義的?」

最初的理想:

解決數位貧富不均的問題,無論在哪種裝置上,都能享有同樣的上網體驗。

相關連結

Data Structures

重新複習資料結構 (data structures),這裡暫時不討論演算法 (algorithms)。首先,我們先了解有哪些的資料結構,常用的資料結構有:陣列、堆疊、佇列、鏈結串列、集合、字典、樹、圖形。

陣列 (array)

陣列是最簡單、最基本、最常用的資料結構,多數程式語言本身都支援陣列的資料結構。陣列通常都是存放同一種資料型別,而且陣列的長度通常是固定不能修改的,例如 C, C# 語言的陣列。不過有些陣列的資料結構是可以存放不同資料型別,而且長度可以任意動態調整, 例如 JavaScript 語言的 Array 陣列 。

存取陣列中的元素使用索引,大部分程式語言的陣列索引是從 0 開始,這和記憶體的位置有關,當然也有部分程式語言的第一個元素索引是 1。若要插入或刪除陣列中的元素,將會需要搬移其他相鄰的元素,這一點是操作陣列時的缺點。

有兩種資料結構是陣列的變形:堆疊和佇列,與陣列的差異在於元素的操作方式。

堆疊 (stack)

堆疊是後進先出 (Last In, First Out, LIFO) 的操作方式,堆疊就像是元素從下而上疊起來,將元素推進 (push) 堆疊頂部,從頂部取出 (pop) 元素。因此,沒有元素插入和刪除陣列中,需要搬移元素造成的缺點。

佇列 (queue)

佇列是先進先出 (First In, Last Out, FILO) 的操作方式, 佇列就像是排隊的概念, 將元素排入 (enqueue) 佇列的尾端,從開頭將元素取出 (dequeue)。同樣地,也沒有陣列需要搬移元素造成的缺點。

鏈結串列 (linked list)

鏈結串列的每個元素稱為節點 (node),每個節點包含資料本身和一個指標 (pointer),指標的目的是指向下一個節點。 鏈結串列改善了陣列的缺點,當需要插入或刪除元素時,只需要改變節點的指標而不需要搬移元素。但是鏈結串列的缺點是存取元素時,必須從頭開始迭代串列直到找到元素為止。鏈結串列有不同的類型,如下:

  • 單向鏈結串列 (singly linked list)
    每個節點只有一個指標,這個指標指向下一個節點。
  • 雙向鏈結串列 (doubly linked list)
    每個節點具有兩個指標的,一個指標指向前一個元素,另一個指標指向後一個元素,因此可以對串列往前或往後存取。
  • 環狀鏈結串列 (circular linked list)
    和一般的鏈結串列 (不論單向或雙向) 差別在於最後一個節點的指標指向第一個節點。環狀結構因為沒有起始點,因此從任意節點可以開始迭代存取。

集合 (set)

資料結構的集合相當於數學上的集合。集合相當於沒有順序概念的陣列,而且每個元素不能相同。此外,對於集合有聯集 (union)、交集 (intersection)、差集 (difference)、子集 (subset) 等等的操作方法。

字典 (dictionary)

字典以「鍵 (key) : 值 (value) 」的形式組織資料,新增和刪除都是以整個鍵值對 (key-value pair) 操作。通常 key 必須是可雜湊 (hashable) 的資料,因為字典的資料結構會利用雜湊表 (hash table) 方式實作,利用 key 可以快速取得 value,這是字典的優點。

樹 (tree)

樹的資料結構有父子關係,每個節點都有一個父節點,以及多個子節點。根結點是唯一一個沒有父節點的節點。樹狀結構大多討論二元樹 (binary tree) 與其變形結構,說明如下:

  • 二元樹 (binary tree)
    每個節點最多只能有兩個子節點,一個是左側子節點,另一個是右側子節點 。
  • 二元搜尋樹 (binary search tree)
    二元樹的一種,但子節點有個規則,左側子節點必須小於父節點的值,右側子節點則必須大於或等於父節點的值。

以樹狀的資料結構來看,還有很多種類型,可以參考維基百科 Tree (data structure) 的說明。

圖形 (graph)

資料結構的圖形相當於數學上的圖形。 圖形是由頂點 (vertex) 和邊 (edge) 組成,圖形依據邊有無方向,分為有向圖與無向圖兩種。圖形是個概念,到底應該要如何以資料結構表示呢?有幾種方式可以表示:相鄰矩陣、相鄰串列、關聯矩陣。

總結

前述幾種資料結構,若以資料之間的關係,邏輯的觀點來看,總共有線性結構、集合結構、樹狀結構、圖形結構共四類。若以物理的觀點,也就是資料實際儲存的方式來看,可以分成順序儲存結構和鏈結儲存結構兩類。

提問

資料結構共有多少類型?

這個問題要改成「資料結構有那些基本類型 」比較正確,例如陣列的變形結構就是堆疊和佇列。依據我目前的參考書來看,共有 6 種基本類型:陣列、鏈結串列、集合、字典、樹和圖形。

字典結構是哪一類邏輯結構?

字典結構可以說是雜湊函式 (hash function) 的應用,利用雜湊表實作的資料結構,邏輯上看每個元素是集合結構的關係。元素之間不是一個一個的線性關係,不是一對多的樹狀關係,也不是多對多的圖形關係。

參考書籍

  • Loiane Groner 著,孫曉博等譯,JavaScript資料結構及演算法實作,新北市:博碩文化, 2016年4月。 譯自:Learning JavaScript Data Structures and Algorithms
  • 程杰,大話資料結構,台北市:精誠資訊,2011年6月。

書太多應該怎麼辦

最近開始整理家中的藏書,預估大概有 2000 本左右。從工作開始之後,每個月以 3000 元左右的預算,平均購買大約 10 本書籍來閱讀,一年下來也累績約 120 本左右,到了最近 3 年發現空間實在沒辦法容納,才慢慢減少購買書籍的數量。直到前陣子閱讀《成功人士為什麼這麼在意書櫃?》這本書,「書太多應該怎麼辦」有比較好的解答了。

《成功人士為什麼這麼在意書櫃?》的作者是「成毛 眞 (Naruke Makoto)」,原書名是《本棚にもルールがある—ズバ抜けて頭がいい人はなぜ本棚にこだわるのか》,Google 翻譯是「書架上也有規定—為什麼聰明又頭腦混亂的人堅持使用書架」,這本其實是有關書架應該要如何整理的書,日文書封面上寫了「Even bookshelves have rules」,中文書名可能是為了市場行銷考量吧。

書櫃是你的外接式大腦

作者提出「書櫃是你的外接式大腦」這個觀念。當我們把一本書讀完,不太可能完全記得所有內容,因此就會把書籍往書櫃上堆置,直到放不下為止(或到處亂放),方便我們以後有機會可以查閱。

結果是,我們通常不會再動它了,想想看你有多少看過的書籍是會再拿來翻閱的,比例是相當低的。家中的衣櫥和冰箱你一定會定期整理,衣服穿著洗滌後會逐漸損壞,食物隨時間會慢慢腐敗,但書櫃就不是這樣了。因為書籍沒有保存期限,放著不會腐壞,你可以買了不看,除非放不下了你才會去處理它。所以我們必須有一套方法來處理這個問題。

整理書櫃的規定

  • 隨時都要有 20% 的空間放置新的書本,不能因為放不下書而不買新的,我們必須閱讀新知識持續成長。
  • 書櫃要放置非文學類的書本,但不要放跟工作相關的書,我們要廣泛且多樣性的閱讀才能開拓視野。
  • 文學類可以買電子書看,因為文學類的內容不隨時間變動更新,且閱讀上有前後順序較適合電子閱讀。
  • 因為書櫃空間有限,只能擺放頂尖好書,你認為「有趣」的書。暢銷書要謹慎評估。
  • 書櫃要放在目光所及的地方,方便每天瀏覽和取用,而且書本擺放要看的到書名。
  • 書櫃上的書本必須分門別類整理,才能快速取用查找。
  • 書櫃應該要夠深,前後放置可以到第二層。

理想書櫃

家裡應該要有三個書櫃,組成一個「理想書櫃」,這概念類似冰箱的蔬果室、 冷藏室、冷凍庫,我認為也類似於電腦的快取記憶體、主記憶體、硬碟的概念。

  1. 新鮮書櫃 (蔬果室、快取記憶體)
    放置新買的、準備要看的、正在讀的書本,篩選後進入主要書櫃,或是轉賣處理。
  2. 主要書櫃 (冷藏室、主記憶體)
    指的就是「 外接式大腦」,依據上面書櫃的規定整理,至少應該有自然科學、歷史、經濟三個分類。
  3. 高塔式書櫃 (冷凍庫、硬碟)
    放置辭典、事典、工具書、年表、地圖、圖鑑的地方,不用看完而是方便查找資訊的書籍。

總結

書太多應該怎麼辦?開始整理吧,決定要留下來的書本有下列幾類:

  • 有趣的書
    「有趣」與否是自己決定的事情,例如自己對書中的一些故事特別感興趣,但對其他人來說可能就有點無聊。不感興趣的東西沒有必要留著佔用空間。
  • 最新出版的書
    對於一些新知識來說特別明顯,像是一些趨勢風潮,當下有必要閱讀認識,但時間過了就沒用了。而電腦資訊相關的書籍因為變化速度很快,過了一年可能版本就改變過時了。不是最新出版具有最新知識的書不該留在主要書櫃上。
  • 資訊量豐富的書
    具有豐富圖表的書一定要留下,雖然網路上很多資訊可以搜尋,但有時候書籍因為有編輯整理反而會有價值。

只留下內容有趣、最新出版、資訊量豐富的書本,其餘的書籍都可以轉售或回收了。透過 TAAZE 讀冊生活 賣二手書是個不錯的選擇,不過要注意太冷門或暢銷書會不太能賣就是了。

Numeric Types

這篇文章將介紹 Python, JavaScript, C, C# 四種程式語言的數值型別 (numeric type)。

Python

Python 的數值型別有 3 種:整數 (int)、浮點數 (float)、複數 (complex)。不過在 Python 2 中還有長整數 (long) 的數值型別,只是 long 型別在 PEP 237 的提議下 ,Python 3 的 long 已經合併為 int 型別。

int 是無限位數、無限精度 (unlimited precision) 的型別,也就是可以存放的整數沒有範圍 (極限值據說是可用的記憶體大小)。 float 是以 C 語言的 double 實作,有關浮點數的資訊可以從 sys.float_info 結構中得知,詳細內容如下表。

屬性
epsilon2.220446049250313e-16
dig15
mant_dig53
max1.7976931348623157e+308
max_exp1024
max_10_exp308
min2.2250738585072014e-308
min_exp-1021
min_10_exp-307
radix2
rounds1

complex 的實部 (real) 和虛部 (imaginary) 是 float 型別,因此 complex 的範圍就是 float 的範圍。

JavaScript

JavaScript 的數值型別只有 Number ,是 IEEE 754 的 64 位元雙精度 (double-precision) 浮點數,浮點數的定義請參考下表 Number 的屬性。雖然最近的 ECMAScript 2015 標準新增 BigInt 型別,但尚未支援各平台,建議評估後再使用。

屬性
Number.EPSILON2.220446049250313e-16
Number.MAX_SAFE_INTEGER9007199254740991
Number.MAX_VALUE1.7976931348623157e+308
Number.MIN_SAFE_INTEGER-9007199254740991
Number.MIN_VALUE5e-324
Number.NEGATIVE_INFINITY-Infinity
Number.NaNNaN
Number.POSITIVE_INFINITYInfinity

C

C 語言 (以 C99 標準) 的數值型別有 char, short int, int, long int, long long int, float, double, long double ,整數的部分都是帶正負號整數,可以加上 unsigned 變成只有正數的無號整數 (unsigned integer) ,而整數的限制範圍定義在 limits.h 標頭檔之中。

注意到整數型別只有定義「至少」幾位元,其關係是 short ≤ int ≤ long ≤ long long,實際大小依據編譯器的定義。另外,char 的範圍也是依據編譯器定義 signed 或 unsigned 而不同。

型別位元範圍
char8unsigned char: 0 to 255
signed char: -128 to 127
short int
(short)
至少 16 -32,767 to 32,767
int至少 16
(通常是 32 )
-32,767 to 32,767
long int
(long)
至少 32-2,147,483,647 to 2,147,483,647
long long int
(long long)
至少 64-9,223,372,036,854,775,807 to
9,223,372,036,854,775,807
float32±1.5 x 10−45 to ±3.4 x 1038
double64±5.0 × 10−324 to ±1.7 × 10308
long double至少和 double 相同 至少是 double 的範圍

C#

C# 的數值型別有 sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal 共 12 種。

型別位元範圍
sbyte8-128 to 127
byte80 to 255
short16-32,768 to 32,767
ushort160 to 65,535
int32-2,147,483,648 to 2,147,483,647
uint320 to 4,294,967,295
long64-9,223,372,036,854,775,808 to
9,223,372,036,854,775,807
ulong640 to 18,446,744,073,709,551,615
char16U+0000 to U+FFFF
float32±1.5 x 10−45 to ±3.4 x 1038
double64±5.0 × 10−324 to ±1.7 × 10308
decimal128±1.0 x 10-28 to ±7.9228 x 1028

總結

  • 在 C, C# 中,char 字元型別也是整數型別的一種,差別在於 C 語言是 8 位元,而 C# 是 16 位元。
  • Python 的整數型別只有 int 一種,而且 int 沒有範圍,浮點數型別也只有 float 一種。
  • JavaScript 的數值型別只有 Number 這種浮點數型別,沒有整數型別 (不過新版本有增加 BigInt)。
  • 在內建型別當中,只有 Python 有複數型別,只有 C# 有 decimal 這種浮點數型別 (精確度較高但範圍較小)。
  • C, C# 提供的數值型別最多,讓程式開發人員有最多的選擇,Python 則居於中間, 然而 JavaScript 最精簡只有一種。

提問

為什麼 Python 的整數沒有範圍?為什麼要這樣設計?

搜尋看來沒有什麼答案,也許是像 PEP 237 的提議,可以簡化程式設計需要考量範圍的因素,一切交給 Python 處理就行了。

為什麼 JavaScript 的數值型別只有浮點數型別?

推測是和 JavaScript 當時簡化的設計有關,在瀏覽器執行的程式語言盡量簡單,於是僅需要一種數值型別,就是 Number 這種浮點數型別,浮點數可以當整數使用,但整數不能當浮點數使用。我們特別要注意 JavaScript 數值的精確度問題。

如果需求超過浮點數的範圍,應該要怎麼解決比較好?

目前想到的方法是以科學記法 (scientific notation) 的方式,各自將尾數 (mantissa) 與指數 (exponent) 兩個部分獨立儲存,以整數型別各自處理計算。又或是仿照 IEEE 754 浮點數的定義設計 128 位元或更多位元的浮點數,提高精確度。

Introduce Yourself (Example Post)

This is an example post, originally published as part of Blogging University. Enroll in one of our ten programs, and start your blog right.

You’re going to publish a post today. Don’t worry about how your blog looks. Don’t worry if you haven’t given it a name yet, or you’re feeling overwhelmed. Just click the “New Post” button, and tell us why you’re here.

Why do this?

  • Because it gives new readers context. What are you about? Why should they read your blog?
  • Because it will help you focus you own ideas about your blog and what you’d like to do with it.

The post can be short or long, a personal intro to your life or a bloggy mission statement, a manifesto for the future or a simple outline of your the types of things you hope to publish.

To help you get started, here are a few questions:

  • Why are you blogging publicly, rather than keeping a personal journal?
  • What topics do you think you’ll write about?
  • Who would you love to connect with via your blog?
  • If you blog successfully throughout the next year, what would you hope to have accomplished?

You’re not locked into any of this; one of the wonderful things about blogs is how they constantly evolve as we learn, grow, and interact with one another — but it’s good to know where and why you started, and articulating your goals may just give you a few other post ideas.

Can’t think how to get started? Just write the first thing that pops into your head. Anne Lamott, author of a book on writing we love, says that you need to give yourself permission to write a “crappy first draft”. Anne makes a great point — just start writing, and worry about editing it later.

When you’re ready to publish, give your post three to five tags that describe your blog’s focus — writing, photography, fiction, parenting, food, cars, movies, sports, whatever. These tags will help others who care about your topics find you in the Reader. Make sure one of the tags is “zerotohero,” so other new bloggers can find you, too.

使用 WordPress.com 設計專業網站
立即開始使用