🚀 三句話總結

  1. 根據自身的職場經驗總結Senior的特色
  2. 根據自身的職場經驗總結Junior的新人缺點
  3. Junior學習有效解決問題,Senior學習有效預防問題

☘️ 為什麼我要了解

因為我自身沒有定義過或是思索過何謂Senior,所以這邊根據自身職場上觀察到我想成為的前輩特色,觀察這些特色是否可以複製以及該如何複製,定義出自己心中最完美的Senior,以此為目標激勵自己朝這方向努力。

🎨 改變了什麼

以前學的東西都是被塞入的,又或是因為工作安排必須吃下的知識,但是沒有理解為什麼需要這些,所以藉由這篇文章梳理下理解為什麼需要,以此定義出Junior和Senior的差別,並定義心中的Senior是長怎樣,讓自己努力成為我心中的那個前輩

✍️ 總結和心得

工程師的里程碑

之所以寫這篇文章,是因為想記錄在工作中遇到的工程師,不論是資深還是初階工程師的一些特質,不算是標準,Senior的定義100個人會有100種界定標準,但是我認為應該是大部分人都擁有的特質和一些技術點,也期許自己可以朝這些技能點和特質發展,所以才紀錄下。

如何成為Junior工程師?

基本上有基礎的程式撰寫能力,我都界定為Junior,而Junior也有低中高,我認為當Junior學完或實現以下的特質,基本上算是 準Senior工程師

學會如何問問題 - 提問的智慧:

在工程師的領域中,有幾本書或文章算是聖經級別的刊物,而如何學會問一個問題,也有聖經文章:提問的智慧。以下為網友整理的精華圖:

在Junion階段,一定會有很多問題不理解,而寫程式是一門複雜的學問,所以在「普通生活」中學會的問問題方式,並不適用於工程界,所以此文章算是教你「工程界」的問問題方式是什麼。

而如何問一個好的問題算是必學的課程,在我大學時候老師也曾經告誡過我們:

好的問題,不一定會有好的答案,但是爛的問題,絕對不會有好的答案。

Ex:

學會乾淨的程式碼 - Clean Code

試想一下,當你學會問一個好的問題時,你的主管看你的程式碼幫助你分析問題點時,他發現你的程式碼寫得很醜,浪費更多主管的時間,那麼會不會下次當你Call Help時,還會有人敢幫你嗎?

而避免把程式碼寫得很醜,也是一門學問,更至有一個人 Uncla bob 為此寫了一本書,此書被我們稱為程式的聖經:Clean Code

Junion寫的程式碼為了實現功能,可能寫得很醜,可能3行能解決的事,卻被寫成10行,但這不是最優先要解決的事,最優先的應該是你解決程式碼中的「怪味道」,光是好的命名這點就可以讓原本別人在閱讀你的Code時降低很多時間,先從最簡單的Clean Code學起,讓別人在閱讀你的程式碼時,就能很快理解,而對方則可以在很快時間內給予你「答案」,而下次在問對方問題時,對方就不會這麼抗拒,畢竟你的Code看起來沒那麼醜。

提升你的實作能力 - LeetCode

身為工程師,最基本的需求就是「解決問題」,而如何用程式碼去解決問題,是需要大量的練習累積經驗無法一步到位,但幸運的是可以透過LeetCode這網站練習,當你練習久了後,就會知道什麼需求可以用什麼方法解決,同時還能看看別人寫的Code,追求別人用3行,你卻要用10行的窘境。

熟悉Git、Commit、Flow、CI/CD

Git - Learn Git Branching

在寫大型專案時,我們常會需要使用一些工具幫助我們進行版本控制,最常見的軟體有:Git和SVN,而這邊推薦首選Git,版控程式是軟體界必學的東西,甚至有一說:

沒版控的軟體公司,不要去

而Git是Command Line的軟體,沒有GUI畫面讓你操作,所以有些人以此為基礎,開發了具有GUI的Git,像是Sourcetree,但是這邊強烈建議先學會 Command Line操作Git,之後才考慮用GUI的Git,記住

不會使用Command Line 的 Git 別叫自己是軟體工程師

這邊推薦練習網站:Learn Git Branching

Commit

如果熟悉Git一定知道什麼是Commit,而這邊要特別注意的是,有些東西不應該加入版控,請參考以下:

  1. 非必要修改的東西請不要加入版控,Ex: Mac系統會有 .ds_store,這很東西不是程式一部分,只是Mac作業系統的副產品
  2. 與個人有關的東西請勿加入版控,Ex: 密碼 or 快取File ..etc 這種機密的東西不應該上傳,因為倒版很麻煩
  3. 非必要的修改or檔案請勿加入版控,Ex: 如有套件管理器,就不需要把套件管理器下載的程式碼加入版控,別人如果要用自己用套件管理下載,不用你加入版控。

而知道什麼東西不該加入版控,那麼來談談 Commit的Message,之前說過寫程式是一門複雜學問,連問問題也要使用「工程界」的格式進行提問,那麼Commit的Message也有他的學問,必須具有鑑別度,不能如以下

1
2
3
4
5
6
7
8
9
10
11
commit 2e49cf213dc0
修改了一些東西

commit 89a7a978f50a
新增

commit a99ee47995d3
刪除

commit 7e57103a41f4
修改


上述這Message並不能了解你做什麼,所以推薦一個格式,初學者可以參考這個格式制定Commit Message,參考影片也有:

https://youtu.be/5DhWqmDP-3U

Git工作Flow

而學會版控功能後,你會發現業界在進行版控時候會有很多規則,最常見的規則是 Git Flow、GitHub Flow、GitLab Flow,這些Flow定義了很多Branch,以及每個Branch可以做什麼事情,遵守這些規則,能夠有效提升程式碼「版控品質」。

這邊推薦 Git Flow,因為他是最複雜的,其他Flow都是簡化 Git Flow,學會Git Flow 之後學其他Flow 難度就會降低。

PS: Git Flow 漸漸被拋棄,詳情可點此處如何看待 Git flow 发明人称其不适用于持续交付?
但他的概念還是可以參考,其地位有點像C語言,學會Git Flow對其他Flow會有更深了解,並且不是每家公司都採用這三種Flow,所以建議還是熟悉Git Flow

這邊推薦 GitHub Flow 文章:团队协作中的 Github flow 工作流程
這邊推薦 Git Flow 文章:一文弄懂 Gitflow、Github flow、Gitlab flow 的工作流

CI/CD

傳統的開發環境中,寫好一個程式後,我們會需要「編譯」,因為電腦只看得懂機器語言(哪怕是直譯式也會需要類似編譯的行為),之後把編譯好的程式交付給使用者,但是這樣的行為有太多變數,很容易造成交付的產品有問題,所以必須採用 CI/CD 方式進行集成和交付。

試想一下,如果沒有CI/CD,今天你要交付一個網頁程式,會經過很多步驟,如下:

  1. 編譯源碼
  2. 測試程式碼
  3. 壓縮圖片
  4. 程式碼混淆
  5. 合併資源
  6. 部屬資源
  7. 清除CDN快取
  8. 通知對方
    …etc

這些步驟全部依靠手動,而手動是最不可靠的,萬一今天忘記某個步驟,交付的品質就會有問題,甚至無法即時交付,並且還依靠環境

萬一在做這些步驟時,會使用到python,但是某一天你的另外一專案需要python 3.0 於是你升級了python,將會導致步驟3失敗了,因為步驟3需要python版本是2.0不是3.0版本。

所以需要CI/CD進行自動化+環境控管,來保持交付的品質,已達成「隨時可以交付」、「隨時可以集成」。

CI和CD的中文名稱分別是:持續集成(CI)、持續交付(CD),這兩個詞的持續,並不是「一直運行」的意思,而是「隨時可以」的意思,CI/CD可以透過管線(pipeline)和 runner 負責專案的 build、測試、部屬,而且這過程必須是自動化,以達到可以隨時集成和交付,而提供管道的廠商有非常多:GitHub、GitLab、Jenkins …etc

推薦網站:【狂神说】CICD到底是什么?十分钟理解DevOps

熟悉Markdown語法

Markdown是一種輕量級標記式語言。它允許人們使用易讀易寫的純文字格式編寫文件,然後轉換成有效的XHTML(或者HTML)文件。 from wiki

由於他可以有效地轉換為HTML文件,經常被我們撰寫成 Blog、說明文件(Github網站、Gitlab網站),本Blog就是全部使用Markdown語法撰寫,而在工程師領域最常被運用在說明文件,算是必學技能之一,堪比Git。

推薦網站:工程師的共筆網站

物件導向

物件導向算是一個基本功,任何你聽過的設計模式還是什麼TDD、DDD、MVC、SOLID …etc 架構全部都基於物件導向實作,物件導向是所有程式碼的基石,所以必須嫻熟於心

如何成為Senior工程師?

我認為的Senior除了「程式力」之外,就是「解決問題」的能力,而並非年齡或是年資,我常遇過年資比我老的但是在面對一些問題時提出的解決方案都非常蠢,因為他們總是不會繼續自主學習。永遠只會被動學習,寧願花時間在遊戲上或是漫畫上,虛度光陰。

而解決問題是一門學問,以下會提供一些思路提升解決問題的能力,而還有另一門學問也是資深工程師必須學會的,就是避免問題的誕生,所以以下也會提到一些技術讓 團隊 or 架構的可預期問題降到最低,這也是我從其他工程師或書上身上學到的。

SOLID

講個小故事,某一天小明到了一家從沒去過的越式餐廳吃飯,小明看著菜單非常猶豫因為她完全不知道這些菜是什麼,於是服務生推薦小明點這10道菜,然後把單子送到大廚那,大廚接到單子後開始做這10道菜。

瀑布流大廚

大廚 把10道菜做完後才允許服務生「一起上菜」,所以小明等了很久後一次10道菜一起上
小明在吃第一道菜時後,發現這餐廳的辣椒完全不會辣,於是請大廚把 2 ~ 9道菜重新加辣,於是大廚很賭爛的就開始重新加辣後就重新再上菜
小明在吃第二道菜時後,發現這餐廳的鹽巴特別少,於是請大廚把 3 ~ 9道菜重新調味,於是大廚很暴怒的就開始重新調味後就重新再上菜
小明在吃第三道菜時後,發現這餐廳的….. 於是大廚直接不做了

敏捷流大廚

大廚每做完一道菜就上一道菜,所以小明只等了10分鐘就吃到第一道菜了。
小明在吃第一道菜時候,發現這餐廳的辣椒完全不會辣,於是請大廚把 2 ~ 9道菜加辣,於是大廚剛炒到第二道菜,剛好聽到小明要加辣,於是就順手加辣了。
小明在吃第二道菜時候,發現這餐廳的鹽巴特別少,於是請大廚把 3 ~ 9道菜重口味一點,於是大廚剛炒到第三道菜,剛好聽到小明要重口味,於是順手就搞了。
小明在吃第三道菜時候,發現這餐廳的….. 於是大廚就幫小明做了

在上述Case我們知道瀑布流開發是講求,上一階段的輸出,會是下一階段的輸入,像是瀑布一樣,而這種開發方式在需求改變時必須付出嚴重的代價。

在明知小明是第一次吃越式餐廳,理應預期他很有可能會改變需求,所以應該選擇敏捷開發讓發生需求改變後將成本降到最低,而為了實現這需求在軟體業有個開發守則叫做SOLID。
遵守SOLID開發原則後,就可以實現「需求改變時,不需更改程式,只需透過新增程式來實現」。

而身為工程師,絕對避免不了「需求改變」,因為現實生活就是這麼白爛,所以學習如何降低需求改變後冒出來的問題,算是工程師必學課程之一。

推薦網站:https://youtu.be/e0UOuQ_lCUY

PS:敏捷開發不是用了這開發方式就能縮短工期,敏捷代表的是「彈性」的概念,敏捷的改變需求可以達到敏捷的實現改變,而敏捷開發有很多規則來實現「彈性」,SOLID守則只是其中之一,還有大量的會議和資訊交流達到資訊交流目的,而這些頻繁溝通也可以算是一種成本。
PS:乍看之下瀑布流是個糟糕的開發方式,其實並不然在大型以及需求非常確定和規格嚴謹的專案中,甚至達到跨部門跨公司級別,瀑布流往往能節省很多時間,因為跨公司之間不能像是敏捷開發的頻繁交流資訊,而此情況瀑布流說不定還會比敏捷流開發來的快。

Dokcer系列

在CI/CD中我們可以透過Pipeline實現自動化功能,但是「環境」問題還沒解決,而在以前都是新增一個虛擬機,又或是直接建置一個專門用於出版的電腦,但是近期有個「容器化」的產品問世

Docker可以讓開發者自行建立「出版環境」,不像是以前必須依靠運維組別提供VM或專用電腦,所以建立「環境」這個工作已經是軟體開發人員的工作,而不是DevOps的工作,而且還可以降低Product環境被玷汙的機率,防範問題於未來

參考影片:https://youtu.be/ArlpZev0K0o

PS:部分程式語言因為其特性,無法使用Docker進行環境控管,所以這東西不強求,但在業界可以用Docker的程式語言中,Docker非常非常重要

提高解決問題能力

基礎+領域廣度

基礎

基礎不好 = 不夠理解程式的運作「根本原理」,就會導致遇到問題時,無法找到問題的根源出在哪,而基礎好的工程師馬上就能知道,這樣的結果是什麼原因導致的,因此能很快速地解決問題。

這邊基礎並不是一直鑽研某個「程式語言」or「Framework」,而是了解工作原理,如果用樹木舉例的話,在一棵樹有一定的規模後,應該把「樹根」往下鑽研,而不是繼續在基礎上面堆疊,除非樹根已經夠深了。

Ex:
假設你是前端人員,你花了好幾年鑽研「React」、「JavaScript」,但是當主管要求提高使用者體驗時,你招式盡出 取消foreach、取消全域變數、var改用let、重構 …etc但仍被要求提高體驗,此時如果基礎好的工程師一定知道,使用者會經過的流程是什麼,Http封包->渲染->畫面。
而拿到前端資料的封包格式Http,該封包有很多可以優化的地方,像是 Http 3.0 壓縮 快取…etc,但是你技能點卻都用在React的各種工具上,用極大的代價優化極小的環節就有點可惜,殊不知還有很多地方要優化而且代價極低。

領域廣度

在上述Case中,很明顯工程師只在意如何把javaScript 和 React寫好,但其實在現實生活中我們只是一塊小螺絲,必須由一堆小螺絲拼裝成一個「成品」,像是前端寫好並不能直接讓使用者用到的,還需要透過「上線」這動作,而上線的FileServer如果沒優化,使用者體驗不是還一樣爛,所以理應把技能樹水平展開,而不是繼續點深某個技能樹。

更何況軟體行業一直在改變,你能確定你的程式語言和框架不會衰亡嗎?所以根本沒理由瘋狂點深技能樹而必須是水平展開

Ex:
一樣是前端工程師案例,但是你這次優化的不是前端,而是後端,像是CDN這類產品就可以提高使用者體驗,而這東西大部分都屬於Devops的工作,除此之外還有像是Nginx這種FileServe存在,除了控制Http 3.0 壓縮 快取…etc在Http協議上優化的行為,其實FileServer的CPU也可以優化,像是使用正確的Zero Copy技術 …etc等技術,還可以更進一步優化CPU達到響應提高進而提升使用者體驗,而這些很明顯不是「前端工程師」的領域,但代價極低,在Nginx這種FileServer上就只是一行程式碼 Off ON 就搞定。

團隊視角解決問題

以前我面試過一個人,能力還不錯還是國外留學生,雖然我們需要的是Junior成員,但是他算是難得可貴的人才,所以有考慮過要破例招募,想說如果我出一個加分題他有答對我就跟老闆提議這人

  • 我:可以聊聊你在上份工作遇到的最大挑戰是什麼嗎?
  • 他:我有次被老闆指派支援公司另一個剛建立的組別,進入後發現該組能力不高,寫的Code非常亂算是隕石開發到時候上線一定會出事,我猜他們主管非常忙可能沒仔細看Code,但是我是支援的人力不屬於該組,所以我就沒跟任何人講,就做好我的模塊給他們合併就好。
  • 我:那上線後真的出事了嗎?
  • 他:對!那時候老闆氣到把整組+我一起罵,後來我才知道他們主管真的忙到沒辦法仔細看Code,所以老闆連我這支援組的人也罵。
  • 我:那如果時間能重來,並且你擁有非常高的權力勘比主管,你會怎麼做?
  • 他:我…. 我想我應該會鼓起勇氣跟主管講「這些Code我仔細看過了,上線一定會出事,請主管幫忙處理下」

從上述的案例中,請問這回答給過嗎?
我的評價是「沒準備的答案」,因為他只以個人視角去解決問題,今天時間重來他有勇氣,但是如果是另外一個比較內向的人,時間重來他還是一樣內向,真以為對方也有你這勇氣嗎?
而如果是我,我會以團隊視角解決這問題,就是考量到這方案「是不是可以被複製」,以利杜絕類似問題出現,很明顯勇氣是不能被複製的,所以應該提出一套可複製的方案,也就是提出SOP去解決問題,到時候內向還是外向都必須遵守這SOP,而且這SOP是無法被繞過的。

SOP:使用Code Review機制,全部人的Code必須由主管核定,沒核定master一律不給merge,交付時只給master

  • 如果到時候要上線沒東西,直接跟老闆講全部都在等主管那邊核定。
  • 如果主管沒看Code就核定,就主管自己的事,要罵去罵他。
  • 如果主管核定有看Code,屆時應該就能提早發現問題。

所以想當然我最終沒有跟老闆提這個人,畢竟他像是一個大寶庫,但需要別人主動去打開,並且還需要別人知道他這些財寶的價值可以用在哪種情境,而這種人對團隊現在的需求和文化格格不入,所以就PASS了。


只有在使用團隊視角解決問題時,才能杜絕類似問題再次出現

獨立思考能力

假設PM跟你說一個需求,Junior可能就直接尻,但是在Senior可能就會了解這需求是為了解決什麼問題,然後可能提供另一種可能性。

Ex:
像是PM跟你說要優化網頁,如果是Junior可能就乖乖改架構,但是身為前端能做的事有一定範圍,所以Senior可能就會了解為什麼一定要我前端優化,原來是老闆說下載太久,使用者體驗不好,於是你就提出或許可以從DevOps開始優化 ..etc

並且從上述範例中,Senior應該能拆解多個解決方案,像是:

  • Step 1 優化Http
  • Step 2 優化CPU
  • Step 3 新增CDN節點,並同時告知會需要增加的金額支出
  • Step 4 修改前端架構,並同時告知會延後幾個月上線並且還需要QA部門支援2個月 …etc 風險告知

然後讓PM選擇,需要優化到什麼地步,之後再進行修改。

缺少獨立思考的工程師,很可能變殺票手,功能來一個做一個,卻沒有去想每個功能要解決的問題是什麼。

所以具備獨立思考後,往往能給出更多優秀解決方案,降低問題的難度,而非「殺票手」、「碼農」

總結

上述的一些條件都是我自己從認識的工程師和我期望成為的工程師身上發現的,他們的特質是什麼,我工作3年後是否能成為這樣的人,而全部不外乎就是「解決問題」,只是Junior專注的領域是在自身,而Senior可能就具有整體性和團隊性的手段讓「問題發生率降低」,以此達到「解決問題」的需求。