2018年9月27日 星期四

如何成為更好的軟體工程師

六月份的時候,被 G 社找去面試,雖然最後沒有上,不過在準備的過程中,以及面試後的自我反省,了解到自己還有很多可以進步的地方,於是踏上了尋找工作的旅程。在之後又持續面試了幾間公司,雖然到目前為止都還沒獲得新工作,不過每次的失敗,都給了我一些對於工作的想法與啟發,想在這篇文章記錄下來,未來可以回來複習一下。

我覺得我一直以來工作算蠻順遂的,第一份工作就有機會進入世界級的外商公司上班,開了眼界;其次我工作很認拼,也都碰到不錯的老闆,升遷也算蠻快的。只是我一直不知道,我到底是怎麼表現好,因此受到賞識,進而維持這些優點,維持這個好的狀態。一直到我加入了一間不一樣的公司,讓我不得不修改原本的做事方式,遺忘了原本的做事方式,一些能力也漸漸一起遺忘了,最後連工作的熱情也漸漸遺忘了。

透過這些面試,讓我重新檢視自己如何工作,把一些能力與感覺抓回來,也更確立了未來的工作態度 -- 持續保持熱情。


一、好的工程師能夠提出 Edge case 驗證想法

Google 主要是面試技術題,在面試前我寫了 Leetcode Easy & Medium 的考題。
我最後幾年,都在做系統架構設計,因此對於這些演算法相對生疏,因為很久沒寫比較深的程式了,一開始寫的時候,平均一題要寫一個小時。

在解了演算法的這些題目之後,我忽然了解到,演算法設計和系統架構設計的相同之處,都是在於「目標情境」的「邊界條件」的處理,能夠將這些邊界條件處理的越好,就是越好的方法,最後的結果才會有好的「品質」。

「目標情境」指的是我們真正要解決的問題。因此邊界條件也不是無窮亂舉,而必須要屬於這個問題的範圍內。

「品質」意味著沒有錯誤,也就是運算的結果都是對的;在正確性最優先的前提下,我們才選擇複雜度、運算時間、運算空間較優的方法。也就是說,如果結果不正確,那麼演算法跑多快都沒有意義。

「邊界條件」指的是演算法的限制,或是系統的限制。例如要設計一個除法的演算法,那麼其中一個邊界條件就是整數最小值除以 -1 的情況是多少?如果設計一個批次處理的系統,那麼最極端應用案例是什麼?

二、好的工程師會先提出能正確解決問題的方法,之後再優化他

由第一點可以知道,「正確」是最重要的,也正代表著「品質」。
因此我們首先必須得到一個「正確」的參考設計,即使這不是最優的解法,例如時間複雜度是 O(n^2)。
接著就是腦力激盪的時候了,是否可以改善現有的方法,例如變成 O(nlogn),而且適用所有情境?又或是的確存在一個比較快速的方法,但是只有當特定條件滿足時,我們才可以使用這個方法?
之所以特別把這個列成一點,是因為重要的是分析問題,而不是找到捷徑找到所謂「正確」的答案。即使用感覺的得到一個很好的解法,但沒有好的分析問題能力,也無法證明這個方法是正確的,這麼一來結果還是不確定的,品質就是不穩定的。
只要學會分析,再搭配一些創意,永遠可以得到更好的解法。

三、學會和別人討論,並嘗試兩個人合作找到更好的解法

每個人的思考邏輯都不一樣,因此每個人切入角度不同,發展出來的長處也都不同。
若是一個人想解法,可能需要很多時間才能找到比較好的答案。
因此與自己觀點不同的人討論,可以幫助自己避開盲點;不同思路的碰撞,更容易激發出更好的方法。
與人討論,如果只是要證明自己的想法是對的,除了傷害彼此感情,而且永遠只會得到「自己永遠是對的」的結論。

四、好的工程師重視基礎能力

工作得越久,一些高級工具用得越多,基礎能力用得越少也忘得越多。
但是要用上述的方式找到更好的解法,最考驗的還是基礎能力,包含一些基礎知識、問題分析能力、溝通能力等。平常工作的時候,也可以多找一些機會練習溫習。

五、好的工程師能夠提前反應風險,對專案做良好的預估

在一個讓工程師發揮的環境裡面,每個人都是專案的擁有者。
專案一定是有挑戰性的,因此我們要針對專案做風險控管,才能避開陷阱、準時交件。
因此在接案的時候,無論是多大多重要的案子,如果能夠提早發現風險並勇敢地提出,也就能越早準備需要的資源,最後也會有比較好的結果。
若是硬吃案子最後開天窗,那麼有可能也是離開公司的那一天。

六、只有對自己正在做的事情保有熱情,才能持續地精進自己的技術

在面試的時候,我發現自己還有很多能力不足的地方。老實說,一開始面試我也只是想找一份穩定一點、福利好一點、薪水高一點的工作。但是越面試到後面,我發現只有持續不斷的去做去挑戰,我的技術能力才有辦法到達下一個層次。

於是我開始回顧過往碰到的許多神人同事,他們是如何工作的?

我發現他們除了上班之外,下班也不斷在做一些自己的專案。與其說他們很認真,下班不斷的在學習,不如說他們是因為對他們做的事情非常有熱情,因此不斷地投入鑽研。唯有找到自己有熱情的事情並且去做,而技術就不自覺的在執行過程中累積提升了。



我今年面試的心得大致就這樣了,對於自己的能力有失而復得的機會是很寶貴的,我從中體會了很多,學習了很多,也感覺到自己的一次蛻變。今後無論是否是在如 Google 這樣的公司工作,也都希望自己能夠謹記上面的要點,希望未來自己能夠成為更合格的工程師。

2018年4月12日 星期四

使用 OpenSSL 建立自己的 CA

最近有要自建 Self-signed CA,發現了這個好的教學。
OpenSSL Certificate Authority

特別在網誌推薦。

2017年3月18日 星期六

修正 fabric.js 在 android 移動物件時頁面捲動

最近被回報 Fabric.js 在 Android 手機上,移動物件時會造成頁面滑動。
去看了一下 fabric 的原始碼,原來他是利用 e.preventDefault() 來避免頁面捲動的。
原始碼:http://fabricjs.com/docs/fabric.js.html#line10465

   /**
     * @private
     * @param {Event} e Event object fired on mousemove
     */
    _onMouseMove: function (e) {
      !this.allowTouchScrolling && e.preventDefault && e.preventDefault();
      this.__onMouseMove(e);
    },

然後就找到這篇,原來 Chrome 為了讓瀏覽器速度變快,所以新增了 passive 參數讓 touch event 不會在 calling stack 中藉由 preventDefault() 給取消掉。而且這個參數在 Chrome 56 以後預設為 true。

window.addEventListener("touchstart", func, {passive: true} );

請見:


那麼要怎麼樣避免捲動呢?Chrome 給的答案是增加 CSS touch-action 為 none

#canvas-parent {
 touch-action: none;
}

請見: https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

2017年3月8日 星期三

[連結] 台灣金流串接程式



https://www.facebook.com/recca.tsai/posts/10154973827344181


===== 以下節錄自上面的內文 =====

說明還沒弄完整所以可能看到程式會不知道如何使用
所有的程式都依附在
https://github.com/Payum/Payum
和omnipay是一樣的功能
原作者的比較
http://stackoverflow.com/....../difference-between......
所以要使用它必須得再去了解一下 payum 如何使用
基本的使用方式
https://github.com/....../Resources/docs/get-it-started.md
另外如果是開發 Laravel 的人門檻會比較低
可以真接使用
https://github.com/recca0120/laravel-payum
==============================================
另外如果想要參考程式碼的話
大家可以只閱讀專案內的src資料夾內的 Api 結尾的程式碼
==============================================
最後 PayumTW 的程式碼不一定會是最新的
所以的程式碼會在我個人的 github 內完成後
再 folk 到PayumTW內
所以最新的程式碼請到原作個人的 github
https://github.com/recca0120/payum-ezship
https://github.com/recca0120/payum-collect
https://github.com/recca0120/payum-ecpay
https://github.com/recca0120/payum-allpay
https://github.com/recca0120/payum-mypay

[連結] Javascript 教學: JavaScript Stack from Scratch

This is a straight-to-the-point guide to assembling a JavaScript stack. It requires some general programming knowledge, and JavaScript basics. It focuses on wiring tools together and giving you the simplest possible example for each tool. You can see this tutorial as a way to write your own boilerplate from scratch. Since the goal of this tutorial is to assemble various tools, I do not go into details about how these tools work individually. Refer to their documentation or find other tutorials if you want to acquire deeper knowledge in them.

https://github.com/verekia/js-stack-from-scratch

2017年2月7日 星期二

Let's Encrypt 工作原理

把官方文件 (https://letsencrypt.org/how-it-works/) 看了一下,發現沒有正確的中文原理說明,所以來把我了解的發佈一下。

先來簡單介紹 Let's Encrypt (LE) 實際使用情況,你會在你機器上面裝一個小程式 (agent) 幫你去 LE 做申請 / 更新憑證的動作。所以這篇文章主要是講解這個小程式做了什麼事情,不然的話其實下指令就可以搞定所有事情,你不會知道中間發生什麼事。

Step 1. 產生 authorized key


這個只有 agent 第一次使用的時候會需要進行。authorized key 可以當作代表 agent 去操作 LE 的 API Key。所以我們可以說這是 API Key 產生流程。



  1. Agent 產生一組新的 key pair
  2. 通知 LE 要註冊 example.com 這個 domain
  3. LE 傳回來說可以用 DNS 驗證或是檔案驗證,2 選 1。然後以下是驗證資料
    1. 在 8303 的位址放 ed98
    2. 請將這個亂數 9cf0b331 加密
  4. 這個範例,agent 選擇使用檔案驗證。
    1. 他在 https://example.com/8303 內容放 ed98
    2. 將 9cf0b331 用私鑰加密,然後將加密結果以及公鑰一起傳給 LE
  5. LE 驗證網址和亂數都正確,這把公鑰就變成 authorized key 可以拿來操作 example.com 的憑證


Step 2. 申請 / 更新 / 註銷憑證



  1. 當 agent 拿到 authorized key 以後,就可以發送 PKCS#10 Certificate Signing Request (CSR) 給 LE 取得憑證。
  2. 產生一組新的 key pair
  3. CSR 裡面包含了
    1. 私鑰的 signature
    2. 公鑰
  4. 把整個 CSR 用 authorized key 加密傳給 LE
  5. LE 驗證 authorized key 以及欲申請的 domain。如果驗證通過,解開取得 CSR 之後核發憑證傳回 agent
這樣就完成取得憑證的程序。

更新以及註銷憑證的流程都類似,就不再多做說明了。

2016年12月30日 星期五

建置網路服務案例 - 以繪禮物為例

今天晚上受邀至朋友舉辦的 Meetup 分享。

分享我如何將一個現成的 business idea (繪禮物 http://www.giftpaint.com) 轉化為網路服務,並且建置出來。

由於此 Meetup 與 coding 有關,所以會簡單帶過 Laravel framework。
希望能讓一些想學程式或者有點子卻不知道如何開始的人有幫助。