[活動筆記] 2020 SCRUM GUIDE UPDATE

前情提要

2020/11/18 將迎來 Scrum 25 周年與 Scrum Guide 的更新,
活動有一些大師對談,錄影放在文末連結之中,
另稍微比較一下 2017 與 2020 Scrum Guide 的差異(以中文為主),
特別感謝譯者這麼有效率的更新,我差不多在 19 號就可以在網站下載

排版與封面

2017 版本主要視覺的位置放了兩個大師的合照,首行字為「Scrum 指南™」
2020 版本主要視覺的位置為「Scrum 指南」,首行字為兩位大師的名字。
理想我會希望使用 2020 的版本,然後兩位大師的名字縮小到角落 :D

目錄

2020 將目的前移到目錄之前,我覺得這樣的調整很好。
讓人可以先讀取本指南的目的。

Scrum 指南的目的

篇幅相比 2017 更長了,並將 2017 版「Scrum 的運用」縮減並挪移至此處。
簡介了 Scrum 的起源,概述了 Scrum 的運用範圍與現況。

另外有兩句預防性的警語,是這個段落的重點

  • 改變 Scrum 的核心設計或 Scrum 的各種理念,遺漏其中任何元素,或是不遵照 Scrum 的規則,是在掩蓋問題,並限制了 Scrum 的各種好處,甚至可能使其變得毫無用處。
  • 這些使用 Scrum 框架內的戰術技巧有很大的變化,因此不在此描述。

這個篇幅簡述了 Scrum 已是被時間與不同產業實証有用的框架,
但擅自修改 Scrum 可能會導致 Scrum 效用打折甚至無用,
並具體說明 Scrum 的戰術實作不會在此指南描述。

Scrum 的定義

相比 2017 的版本,這裡直接提到了 Scrum 中所有的角色與其職責。
並明確的說明「原封不動地應用 Scrum」, 並強調這份指南是人之間的指引
而不是具體的流程、技術與方法。

這裡也是我覺得很好的地方,以前在首次與團隊成員說明 Scrum Guide 時,
如果按照 2017 的章節說明,我都要另外安排一個段落先簡述 Scrum 中的角色,
因為 2017 在角色出現的篇幅比角色的說明還要早。

Scrum 的理論

2020 的版本加上精實思維(Lean Thinking),
並具體說明了檢視、調適的事件( 2017 翻譯為活動)與三大支柱的關係。

透明性的段落強調了没有透明性的檢視會產生誤導和浪費(做出讓價值減少且風險增加的決策)
很有感觸,我在團隊導入 Scrum 的首要宗旨就是看見事實。
(有機會再談談如何定義事實與 Ruddy 老師說的「看見全貌」的差異之所在)

檢視性強調 Scrum 將以 5 個事件有節奏實踐檢視性(具體作法與事件在這個段落還沒提),

檢視性促成調適性。 沒有調適性的檢視是沒有意義的。Scrum 的事件旨在激發改變。

這句話作到了承先起後的作用,可以將檢視性視作三大支柱的樞鈕。

調適性的篇幅提到了授權與自我管理,這也許是導入常常碰到的地雷。
團隊不被授權或缺乏自我管理的能力或意識(有點像有沒有病識感)。

2020 的編排我很喜歡,除了一再預告事件如何產生三大支柱之外,不再僅僅以順序暗示三大支柱的關係。
而是明確的說明透明性促成檢視性。檢視性促成調適性。
(有點像真善美,沒有真後面就會變成假善、假美那就豪無意義了)

Scrum 的價值觀

對承諾、專注、開放、尊重、與勇氣的排版更明顯了,另外 Stakeholders 也明文納入其中了。

誒、不對啊,這些態度不是跟四維八德一樣,小朋友都知道嗎?
而且應該不論是你的老闆、雞巴主管、龜毛客戶、秋條前輩到所有人都應該要有相同的態度,不是嗎?
這就是知易行難吧… 說個滑坡的,最近在思考尊重與尊敬的差異,
朋友給了我一個例子:

  • 尊重:念在你是一代宗師,你自盡吧
  • 尊敬:我的戰鬥力只有六千,他起碼有一萬以上

聽說看得懂的都是老人。

Scrum Team

引言強調一位 Product Owner(2017 在後面的段落才提到),
強調了沒有子團隊與階級架構(具體實務上會影響到組織結構,實作起來並不容易,需要更多的經驗)。
這次沒有翻譯目標/目的了,直接使用 Product Goal 並在後面的段落具體指由 PO 開發、描述溝通。

然後強化了對當責的描述,調整了後面篇幅的介紹順序
2017:PO > Development Team > Scrum Master
2020:Developers > PO > Scrum Master
我認為順序都是有暗喻性的,但解讀方式是自由的,就不過多解釋了。

重點是責任的部份,我覺得比起 2017 更能簡單的用 Scrum Guide 說明現在角色的職責所在了。

Developers

● 打造一份 Sprint 的計畫,也就是 Sprint Backlog;
● 藉由遵循完成之定義,以灌輸品質;
● 每天調適其邁向 Sprint Goal 的計畫;和,
● 作為專業人士對彼此負責。

Product Owner

● 開發並明確的描述溝通 Product Goal;
● 創造並清楚的描述溝通 Product Backlog items;
● 對 Product Backlog items 進行排序;和,
● 確保 Product Backlog 是透明的、可見的與可理解的

這裡特別加上了

Product Owner 可以自己做上述工作,或者也可以將職責委託他人,然而,Product Owner 仍肩負最終責任。

這句話我視為對大型組織導入 Scrum 的困難之處的回應。
錯誤 Scrum (其實就不是 Scrum)會產生缺乏實際權限的 PO
或是有權無(卸)責的傳統型領導。

Scrum Master

明文Scrum Master 對 Scrum Team 的效能負責;職責更明確了,語句更洗鋉,贅字更少。
但我覺得「真正的領導者」這段文字將會產生轉型時的爭議,特別是將「僕人式領導」文字又被拿掉。
我會建議作為 Scrum Master 要把這件事放在心中,Title 只是浮雲啊。

Scrum 事件(原為 Scrum 活動)

Sprint

明文採用時間較短的 Sprint,可以建立更多學習周期,此外更加強調三大支柱與 Sprint 的關係。

特別提醒經驗主義的重要性,更勝於實際的做法(諸如:燃盡圖、燃起圖,或是累積流量圖等…)
這與我的經驗也是不謀而合,主管一開始就投入過多心力在要求製作圖表,
而忽略了在圖表之前,進行預估其實是需要訓練的,最後圖表變成作假帳…
失去透明度,檢視性與調適性將無法發揮功能,Scrum/Sprint 將會失敗(或是不知道成功或失敗)。

取消 Sprint 的章節被大幅縮減,僅以不合時宜一句代過。
反而釋放更多空間給 Product Owner。
我覺得 PO 當要取消 Sprint 時,要思考以下的問題,

  • 要如何與其它角色互動?
  • 要如何持續實現 Product Goal?

這樣的文字編排方式,我覺得是很大的改善,強調在 Scrum 之中,
我們的所有行為都是為了實現三大支柱,而我們相信這樣的方法可以領我們到達終點之地。
後面的事件也都有類似的描述,我就不再補充。

Sprint Planning

2017 版本
第一個討論題目:這次 Sprint 能做出什麼?
第二個討論題目:如何完成所選的工作?

2020 版本
主題一:為什麼這次 Sprint 有價值?
主題二:這次 Sprint 能完成(Done)什麼?
主題三:如何完成所挑選的工作?

明顯多了一個有關價值的主題,但是需要與 Stakeholders 在 Sprint Planning 結束前被確定下來,
就我實務的經驗 Stakeholders 與 PO 會比 Developers 提早決定未來的目標,
所以 Stakeholders 依然不是會議中必要的角色。

Daily Scrum

1
2
3
4
Developers 可以選擇他們想要的任何 Daily Scrum 的結構和技術,
只要他們的 Daily Scrum 專注於實現 Sprint Goal 的進展,
並且產生下一個工作天可執行的計畫。
這樣可以更專注並改進自我管理(self-management)。

把經典的三個問題拿掉了,這也符合我的經驗,不要流於形式,
而是更專注在實現 Sprint Goal,不流於形式則更能讓團隊自我管理。

Sprint Review 與 Sprint Retrospective

這兩個段落的篇幅都縮短了,但是我覺得更言簡意賅。
但投影片展示的描述,我還比較喜歡 2017 版本的描述 是為了引發意見的反饋和提升協同合作
但的確實務上往往會淪為簡報報告。

關於 Retrospective 這個會議對我的定義,
我目前的團隊沒有在跑 Scrum ,但是我直接引入 Retrospective。
Retrospective 是一個可以雕塑團隊的會議。
有趣的事,團隊現在調整的越來越像 Scrum (當然依然不是 Scrum)

Scrum Artifacts

明文: Artifacts 的設計是為了使關鍵資訊之透明性極大化。(其實 2017 年的版本也有提到)
2020 版本的文字組織更簡明之外,都加上了承諾的區塊,

  • Product Backlog 是為了實現 Product Goal 的承諾
  • Increment 是為了實現對完成之定義(Definition of Done) 的承諾
  • Sprint Backlog 是為了實現 Sprint Goal 的承諾

結語

結語的部份並沒有太大幅度的修改,
但是我想要再一次強調 「雖然實施部分的 Scrum 是可能的,但結果就不是 Scrum 了。」

小結

整體的文章的結構完整性更好了,三大支柱與活動的連結,產出與承諾的連結。
然後將實作(戰術)面與角色的行為(戰鬥)樣版移除,我不認為這樣會變得模糊不清;
反而給了更多空間讓團隊發揮。

想起以前聽過「守、破、離」的演說,我想這次 Scrum Guide 有一點這樣的味道,
在 25 年前,什麼經驗都沒有情況,這樣的樣版帶來了相當大的幫助,
現在我們都有一些實作有一些失敗有一些成功,是時候把樣版移除了(或是回到問題的本質)。

  • 你真要的三個問題嗎 ? 背後想問到的是什麼 ?
  • 真的不取消 Sprint 嗎 ? 為什麼不行 ?
  • 不站立真的不能開 Daily Scrum 嗎 ?

校錯

  1. 的的
  2. 的的
  3. Artifacts

參考

(fin)

[生活筆記] 收支流程設計

耶和華所賜的福使人富足,並不加上憂慮。— 箴10:22.

前情提要

投資理財是現代人生活極為重要的部份,
但是我在學生時期並沒有學習到這方面的知識,
出社會也大概 10 年了。稍微作個記錄與分享。

概念

開源節流是基本理財認識,簡單分為收入與支出。
收入方面,最常為工資所得,在網路時代也有很其它的賺錢方式,
最主要我想還是要建立系統,這裡不過多著墨,
我的系統屬於股票投資,但是記得你可以不只有一個系統,而建立系統是需要時間與反覆思考的。

支出方面,其實滿足一個人的生活所需,金額不會太大,
當然想過得比較滋潤的話,會比較花錢,
跟據你所居住的區域來說(不是要戰南北),還是會有比例上的差異,
你也可以用時間來轉換成本,不過裡面藏著一些魔鬼細節,小心得不償失。

舉例來說:
如果是自行開伙,飲食的費用並不會太高(特別是家庭人數較多的情況),
但是就要考量到材料準備、保鮮、整理等環節,外食也可以有便宜的選擇,
但是可能會是太油太鹹太甜的餐點,導致健康受到影響。

但除此之外,孝親、偶爾為之的旅行、進修、稅、保險等等…什麼都要花錢。
簡單的一句,所有的支出,我都建議預算制。

以下是以一個小資上班族(就是我啦)的概念去設計的,
不包含保險、股票、信用卡等…其它的工具。
如果有人喜歡,也許未來才再寫相關文章吧。

帳戶分類

受薪帳戶(InCome Acct)

受薪階級通常會有薪轉戶,至少要有1次以上的跨行轉帳免手續費
如果非工資收入(接案/紅利等…),應該儘可能直接轉入主帳戶(Main Acct)

主帳戶(Main Acct)

目的:負責最多轉出轉入功能的帳戶,主要的活存會放在這裡,
應該有一定次數的跨行轉帳免手續費,或是約定帳戶免手續費
依個人使用習慣,建議要有 5~10 次以上,此外要有好用的APP/網銀
最後才是活存利率要儘可能的高,因為你大多數的生活費會停滯在此。

目前有些網銀放 5 萬或 10 萬就有 2% 以上的利率,比定存還高。
10 萬放一年就有 2000 是蠻值得的,當然不要本末導致,
省下的跨行交易手續費與其方便性才是我們要的。
這個帳戶的設計上金錢會有小額高頻的流通,
不要為了 2% 而讓錢鎖死不流動,
假設股市的投資如果有 5% 報酬的話應該讓現金流向股市市場(需要考慮投資風險),
當然有閒錢還是可以考慮…

2020 年可以參考這篇文章,轉帳免手續費帳戶比較
雖然開戶作業有時候很麻煩,這些優惠也常常過幾年後就消失與改變。
但是僅僅這幾年中帶來的方便性也是很高的喔,手續費這種磨血的花費真的建議能省則省。

証券戶/証券銀行

目的:主要的股票投資帳戶,銀行與証券戶轉帳不應有手續費,
還沒有投資就先虧一筆,就好像跑百米你讓人家 10 公分,
你覺得沒差嗎?我覺得有差,跑百米我不是 Bolt ,理財我不是連公子。
証券銀行轉到其它銀行有一定次數的跨行轉帳免手續費
這裡的次數不用多 1~5 次即可,主要是我的交易頻率其實不高,
需要交易,通常是有大筆資金需要轉投資其它項目的時候,
反而是單日/周/月轉帳上限比較重要,可以在開戶的時候作約定。
最重要的是証券交易手續費要儘可能的低
基本上會有 1.425‰*0.6(ex:富邦) 的折扣,
高交易額或有活動開戶的券商可以更低 (ex:華南 1.425‰*0.3),
不要小看這千分一點四二五的 3 折,以前我不知道,傻傻被扣的錢可以訂好幾年的 Spotify 了
最後要有 好用的App (實際上好像每家都一樣,都是三竹作的?)

其他投資

活存

在低/零利率時代,活存已經不適合作投資的首選,
所以通常會與 主帳戶(Main Acct) 作結合,
主要用於生活上食衣住行娛樂所需的花費,
方便性將大於投資目的,但是仍要選擇活存利率高,
或是回饋高(ex:刷卡回饋/ShopBack)的消費方式

定存

利率要高,但是在低/零利率時代,定存已經不是良好的投資標的。
但建議可以將緊急預備金作為定存

外幣:

性質會與活存類似,但以外幣計價,應為國際通用貨幣(美金、歐元等…),利率要高,
主要的目的為美股、旅遊、海外置產(目前沒有),特性是交易手續費都不便宜,所以持有比例不會太多。

美股/其它市場股票

台股之外第一選擇,以美股為主,
好處是標的超多,可以賺世界上所有標的的錢,
缺點是美金計價所以想轉換成現鈔或是台幣手續費都很高,
沒特殊情況這些錢不會拿出來花,會變成純粹的投資。
研究中…

黃金/貴金屬:

有使用黃金帳戶買過,非實體黃金,
只能賺差價而不生息,所以不愛,目前已經不再投入。

支出

所有的支出應該都採取預算制
每年編列並支出,作為個人,不應有消耗預算的行為,
但是可以挪移至下一年度。

Fixed Charge (固定支出)

  • 保費(綁定信用卡)
  • 稅金(分期 0 利率)
  • 孝親費
  • 訂閱制服務
    • 域名( Domain )
    • Spotify (綁定信用卡)
    • 水/電/瓦斯
    • 網路/手機電信/第四台
  • 生活費
  • 投資
    • 定期不定額
    • 主動式投資

浮動支出

預算制設定上限,但是以實支實付為主

  • 學習費用
    • 買書
    • 上課
  • 娛樂費用
    • 旅行
    • 聚餐
  • 婚喪禮金
    • 好友/親人
    • 普通同事/朋友,只包不去通常可以省時省錢

Over View

Cash Flow Over View

參考

(fin)

[生活筆記] 簽署軟體工藝宣言

As aspiring Software Craftsmen we are raising the bar of
professional software development by practicing it and helping
others learn the craft. Through this work we have come to value:

Not only working software, but also well-crafted software
Not only responding to change, but also steadily adding value
Not only individuals and interactions, but also a community of professionals
Not only customer collaboration, but also productive partnerships

That is, in pursuit of the items on the left we have found the items on the right to be indispensable.

作為有理想的軟件工匠,我們一直身體力行,
提升專業軟件開發的標準,並幫助他人學習此工藝。
通過這些工作,我們建立以下的價值觀:

不僅要讓軟件工作,更要精益求精
不僅要響應變化,更要穩步增加價值
不僅要有個體與互動,更要形成專家的社區
不僅要與客戶合作,更要建立卓有成效的伙伴關係

也就是說,左項固然值得追求,右項同樣不可或缺。

簽署心得

這些價值觀我是相同認同的,
可是這個網站的感覺並沒有呈現出那樣價值觀啊…
或許還少了一點美感.

我的簽署資訊如下,
30196 Marsen (Taiwan) 2020/10/28,
查詢功能不能查 ID 與國家有點弱,
沒有正體中文的翻譯, 補充資料的部份很不錯,
但是也只是沒有系統的散落在那裡.
想給點回饋,也找不到留言區或討論區, 或是網站的 Repository.

參考

(fin)

[實作筆記] 怎麼建立一個網站?(四) - 自訂網域 EMail

前情提要

擁有自已域名的網站已經 4 年啦, 雖然我只有用在 Blog 上,
而且是用靜態網站的方式呈現,但也是算小小的一個成就.
不過其實心理還是有一個小小的缺憾,就是我沒有自已域名的 email.
之前沒有好好作功課,想到還要架設一個 Mail Server 就覺得不可能.
但其實並沒有那麼複雜.
我使用 Google Domain 的服務結合 CloudFlare.
大約只要 30 分鐘就能收到信啦.

實作

首先是進入 Google Domain 的後台,
記得如果你人在台灣是不被允許使用 Google Domain 的服務,
所以必需要透過 VPN 跳轉到美國才能操作後台喔.

真的是超簡單的,但是數量上限為 100 個,
加上 Google 的服務常常說收就收, 有商務需求的人還是不建議這個方式喔.
電子郵件 > 新增電子別名,輸入自已想要的名字,然後填入現有收件者電子郵件地址

![新增電子郵件別名](/images/2020/10/email/add_forward.jpgJ

輸入轉寄電子郵件

如果你全部使用 Google 的服務的話,這樣子的設定就好了,
DNS 的 MX 記錄 Google 會自動幫你處理到好.
但是如果你像我一樣, 使用了別的 DNS 服務就必須要自已手動將 MX 記錄註冊上去喔
在 CloudFlare > DNS 就可以進行設定.

名稱/主機/別名 類型 存留時間 (TTL) 優先順序 值/回應/目的位置
空白或 @ MX 1 小時 5 gmr-smtp-in.l.google.com
空白或 @ MX 1 小時 10 alt1.gmr-smtp-in.l.google.com
空白或 @ MX 1 小時 20 alt2.gmr-smtp-in.l.google.com
空白或 @ MX 1 小時 30 alt3.gmr-smtp-in.l.google.com
空白或 @ MX 1 小時 40 alt4.gmr-smtp-in.l.google.com

MX

設定完成後依照 Google 的說法會收到一封信(但是有些情況收不到)就會生效,
我實測上沒收到信,但是寄信馬上就生效了.
有了自已域名的信箱虛榮感專業度是不是又上升了幾個百分點呢?

補充 20201118

前面已經可以透過自已的域名收信啦,
那麼怎麼寄信呢?

想像一下,如果用 [email protected] 收信,
卻用 [email protected] 回信,
是不是整個 Low 掉了,而且收信者是不是會懷疑怎麼寄信給 A 卻是 B 回信呢?。

為了解決這個問題,請參考在 Gmail 中使用別名傳送電子郵件

  1. 產生應用程式密碼

    • 登入Google帳戶後,前往Google 帳戶頁面。
      登入Google帳戶後,前往[Google 帳戶](https://myaccount.google.com/)頁面。
    • 左側安全性 > 應用程式密碼 > 選取應用程式(選擇郵件) > 選取裝置(其它) > 輸入自已的 Domain > 產生
      登入Google帳戶後,前往[Google 帳戶](https://myaccount.google.com/)頁面。
      輸入密碼
    • 把系統產生的 16 個字元密碼記錄下來。等一下我們會需要用到這組密碼
  2. 新增電子郵件別名

    • 登入 Gmail > 設定 > 帳戶和匯入 > 選擇寄件地址 > 新增另一個電子郵件地址
    • 電子郵件地址輸入 自訂網域信箱 > 勾選「視為別名」
    • SMTP 伺服器輸入 smtp.gmail.com 通訊埠 587,選取採用 TLS 的加密連線
      SMTP 設定
    • 使用者帳戶請輸入 Google 帳戶(不用包含@gmail.com),密碼使用上一步的應用程式密碼 > 新增帳戶
    • 系統會寄一封驗証信,驗証後即可使用新的信箱寄信了
      驗証信箱
  3. 變更「寄件者」地址

    • 登入 Gmail > 設定 > 帳戶和匯入 > 選擇寄件地址
    • 設定回覆郵件時:來自和郵件傳送地址相同位置的回覆
    • 將自訂網域的信箱設定為預設郵件

參考

系列文章

(fin)

[實作筆記] ElasticSearch Reindex

前情提要

初探 ElasticSearch Service (以下簡稱 ESS ),
結合 Logstash、Kibana 合稱 ELK,
Elastic Cloud 提供更多的功能雖然蠻多還用不到,但比起自已架設會快相當的多。
因為主系統仍在開發中,只有部份功能上線,所以我選擇 ESS 作為我們的 Log System。
選擇 ESS 的原因如下:

  1. 快速實現,只需要在 Elastic.io 簡單的操作,便可以有一個功能齊全的服務
  2. 提供很全面的 Kibana 圖形介面
  3. 與 .NET 的整合很單純,安裝完 NuGet 套件後,只要設定好 Config 立即可以使用
  4. 開源且社群活躍,也是目前主流的 Distribution Search Engine

現有配置如下

Summary

初始的配置更低,是使用最小單位、最少節點的配置。
Memory 只有 1 GB,Storage 有 30 GB。
在初始配置的情況下,JVM memory pressure 常態性達 70% ~ 80%,
這是個異常狀況,在實務上緊急將 Memory Scale Up 到 2 Memory 暫時解除這個問題。

效能問題

追究後面的本質原因的話,是在系統設計上, 每日建立新的 Index
在官方的 blog 也有提到這樣的實踐方式。

a lot of people use Elasticsearch for logging.
A standard format is to assign a new index for each day.
中略 …
Indices are fairly lightweight data organization mechanisms,
so Elasticsearch will happily let you create hundreds of indices.

但是實務上我產生了太多的 Shards ,這也是初學者常踩的一個雷包,
一不小心就會 Oversharding 可以參考 How to size your shards 進行修正。

這裡我使用了 Reindex 這個 API 來將一些碎小的 Index 作結合(Combine Smaller Indices)。

實作記錄

Reindex 的 SOP

  1. 確保 maximum shards 的足夠
    ESS 為了避免 Oversharding 導致整個 Cluster 崩潰會有設定一個上限值,
    7.x 版本預設為 1000 ,而 Reindex 每一個 Index 都會需要 2 個 Shards (猜測是SWAP機制)
    以我為例,原本我的 Shards 已達 999 ,當我試著要 Reindex 時會拿到以下會錯誤。

    this action would add [2] total shards, but this cluster currently has [1000]/[1000] maximum shards open

    處理的方法也很簡單,只要透過 /_cluster/settings 加大 cluster.max_shards_per_node 即可。

    1
    curl -X PUT localhost:9200/_cluster/settings -H "Content-Type: application/json" -d '{ "persistent": { "cluster.max_shards_per_node": "3000" } }'

    實務上我 Reindex 後會刪除碎小的 index,刪除後 Shards 的數量也會下降,
    當 Shards 剩餘數量足夠時,我會重設回 1000。

  2. 執行 reindex ,請確保新舊 index 符合商業邏輯
    example:

    1
    2
    3
    4
    5
    6
    7
    8
    {
    "source": {
    "index": "staging-aaa-service-2020.06.*"
    },
    "dest": {
    "index": "staging-aaa-service-2020.06"
    }
    }
  3. 確保查詢一致

    • query 數量為 N
    • Reindex
    • query 數量為 2N
    • delete
    • query 數量為 N
  4. 執行紀錄

    • staging-aaa-system-*
    • staging-bbb-server-*
    • staging-ccc-service-*
    • prod-aaa-system-*
    • prod-bbb-server-*
    • prod-ccc-service-*
      • prod-ccc-service-2020.09-* 有掉資料(12萬筆→9萬筆)
        Loss Data
  5. 結果評估
    Memory 只有 2 GB,Storage 有 60 GB 時。
    ReIndex 並刪除碎小 Indices 前 JVM memory pressure 常態性達 40%,
    執行後,JVM memory pressure 約為 20%。
    也就是說我可以改用更小(便宜的配置處理目前的資料量)。

JVM Memory Pressure Down

改善建議

  • 重要敏感的資料,要先備份才能進行 Reindex 的操作
  • 下次 reindex 遇到大量資料,要切成更小的單位進行,
    比如說每 10 天或每天,減少一次性 reindex 的資料量,
    減少失敗與掉資料的可能性發生。
  • 需要將系統改用較長的時間周期去建立 Index
  • 縮小雲端系統配置。

進階思考

  • 如果我想要維持 Daily Indices Created 但是又不想讓 Shard 成長爆量,我應該怎麼作呢 ?
  • 或是有什麼機制,可以讓我定期將某些資料 Reindex 嗎 ?

參考

(fin)

單元測試分享(一) --- Why ? How ? What ?

前情提要

目前參加的讀書會有點進入了倦怠期,
參加的人數出席不穩定,會議過程有點感覺像是在照本宣科。
所以我們安排每隔幾周,由不同分享一下個人工作上不同的經驗。
讓負責分享章節的人可以有更多時間準備,
同時也可以讓聽者換換口味同時喘口氣。

對於我來說,可以重新整理一下過往的經驗。
試著能不能更有組織的分享單元測試這個工具與知識。
同時,因為是線上分享會的形式,當我無法觀察觀眾的表情時,
遠端會議應該怎麼進行才能更有效呢?

遠端協作的 Conversation Cost 仍然相當高

進行方式

  • 先問為什麼?
  • 輪流發表一下想法(TimeBox:60s)
  • Live Coding (如果是現場分享,我會希望多一點實作)

思考問題

  1. (單元)測試是什麼呢 ?
  2. 為什麼要寫(單元)測試 ?
  3. 什麼樣的情境需要(單元)測試?

這裡的設計是 What、Why、When,我覺得改成 What、When→How、Why 會更好。
主要的目的是引導聽眾思考 Why,這裡我的受眾應該為開發人員,
實務上還有可能會是 QA(測試人員)、產品經理(PM/PO*)、維運人員、
營運部門甚至是老闆或客戶。

舉例情境如下:

問:單元測試或是測試是什麼呢?
答:是一種自動化的對程式的方法進行驗証 blab blab ….

捕捉到關鍵字 自動化 方法…可以延伸提問

  • 測試不一定要自動化,但是單元測試建議要作到一鍵測試(半自動)
  • 單元不一定是方法,但我們可以以方法當作最小粒度來討論,
    後續的分享會對粒度再作討論,但重要的是團隊的認知要一致

進一步提問什麼樣的情境需要(單元)測試?
如果現場乾掉了,可以改成以下的提問:

  • 上 Prod 前要不要測試?
    • 那上 QA/Stage 要不要測試?
  • 開發新功能要不要測試 ?
    • 那 HotFix 要不要測試 ?
  • 拿到一份全新沒看過的 Source Code 要不要測試 ?

你會發現測試無所不在,那我們為什麼(Why)要測試啊?
我的回答,(單元)測試是品質保証的一種手段,

如果上線前,(單元)測試全過,
我就對被測試保護的方法(情境)有信心不會壞。
同樣的,在部署到其它環境時測試通過,我對品質信也就會跟著提昇。
換句話說,測試是品質的可量化指標。

可能的問題:測試全過,上線還是有可能會壞掉啊
回答: 壞掉是什麼樣的情境 ? 是不是一種沒有被測試保護到的情境 ?
是的話只要加上情境即可,一般來說我們應該可以作到 96 % 以上的常態情境
剩下考慮發生機率與重要性,應該加上測試就加測試保護,
這裡不限定單元測試也包含整合/端到端/手動等其它測試。

另一個情境是開發新功能,
任何功能都是方法與流程的組合
當你在開發新方法或新功能時,如果能同時寫好測試
那你就會有*
一份具備可量化品質的代碼**,
同時還可以帶來的額外好處是,當有一個新人拿到你的代碼時,
他會有一份測試可以當作規格書來閱讀。

注意:這裡可以代入很多其它相關的概念
比如說:TDD、Code Review、可讀性、Pair Programming

理解方法與流程是最耗時的一件事,
如果有測試可以節省相當多的時間,
但要注意測試也是人寫的,如果為了寫而寫,很容易寫出垃圾測試,
試著在開發流程上引入 Pair Programming、Code Review、Pull Request 等…機制
另外當代碼成長到一定程度時,
如果需要重構,測試將提供一定的保護網(看覆蓋率多少)。
但要小心實務上不應該過度追求覆蓋率。

這裡提供一個觀念,不要為了 Design Pattern 而 Design Pattern
但是即有的代碼需要重構之時,Design Pattern 可以提供像是燈塔般的指引作用
只要巧妙的設計測試案例,走向目標。

此外,當代碼有了單元測試的保護,
在開發日常的除錯作業將會有很大的幫助,
測試可以幫你快速的定位錯誤。
即使測試並未攔截到錯誤的話,那也表示你發現了一個前所未有的情境,
而只要加上這個測試情境,再修改代碼,未來這個情境將不會再有錯誤。

經典書籍對單元測試的定義

1
2
3
4
5
6
7
一個單元測試是一段自動化的程式碼,這段程式會呼叫被測試的工作單元,
之後對這個單元的單一最終結果的某些假設或期望進行驗証。
單元測試幾乎都是可以使用單元測試框架進行撰寫的。
撰寫單元測試很容易,執行起來快速。單元測試可靠,易讀,並且很容易維護。
只要要產品不發生改化,單元測試執行結果是穩定一致的。

--- <<單元測試的藝術2nd>>

F.I.R.S.T Principles

1
2
3
4
5
6
7
- Fast : 快速→不夠快就不會被頻繁執行
- Independent :獨立→互相依賴的測試,會讓除錯變得困難
- Repeatable : 可重複→在任何環境下執行都有相同的結果(EX:時間/網路)
- Self-Validating : 自我驗証→測試是否通過,不需額外的判斷與操作
- Timely : 即時→產品代碼前不久先寫測試

---<<Clean Code>>

小結

上面提到很多工程面的實踐,
也不僅限於單元測試,更多的是測試與品質的關係。
一再強調的觀念是:

測試是品質的可量化指標。
測試是品質的可量化指標。
測試是品質的可量化指標。

而回到工程面上來說,作為第一線的品質把關,
開發人員本來就應該對自已的代碼提供單元測試,
而 TDD、Test As Document、Refactoring、Design Pattern 等…是環環相扣的工程實踐,
Pair Programming、Code Review、Pull Request 等…是工程流程的實踐
單元測試正是那個將各種實踐結合在一起的一種工具。

Unit Test is basic tool

在心法上,要將單元測試視作工具,而非聖盃,
TDD 或是覆蓋率也是同樣的道理,御物而不御於物。

1
2
可用的軟體 重於 詳盡的文件
<<敏捷軟體開發宣言>>

引用一下敏捷宣言:
可用的軟體 重於 100%覆蓋率的代碼
可用的軟體 重於 測試全過的代碼
右側項目雖然有其價值,但我們更重視左側項目。

而這裡可用的最低標準,我認為是符合品質期待

First Test

第一個單元測試,加法計算器

Case:Add(+) : 1 + 1 = 2

1
2
3
4
5
6
[Fact]
public void Add_1_1_is_2()
{
var target = new Calculator();
Assert.Equal(2, target.Add(1, 1));
}

Production 代碼

1
2
3
4
5
6
7
public class Calculator
{
public int Add(int first, int second)
{
return 2;
}
}

Next Case

用 Test Case 逼出邏輯,用最簡單的方法實踐

1
2
3
4
5
6
[Fact]
public void Add_2_1_is_3()
{
var target = new Calculator();
Assert.Equal(3, target.Add(2, 1));
}
1
2
3
4
5
6
7
public class Calculator
{
public int Add(int first, int second)
{
return first + second;
}
}

3A 原則

  • Arrange(準備、初始化)
    如果 Arrange 過長會是一個壞味道,
    表示這方法相依太多參數、服務或模組
    範例:

    • target = new Calculator();
    • first number is 2
    • second number is 1
  • Act(執行/呼叫受測行為)

    • target.Add(2, 1)
  • Assert(驗証)

    • `Assert.Equal(3, acted result);

不要過度追求可讀性,而將測試程式變得難以理解,
可以使用測試驗証框架(ex:Fluent Assertions),
或是抽出方法來增加可讀性,但比起可讀,更重要是可理解。

彩蛋

後續的 Live Coding 會讓參加者完成後續的方法測試,
加法、減法、乘法、除法…
特別計算到除法的除零邏輯時,應該拋出錯誤。
趁這個機會可以介紹如何驗証 Exception。

進一步可以介紹如何使用 fluentassertions

1
2
3
4
5
6
[Fact]
public void Divide_7_0_is_Exception()
{
Func<int> act = () => _target.Divide(7, 0);
act.Should().Throw<DivideByZeroException>();
}

(fin)

[生活筆記] TUTORING APP 多特英 第四屆體驗大使 --- 心得篇

前情提要

直接連結前篇 吧。
APP 下載連結我也不囉唆,直接給。

使用記錄

我在使用前就知道接下來兩個禮拜並不輕鬆,
除了一些平日的課程之外,還有排舞與游泳的練習與它牌的英語課。
所以我計劃第一周上 4 次課(80分鐘),
第二周上 5 次課(100分鐘)。

我原本的想法是這個 app 應該可以用一些空閒時間來填補,
但是實際上真的沒有那麼簡單。

心態面

畢竟這是一個跟真人對話的英文口說 APP ,同時要使用你並不擅常的語言。
以我來說並不是那麼容易的東西,通常老師也會跟你作一小段的開場白,
問問你今天過得好嗎,或是簡單的自我介紹,身為內向者其實要保留一點心力來回答。

環境面

一開始我認為我可以中午午休在咖啡廳/樓梯間/公園之類的地方進行,
實際上沒那麼容易,一方面是心態上面的問題,
如同上面所說,開始的時候需要一點心理建議,需要一點儀式感,
在公眾場合會讓困難度倍增,有陌生人在旁邊,即使有使用耳機,
但恥度不夠仍然無開始課程。
另一方面,在公眾場合有較高的機率發生未逾期的狀況,所以可能會導致課程被中斷。

我自已經驗是,有一次我跟一個老師通話,才開始 5 分鐘,
家裡就有人回來,然後敲我的門,被迫中斷了課程,
雖然我有跟老師說我馬上回來,但是不知何種原故,我回來時老師已經中斷課程,
並且離線了。

師資面

這次體驗老師都是國際老師,我的經驗是大多是菲律賓老師,
只有一位應該是韓國老師,希望有機會在平台上看到台灣老師唷
然後有部份的老師我上課起來仍然是有一些環境音的,
影不影響,我覺得就看個人,是可以跟老師溝通一下。

未來有機會的話,我可能還是會試試母語老師,不過沒有上過也很難比較就是了。
這次的 9 堂課就老師我來說,覺得都是很 OK 的唷。

課程面

對我來說理想的上課時間可能至少 40 分鐘一次比較能有完整的對話。
但是 20 分鐘以目前的課程來說,其實也是夠了。
它內部推薦給我的課程等級是 Int. Low 大概還在講解基本的時態,
這個評分我相信是準確的,但是課程仍是有些無聊,比起課程的理論,
也許我需要更多的實際應用,能在對話上實際演練。

APP 面

主要的操作是蠻簡單的,也算好理解,
不懂的地方也可以問老師,但是我不確定是不是安卓與 iOS 的差異,
我之前問的一些按鈕的位置,老師的說明跟我實際上看到並不一樣,
所幸我很快就有找到,不然蠻浪費時間在這裡的。

說明一下課程中,你會看到教材頁,老師在滑動時,你的教材也會連動,
另外還有對話頁,可以在這些透過打字跟老師溝通。
我是使用 iPhone 7 ,在課程中老師有時候會傳訊息給你,
當我切到對話頁,想再切換回教材頁時,常常會反應不良,
我不確定是延遲或是觸發區太小我按不到,但是的確是一個困擾。

還有的時候教材連動會斷掉,不確定機制為何。
但是對我來說不影響,只要問一下在第幾頁就好了。

心得與題外話

我在上面說到,我本來打算第一周上 4 堂課,第二周上 5 堂課的,
但是我真的是在第二周忙到爆炸了,所以我在最後的一天的晚上 10 點鐘,
一口氣上完了 5 堂課。

唯一的問題大概就是太晚了找不太到老師(因為大多為菲律賓老師,而時區與台灣相同),
另外中間還有發生跟老師有誤會導致課程中斷的事。
所以整體而言,跟我原先的預期大概只完成了 87 % 左右。

不過三更半夜的在 2 個小時內找到 4 個老師上課,這就是現實生活中難以實現的事吧。
多虧了網路的無遠弗界,再加上 TUTORING APP 這樣的線上英文學習媒合才辦得到吧,
當然希望未來有更多時區的老師可以選擇囉。

參考

(fin)

[翻譯] AHA Programming 💡

The dangers of DRY, the web of WET, the awesomeness of AHA.

前情提要

為什麼我要翻譯 ? 練習英文,同時學習程式開發的原則 。
程式開發原則其實超級多,稍稍整理一下。

物件導向程式設計的 SOLID 原則

這五個知名的原則,可以一言以蔽之 — 高內聚、低耦合。
而我自已更喜歡 Teddy 老師的五則皆變:「面對原始碼改變的五種不同策略」

SRP(Single Responsibility Principle) 單一職責原則

A class should have only one reason to change
以一個類別來說,應該只有一個引起它變化的原因。

舉個實務上在改動代碼的例子:
線上回報了一個購物車的問題,
你去追查發現購物車保含禮品與折價券的情境下,才會發生問題,
同時主管要求你,這段代碼發生異常時加上 Log 並發 Email 通知。

你會怎麼改呢 ? 加個 if 判斷購物車/禮品/折價券之間的對應關係 ?
使用 Try Catch 補捉異常,記錄 Log 並發送 Email ?
那麼這些邏輯應該被加到哪些類別呢 ?
請思考一下
在這個原則底下,應該考慮 if 的邏輯屬於購物車/禮品/折價券中的哪一類 ?
而三個商務邏輯如何互動,當前的設計也是要注意的方向。
Log / Email 也是同樣的,是否也應該隸屬獨立類別呢。
請思考一下,請思考一下。

這遵循這個原則的程式設計下,可以有效減少單一類別被改變的機會。
以上面情境為例,Log / Email / if 的邏輯都是不同的職責,
如果設計得當,一個職責需要異動時只會修改到一個類別。

OCP(Open Closed Principle) 開閉原則

software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification
軟體實體(類別,模組,函式等等) 應該是可以擴展的,但不能被修改

同上的情境,遵循 OCP 在面對新增需求的時候,可以單純透過新增類別或方法來達成需求。

LSP(Liskov Substitution Principle) 里氏替換原則

Subtypes must be substitutable for their base types.
基底類別應該要能夠被他的衍生類別給替代而不影響原本的功能

這裡提到的原則,其實是對繼承的限制,在強型別語言都已經有這方面的實作了。
以上述的例子來說,Log/Email 的實作至少應該有一層的抽象隔離,
並以繼承抽象的實作來,
也就是說實際上如何 Log 可以是 files、DB、Clound 或任何其它的東西。

這裡也跟下面的 ISP 相呼應。

ISP(Interface Segregation Principles) 介面隔離原則

No client should be forced to depend on methods it does not use.
不應該讓使用者去依賴他根本不會使用到的東西

介面是方法的抽象,所以我認為當一個介面有超過一個方法時,
就應該思考一下有沒有違背這個原則。
實務上會有許多的同類型的介面應該被歸屬到同一類之中,
簡單可行的方法是當你實作一個介面時,會不會要跟著實作許多用不到的方法呢?
如果有的話,試著將它們拆分成不同的介面吧。

DIP(Dependency Inversion Principle) 依賴反轉原則

High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g. interfaces).
高層模組不應該依賴於低層模組。兩者皆應該依賴抽象。

Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.
抽象不應該依賴細節。細節應該依賴抽象
DRY(an acronym for “”)

DRY

直接透過 wiki 的圖片來說明上面的例子。
想像 Object A 是購物車 Object B 是 Logger,
Figure 1 顯示的就是直接相依的情境,而如果我們可以透過一個 ILogger 的介面就可以反轉相依,
使得購物車與 Logger 都相依與介面,
現行主流的程式也都有提供對應的 DI Framework 或 Libary,
只要好好使用,這個原則並不難實踐了。

小記

說得有點太多了,以上的部份未來另外抽成相關的文章吧。

主文

DRY

DRY(Don’t Repeat Yourself 的縮寫,不要重複你自已),一個古老的軟體原則,
在維基百科的定義如下:

Every piece of knowledge must have a single,
unambiguous, authoritative representation within a system
每一項知識都必須在系統中具有單一,明確,權威的表示形式

儘管實務上比定義更為寬鬆,我仍然認為這個一個好習慣。
使用 Copy/Paste 最大的問題是,當某處發現了一個錯誤,
我會意識到其它複製貼上的地方也有相同的錯誤,並且需要被修正。

我曾經接手了一份代碼,有著大量重複代碼,為了修正一個 Bug 我需要修改 8 個地方!
抽像化這部份的代碼成為一個隨處可呼叫 funciton 將有很大的幫助。

WET

另一個概念是WET(Write Everything Twice)

You can ask yourself “Haven’t I written this before?”
two times, but never three

你可以問自己 “我以前沒有寫過這個嗎?” 兩次,但從來沒有三次

在上面的例子中,有時候過度抽像比重複更有害。
那是一份 AngularJS 代碼與一些 AngularJS controller,
這份代碼傳遞 this 給一個猴子補丁(Monkey Patch)方法(註:一種在runtime時動態修改代碼的技巧),
這個方法會用某種方式提供 controller 額外的能力。
但是這超級讓人困惑,而讓人害怕修改。

這個代碼在三個以上的地方重複使用,但是抽象性很差,我寧可代碼重複。

AHA

Avoid Hasty Abstractions
避免草率抽象
prefer duplication over the wrong abstraction
寧可重複也不要錯誤抽像
Optimize for change first
為改變而優化

關鍵是我們不會知道代碼的未來。
我們無法確認,我們能確認的只有改變可能會發生,
如果沒有發生,為什麼要修改代碼 ?

注意以下事實:

  • 不要介意重複,直到你對重複代碼的用例有信心為止
  • 代碼有差異的部份,是否可以抽出參數提供給你的方法
  • 逐步執行的過程,可以抽象共用的部份將會躍來而上
  • 不用擔心何時該對重複代碼進行抽象,直到你接觸到他

結論

不用擔心何時該對重複代碼進行抽象,
這不是一個硬性規定,也是為什麼我更喜歡 AHA 勝於 DRY 或 WET.

相關文章

(fin)

[生活筆記] L 的轉職閒聊與問題

前情提要

朋友想轉職,隨便尬聊了一下,有談到自已的職涯,
還有我對軟體產業的一些看法。

自我解析

資策會對我的意義,系統的整理學習程式的概念,
在 2008 年找不到工作時,透過它成為就業的門檻。
薪資的成長 N → O 我大概花了 10 年。

  • N,N+5,N+7,N+10…
  • M,M+1,M+2…
  • O…

軟體

  • 軟體工程師機會仍然很多,但薪資在掉,整體趨勢有偏向 M 型化。
  • 第一份工作用來洗經歷
    • 挑一下薪水(起薪不要太低)
    • 找能加分與學到東西的公司/產業/新創 => 可以透過社群的聯結去尋找,facebook 也找得到
    • 前期要不恥下問,閒聊去建立聯結,有機會可以找到好公司(有大神的公司)
    • 這個技能很百搭,其實會走各自的路
  • 1~2 年跳回到 6 萬 => 一直跳槽就有機會,不要騎驢找馬但是要建立連結。
  • 為何不換公司而要換產業 ?
  • 程式 & 英文 是百搭的必修技能
  • 無人車/電動車/人臉辨識
  • 寫程式也有很高壓的環境,也會作假,也會有不合理的要求
  • 新創公司大多要年輕人,30 歲以上會嫌老,但頂薪有限
  • 中大型公司大多要穩定,結婚生子會加分,
  • 這個產業要賺錢的話跳槽可能最快
  • 理想加薪路徑
    • 4x up 第一份工作,每半年 Promo 自已一次
    • 一年後至少上 50k 繼續每半年 Promo 自已一次(包含社群分享之類的…)
    • 靠跳槽與 Promo 自已,兩年後上 60 k …
    • 時間是理想值(實際上,3~6 我大約花了 5 年,有很多人是比我快的)
    • 6~10 應該都還有上升空間,應該可以到 120 ~ 150 / year
    • 再往上應該要跨管理
  • 薪水不會比時間重要
  • 我們的好處是可以接案(但是也要花時間)

資策會的課程設計(AIoT)

資料庫

  • MySQL
    • PostgreSql
    • MsSQL

用來有系統有結構性的儲存資料。
主要先掌握關聯性資料庫的概念就好,
如果要專精這塊未來主要會效能調校(需要理解資料庫的底層設計才能作到又快又好,不同牌的資料庫多少會有不同)

  • NoSQL
    • MongoDB
    • 其它

後端

主要的商業邏輯的程式部份,學好 Java 才是課程主體。
可以考慮學習其它的語言。

  • Java to DB
  • Java
  • Java to Web

前端

HTML、CSS、JavaScript 是前端工程師的必須項目,
門檻也不高但是 JavaScript 會有很多特異的行為要注意。
學好後再學主流的 Framework(Angular、Vue 或 React)。

  • Html & Css
  • JavaScript
  • JQuery(不要拿來跟 Angular、Vue 或 React 比較,它的存在有歷史因素,現在學的 CP 值比較低,直接學好 JavaScript 為主)

主流程式開發(Web & App)之路

Before

F2E

F2E

Back-end
Back-end

DevOps
DevOps

參考

(fin)

[生活筆記] Young Marvel 1.0 小結 --- 需改善消化系統

有些事情一時間我沒辦法說得清楚,
總要一些沉澱…

這個課程也算是跌跌撞撞的完成了。
中間卡了個中共肺炎,又遇上炎熱的夏天,
練習室的冷氣顯示好像是我殘餘的血量而不是希望的溫度。

消失了兩個教室,但是人都還在,沒事、沒事。
肺炎的關係室外的 Social 沒有了,
淹水的關係地下室也沒有了,
上課 Follower 總是少幾個,但也不是大問題;
資深的 Leader 沒有走到最後,其實對我也還好。
沒事、沒事…吧。

喜歡兩個人的 Solo 再結合的橋段,
喜歡聽著音樂即興發揮,雖然我常常是即興發呆,
開始會注意到 Routine 之中的 And 拍。
試著 6+2 或是 2+6 甚至是 2+4+2 的方式打散固定的東西。

但是老實說,我還是覺得沒有進步。
總歸一句,吸收與消化能力太差,
從生物的例子來說,我缺乏分解肉的酶。
花再多時間啃頂級的牛排也得不到養份,
小藍莓雖然好消化,但是沒有蛋白質。

下個問題是…如何產生酶 ?
太大哉問了,好難回答。

其它零碎的想法:
風城的熱情大過天龍,是因為取之不易,所以珍惜 ?
如果斷掉了,黏了幾次還是好不了就放棄了吧 。
停損很重要、退場很重要,理財如此、工作如此、生活如此。
點頭之交仍然是最好的狀態,再熟一點就會開始莫名奇妙的要求。

(fin)