學習 design pattern 的五個階段

Level 0
什麼是 design pattern?

Level 1
買書回來翻了幾頁,覺得頭痛痛。

Level 2
咦,這不就是寫 Java 常會用到的嗎?

Level 3
認為軟體的設計就該由 design pattern 組成,開始濫用 design pattern。

Level 4
對於過去濫用所造成的災難感到難過,學著把 design pattern 用在刀口上。

Level 5
不再執著於書上寫的那些,隨手解耦皆 pattern。

 

張貼在 Design pattern, 軟體開發 | 標記 , | 發表留言

四月是你的敏捷 — 敏捷導入筆記

趁記憶還新鮮,記錄一下四月底導入敏捷方法的過程。
注意:以下寫到的內容可能會跟書上寫的或你跑過的敏捷有不小的差異。

起初是以前同事提到他們公司(不是我以前待的)在維護用 C++ 寫的 game server 有些不順。他想到我有這方面的經驗,於是跟老闆介紹我過去幫忙一週。

2020/04/27 (D1)

早上十點老闆和團隊成員開會,我也一起參與。成員各自報告這週要做什麼,星期四會再開會確認進度。
會議結束後我問一下團隊「有哪些待辦事項或是 bug 我可以幫忙處理的嗎?
得到的回答是「本來有一個遊戲跑幾個小時 game server 就會掛掉,但我剛才看沒有掛掉,所以目前沒有了。」(咦,所以我可以回家了嗎? XD)

好吧,不然我先把程式編起來跑跑看,順便看看程式寫法有什麼可以改善的。
結果光是初始化就卡住,而且在我的電腦才會發生。面對完全不熟的程式碼,查了幾個小時才發現是 race condition 的問題,解決。

下班前被老闆找去泡茶,老闆也問了一些問題,最主要的問題是「照你看來 x 月能順利上線嗎?」看得出來老闆有點煩惱。
唔,我才剛來一天,這個問題你們應該比我更清楚啊?
到這邊我才發現更大的問題,團隊並沒有整理出 product backlog 之類的清單,難怪連有哪些待辦事項都無法回答,自然也無法做進一步的評估。
當下只好跟老闆分享一下在以前公司的敏捷工作方式,但沒有建議現在就導入,擔心團隊成員會覺得要多做一些事、徒增壓力,造成反效果
不過待辦清單還是要列吧,不然我也不知道能幫什麼忙,老闆同意。

2020/04/28 (D2)

一早老闆就在群組說明了跟客戶約好的上線時間、預計何時開始內部測試,並要求團隊成員把各自的待完成項目整理出來。
等負責 game server 的同事整理完清單,我先跟他講解昨天解決的問題和發生的原因,順便說明一下多執行緒共用變數可能產生的問題和解法,然後討論一些他在工作上遇到的困擾。
接著想說看一下他寫程式的過程好了,因此給了一些程式設計、跟同事溝通和工作安排的建議。

很快又到了下班泡茶時間,老闆還是問了相同的問題「照你看來 x 月能順利上線嗎?
好吧,來看看團隊的待辦清單寫了什麼。看著看著發現一個問題,這些都是團隊成員各自認為需要做的,但是這些都做完產品就可以上線了嗎?誰知道這些是不是客戶要的?
像這樣小規模的遊戲公司,通常是老闆去了解客戶需求,因此老闆是最接近 product owner 的角色,產品狀況是否能上線也是由老闆決定。
但是目前列出的清單只有工程師和美術的觀點(是的也沒有企劃),並沒有老闆(PO)和客戶的觀點,這樣如何能確定那些做完就會滿足客戶的需求?
因此我要求老闆明天把產品目前的版本從頭到尾整個看過一遍,列出一份待辦清單。
另一方面發現團隊沒有特定的工作流程,這不是長久之計,所以決定來導入一個由之前的敏捷經驗簡化、針對團隊客製化過的工作方式

2020/04/29 (D3)

一上班老闆就把大家都拉進來開會,他一邊看目前的產品,一邊提出哪些地方要改善或是簡化甚至拿掉。
在這個會議我偶爾會根據之前的開發經驗給予建議,但主要是引導團隊成員提出意見、團隊自行取得共識
同時也提醒老闆,如果想要如期上線就要盡量抓出哪些是可以不用做、簡單做或是上線後再做
因為產品規模不小,開著開著一天就過了。

2020/04/30 (D4)

隔天放假,所以這天是最後一天了。
也是一早就拉會議,先跟大家說明看板和每日立會,尤其著重在報告的重點和積極正面的心態。例如如果有人離題了,成員可以用溫和的方式提醒而非指責,這不是批鬥大會
有成員表示他前公司的每日立會搞得像是每天都在盯進度,我也不希望導入敏捷造成團隊壓力變大,所以建議初期先不要每天都立會,並且傳達一個觀念,沒有什麼是一定只能這樣做的,只要團隊有共識怎樣會更好,那就來實行看看
接著要團隊開始估工時,跟大家說明估太緊會有什麼問題,若有人估了大家覺得太長的工時,先不要懷疑他是否想偷懶,而是先確定他是否充分理解需求、需求想達到的目的,或是把做法想得太複雜了
這時有團隊成員提出應該要有驗收清單,很好,團隊能自行思考目前的工作流程還缺少什麼並提出,經團隊成員討論大家都覺得有需要,因此整理了驗收清單。
整理了一部分驗收清單並估工時,因為時間因素只估了一部分,但已經足以讓老闆認知到 x 月有沒有可能順利上線,面對現實
下班時有團隊成員表示「終於可以看到專案的目標在哪了,之前一直做一直做也不知道到底要做到哪裡。
比較可惜的是後續沒法跟團隊一起跑,只能祈禱不會跑歪了。
(結果 game server 的部分沒什麼幫到忙 XD)

總結

  • 因為經歷過初學敏捷的陣痛期,深知痛點在哪。所以我導入的是從經驗簡化、針對團隊客製化的版本,務求對團隊的衝擊最小化。
  • 著重於敏捷精神、讓團隊理解為什麼要這麼做,而不是要求團隊一定要做哪些形式、沒得討論。
  • 盡量不提及敏捷、Scrum 術語陷入名詞解釋,而是用團隊已經習慣的用語或是簡單易懂的用語。
  • 不建議團隊現在去看相關書籍,把書上寫的不了解為什麼的東西拿來直接硬套在團隊,失敗的機會很大,大家也會很痛苦。等團隊跑個一年後,真的覺得這個方法有幫助,真的很有興趣再去看書。
  • 以引導的方式讓團隊練習自己達成共識、做出決定,而非直接幫團隊做決定。
  • 鼓勵團隊成員提出意見,不管是怎樣的意見大家都以正面的心態看待、積極討論。
  • 除了要求 PO 對待辦清單做排序,甚至要忍痛做取捨。
  • 不執著於我們跑的敏捷是否正規,重要的是對團隊是否有幫助。如果之後團隊演化出更合適的工作方式把目前的取代掉,那是一件好事。

 

張貼在 軟體開發, 敏捷方法 | 標記 , , | 發表留言

CMake

Debug:

cmake -DCMAKE_BUILD_TYPE=Debug ..

Release:

cmake -DCMAKE_BUILD_TYPE=Release ..

張貼在 未分類 | 發表留言

ssh 免密碼登入、只能用 key 登入

免密碼登入:
$ ssh-keygen
把 ~/.ssh/id_rsa.pub 的內容加入遠端主機欲登入帳號的 ~/.ssh/authorized_keys。
遠端 ~/.ssh 目錄的權限要設為 700,~/.ssh/authorized_keys 的權限要設為 644。

只能用 key 登入:
/etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication no

參考資料:http://linux.vbird.org/linux_server/0310telnetssh.php#ssh_nopasswd

張貼在 未分類 | 發表留言

sudo 免密碼

$ sudo visudo
找到
%sudo ALL=(ALL:ALL) ALL
改成
%sudo ALL=(ALL:ALL) NOPASSWD:NOPASSWD:ALL

張貼在 未分類 | 發表留言

Linux 網路設定

/etc/network/interfaces
auto lo
iface lo inet loopback

allow-hotplug eth0
iface eth0 inet static
address 192.168.1.123
netmask 255.255.255.0
gateway 192.168.1.1
dns-nameservers 192.168.1.1

張貼在 未分類 | 發表留言

Building C++ Boost Libraries

建置步驟:

bootstrap
b2 -j4 address-model=32 variant=debug,release threading=multi link=static runtime-link=static,shared

把 stage\lib 目錄改名為 lib32。

b2 -j4 address-model=64 variant=debug,release threading=multi link=static runtime-link=static,shared

把 stage\lib 目錄改名為 lib64。

b2 -j4 address-model=32 variant=debug,release threading=multi link=shared runtime-link=shared

把 stage\lib 目錄改名為 dll32。

b2 -j4 address-model=64 variant=debug,release threading=multi link=shared runtime-link=shared

把 stage\lib 目錄改名為 dll64。

-j4 參數表示同時編譯 4 個檔案以縮短建置時間,剛好讓我電腦的 4 個核心都用上。
注意:32-bit 和 64-bit 不可以下在同一個指令,因為編出來的檔名一樣,會失敗。

Lib 檔案命名規則:

mt:     variant=release threading=multi runtime-link=shared
mt-gd:  variant=debug   threading=multi runtime-link=shared
mt-s:   variant=release threading=multi runtime-link=static
mt-sgd: variant=debug   threading=multi runtime-link=static

link=static 檔名開頭有 lib,link=shared 則沒有。

參考資料:

張貼在 C++, 軟體開發 | 標記 | 發表留言

C++ Smart Pointer: std::unique_ptr

std::unique_ptr class template

Header: <memory>
Namespace: std

unique_ptr 是一個封裝過的指標,用來管理物件的生命週期。

特性:

  • 解構時會釋放它所擁有的物件。
  • 例外發生時會被解構並釋放它所擁有的物件,避免 memory leak。
  • 不可複製,但可將物件所有權轉移出去。所以不會有兩個 unique_ptr 共同擁有同一個物件,避免同一個物件被釋放兩次。
  • 可自訂釋放物件的方式。
  • 可存放在 STL 容器。
  • 可支援陣列。

用法:

  • 使用 new 配置物件時把指標傳入建構子,然後它會在解構時 delete 指標釋放物件。

範例:

void f()
{
	unique_ptr<int> p(new int);  // p 擁有 int 物件。
	*p = 123;
	// p 解構時會釋放 int 物件。
}
  • 使用 move() 和 return 轉移所有權。

範例:

unique_ptr<int[]> f()
{
	unique_ptr<int[]> p(new int[10]);  // p 擁有 int 物件陣列。
	p[0] = 123;
	unique_ptr<int[]> p2(move(p));  // p 的物件所有權轉移給 p2。
	p2[0] = 456;
	return p2;  // p2 的物件所有權轉移給 caller。
}
  • get() 回傳物件指標。
  • release() 釋放物件所有權並回傳物件指標,不會釋放所擁有的物件。
  • reset() 管理新的物件並釋放原本擁有的物件。

範例:

void f()
{
	unique_ptr<int> p(new int);  // p 擁有 int 物件。
	*p.get() = 123;
	unique_ptr<int> p2;
	p2.reset(p.release());  // p 釋放物件所有權,p2 管理 p 原本擁有的物件。
	*p2 = 456;
	// p2 解構時會釋放 int 物件。
}

參考資料:

張貼在 C++, 軟體開發 | 標記 , | 發表留言