[工作筆記] 退出 Azure DevOps 的組織

前情提要

Azure DevOps 是一個由微軟開發的服務,提供開發團隊協作和快速交付軟體的解決方案。
它包含了版控、工作追蹤、持續整合/持續部署 (CI/CD) 等功能。
其中,我將重點使用其 Board 功能來進行工作項目的管理和追蹤。
然而,有一天我發現自己被不知名的人邀請進了一個 Azure DevOps 的 Organizations,
所以我開始尋找如何自行退出的方法。

解法

首先進入 dev.azure.com,點擊 user setting icon (這在畫面的右上角,是一個人的右下角有齒輪的圖案)。
點擊 Profile 進到以下頁面,可以看到提示如下:

1
2
You are currently subscribed to other communication regarding Visual Studio and/or Visual Studio Subscriptions.   
Please visit the complete Azure DevOps Profile Page to change those settings.

點擊連結到 Azure DevOps Profile Page

這裡就可以看到你的 Organization 並選擇離開

誤區

my account 也有 Organization 但是不可以隨意離開。
簡單來說,在微軟的 my account 中,Organizations 代表的是你所屬於的 Azure Active Directory (Azure AD) 組織。
這些組織可能是你的工作場所、學校或其他團體,他們使用 Azure AD 來管理員工或成員的身份和訪問權限。
這裡的組織並不等同於 Azure DevOps 中的 Organizations,並且不能隨意離開。

參考

(fin)

[踩雷筆記] 解決 GitHub 帳戶在 VS Code 中的管理問題

前情提要

當我使用 VS Code 時,我需要同時存取多個 GitHub 帳戶,
自已的 Github - 主要存取 VS Code 一些地端的設定值
公司的 Github - 有免費的 Copilot 這很好用。
兩個都我需要,我要作出大人的選擇。

實務上的困境

我可以同時登入兩組帳戶,但是無法達到我要的需求

登入兩組帳戶的方法

  1. 確保安裝了 Github Copilot 與 Github Pull Request and Issues 套件
  2. 如果有其它 Github 帳號已經在登入狀態的,都先登出,並重啟 VS Code
  3. 準備好兩個瀏覽器,分別登入公司與自已的 Github Account
  4. 點擊在左下的頭像 Icon (沒有頭像 Icon 的話在左側欄任一處點右鍵,將帳戶打勾)
  5. 選擇”使用 Github 登入,以使用 Github Copilot”
  6. 選擇登入公司帳戶的瀏覽器,此時會提示要開啟 VS Code,選擇開啟
  7. 回到 VS Code,重複第 4 步
  8. 選擇”使用 Github 登入,以使用 Github 提取要求和問題”
  9. 選擇登入自已帳戶的瀏覽器,此時會提示要開啟 VS Code,選擇開啟

如果你的預設瀏覽器是登入公司 Github 的帳號,就複製網址,貼到登入自已的 Github 帳號瀏覽器,反之亦然。
但是這個作法,實際上沒有什麼幫助,備份與同步設定與 Copilot 會共用同一組帳號
我並不需要 Github Pull Request and Issues 相關功能。

手動組態同步

早期 VSCode 有人寫了組態同步的擴充套件,但是目前內建在 VSCode 內部後不再維護了。
但是我需要的就是自已長期以來的使用的設定,所以可以先登入自已的帳號。
再登出後,登入公司帳號。缺點是需要手動處理。

安裝第二個 VSCode

這個方法也有很多不同的實作方式。
簡單說一個官方直接支援的方式。 VS Code Insider
這算是一個搶先試用版的 VSCode,也有其對應的風險。
但是你就可以在系統上安裝兩個 VSCode,並登入不同的帳戶。

花錢為自已的帳戶買 Copilot

這或許才是最大人的解法。
我們要的是”同步組態設定”與”Copilot”使用權。
根帳號本身其實沒有什麼關係。
資本主義大好,但就失去了一些童趣了。

參考

-https://tutorials.tinkink.net/zh-hant/vscode/copilot-usage-and-shortcut.html
-https://code.visualstudio.com/docs/?dv=osx&build=insiders

(fin)

[工作筆記] 問題,不重要不緊急,就永遠不作了嗎?

問題

最近我在公司引導大家一些敏捷方法的實作,
在這過程中討論了 PBI 排序的原則,價值和風險。
那麼問題來了,這樣有一些事情很小,但價值也不高,又沒有什麼風險,那不就永遠作不到了嗎??

回答的心路歷程

這是一個很好的提問,我反思一下常見的四象限模型,即「重要緊急矩陣」中,
我可以把重要對應到價值,緊急對應到風險,然後 A、B、C、D 四象限,
我們知道要先作 A、B 這樣我們 C、D 的事永遠都不作了嗎 ?

我分享一個故事如下:

有一位教授,他拿著大石頭、小石子、沙子和一個玻璃罐,
先放入大石頭,問學生滿了沒? 再來是小石子,再問學生滿了沒?
最後再倒入沙子,問學生滿了沒? 結果還是沒滿,還可以再放入水

你學到了什麼?
—常見的說法是要先處理重要的事情,順序很關鍵。

我們可以有一些反思,首先當然是重要的事先作(大石頭先放),
再來,你總是還有辦法找到一些空隙。
—時間就像乳溝一樣擠一擠就有了。

這是我當時的回答,
—如果你能守住重要的事,剩下的小事,你是有辦法找到空隙塞進去的。

回答後的反思

我要怎麼知道可不可以塞進去??
這就是透明度的重要性,在 Scrum 或看板方法都有提出。
而我們可以在 Scrum 的每日例會使用看板方法(現行主流的作法),
加上每次迭代所行成的 TimeBox,正好可以對應這個故事中玻璃罐。
有趣的是,我沒想過如果玻璃罐不是透明的話,教授的問題還有意義嗎 ?
正是透過每日例會與看板方法,讓我們可以透明的掌握進度(瓶子剩多少空間/你剩多少時間),
所以你可以判斷是不是可以再塞下石頭或沙、水。

TimeBox

它是一種任務和時間管理的方法,將任務分成小塊,每塊都有一個簡短而固定的時間,以確保高優先級的任務能按時完成。

看板方法

它包括將工作可視化、限制同時進行的工作(WIP)、管理流程、明確陳述流程政策、實施回饋循環以及以協作方式改善。
這些原則和工具都教導我們要優先處理最重要的事情,這是成功的關鍵。

看板方法我還會聯想到限制理論(Toc),但就不過度展開了。

(fin)

[生活筆記] 潛水日誌

20230916

一潛(導潛)

1
2
3
4
5
地區: 東北角美灩山
入水時間: 14:08 |潛水時間:41 |出水時間: 14:49
能見度: 10m |平均水深: 4.8m |最大深度: 10.5m |水溫: 26.4
起始壓力: 200 |結束壓力: 70 |SCR: 3.17 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

時隔半年再次下水
第一潜稍嫌緊張
首次體驗美灩山
無浪無流,嘗試三角、四角導潜
浮力控制不當,未注意深度
未能找到原位

二潛(放呆)

1
2
3
4
5
地區: 東北角美灩山
入水時間: 16:11 |潛水時間: 57 |出水時間: 17:08
能見度:8m |平均水深:5.1m |最大深度:11.5m |水溫: 26.8
起始壓力:200 |結束壓力:100 |SCR: 1.75 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

第二潛是與小夥伴伴潛屬於放呆行程,比較沒有那麼緊張,
算是複習了一下背滾式與跨步式入水,
不過小夥伴的問題有點多,一個是有人被海膽刺到膝蓋,
另兩個小夥伴二級頭跟 BCD 卡住而不自覺,直到教練去救援,
回程有看到黑色相間類似蛇的生物

三潛(導潛)

1
2
3
4
5
地區: 東北角美灩山
入水時間: 17:30 |潛水時間:38 |出水時間: 18:08
能見度: 5m |平均水深: 7.1m |最大深度:11.8m |水溫: 26.5
起始壓力:200 |結束壓力:100 |SCR: 2.63 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

這次練習導潛主要是跟著教練,並繪製海圖,
方向感本來就不好的我,加上水深這個緯度,
其實是個蠻大挑戰,我只知道大概的路徑是一個狹長的 U Turn,
試著認地形,入水後右側是壁,左側是斜坡,前進20米左右會出現沙地,
這裡教練會稍作轉向,然後出現一個更深的地方,大約有到 11 米
之後我就有些迷航了,可能是在附近作了一個四角或三角的繞圈
海圖繪製比例失恆,所幸未來還有好幾次的潛水機會

四潛 (夜潛)

1
2
3
4
5
地區: 東北角美灩山
入水時間: 19:03 |潛水時間: 53 |出水時間: 19:56
能見度: 12m |平均水深: 5m |最大深度: 11.9m |水溫: 26.3
起始壓力:200 |結束壓力:50 |SCR: 2.83 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

最擔心的夜潛反而是最美的一潛,作好安全工作後再下水其實不會有什麼心理壓力,
除了教練外還有一個陪潛的前輩,看到很多生物但是叫不出名字,
過程中有點小意外,前輩以伏地魔之姿突然從下方出現,害我撞向礁石同時被海膽刺了,
所幸以前有被刺過的經驗,知道不會有生命危險,所以我沒有驚慌,但上岸後手上還是多了 4 個黑點,

20230917

一潛(高氧)

1
2
3
4
5
地區: 東北角龍洞四號
入水時間: 9:51 |潛水時間:35 |出水時間: 10:26
能見度: 10m |平均水深:16.2m |最大深度:25.5 |水溫: 25.6
起始壓力:200 |結束壓力:100 |SCR: 2.85 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

突破個人最深的記錄,沒有什麼感覺,下水點的魚群很多,
但深一點的地方就沒有魚了,看到很多三點蟹的空殼,
聽說是漁船上拋下來的,另外撿了一些垃圾

二潛(高氧)

1
2
3
4
5
地區: 東北角龍洞四號
入水時間: 11:07 |潛水時間: 45 |出水時間: 11:52
能見度: 10m |平均水深: 11.8 |最大深度: 25.8 |水溫: 25.7
起始壓力: 200 |結束壓力: 100 |SCR: 2.22 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

再次突破個人最深的記錄到 25.8,浮力的控制還是很差,到深處會揚沙,
突中遇到一團揚沙大隊,簡直是我,
回程時有看到小丑魚

三潛(放呆)

1
2
3
4
5
地區: 東北角美灩山
入水時間: 14:47 |潛水時間: 37 |出水時間: 15:24
能見度: 8m |平均水深: 5.1 |最大深度: 8.6 |水溫: 26.1
起始壓力: 200 |結束壓力: 100 |SCR: 2.70 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

看小夥伴考試,感覺大家很慌張,不過也都通過了,沒有到 11 米處的沙地
覺得有遇到流,但是教練是很清鬆就踢過去了,有種提早回程的感覺

四潛 (夜潛)

1
2
3
4
5
地區: 東北角美灩山
入水時間: 18:54 |潛水時間: 51 |出水時間: 19:45
能見度: 12m |平均水深: 5.1 |最大深度: 11.2 |水溫: 25.9
起始壓力: 200 |結束壓力: 100 |SCR: 1.96 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

看到最多生物的一次,饅頭海星、海蛞蝓跟他的卵、海鰻、河豚、龍蝦
獅子魚、還有鼻子長長的不知什麼魚、黑的紅的、睡覺的、龍蝦等…
微型生物也很多,但是我看不太到,要很靠近峭壁,所以中心浮力控制要很重要。

20230918

一潛(打浮力帶)

1
2
3
4
5
地區: 東北角龍洞四號
入水時間: 09:04 |潛水時間: 53 |出水時間: 09:57
能見度: 8m |平均水深: 6.3 |最大深度: 8.4 |水溫: 25.2
起始壓力: 200 |結束壓力: 50 |SCR: 3.65 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

第一次打差點拉不住,後面就好多了,
不過看了紀錄,發現深度起伏很大,
中心浮力沒有控制好,應該至少有打了10次以上

二潛(打浮力帶)

1
2
3
4
5
地區: 東北角龍洞四號
入水時間: 10:18 |潛水時間: 40 |出水時間: 10:58
能見度: 8m |平均水深: 6.4 |最大深度: 12.2 |水溫: 24.9
起始壓力: 200 |結束壓力: 50 |SCR: 3.75 Bar/min
天氣: 晴 |浪況: 無浪 |目的: 訓練 |方式: 岸潛

覺得很難控制趴姿,看了錄影,其實還不差,就是一直會停腳,
中心浮力控制不好外,還有旋轉的問題,所以一直忍不住踢腳,
不僅耗氣,看起來也很好笑,打氣只要二級頭向上就好,不用按壓

(fin)

[工作筆記] 採蘋果

前情提要

公司有三台 Macbook pro 2017 年款,普遍都有電池的問題,
為此研究了一下在台灣舊機換新機的策略。

折抵

選擇好你的新機,在「加入購物袋」前,找到「加入換購方案」,依指示輸入郵遞區號、選擇製造商 Apple 後
輸入序號後選擇相關的硬體設備。
就會出現一個換購的金額,再繼續完成你的購物袋即可。

企業商店

企業採購的話可以有累積的金額優惠,如果滿足到累積的金額(一年內 5000 美金),就可以以優惠的方式來做訂購,
需要打電話(見文末參考),使用統編建立企業商店。
其它方式與折抵一樣。
訂單成立後可以刷卡或是匯款,刷卡可以立即看到訂單進度,
而匯款後需要再打電話(0800-020-021)確定訂單進度。

折抵的部份會再出貨後 14 天來回收舊機器,應該有足夠的時間轉移資料。

參考

(fin)

[工作筆記] 軟體工程的檢傷分類

前情提要

回想一下你手頭上的工作,你如何決定你的工作順序?
常見的有緊急/重要四象限法。
另外在一些方法論上,利如 Scrum 交由特定角色排序,
而急診室的檢傷分類如下。

1
2
3
4
5
6
7
8
9
第一級(復甦急救,立即處理-病況危急生命或肢體,需立即處理。如:心跳、呼吸停止、肢體及嘴唇發青、發紫,體溫高於41度或低於32度,無意識或意識混亂、持續抽搐且無意識。

  第二級(危急,可能等候時間10分鐘)-潛在性危及生命、肢體及器官功能,需快速控制與處理。如:急性意識狀態改變、持續胸悶、胸痛且冒冷汗、低血糖(<40mg/dl)、外傷造成之大量出血,頭頸軀幹骨盆部位血流不止、高處墜落、車禍(乘客被拋出車外)、頭部撞擊後曾失去意識等。

  第三級(緊急,可能等候時間30分鐘)-病況可能持續惡化,需急診處置;病人可能伴隨明顯不適症狀,影響日常生活。如:無法控制的腹瀉或嘔吐、外傷後肢體腫脹變形疑似骨折/脫臼、高血壓(收縮壓>200mmHg或舒張壓>110mmHg)且沒有任何症狀等。

  第四級(次緊急,可能等候時間60分鐘)-病況可能為慢性病及急性發作,或某些疾病之合併症相關,需在1至2小時做處置避免惡化。如:局部蜂窩性組織炎、急性咳嗽但沒有發燒、發燒但無其他不適、反覆性疼痛或暈眩等。

  第五級(非緊急,可能等候時間120分鐘)-病況非緊急,需做鑑別性診斷或轉介門診。如:慢性噁心、嘔吐或打嗝、輕微擦傷,瘀青,軟組織受傷、螫傷或咬傷,但無發燒或疼痛不適、輕微腹瀉,無脫水現象等。

我們可以參考。以等級與具體案例作為分析。

個人的經驗是以 3+1 個維度分析,
主要為發生風險、發生頻率、影響範圍和可否重現。

判斷流程

  1. 是否為線上問題:線上問題較可能產生價值的耗損
  2. 發生頻率:高頻的問題如果不處理會帶來大量干擾、下一階段可能會麻痺,甚至讓真正的問題從眼前跑走
  3. 影響範圍:誰會感到痛苦?老闆?客戶?PM ? RD ? 營運?怎麼作可以停止或減輕他們的痛苦。
  4. 風險評估:不作會怎麼樣?作了會怎麼樣?

定義

x 的維度是風險的高低,風險高者需安排修正,風險低小者可以再觀察
y 的維度是影響範圍的大小,範圍大者需優先停損縮小範圍,範圍小者就安排修正
z 的維度是發生的頻率,高頻者需優先停損止傷,低頻者需要觀察,如果發生一次就會形成持續性或永久性的傷害即為高頻
加上可否重現分析如下:

可重現

高風險/高範圍的情況下,頻率已經不重要,重要的不能讓發生 0 次的事情發生 1次,
一但發生只能砍掉重練,具體例子如廣達被勒索病毒攻擊

維度一:高風險/高範圍/高頻率:終止營業、暫停營運的等級
維度二:高風險/高範圍/低頻率:終止營業、暫停營運的等級

應急辦法,止血: 先限縮風險、範圍、頻率至少其中之一。

低風險/高範圍的情況,即使發生了仍有轉還的空間,高頻時處理的重點在縮小範圍與暫時的降噪
一但修正,理應停止降噪的設定,低頻時安排修正計劃即可

維度三:低風險/高範圍/高頻率:部份功能停止運作。應暫時的降噪(暫時停止通止,避免有其它警告被淹沒),安排修正計劃
維度四:低風險/高範圍/低頻率:部份功能停止運作。儘速安排修正計劃。

在高風險的情況,如果有小範圍的異常,都應立即處理,重點在於能不能根除問題,或是緩解發生頻次

維度五:高風險/低範圍/高頻率:根除問題,或是緩解發生頻次
維度六:高風險/低範圍/低頻率:根除問題,或是緩解發生頻次

在低風險/低範圍的情況下,要小心避免讓人習慣這類型的錯誤(麻痺),或是產生過多雜訊影響判斷。
偶一為之但是知道原因的話可以不處理

維度七:低風險/低範圍/高頻率:降噪或是設定提示水位
維度八:低風險/低範圍/低頻率:不處理

不可重現

不知道自已不知道是最可怕的,如果發生時是高風險/高範圍大多也沒救了,
就死前能不能有所收獲

維度一:高風險/高範圍/高頻率:終止營業、暫停營運的等級
維度二:高風險/高範圍/低頻率:終止營業、暫停營運的等級

低風險/高範圍的情況,即使發生了仍有轉還的空間,高頻時處理的重點在縮小範圍與暫時的降噪
一但修正,理應停止降噪的設定,低頻時安排修正計劃即可

維度三:低風險/高範圍/高頻率:暫時的降噪(暫時停止通止,避免有其它告警被淹沒),查明原因,安排修正計劃
維度四:低風險/高範圍/低頻率:查明原因,安排修正計劃

在高風險的情況,如果有小範圍的異常,都應立即處理,重點會在能不能根除問題,或是緩解發生頻次

維度五:高風險/低範圍/高頻率:查明原因,根除問題,或是緩解發生頻次
維度六:高風險/低範圍/低頻率:查明原因,根除問題,或是緩解發生頻次

在低風險/低範圍的情況下,要小心避免讓人習慣這類型的錯誤(麻痺),或是產生過多雜訊影響判斷。
偶一為之但是不知道原因的話要特別小心標記,這很可能是別處發生問題的潛兆

維度七:低風險/低範圍/高頻率:查明原因,降噪或是設定提示水位
維度八:低風險/低範圍/低頻率:查明原因

小結

幾個重點,預防勝於治療,
真的發生時儘可能讓風險降低、範圍縮小、頻率減少,
十萬火急時可以先用暫解去處理,減少傷害。
但是回到正常流程就是要找出根本原因,並用正確的方式治療。

我作了個表以供參考

情境 風險 範圍 頻率 行動
可重現情況(Reproducible)
1 立即處理,確保不再發生。
2 立即處理,確保不再發生。
3 暫時降噪並制定修正計劃。
4 制定修正計劃。
5 根除問題或減少頻率。
6 根除問題或減少頻率。
7 降噪或設定提示水位。
8 不處理。
不可重現情況(Non-Reproducible)
9 查明原因,可能無法挽救。
10 查明原因,可能無法挽救。
11 暫時降噪,查明原因,制定修正計劃。
12 查明原因,制定修正計劃。
13 查明原因,根除問題或減少頻率。
14 查明原因,根除問題或減少頻率。
15 查明原因,降噪或設定提示水位。
16 查明原因,特別小心標記可能是其他問題的潛在預兆。

(fin)

[生活筆記] 一些程式轉職相關的問答

前情提要

一直有在作程式相關的助教、導師相關的工作,有些學生的問題很棒,也是我的盲點。
沒有心思好好整理,至少記錄下來,給未來的自已一絲反芻機會。

問題

Express.js在業界的實用性如何? 優點和缺點是什麼? 有需要再學習第二種語言/框架嗎?,建議的選擇是?

算常見的 Nodejs 的 Web 框架,優點就是夠主流,資源好找。
缺點就太簡單。

語言/框架可以多學,自已判斷。不知道就先跟著公司或社群走。

參考文章10 Best Nodejs Frameworks for App Development in 2023

Google 關鍵字: Nodejs Web Framework 2023

思路:不論什麼樣的程式語言,我的本質是 Web 開發,不同的語言與框架有不同的場景,總不缺乏新的挑戰者,
可以觀望、研究、測試、入坑,沒有一定的正確的答案,能夠快速作出判斷與取捨是重要的,但這需要經驗。

2. 如果想要在自有主機上部署Express.js,比較適合搭配的web伺服器軟體是?

這裡的”web伺服器軟體”是指什麼? Nginx 或 Apache 嗎?
選擇適合的場景就好。目前業界主流是 Nginx,思路參考第一題

3. 樣板引擎在業界的使用度高嗎? 有使用的話會是在什麼情況呢? 有比較主流的選擇嗎? 還是大部分被前端框架取代了?

註:學生這裡指的是 express + handlebars 的開發方式
大部份都前後分離端了,維護舊案可以能會碰到。
樣板引擎主要會發生在 Web Form 這類的舊專案,主流可能是 Php 或 Asp.Net 的某些專案。
或是在 2010 很主流的 MVC 開發方式,這段時間各家語言也有自已的解決方案。  

思路:理解為什麼會有前後端分離的發生,某些情況的小專案,樣板引擎的開發方式會比前後端分離有效率。

4. AC一個練習教案的規模,大概有幾十個到百個檔案要維護。實際業界專案的檔案數量應該更多,檔案間的關係複雜,維護人員要如何弄得清楚呢? 有沒有什麼比較好的管理工具?

檔案是指程式碼的部份嗎?  
學會架構分層,基本就三層式架構、MVC、MVVM、MVP、MV* 等,
使用 OOP 語言的話可能也要依 Pattern 分層,現在比較流行 DDD、六角架構等…
再大一點會是微服務的情況。

思路:想一下檔案間的關係複雜,那你會怎麼作?基本上就是分門別類,
好的分類可以讓錯誤發生時可以快速定位、實作功能時可以職責分離。
舉個生活化的例子,就是像是整理你的房間。

5. 在前後端的協作中,如何決定一項功能應由前端製作或後端製作? 舉例來說,要加上分頁的功能,本質上只是資料的整理重排,這樣的功能應該由前端或後端做呢?

Case by Case, 以我來說跟畫面有關的歸前端、其它歸後端。  
分頁通常會由後端處理、但是有些情況前端也要處理。
Ex: 避免太頻繁的 request 到 Server,一次性回傳大量資料,由前端自行製作分頁。

思路:還是以需求為依歸、預設一個簡單的原則。團隊合作的話,最理想是團隊共識,次之由 Leader 決定,不要發生由某端強勢主導的情況。
舉例說明,欄位檢查,前後端都要作,前端的目的是引導使用者正確操作,後端是真正的防護。

6. 求職網站中許多職缺要求會其他程式語言如: C# or PHP,會建議再去學其他語言嗎? 有推薦的學習平台或課程?

我會想學 TypeScript、Python。
程式在 web 開發上有類似的作法,更多領域其實也需要程式人才,
例如:手機 App 開發、IoT 開發、AI 工程師等…
建議找一個自已可以生存的領域,專研打磨裡面的技術會建議
社群活動可以用來搜集關鍵字,
Udemy 的課程很便宜,YT 也有很多大神的頻道可以學習。

思路:唯一的問題是學不完,怎麼整合應用變現,這個時候就不只是求職了,公司只是某一些技術棧整合的結果,
當你學的更多時,或許可以有別的出路?

7. 建議如何練習LeetCode? 才不會好像只是背答案,而不是懂背後的邏輯。有聽說 NeetCode 平台不錯用?不知道助教是否推薦

就是多刷多累績經驗,看題目、看答案。
兩個重點,把題目看懂、把答案看懂,試著把自已的思路轉化成程式
平台很多:NeetCodeLeetcodeHackerrank

思路:助教用 TDD 刷 LeetCode,實務上蠻常遇到面試造火箭、入職擰螺絲的狀態,
但是仍然不知道要學什麼或作什麼樣的 Side Project 時,刷題是一個好的選擇。

8. Junior工程師除了準備作品集,LeetCode 與程式語言的觀念外,通常面試還會考什麼嗎?

我主要會問架構與流程題,如果能把自已開發的架構與流程說明清楚,就可以同時觀察到技術能力與溝通能力。

思路:常常去面試就會知道現在業界常問什麼了。

10. 職場上在開發專案時,後端工程師的實作範圍會是全部一手包辦還是還會細分工作?或者工作架構會是怎麼分配的?

看公司,建議去有分工的公司,一手包辦很可能會很雷,學到的可能也是一堆大泥球的作法

12. 除了現有AC課程之外,助教建議Junior後端工程師還需要提升哪方面的技術

掌握好版控與協作流程/自動化與容器化技術/實用精實的開發實踐

  • Git、Docker、AWS/Azure/GCP、K8S
  • TDD (BDD、ATDD)/ Refactoring /Design Pattern

13. 目前軟體業有受到景氣影響而減少職缺數嗎或停止招聘

國外有一波大裁員,有影響到,但台灣本身還好
至少我還好

14. 請問助教平常寫程式會如何結合AI加速開發,有建議相關課程嗎

Github Copilot+TDD

15. 網站若有多國語言版本,技術上要怎麼實作呢?

關鍵字i18n

1
2
3
4
5
6
7
8
{
"tw":{
"login":"登入"
},
"en":{
"login":"Login"
}
}

16. 手機版和電腦版的網站要怎麼分割呢?

我知道的兩種作法

結語

部份題目涉及專案內容,所以排除掉。
但是有關從無到有開發一個專案,或是與人合作開發專案,是整個職涯中會很常發生的事。
現在不作,以後也會遇到,可以儘量去嚐試。

(fin)

[實作筆記] Websocket 初體驗

前情提要

tl;dr, websocket 至少是一個 10 年以上的技術了,但是筆者一直沒有機會實作它。
大部份的時候是應用場景不符合,或是簡單 Long Polling 已經足夠,甚至就算用 Polling 這個方法也無法把 Server 打掛。
另一個情況是團隊已經很成熟,有專門負責的部門在統一處理這塊邏輯,
而通常這塊邏輯會與主要的核心功能作切分,所以我也沒有機會接觸到。
這次難得有個小型的專案,有機會實作,故稍作記錄一下。

需求

使用者會停留在某些頁面等待系統的資料狀態更新,大約每 10 秒要作一次 Polling,
而平均資料狀態更新需要 3~10 分鐘不等。在這個情況下要改用 websocket,
(註:我不認為這是一個很好的應用場景,但是牽扯更多未揭露的調整故不展開討論,
EX:Heartbeat、Keep-Alive 等等…機制也未討論到)

WebSocket Server 實作

使用的技術:Typescript + Express + ServerSocket

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// import library
import express, { Request, Response } from "express";
import { Server as ServerSocket } from "ws"; // 引用 Server

if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
// form env 指定一個 port
const PORT: number = Number(process.env.WS_PORT);
// 設定斷開時間
const CT: number = 1000 * Number(process.env.CONNECTION_TIMEOUT);
const app = express();
const server = app.listen(PORT, () =>
console.log(
`[Server] Listening on http://localhost:${PORT} , timeout is ${CT} ms`
)
);
const wsServer = new ServerSocket({ server });

// Connection opened
wsServer.on("connection", (ws: WebSocket, req: Request) => {
// Connection 建立時發生的邏輯

// Listen for messages from client
ws.on("message", (data: string) => {
try {
// 發送 Message 時發生的邏輯
} catch (error) {
console.error("Invalid JSON format: ", data);
}
// Get clients who has connected
const clients = wsServer.clients;
// Use loop for sending messages to each client
clients.forEach((client) => {
client.send(JSON.stringify(docStatus));
});
});
// 設定 ping 時間間隔,用來讓連線太久的 Client 斷開
const interval = setInterval(() => {
if (ws.alive) {
ws.terminate();
clearInterval(interval);
return;
}

ws.alive = false;
ws.ping("", false, () => {
console.log("[Timeout]", ws.key);
});
}, CT); // 30 秒

// Connection closed
ws.on("close", () => {
// Connection 關閉時發生的邏輯
console.log("[Close connected]", ws.key);
});
});

// 新增一個路由處理器
app.get("/", (req: Request, res: Response) => {
// health and version check
res.send(`WebSocket Running Version ${process.env.WS_VERSION}`);
});

前端實作,收送雙向

使用的技術:JavaScript
以下內容大多參考於神 Q 超人的文章,
作為參考用,實務上會搭配使用的前端框架作修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var ws;

// 監聽 click 事件
document.querySelector("#connect")?.addEventListener("click", (e) => {
console.log("[click connect]");
connect();
});

document.querySelector("#disconnect")?.addEventListener("click", (e) => {
console.log("[click disconnect]");
disconnect();
});

document.querySelector("#sendBtn")?.addEventListener("click", (e) => {
const msg = document.querySelector("#sendMsg");
sendMessage(msg?.value);
});

function connect() {
// Create WebSocket connection
ws = new WebSocket("wss://localhost:8088");
// 在開啟連線時執行
ws.onopen = () => {
// Listen for messages from Server
ws.onmessage = (event) => {
// 收到訊息的 Logic
console.log(`[Message from server]:\n %c${event.data}`, "color: yellow");
};
};
}

function disconnect() {
ws.close();
// 在關閉連線時執行
ws.onclose = () => console.log("[close connection]");
}

// 監聽 click 事件
document.querySelector("#sendBtn")?.addEventListener("click", (e) => {
const msg = document.querySelector("#sendMsg");
sendMessage(msg?.value);
});

// Listen for messages from Server
function sendMessage(msg) {
// Send messages to Server
ws.send(msg);
console.log("[send message]", msg);
}

後端實作,只送不收

使用技術: php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
include "./vendor/autoload.php";

$client = new WebSocket\Client("wss://localhost:8088");

$message = json_encode(array(
"your_property" => "Your Data",
"complex_property" => array(
"no" => 1,
"status" => "Hello word"
)
));

$client->text($message);
$client->close();
?>

後記

實務上在股票看盤即時更新、多人聊天室、多人網頁遊戲上或許十分有用,
但實際上在這此的案例上就有些大材小用了,先當作學習了。
在查找資料的過程有一段話很受用,
我稍作總結如下:
當討論到 WebSocket 時,不應用 Http 的標準去審視它,
更應該關注這些 Connection 會持續連接多久? Connection 之間交互的行為是什麼?  
是運算密集的行為還是讀寫密集的行為?…等等,才是你決策的關鍵。

參考

(fin)

[踩雷筆記] Gitlab CI 執行 Command 結果與本地環境不一致

前情提要

我們建立 CI 的一個目標是讓繁鎖的工作流程自動化,
而自動化的前題是標準化,而自動化的未來是可以規模化。
每一次的自動化,就像是在為工作流程添加柴火,讓未來的的每一步可以走的更穩更快。

問題

一直以來我認為只要在本機環境上可以執行的指令(command),就一定可以在 CI 中執行,
沒想到這次不一樣。

下面這個語法是我 CI 流程的一部份,主要的目的是要重啟 pm2 的服務

1
pm2 restart app.js

這段在 Gitlab-runner CI 的寫法如下,主要的目的就在 Gitlab-runner 中將指令送到指定的機器$VM

1
- ssh -i ~/.ssh/id_rsa gitlab-runner@$VM 'pm2 restart app.j'

不過我會收到錯誤訊息

1
bash: pm2: command not found

當我直接在$VM執行時,確又不會有錯誤

根本原因

原來在 Unix-like 系統中,shell 分為 Interactive Shell(互動式)和 Non-Interactive Shell(非互動式)。
兩者環境變數和 PATH 不同,導致在 CI 或遠程機器上執行命令可能與本地不一致

查詢了一下兩者的 PATH 如下

Interactive Shell

/home/gitlab-runner/.nvm/versions/node/v20.4.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Non-Interactive Shell

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

明顯可見的差異在於NVM的路徑設定,這個 PATH 是在安裝 NVM 時被加上去的

解法

我們可以選擇重新 export NVM_DIR 這個作法

1
2
- ssh -i ~/.ssh/id_rsa gitlab-runner@$VM 'export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" &&
pm2 restart app.js

另一種作法會多上一層 shell,並再次執行互動式的 bash 我覺得較不易理解
不好維護,故不採用。

1
- ssh -i ~/.ssh/id_rsa gitlab-runner@$VM 'bash -i -l -c "pm2 restart app.js"'

參考

(fin)

[生活筆記] 2023 半年工作回顧

前情提要

這份是 2023 年, 3 至 6 月間,我在工作上獲得的成果,
以理性務實的態度推動各項工作,以下是在這段時間內所取得的重要成果:

敏捷觀念的引進與實踐

我引進了迭代開發要事優先的敏捷觀念,
同時建立了 PBI(產品待辦項目)與工作看板,以確保團隊的工作透明度
我們每日召開立會,及時更新資訊,並建立了文件系統,以便於知識的分享與傳承。

前後端分離的優化

我推動了前後端分離的工作方式,使專業得以適當分工,減少了彼此等待的時間。
這樣的優化使得服務可以被重複使用,避免了重複開發,節省了寶貴的時間與資源。

自動化的部署機制引入(CI/CD)

我們成功建立了自動化的部署機制,每次部署都節省了至少 10~30 分鐘的時間,
同時大幅減少了人工操作可能帶來的錯誤風險
這項優化為團隊帶來了高效率與更穩定的工作環境。
這是持續性的正面效益,假設每周部署 10 人次以上,以換算時薪為 600 計算,
每年每位 RD 約可以省下等值於 8 萬的工作時間。並大幅下降風險。

準時交付 N 系統,完成參展目標

我們順利地在新加坡、法國、台北和高雄四地參展,並提供了展場現場的支援,
這已超出我們本職專業的範疇。
但我們成功地達成目標,贏得了更多的曝光與商機。

帶回自主開發的 I 上鏈系統,省下外包費用

為了節省成本,我們將原本要外包的 I 上鏈系統帶回自主開發,從而節省了公司大筆的費用與時間。
這項舉措不僅讓我們獲得了更多的控制權,還提升了整體效率。
此項目,粗估至少擁有 300 萬以上的產值。

其他突破與調整

除了以上成果,我還做了以下貢獻:

  • 解決了公司 domain 數量達到上限的問題,通過與系統商的溝通,成功解除了限制。
  • 幫助查找了未關閉的 AWS 資源,避免了資源的浪費。
  • 調整了資安需求,提高了系統的安全性。
  • 協助調解了系統與需求之間的衝突,確保了順利推進工作。
  • 未來的發展計劃
  • 為了持續推動工作的進步,我擬定了以下計劃:

下一步

  • 將預計外包的 P 系統帶回自主開發,進一步節省公司費用。粗估其價值為 110~800 萬之間。
  • 積極招募人才,引進新血,提升團隊實力。
  • 推進單雲轉多雲的轉型,增加靈活性與彈性。
  • 針對資安問題進行調整,包括關閉公開 IP 和加密資料等措施。
  • 處理舊系統 L 的大泥球,逐步優化系統結構,提高整體效率。

結論

整體而言,在短短三個月內,接手的專案已為公司撙節了 150 萬 左右的支出,
而在自動化工具,用一個粗略評估的方式,假設每周每個 RD 會部署 5 次,
一年 52 周,一次部署可以省下 10 分鐘的情況下,目前公司 5 位 RD:
5*5*52*10= 13000 分鐘,大約可以省下 1.25 個人月,用來作更有意義的事。
而其它工作在長久看來也會持續帶來收益,整體而言,這三個月的產值已超過 500 萬
希望在未來的日子裡,能夠持續取得進步,為公司的發展做出更大的貢獻。

(fin)

Please enable JavaScript to view the LikeCoin. :P