分類
Books

克服團隊領導的5大障礙 讀後感

一本講公司領導團隊的寓言故事書。

蠻特別的是跟一般講領導個人特質的書不一樣,這本情境是在領導團隊(這裡指的是由公司CEO, 財務、業務、行銷、客服、產品部門等一級主管組成的領導團隊)中展開。最大的觸動就是對於公司管理層來說,你的 leadership team 應該才是第一順位重要,應該要比自己部門團隊更親近才是。

這跟現實中往往相反,因為主管通常會跟自己部門最親近,而不是領導團隊,這導致本位主義,不知道別的部門在幹嘛,無法像一個團隊達成公司的目標。

就像一個籃球教練分別跟五個球員談話,每個人都不知道教練跟其他人講了什麼。這不是 Team,而是一群個人在打球。

至於書名所謂的五大障礙,主要就是講溝通,先有信任,然後開會不要害怕衝突,要有承諾、責任、成果等等。這部分內容就比較老生常談,而且我覺得書中故事能順利展開的最大原因,就是主人公(新CEO)很厲害能夠引導溝通,進而產生公司變革。而現實中不是每個人都會這麼能主持會議溝通的….

分類
Books

資本主義沒告訴你的23件事 心得摘要

這本就是對著自由市場經濟開幹的書啊,改變了很多我對資本主義的認知,光是看各章標題就很吸引人。市面上的經濟學大多是自然市場經濟學背景,而這本書用了更多事實舉例跟數據來反駁,有種說了大實話的感覺。

  1. 根本沒有自由市場

    每個市場都有他自己的各種限制,有多自由是政治定義的。市場不是客觀的。自由貿易、公平貿易也是如此。市場的邊界是由政治決定的。
  2. 經營公司不該以股東的利益為優先

因為股東是公司流動性最高的厲害關係人,最不在乎公司的長期發展 (除非是大股東),尤其是小股東,只在乎最大短期利益。股東可輕易退出公司,只需要賣股票就好了。

其他利害關係人,例如員工、供應商,反而對長期利益更關心。

因此,長期的穩定好公司,其實會有各種手段來減少浮動股東對公司的影響,例如 政府擁有的股份、不同等級的骨釘,保證創始家族的控制權、公司有勞工代表、友好公司交叉持股 等等

分類
Books

創意競擇 讀後感

過年期間看了這本創意競擇,想說網上有人推薦,是不是有什麼產品開發的真知灼見。這書比較特別的是作者是 Apple 的第一線軟體工程師,分享一些幕後故事。但是看完覺得果然格局就只是軟體工程師的角度而已,其實頗為失望。整本書也就兩個專案: Safari 瀏覽器的開發 跟 iOS 鍵盤,用兩個專案來談 產品創意流程,實在是有點薄弱了。

第一章講了一個跟賈伯斯的 Demo,覺得有點誇張,就是一個員工粉絲晉見賈伯斯神的過程,作者非常自豪自己可以被納入產品核心圈有機會跟賈伯斯做實際demo。接下來幾章講他如何抄(移植) Konqueror 瀏覽器原始碼到 Mac 的故事,其實蠻無聊的,所謂移植就是苦幹而已。

第五章也是鬼扯,老闆說效能優先,於是全部人就過早優化,每個 code commit 都要通過 Page Load Test,完全就是老闆說的都對,老闆的老闆賈伯斯說新推出的瀏覽器要效能優先,這太神了。

下一章寫編輯器,竟然可以自幹一年沒有 PM 管理,最後作者說有完成但並沒有真的整合進瀏覽器實用。 然後作者嫉妒同事升管理職自己沒有,跟老闆抗議後,改去接管理職三個月,但因為覺得被分配的團隊工作不重要,而且聽到隔壁團隊好像在做什麼重要的神秘案子,於是還厚臉皮去跟老闆說不想做管理了,想去公司的秘密團隊,超好運的就轉調去神秘團隊,超好運那就是在開發 iPhone,作者負責開發觸控鍵盤(因為老闆覺得作者之前做編輯器,跟做鍵盤好像有關係)。

在 Apple 幾乎不開腦裡激盪會議,都是用 Demo 會議直接比較原型,例如觸控鍵盤的方式,這就是作者所謂的創意競擇:演示、意見回饋、下次演示。以及用 dogfooding 方式試用回饋。作者發明 iphone 的觸控螢幕鍵盤的自動校正功能 蠻厲害的,Apple 在 Touch UI 下了很多功夫優化。

設計是指產品如何運作,而不只是外觀。Apple 不愛做 A/B testing, 而是更多用品味來判斷。這相比 Google 愛用資料做判斷的文化。但是哪些用演算法判斷、哪些用人唯主觀判斷,只能不斷反覆多次設計和體驗後才決定。作者提到科技與人文藝術的交會: 其實也就是重視 UX,軟體設計團隊以人機介面團隊自居云云。

分類
Books 商業管理

非線性成長 讀書摘要

這本非線性成長(簡體書),算是 2020 年念過最喜歡的一本書。作者黃有燦是三節課的共同創辦人,我也買過三節課的好幾門課程,都還不錯。

我通常不太喜歡看個人成長的書,因為大多是很顯而易見的正確教條,舉例跟故事性太少。例如 Ray Dalio 的原則,他的原則很棒,但是書讀起來其實蠻無聊的。但非線性成長這本寫的很精彩,總結個人經驗有邏輯又有很多案例,不只是個人成長,連如何營銷管理的思考架構也有提到。對於已經工作 5 年以上,本行專業技能已經不成問題,想要有所突破的工作者,會蠻有幫助的。

分類
Agile Books

實戰敏捷開發 Practices of an Agile Developer (5) 除錯篇

Update(2009/9/22): 看到另一篇說明 bug report 該有什麼內容

debugging 最大問題在於,它是一個未知的時間箱子,不知道要花多久才能 debug 完。這章談的是幾個除錯上的技巧。

說到除錯,我也推薦閱讀如何有效地報告錯誤這一篇文章,談的是如何正確回報錯誤,好的錯誤回報可以節省很多時間,而不僅僅只是一句 “程式不會動” 而已。

Keep a Solutions Log (紀錄下解決問題的辦法)

解決問題一直是軟體開發者的工作項目(這裡指的問題比較像是軟體安裝、版本、函式庫使用等等問題,例如 windows 上如何把 MySQL Ruby gem 裝起來等等),不過有時候會碰到似曾相似的問題,疑?我以前是怎麼解決的?拜網路發達之賜,Google 搜尋一下通常會有不少幫助,但是還是得花不少時間找尋解答。

自己維護一份簡單的 solutions log 吧,紀錄下日期、問題描述、解法、參考網址等等資訊,之後碰到類似的問題就可以搜尋的到。將這份 log 用 wiki 維護也是不錯的主意。或是寫在 Blog 上,這樣 google 搞不好還會搜尋到自己以前寫的解法…XD

Warnings Are Really Errors (把警告當真)

編譯器(這裡泛指 complier 或 interpreter) 的警告常常有人是忽略不看的,反正可以編譯執行不會 error 就好了?書上舉了 C++ 的例子,編譯器的警告還是蠻有用的(我想特別是 static 語言)可以幫助你找到跟避免潛在的 Bugs,請不要忽略。請將編譯器的警告也當作程式錯誤或無法通過測試的程式一樣認真處理。

我自己寫 Ruby/Rails 的經驗,最常見的警告像是有:


link_to ( 'login', login_path ) # warning: don't put space before argument parentheses

因為中間多了一個沒用的空白。或是

p Array.new 3, 1 # warning: parenthesize argument(s) for future version

因為 interpreter 覺得 ambiguities 不清楚,這時要請你括號括清楚。另外就是 DEPRECATION WARNING 警告了,告訴你這函式將來的版本將會移除,請不要再用了 :p

Attack Problems in Isolation (隔離除錯)

要在一個大系統找特定問題,不要整個系統一起測,而是將分開隔離找出病因。如果有做 unit tests,我們知道可以將 dependence 的東西用 mock object 隔離出來,這樣測試的時候就不會被外部因素干擾。同理在抓整個系統中的特定 Bugs 的時候,必要的話可以做一些假的 prototype 元件用以隔離抓出問題所在,同時也比較好除錯測試。

我自己土法煉鋼除錯 CSS 也是如此,先移除 CSS 檔案的一半,看看問題是不是出在這裡,然後再砍一半直到找到有問題的那一行。(Binary search?)

Report All Exceptions (回報所有的例外)

如果呼叫一個可能會丟例外的函式,當碰到例外時,盡量可以處理就處理,不然請讓他自然傳播(Propagate)上去給上一層 Caller 處理,不要攔下來又什麼都不做。如果在整個 call stack 中有個傢伙寫了個空個 catch 所有例外,然後 return null 什麼都不做,到時候要找 Bugs 你就會很想殺人了,因為非得 trace 進去 call stack 才能找到原因。

不要覺得自己不會這樣寫,其實常常我們會想”暫時”不想處理這個例外,於是就留下這樣空的例外處理程式碼(然後繼續留到 Production code)。決定要在哪一層處理例外是個設計上的考量,但是如果呼叫一個函式卻要考慮處理二三十種以上的例外可能就有設計上的問題了。

Provide Useful Error Messages (提供使用者有用的錯誤訊息)

一般性的錯誤訊息如 “Something went wrong” 對使用者來說,可說是一點幫助也沒有,既沒有告訴用戶可以怎麼解決,就算使用者想要求助也不知道發生什麼事情。所以盡量提供詳細的訊息告訴使用者發生什麼事情。

當然,如果是比較嚴重的程式例外錯誤,對開發者來說,因為有 logging 的關係,所以看 log 應該可以知道大概的情況並排除,這類的錯誤對使用者來說也沒辦法自行排除,也只能告訴用戶說這不是因為他們操作錯誤的原因。

關於這個議題這一節講的不是很清楚,我個人推薦有本 37 signals 的小書可以翻翻:Defensive Design for the Web 圖文並茂共有40條 Guideline 告訴你如何改進網站的錯誤提示訊息、表單填寫等等,例如:

  • 錯誤訊息要明顯,使用顏色、Icons 等效果
  • 錯誤訊息包含這是什麼錯誤以及如何修復
  • 整個網站用一致的錯誤提示方式
  • 在錯誤提示後,不需要再回上一頁才能修正問題
  • 用易懂、禮貌的字句
分類
Agile Books

實戰敏捷開發 Practices of an Agile Developer (4) 程式篇

趁著新年連續假期,終於把這一章念完了:隨著開發的進展,程式逐漸變得怪獸。這章談幾個重點幫助你讓程式容易了解、擴充及維護。

Program Intently and Expressively (寫清楚了解的程式)

厲害的程式是沒有人可以看懂的程式?程式的可閱讀性比寫得方便還重要,寫只會寫一遍,看卻會看很多次。很多時候會有機會要修 Bugs 或是新增功能,這時搞懂本來的程式常常是一開始最困難的地方,如果一開始寫的人就以可讀性為重要目標,那你就會輕鬆的多。

舉個我自己常見的例子就是 Magic Number,很多人喜歡是一個數字來代表 Type code。例如 1 代表 foo、2 代表 bar、3代表…etc,然後程式裡面就直接寫 1, 2, 3。方便是方便,但是沒多久就會忘記這個 1,2,3 各代表什麼意義。最簡單的解決手法就是請改用字串 constant 處理,或者是用 class 來表示 type。

透過程式語言本身的特色可以寫出更有表達力的程式,函數名稱應該傳達出意圖、參數名稱應該表達出他們的用途,寫出好閱讀的程式我們可以避免很多不必要的註解跟說明文件。一些你覺得明顯簡單的地方,不一定對別人也是如此明顯,甚至是幾個月後的你自己。請想想看幾個月後自己來看還會看得懂嗎?

Communicate in Code (寫出可以閱讀的程式)

我們都討厭寫文件的一大理由是:所謂的文件跟程式碼常是分開的兩碼子事,因此很難讓文件跟的上程式的更新,最終變得難以維護。因此最好的寫文件方式,就是透過程式本身和程式中的註解。

註解是用來寫目的、限制條件跟預期結果等,而不是寫出以下這些程式一行行會做些什麼(請不要拿註解再寫一次程式碼在寫的事情)。一個簡單的判斷方式是:寫在函式 “裡面” 的註解多半是不需要的 (尤其是註解寫 what? 而不是註解 why?)。在重構一書更直言回答哪裡需要重構?那就是有註解的地方:如果程式碼前方有一行註釋,就是在提醒你,可以將這段程式碼替換成一個函式,而且可以在註釋的基礎上給這個函式命名。

你要做的事情應該是讓 source code 本身容易了解,而不是透過註解。透過正確的變數命名、好的空白間隔、邏輯分離清楚的執行路徑等手法,我們很少需要在函式裡面註明這些程式在做什麼,我自己的經驗除非是有參考外部的程式碼或複雜演算法,我會多註明參考來源(網址)。否則沒有必要的註解對我來說就像噪音一樣,妨礙閱讀。

變數跟函式的命名是件非常重要的事情,有意義的命名可以傳達出程式怎麼進行,我舉個 Rails 例子:

p = Post.find(param[:id])
if p
   p.destroy
else
   p = Post.new( param[:post] )
   p.save
end


可以改寫成以下這樣具有清楚意含:

existed_post = Post.find(param[:id])
if existed_post
  existed_post.destroy
else
  new_post = Post.new( param[:post] )
  new_post.save
end

有一種 Job security 的方式就是把程式中所有的變數名稱都代換成亂碼,保證拿到的人超級難看得懂。這就是為什麼手工打造的程式碼有其不可取代的重要性,只要拿到整合型 IDE 像是 Dreamweaver 產生出來的 HTML/CSS code 都很想殺人,因為裡面的變數都是編號產生出來的,根本沒辦法閱讀及擴充。

另外就是大家很喜歡用縮寫,這在我之前寫的文章 物件導向程式的九個體操練習 也有提到,這些只有一個字母的暫時變數並沒有辦法傳達出任何可以幫助了解的資訊。

Class, module, method 前面是個寫註解的好地方,而且每個語言都有工具(例如 RDoc, Javadoc… 等)可以幫忙從程式碼中整理出好看的純文件,這些說明通常有:

  • Purpose 目的
  • Requirements(pre-conditions) 預期的輸入是什麼
  • Promises(post-conditions) 什麼樣的輸入,會有什麼樣的預期輸出
  • Exceptions: 有哪些例外(exceptions)情況

這些說明可以幫助我們由大局觀了解程式是怎麼運作的,而不需要仔細看其中每個 method。