2017年4月21日 星期五

到底甚麼是Senior engineer 2

最近反覆讀完這一篇文章Senior Engineers Reduce Risk, 加上近期公司遇到的事情, 讓我反思很多. 也對 Senior engineer有了更進一步的認知.

以下文章是個人讀完該文章, 並把自己認知的部分翻譯出來. 加上自己的經歷, 補充一些觀點

Senior engineer 能夠減少風險


文章一開始就說明很多表面上的事情不代表Senior engineer, 比如說多年的工作經驗, 開發/維護一個知名的開源專案, 研發出公司的旗艦產品的雛形等等. 他確實那一件事情做的很棒, 是一個專家. 但不代表真的是一個合適的Senior engineer. 尤其是當大家對於Senior engineer的與需求有所不同時候, 錯誤認知就變得很危險.

當我們把周遭收集到對於Senior engineer 的文章/定義統整起來之後, 你會發現符合的概念/條件, 多的難以計數, 讓人十分感到挫折. 當試著把這一堆定義應用在真實工作環境裡遇到的Senior engineers, 很難找到完全符合所有條件的人. 或許有一部分只是有Senior engineer的職稱, 沒有的實力. 但這樣的情況實在反差太多了. 我們可以是著思考, 那一些對於Senior engineer的解釋, 是根據他們所在的公司與產業所必備的. 但這樣的理解只是徒增對於Senior engineer的混亂, 並沒有任何幫助.

Senior engineer真正的功能是減少風險, 風險多半都會被誤解成是技術上的風險. 比如說產品的功能不正確or尚未如期完成. 但在商業層次方面有著更應該注意且避免的風險, 比如研發程序風險, 產品設計風險, 業務風險, 公司文化等等. Senior engineer 應該有能夠看到這些風險, 並且盡可能地減輕

新創公司的product-market-fit風險

許多創公司的失敗是來自於錯誤的產品, 核心風險跟技術沒有太多關係, 如果產品本質上就沒人需要, 就算能夠做出來也不會有甚麼改變. 這時候工程師應該是要盡可能地做好研究, 或者縮小研究. 建立雛形驗證, 吸收足夠的商業領域知識, 有完善的指標來協助降低公司破產的可能性

招募的風險

一但公司的產品符合市場需求, 接著得讓產品可運作, 擴增, 並且易於符合顧客多樣要求. 新的顧客需求會產生技術上的風險. 但更進一步的是招募風險, 這樣的風險直接影響公司的生產與文化. 如果公司沒辦法施招募的人有足夠生產力, 最後也只會被人力成本給壓垮

永遠沒有完成的風險

公司成長, 每一項新專案都會跨許多部門, 可能會遇到專案進度的延遲, 為了讓專案的成果可預期且維持品質, 會設立處理程序, 與經常性的溝通會議, 來控制生產力的變因, 使其穩定. 這時候最大風險就是部分工作永遠都沒有完成. 此時工程時忙忙於處理程序, 優化產品, 確保可靠的產出.

實際遇到的風險非常取決於誰創立公司, 做了些什麼事情, 招募了哪些人. Senior engineer 可能是有目的的去減少風險, 或只是剛好當時具備有正確的技能來避免風險.

辨識風險並且明確傳達

大目份已知的風險, 多半都被良好的管理. 因此根本無法分別真實的風險或者感知的潛在風險. 也無法預測真實的衝擊與潛在的衝擊. 而Senior engineer能夠識別出有重大代表性的風險, 並且明確的解釋給其他人知道, 讓大家重視他並且著手處理.


盲目樂觀的風險

未知的風險是很困難去分辨, 但最致命且應該可以避免的是盲目樂觀的風險. 最近公司產品的大版本更新, 把主的產品資料從mysql移到Redshift , 其實在過程中我有感知道大量資料在當前的Redshift cluster下, 執行效率差, 會造成產品適用性不佳, 潛在造成核心系統沒辦法良好運作. 這是已知風險, 但我卻認為可以加大Redshift cluster來解決, 確實這是一個方式, 但會讓公司的營運成本加劇. 沒有顧慮到成本的我, 就是落入盲目樂觀. 沒有做到來思考更全產品系統的衝擊. 對於在眼前卻盲目樂觀的後果, 儘管新產品功能開發完成, 也是毫無意義.

風險的評估應該是一系列的系統運作來思考, 包含公司的營運, 顧客的感受, 商務的考量, 時間的驗證等等. 它是一個層層相關, 交錯複雜的不確定的結果. 要辨識風險, 就應該經過公司的每一步驟驗證, 才能真正避免, 而非落入盲目樂觀.

Senior engineer 選擇風險與公司

每一間公司擁有不同的風險, 因此每間公司對於Senior engineer的要求也不一致. 一個Senior engineer花了5年時間在大公司把小的元件作成一個完善的系統, 不會符合新創公司的需求. 對Senior過度的解讀和不切實際的要求對工程師和公司都有壞處.

Senior engineer透過嘗試與犯錯, 學習並享受會解決某類問題. Senior engineer也應該找有著相同類別問題的公司. 如果相反, 會造成挫折與失志.

與此同時公司應該儘早, 經常性傳達所擁有的風險. 如果一間公司覺得只有技術上的風險, 這是不可能的. 儘管表面上稱作只有短暫性的風險, 然後專注在技術上的細節. Senior engineer要明確知道確實是個真實風險. 誠實的面對一切事才會讓事情變得更容易處理.




2017年4月16日 星期日

學習這件事


20多歲時候 年輕的時候
閱讀太少, 人生經歷太少
腦袋空空根本沒什麼好想, 對於很多事物的概念都沒有
最多只明白教科書單一領域的技術與知識(更多的是畢業了, 連這方面知識都不足夠)
但真實世界是, 你該面對的問題不會等你準備好了才發生
比如說
  1. 工作選擇, 該選甚麼領域工作, 你的興趣跟工作有關係嗎
  2. 伴侶選擇, 合適伴侶是甚麼? 該怎麼決定婚姻?
  3. 財務管理, 錢放銀行真的好嗎? 儲蓄險真的划算嗎? 有甚麼風險?
其實在知識不足的情況下, 我們很難做好思考, 並有一個良好決定 
凡事都要思考, 但很明白腦袋空空的思考會很挫折
我們需要的是一個可學習性的方式, 要是可以 可依循, 可衡量, 可驗證 

最基本且唯一的步驟直接閱讀書籍, 大量閱讀
然後做筆記, 以便時時刻刻的複習
因為書籍是一個完善有架構的知識體系
你在裡面可以學習到
  1. 該領域的架構知識, 比如財務你會明白複利, 金融商品, 報酬率, 貨幣等等
  2. 方法論, 比如要穩定累積財富, 有定投, 定期股債平衡, ETF 等等
  3. 過往可行的經驗參考, 比如巴菲特的歷年投資策略 
以上三點就對應到三大目的
  1. 可依循
  2. 可衡量
  3. 可驗證
最終達到可學性這個目的, 避開了思考恐慌以及挫折

閱讀書籍之後, 接著就要做筆記摘要
因為你閱讀過後很難長久記住,
你需要一個捷徑 專屬於你自己的捷徑,
因為你閱讀一本書能學習到甚麼, 是根據你的知識量級
比如說當前你在意的是 穩健的投資策略, 你很害怕損失
所以你讀財務相關書籍, 都會特別對能夠規避風險的方式有記憶
但對於高價值/高報酬/有風險的方式你會直接忽略
這是一種選擇性盲點, 很多人都是如此, 這很正常
因此你的筆記也會針對這方面去記載, 去時時刻刻提醒你這方面的要點
但你個人的知識量級會隨著不斷閱讀而成長, 就好比同一件事50歲的中年人的解讀跟20歲的剛出社會的新鮮人的理解會不一樣
以上我們很明白個人專屬筆記的要點
  1. 透過快速複習, 幫助長期記憶與思考
  2. 當自己成長更多時候回來看, 可以看到當初沒有想到的知識
  3. 完善你的知識體系

閱讀是第一步驟, 是最高頻
個人筆記是第二步驟, 次高頻, 畢竟不是每次閱讀都好作筆記(關係能否看懂, 能否有所學習)
第三步驟即是發表文章, 分享與教學 超低頻 (知識的融合與再產出需要時間累積)

第三步驟可稱之為深度學習
這是在你擁有
  1. 基本概念, 方法論, 參考經驗
  2. 個人筆記, 個人經歷與實踐的紀錄
  3. 深度學習, 結合自己的過往, 透過教學來連集更多的延伸與進步
透過教學, 你需要提煉出你過往學習的一言一語
最後抽象化成一個說法, 一份投影片, 一本書之類的
然後你會遇到他人的問題, 這是你以前自學不會遇到的
問題可以解答很好, 無法解答更好, 因為這就是進步的機會
這就是真正思考的開始, 而這個時候你已經具備完善的知識來幫助你思考了

所以說為什麼我們要
  1. 大量閱讀
  2. 反覆閱讀並作筆記
  3. 並把它分享出來

2017年4月4日 星期二

到底甚麼是Senior engineer

在工作滿2年多之後, Junior engineer的我開始思考甚麼是Senior engineer, 就跟打遊戲練功升級一樣, 想要有一個明確的衡量指標, 明白自己現在的程度, 才可以好好規畫職涯/人生的下一步.

具體來說我是當了1年半的Backend Programmer(後端工程師), 以及半年多的Devops, 而Devops的經驗讓我有完整的視野來思考, 身為一個Senior engineer 是該具備些甚麼

1 看待問題的能力


If I had only one hour to save the world, I would spend fifty-five minutes defining the problem, and only five minutes finding the solution.
愛因斯坦說過如果給我一小時拯救地球, 我會花55分鐘去界定問題, 花5分鐘解決
(該文真正出處http://quoteinvestigator.com/2014/05/22/solve/)

多半會以為是解決問題的能力, 這是以技術與研究的角度出發, 進入職場後, 技術是用來實現商業, 市場, 使用者等多方需求, 多半問題到你手上的時候都是片面的, 或者資訊不齊全,只針對片段的問題作答, 會不斷碰到相同問題, 或者一系列牽連的後果蜂擁而來.  因此需要理解環境背後的前後關係, 才能夠真正解決問題

反指標: 遇到問題就埋頭苦幹, 做完才發現答非所問

另一方面經驗一直是職場累積的一個重要因素, 但過去的經驗應該是幫助我們解決問題, 而非限制我們的思考. 隨著商業產品的變化以及科技推陳出新, 你會遇到過往經驗無法解決的問題. 有時過往經驗幫助我們識別, 有時是一個全新問題, 如果還是用已知的框架去限制, 會適得其反. 

反指標: 遇到問題直接用過往經驗思考, 儘管不合仍是硬套

2 理解複雜事物的能力


包含是理解技術與商業上的關聯. 因為隨著商業發展, 或者科技進步, 你會持續遇到
  1. 複雜的客戶需求
  2. 交錯的架構設計
  3. 不明確的邏輯關係
  4. 未知的潛在衝突
從完成一件商業產品的過程, 先要釐清楚客戶確實提出的需求, 假設尚未提出或者未來潛在的市場可能, 解決其中的矛盾, 並簡化設計架構達到最佳化, 最後總結出可用資源內團隊可以達成的可用產品.

更確切來說, 事物起始於經過抽象後的表層需求, 這種以簡化成可敘述出來的需求, 直觀看很容易明白, 但在實踐商業價值過程中, 就得解構出背後的邏輯, 還有前後的因果關係, 接著抽象化成可執行的設計架構, 處理衝突與聯合外部資源等, 最後才成為那個最簡化的產品,

有足夠的複雜事務理解力, 才有辦法事先評估, 設想, 尤其是針對未來不確定性的部分, 充分想像可能性並避開錯誤, 就會有掌握, 風險也就變成可控, 產品與專案也就有一定品質的完善 

反指標: 追求複雜與新的技術, 不明底層意義, 也沒有造成商業貢獻

3 不斷自我迭代的能力


資深, 是一種主動進化的狀態. 擁有當前能夠處理所有職場上的能力之後, 還要加上時間的因素. 隨著時間演變, 不僅科技持續進步, 商業也不斷追求高成長率. 個人的能力也要可以保持一定的水準.

一個資深的工程師, 不會只有工作內的資深, 而是時時刻刻都在呈現這種狀態, 也就是持續迭代學習與成長. 有可能是思考過去的已完成的部分是否可以再優化, 或者閱讀其他材料, 試著連結看似不同的技術, 市場等事物. 當環境變遷時候, 可以承受挑戰, 用那已儲備好的101種方法, 來不斷試驗與尋找出路.

反指標: 滿足於當前狀態, 或者只專注當前的技術, 卻不去連結思考其他可能



2016年11月16日 星期三

Micro service 的12個必備要素

原文自https://12factor.net/

app=Micro service
  1. 1個app只有 1 份Codebase 
    1. 每一個app只會有一份code, 意即如果你有個app A 但他有多份code, 它其實是分散式系統,可以切得更細.每一份不同的code都是一個獨立app才對.
    2. 多個不同的app 若共用同一份code也不對, 理應是共用的code做成common Library
  2. app的Dependencies定義明確且獨立
    1. app會用到哪些相依性元件應該是明確定義在某一份文件裡面, 比如Ruby Gemfile or scala build.sbt, app 不該用到隱性系統層面的元件, 比如liux下的curl, cronjob 等等, 這些東西一旦換了環境或者換了版本, 會出現難以追蹤的Bug 
  3. Config是app佈署在各式環境的相應設定(production/staging/development/etc..) 
    1. 內容項目
      1. 後端服務(database/memcached/auth service)
      2. 外部服務的授權key
      3. 每一份部屬的app的設定 like hostname 
    2. app的config理應獨立在config檔案裡面,如果放在程式碼裡面是違背12factors規則
    3. 當開放app code程式碼且不須任何授權性的考量,代表該app config做得很完善.
    4.  app config有別於framework/program module類的config,這些config並不因每一份佈署有差別(會有佈署差別: hostname, credentials. etc..  )
    5. config相關內容並不會紀錄在版本控制, like git
    6. 12factors 理應把config真實內容放在部屬的環境變數裡面
    7. 分群管理(用name space分config)的方式 like development, test, production. 會有佈署與擴張的困難
  4. app應用後端服務皆為統一的附屬資源
    1. 內容項目
      1. data stores. like mysql/couchbase/smtp server
    2. 同一的資源亦即不管是存取本地資源還是外部第三方資源,都不需要改變代碼. ex change local MySql to AWS RDS, 代碼都用jdbc url 連接,不有搬遷改變的問題
    3. 附屬資源意即當後端資源有問題, 只需要佈署時卸下有問題資源, 然後接上新的備援服務,過程中都不會改變到程式碼. ex if app's database is misbehaving , just detached bad one and attached backup one
  5. 確實的分別建置build與執行run階段
    1. 包含項目
      1. build stage意即打包程式碼成為可執行的應用 ex jar
      2. release stage意即將build stage產生的可執行app結合相應佈署的config, 最後得到是可在佈署環境立即執行的app
      3. run stage啟動app, 使其維持在執行狀態
    2. 確實的階段分割, 確保程式碼的修改不會影響到後續的build/release/run stages
    3. release stage產出的每一份可執行app理應有一個獨立的編碼, 表示每一release是不可改變(code/config),有任何改變都是新的release
    4. build stage是開發者負責管理與啟動, 開發者彈性去處理錯誤與發佈補丁
    5. run time stage會是自動化or系統管理者的工作. 以避免app在半夜壞掉時沒有開發者可以及時處理
  6. one or more stateless app:執行app理當視為一個或者多個無狀態的程序
    1. app=process:在開發階段app可能由interpreter來呈現, 到了production更複雜的執行環境下, app是一個/多個系統程序process會更好管理(因為該環境可能不只有一個app, 多種類app都統一用process視角會省去管理複雜度)
    2. stand-alone and stateless: app process理應無狀態且彼此獨立, 有任何該保存的狀態資訊應當放到後端服務 ex database
    3. single-transaction:記憶體與檔案系統地的應用理當單一性,意即當前使用完,不保留到未來程序使用. 如此可以避免當app轉換生命週期時,狀態不一致(因為無狀態,無local state)
    4. build include all component:app會應用到的相關元件應該build stage就建置完善, 而非到runtime才去生成. 就不會有狀態問題
    5. no sticky session no local state:意即不暫存使用者資料, 期許下一次的訪問更快速, 如此一來app 就有local state, 違背stateless 精神, 這方面的需求理應放在time-expiration data store like Memcached/Redis.
  7. self-contained. 12factors app理當是自身健全的服務, 有別於比如php app 需要依賴Apache HTTPD模組/ Java app依賴Tomcat. app可以直接對接網路埠口port, 直接接收並處理且回應任何請求. 當app能直接處理請求, 他自己也可以成為別的app的後端服務, 透過提供對應的address like url 到其他app的config
  8. process concurrency: 12 factors app用process來實現多工, app process架構符合unix process model. process model可以應用到各種不同的工作內容 like HTTP request 就是web process, background task就是worker process. 這種設計有別於比如java用thread實現多工. 只有開發者自己明白thread的狀況, 不易於管理. process model的優勢來自於share-nothing/horizontally/partitionable, 使app易於擴張.
  9. disposability: 12factors app process是可以隨時啟動或者暫停, 易於擴張, 快速的佈署與程式碼的/config修改, 並且有健全的production deploy.
    1. minimize startup time: app盡可能快速的可處理外部request, 保持敏捷的擴張, 也提供了服務的強健, 意即當硬體有問題時, 可以很快的置換機器
    2. gracefully shut down anytime: 能夠隨時停止接收request, 並處理好剩餘任務. 即使任務是耗時的, 當新的app起來時候, 也應該無縫的恢復.
  10. dev=prod: 盡可能包持development/staging/production各階段條件都一致
    1. time gap: 開發到佈署產品的時間差 
    2. personal gap: 開發者程式碼vs操作人員佈署
    3. tool gap: 開發環境vs佈署環境






2015年4月23日 星期四

Scala knowledge, <:< type

前言
Scala type system 可以有type constraints, 比如[ T <: Int ] 要 type T 是 Int後代, 不過有些更進階的符號, 看起來會以為是operator, 事實上是一個type的 syntax sugar進階應用, <:< 就是一個最好例子

2015年4月18日 星期六

Scala knowledge - Type members, Path-dependent type and Dependent method types 的意義與由來

前言
從OO出身而言, 大家比較有概念的是class or object, 但到了FP世界, 就有type的概念, 看起來很相似又好像有點混淆, 但本質上應該都是一樣的...

2015年4月9日 星期四

Scala knowledge - Existential types

前言
Scala 的Type parameter 是一個強大的特性, 實現許多抽象化資料結構, 但Scala run 在jvm上, 仍是受到type erase限制, 因此在Type parameter中需要再處理抽象化type時候, Existential types 是一個很好詮釋Abstract data type的方式