顯示具有 工作 標籤的文章。 顯示所有文章
顯示具有 工作 標籤的文章。 顯示所有文章

2022/12/10

NoEstimate - Allen Holub


上週同事分享了這個 Allen Holub 的影片
花了一點時間觀看並做了些筆記
在此紀錄一些小小心得

估算永遠都是在猜,而且總是猜不對


Allen Holub 說應該不要再對 tasks 做估算
因為從過去經驗來看
永遠都在猜而且也總是猜錯 (就是說估不準啦)
而你一旦有了估算,就會很自然地出現 deadline
有了 deadline,團隊就很容易被迫加班為了趕上 deadline
因此他認為估算導致了團隊無法 agile

加入機率在估算裡面


他提到 Steve McConnell (Code Complete 作者) 在 Software Estimation 書中提到一些方法
The Clean Coder (Uncle Bob 的書) 裡面也有提到 PERT
簡單說就是你不能只估一個時程
你應該要附加上這個時程可能實現的機率是多少,例如 20%
但 Allen Holub 說其實聽的人對 20% 這個數字是沒有概念的
他用可以裝填五顆子彈的左輪手槍來說明機率
(我覺得很棒的例子 XD)
當這把左輪手槍裡面只裝著四顆子彈時
你用這把左輪手槍指著自己的頭開槍
成功 (存活) 的機率就叫做 20%
一顆一顆拿掉機率就變成 40% -> 60% -> 80%
你說時程有 80% 機率會成功實現
跟此時開槍有 80% 不會轟掉腦袋
講者說就算是 80% 他也不會覺得開心 XD
很好的體現了這樣的估算其實也不一定有幫助

建議數有幾個 stories 不要用 story points


作者提到使用 story points 有個目的是要模糊估時這件事情
然而因為 story points 是個數字
很多時候會自然地被轉換成估時
所以他建議改用 Trivial、Easy、Normal、Hard、Herculean、Don't Know
這樣的字眼來避免 story points 變成工時
但你仍會需要一個可以評估的基準來做很多商業上的決策
他建議使用 projection 的方式 (可以從 24:28 開始看)
就是利用一個 iteration 可以完成多少個 stories
與 backlog 中的 stories 的總數去做 projection
你會得到一個做完所有 stories 可能的時間點
而根據研究結果發現用 stories 總數與 story points 總數
彼此的誤差大概只有 7% ~ 8% 左右
因此他建議不要再做 story points 的估算
(當然估算 story points 的過程帶來的溝通效果還是要做
只是不再要大家估算這個 story 是多少 points)

在前公司待的團隊一開始 team lead 就說我們不要估點數
大家有個默契就是一張票盡量評估約三天左右完成
然後就這樣一直執行了兩年多 (今年過完就三年了)
超過三天還是沒做完怎麼辦
通常會看情況是否可以拆開分段做
還是真的就是要多過三天
那就繼續做到完為止

2021/01/17

趨勢內訓 - Team Building 贏向 2021

標題是這次工作坊的主題 XD

2020 最後一周
團隊特別安排了一個整天的工作坊
帶這個體驗式學習活動的是鈺勤的魏大統老師
過去我也有參加過類似的訓練
不過這一次有蠻多活動都蠻有意思的
特別寫文章記錄一下一些感想
(其實是後來發現沒有寫下來很快就會忘記了XD)

防雷警告


我是建議不要特別去找答案
畢竟這些活動的設計
有點故意要當下讓你去體驗碰到問題時
心理或身體最直覺的一些反應
藉此觀察自己的盲點等等
以下我會先以記錄活動的基本介紹
最後再放上查到的一些資料跟個人的感想
要躲雷的就不要看到最後了

Four Square Puzzle



這是一個請大家等分圖案的小謎題
我查到的名稱叫做「四等分正方形 puzzle」(不是很確定原出處)
會要大家一起想怎麼用不同的方式等分這幾個正方形的白色區域

均等三角形


艾雪 Reptiles [圖片來源:wikipedia.org]

講師將我們分為三組
每組用小的 15 片特殊巧拼 (三種顏色各五片)
拼出他要求的「均等三角形」
最後大家再一起用大片的合拼一個均等三角形

特殊的巧拼可以在網路上買到 (蜥蜴拼圖 [] [])
這個圖案是荷蘭著名藝術家 M. C. Escher 的一個版畫作品 Reptiles
故宮 2014 年的時候有他的展覽 (艾雪的魔幻世界畫展)

Balancing Nails Puzzle


也是一個實體的小謎題
講師把大家分為三組
每組有一塊木頭
木頭上已經釘好了一根鐵釘
還有十根分開的鐵釘
目標是把十根鐵釘都放上那根釘子

DISC assessment


DISC 四大人格特質

前公司 VIVOTEK 的面試都會請應徵者做的一個分析
不過這次老師給的題目跟 VIVOTEK HR 的題目不大一樣
總之就是一般的人格分析

團隊領導的五大障礙


團隊領導的五大障礙 [圖片來源:博客來]

五個障礙是有先後關聯的
分別是:喪失信賴、忽視成果、害怕衝突、缺乏承諾、規避責任
書裡面有一個 checklist 來讓你知道你的團隊中該加強甚麼部分

Johari window


Johari window

心理學家 Joseph Luft 與 Harry Ingham 提出的
主要是想表達自我認知與他人認知的差異
進而鼓勵大家如何調整自我達到更好的工作氣氛與溝通效率

蘋果鳳梨遊戲


一個蠻有趣的破冰遊戲

Cycle time puzzle


Cycle Time Puzzle [圖片來源:mikecardus.com]

用十四條長短不一的木板
一開始由長到短從下往上堆疊在一起
看看團隊可以在多少時間內組合成跟圖一樣

以下雷區


感想與資料


Four Square Puzzle


參考資料:https://www.google.com/search?q=four+square+puzzle+area
不要被過去經驗限制
這遊戲在第三個項目時
會出現一個比較複雜的答案
導致你在最後一題時卡住
但是其實最後一題很簡單
曾經讀過一本書 - Think Again:避開錯誤決策的四個陷阱
裡面就提到了誤導性的經驗
過去成功經驗有時候會造成失敗的原因
所以處理問題時要常常提醒自己跳脫直覺或是經驗
這也是我喜歡團隊群體智慧的一個原因
因為別人有機會看到自己的盲點

均等三角形


這活動其實很多課程或工作坊都會有類似的
就是對於提出需求的人
你有沒有問清楚他要的到底是甚麼
其實定義上根本沒有均等三角形這種東西
但我們接到題目後
就很自然地認為是正三角形
所以導致了很多的浪費與重工

Balancing Nails Puzzle


參考資料:https://www.google.com/search?q=balancing+nails+puzzle
這裡老師想提的是面對困難的態度
一開始花了五分鐘
老師會暫停請每個小組討論要不要再繼續
大家可能會因為時間(接近休息時間了)或是其他因素
就想說放棄好了
而一個人表現出放棄的念頭時
會很明顯地影響到團隊裡其他人
另外就是一但決定放棄
接著也不會再去想方法達成了
當然我覺得停損也是蠻重要的考量點

DISC assessment


隨便 google 都可以找到很多題目,就不列了
一開始老師說有沒有聽過可以把人的個性分成四類的方法
我第一個想到的就是星座 XD
DISC 粗略把人分為了四大類
能稍微讓你了解同事們的人格特質
有助於理解大家的使用手冊
有趣的是
我在前公司測了不只一次
剛進公司的時候好像是貓頭鷹或無尾熊
隨著年資增長以及擔任管理職後
開始變成老虎或是孔雀

團隊領導的五大障礙


這本書當時在 VIVOTEK 的讀書會中有讀過
書中以一個虛構的公司帶出作者想表達的中心思想
用故事的方式讀起來比較不生硬
但是相對的有時候會讓人覺得讀了很多不相關的東西
書中作者有給出一個高效團隊評估問卷
總共有十五個問題
有興趣的可以用書名加上 team assessment 去搜尋
這個活動因為我看過書了所以沒有新的體悟
難的地方在於你要怎麼塑造環境來建立出這樣的團隊

Johari window


參考資料:
https://zh.wikipedia.org/wiki/%E5%91%A8%E5%93%88%E9%87%8C%E7%AA%97
https://en.wikipedia.org/wiki/Johari_window
這也是我之前聽過的
最先是在趨勢 TLC 內訓中看到
概念很簡單但是卻用了一種很好理解的模型來說明
重點是你應該要多說自己的想法
以及多聽其他人對你的意見
才能將所謂的開放我 (Open Self) 擴大

Cycle time puzzle


參考資料:https://www.google.com/search?q=cycle+time+puzzle
最後這個活動最有意思
當然是關於團隊合作﹑集體智慧﹑目標﹑向心力﹑持續改善等等有關
不過這類活動最難的地方
還是你要怎麼把在過程中體悟到的帶到平常的工作
非常需要自覺跟自我反省的功力

2020/12/16

利用 GitHub Actions 發布 React app 到 GitHub Pages

最近有佛心同事開了 React 教學工作坊
赫然發現自己已經好久沒有寫 UI 相關的程式了
果然是用進廢退
不過上了幾次課之後
一些相關的感覺又慢慢找回一點點

上完課後自己又重新作了一次工作坊上的 lab
忽然想到
若是要給別人看看自己寫的 React app
能否用 GitHub Pages 當作一個 demo site
又想到可以用 GitHub Actions 來佈署 GitHub Pages
基於上述的想法
蒐集了一些資料來玩玩看

首先是將 React app 放到 GitHub Pages 上
主要是參考西打藍 Siddharam 這篇文章 - 將create-react-app佈署到GitHub Pages
不過裡面是在 local 利用 gh-pages 這個套件
作出發布用的資料夾後
把東西推到自己 repository 的 gh-pages branch 內


設定 dev 相依套件 gh-pages 以及 homepage 屬性


接著要利用 GitHub Actions 作到自動佈署 GitHub Pages
參考找到的 Christoph Michel 這篇 - How to deploy a create-react-app with github-actions
裡面提到要讓 GitHub Actions 能夠作 git push
必須設定一個 deployment key
文章內有說明步驟
或是參考 GitHub 官方文件也可以很輕鬆完成


設定 deploy keys 跟 repository secrets


不過 Christoph Michel 那篇介紹的是
當每次 git push 到 master branch 時
會自動觸發 GitHub Actions 來發布
但我想要一種情境是
我可以手動選擇要發布的 branch
例如我可能作了兩個版本
個別放在 branch A 與 branch B
我想要隨時可以手動發布 branch A 或是 branch B 到 GitHub Pages
參考 Adam McArthur 這篇 - How to Manually Trigger a GitHub Actions Workflow
學到了一個手動觸發的 event - workflow_dispatch


手動觸發事件 - workflow_dispatch

最後放上這個 repository 給有興趣的人參考
https://github.com/LaurenceCheng/react-workshop-2020-winter

參考資料:

1. create-react-app docs
2. 將create-react-app佈署到GitHub Pages - 西打藍 Siddharam
3. How to deploy a create-react-app with github-actions - Christoph Michel
4. How to Manually Trigger a GitHub Actions Workflow - Adam McArthur
5. Working with GitHub Pages - GitHub Docs
6. Managing deploy keys - GitHub Docs
7. Manual events - Events that trigger workflows - GitHub Docs

2020/11/24

在 Windows 上用 PyCharm 開發, 在遠端 Linux 上執行

情境是這樣的

我想在 Windows 上使用 JetBrains 的 IDE - PyCharm 作開發
但是在遠端的 Linux 上執行開發好的 Python 作測試

基本上 JetBrains 的文件算是寫得蠻清楚的

首先先看一下 Linux 上的環境大概是怎樣
我以一台 AWS EC2 的機器當作遠端的 Linux
怎麼開 AWS EC2 跟怎麼連上開好的 EC2 我就不說明了
可以去看 AWS 的文件 [Launch your instance][Connect using WSL]
還有一個等等會用到的 [Connect using PuTTY]
裡面有教怎麼用 PuTTYgen 把 private key 從 .pem 轉出 .ppk 檔
後面 PyCharm 連線時會需要 .ppk 檔

首先,在遠端的 Linux 上安裝好 Python 3.7.9 以及作好 venv 的設定
我們放了一個測試的 mytest.py 在 /home/ec2-user/ec2_python3_workdir 中
當作遠端的環境


遠端的 Linux


接著啟動 PyCharm 開啟本機的對應的資料夾
我的情境是本機與遠端的資料夾
是同一個 repository 的 working copy
(不過後來發現其實遠端不必是 git 的 working copy)


啟動 PyCharm 選擇開啟本機資料夾


進入後可以發現有 Python interpreter 設定的警告訊息
接著進入 File 選單開啟設定


選擇 File -> Settings


進入設定之後,點選 Python Interpreter 項目
在右邊的區塊可以看到 Python Interpreter 的下拉選單顯示 "<No Interpreter>"
所以我們點擊選單右邊的齒輪按紐
準備新增一個 Python Interpreter


新增 Python Interpreter


新增的時候選擇 SSH Interpreter
在介面上點擊 Existing server configuration 右邊的 "..." 按鈕
建立新的 SSH configuration


建立 SSH configuration


進入到 SSH Configurations dialog 後
點擊左上角的 "+" 可以新增 SSH configuration
在右邊的連線資訊中輸入 EC2 的 FQDN 與 User name
Authentication type 選 Key pair 後
在 Private key file 中填入一開始我們轉換好的 .ppk 檔


填入遠端 Linux 連線資訊


按下 Test Connection 按鈕
確認填入的資訊是可以成功連上遠端 Linux 機器的
接著按下 OK 直到回到 SSH Interpreter 那個 dialog 後按 Next


測試連線成功


下一步是設定遠端 Linux Python 的路徑
我們因為有用 venv 的關係
所以路徑設定為 /home/ec2-user/ec2_python3_workdir/.venv/bin/python3
這裡可以直接瀏覽遠端 Linux 上的檔案系統
選好後按下 OK


選擇遠端 Linux 要使用的 Python interpreter 路徑


再來設定本機與遠端同步的資料夾
就設定到 /home/ec2-user/ec2_python3_workdir
這個設定是讓之後在本機上的修改
都會上傳到遠端 Linux 的這個路徑中
設定好後就一路 OK 到底
然後回到原本 Project 的介面


設定同步資料夾


這時候可以打開 Remote Host 的視窗
展開到我們設定同步的資料夾時
可以看到綠色的 highlight
每次修改本機檔案後儲存
可在右下角 File Transfer 視窗看到 PyCharm 在幫我們上傳


本機編輯後可自動上傳至遠端 Linux


最後就是按下執行
在左下角的 Run 視窗能看到執行結果
也可以透過右邊 Remote Host 視窗開啟遠端的檔案來看
到這一步算是完成了本機開發遠端執行的目的
後續要接著執行 unit test 並在 PyCharm 的介面上看到各項測試綠燈也是可以的


遠端執行修改後的結果

2020/03/02

在 Windows 上用 Visual Studio 2019 開發 Linux C++ 程式

情境是這樣的

我已經存在一個 repository 寫好了 Makefile
可以在 Linux 上透過 make 編譯出執行檔
想用 Visual Studio 開發並 debug 這樣一個程式

手上有的環境跟 GitHub repository

其實 Microsoft 官方文件介紹得非常清楚
跟著文件做就可以很簡單的建立一套開發環境

首先在 Visual Studio 上必須先安裝 Linux development with C++ 的 workload

安裝 Linux development with C++ in vs2019

接著在你的 Linux 系統上確認有安裝需要的套件
g++, gdb, rsync, zip, make, openssh-server 等

然後啟動 Visual Studio 後進入 Tools > Options 選單
在 Cross Platform > Connection Manager 頁面按下 Add 按鈕
並輸入連線的資訊
當然可以使用 SSH Private Key 的方式做認證

設定與 Linux 的連線

輸入與 Linux 連線的資訊

接著就可以建立新的專案
選擇 Makefile Project (for Linux) template
路徑設定在我們已經有的 repository 資料夾內
因為後續路徑關係
我們把 .sln 跟 .vcxproj 兩個檔案放到跟 Makefile 同一層

建立 Makefile Project

選擇在原本 Linux 程式的 repository 資料夾下建立

把 .sln 與 .vcxproj 移動到 Makefile 同目錄

再來把所有相關的 sources 跟 Makefile 都加入專案內
接著進入 Project > Properties 選單
在 Remote Build 頁面的 Build Command Line 設定填入 make all
最後按下 Build Solution (Ctrl + Shift + B)

加入已存在的檔案

設定 Remote Build

可以看到執行建置時, 複製到遠端 Linux 並執行 make all

這時候可以在 Linux 裡面發現被複製過去的檔案
default 會在使用者的 home 路徑下的 projects 資料夾
這個路徑也能在 Project Properties 裡修改

設定複製到遠端 Linux 的路徑

檔案被複製到 Linux 上的樣子

最後設定 debugging 的資訊
跟以往在 Windows 上的設定類似
不過路徑改為遠端 Linux 上的
執行沒問題後就可以加上一些 breakpoints 來試試看吧

設定 debugging 啟動資訊

用 Visual Studio 2019 debug Linux C++ 程式的過程

我沒有使用更多深入的功能
但就目前有接觸到的基本功能來說
體驗算是與原本開發 Windows C++ 程式非常一致
很快就可以上手

2019/07/17

眼前的黑不是黑,你說的 I 是哪個 i

[蕭煌奇的經典歌曲]

基於這個案例實在太經典了
除了前公司,現在的公司也有遇到過
本來想請前公司的同事幫忙
把我在內部分享的文章轉寄給我,然後重貼在這裡
但是據說該 forum 已經暫停服務
所以乾脆重新再寫一次吧

一個土耳其客戶回報某個功能失效


記得從 log 檔分析
是類似找不到某個 database table 的錯誤
研究了半天發現是大小寫不一致造成的
假設有一張 table 名字叫作 CustomerInfo
在建立 database 時寫成全小寫的 customerinfo
但是在程式裡面使用 SQL statement 時是寫成 CustomerInfo
在英文語系的時候很正常
可是在土耳其語系的時候就不行了
原因是土耳其語有兩個意料之外的字母

大寫字母 小寫字母
Iı
İi

所以 CustomerInfo 與 customerinfo 是不一樣的字母組成

其實字母數都不一樣的匈牙利語


又有一次遇到了類似的問題
也是找不到某個 database table 的錯誤
這次大腦的迴路就響起了警鈴
難道又是跟大小寫有關
假設有個 table 叫做 BasicSet
一樣建立的時候用全小寫
使用的時候寫成了 camel case
原因是匈牙利語中有特殊的字母

大寫字母 小寫字母
Cscs
Dzdz

所以 B-a-s-i-c-S-e-t 跟 b-a-s-i-cs-e-t 根本連字母數都不一樣

結論


就是大小寫使用的時候一定要一致
Windows 不是 case sensitive 的環境
所以導致測試的時候可能會忽略了這一點
這次公司遇到的就與 database 無關
而是在執行指令的時候踩到了這個雷

參考
土耳其语 - Wikipedia
匈牙利语 - Wikipedia

2019/03/19

Scrum Drawing Game by Juggernaut



前言


今天在公司內部上到了 Diro 哥非常推薦的一門課
Scrum Drawing Game [參考: Scrum Drawing Game 1.2 四小時豪華版]
講課的人是發想出這個遊戲的作者 Juggernaut
第一次與賈格的一面之緣是在新竹的敏捷活動
當天也是第一次參與 91 哥的 workshop
非常感謝我待的 Group 特地安排一個專班
請賈格來帶這一個 workshop
即使過去在前公司 VIVOTEK 跑了三年多的 scrum
還是可以從這樣的 workshop 學習到很多東西

客戶想的跟說的跟你認為的永遠不一樣 [圖片來源 : knowyourmeme.com]


產品探索的重要性


因為 Scrum 的精神與流程還算有點經驗
所以敏捷開發與 Scrum 的部分只是再次透過賈格的說明
重新驗證自己的理解有沒有問題
不過倒是對於產品探索本身有了一些新的學習
今天我們不是得分最高的組別
我後來覺得在唯一一次 stakeholder 到團隊來說明需求的時候
有一些地方做得不好以及應該可以做得更好

  1. 團隊說了太多話
  2. 大家可能急著把想做的事情列出來,卻不知不覺說了太多假設的事情。
    例如:客戶列了很多跟隱私有關的需求,我們就以為他一定很重視隱私。
    結果我們先把整個房子對外窗都做單面玻璃,還在大門做了指紋跟虹膜辨識。
    客戶驗收了,但是這項需求的 value 卻是 0... Orz

  3. 團隊應該要只問問題
  4. 回家的路上跟洗澡的時候,我想想,團隊應該只能問問題。
    因為很難得可以直接接觸客戶,應該要放下所有腦補,直接以很多的問題來確認客戶到底在想甚麼。
    甚至應該問客戶最重要最在乎的是甚麼,因為那通常是對方認為對他價值最高的事情。
    所以「聽」跟「問」是很重要的。
    這點也呼應了 91 哥說的,需求是問出來的,以前我們會抓著 PO 把事情問清楚。
    很有趣的,離開了那樣的情境,反而卻忘了要做到一樣的事情。
    看來是還不夠融入自己的靈魂啊 XD

2018/11/13

用 Stylus 幫你的 GitHub 網頁換皮

原本 GitHub 的配色 [截圖至 github.com]
可能有人跟我一樣比較偏好暗一點的背景色
所以我試著找方法來改變 GitHub 網頁的配色

修改後 GitHub 的配色 [截圖至 github.com]

研究了一下發現 GitHub-Dark 這個 repo
裡面有教你透過安裝 Stylus 這個 browser extension
再加上套用設計好的 CSS
就可以將你的 GitHub 網頁套用你喜歡的配色
不過 Stylus 是透過 URL matching 來決定哪個網站要套用哪套 CSS
如果公司使用的是 GitHub Enterprise
你就需要修改 Stylus 的設定把 self-hosted 的 domain 加入
這裡以 Chrome 為範例示範流程

點下右上角 Stylus Icon 後點擊 Manage 按鈕
點擊 GitHub Dark (看起來不像可以點的樣子)
1. 點擊最右邊的加號
2. 在 URL matching the regexp 填入你想套用的 GitHub domain
3. 最後點左上角的 Save

2018/07/19

再見 VIVOTEK

本文開始,文長請見諒

初見晶睿通訊


其實當初國防役在面試的時候
VIVOTEK 並沒有在我投遞履歷的清單當中
因為金門王的建議
所以我才投了 VIVOTEK
當時第一關的面試官是 Bruce
我到現在還記得他問了甚麼問題 XD
也在面試的過程中
跟未來會合作多年的 Diro 哥打到照面
很幸運的我通過了第一關的面試
接著與當時的經理喬伊及藍總的面試也順利
於是我就這樣取得了 VIVOTEK 的 offer

國防役的四年


我在 2007 年 10 月提前先到公司上班
之後再到關西受國防役的軍事訓練
2008 年的 1 月 14 日是我的報到日
也是在 VIVOTEK 國防役正式啟動的日子
很幸運地加入了當時研發二部 (R2) 的 Server Team
組長是 Lloyd
我們組一開始含組長總共就三個人
R2 在那時候所有的人也才二十人不到
但是我覺得我們是小而美的單位
當年肩負了相當重要的自有品牌軟體的開發
印象非常非常深的是有一年跨年夜
離開公司的時候跟同組的 Jason 說
「你等下說不定會在福和橋上看到一零一煙火喔 XD」
結果連假結束 R2 的大家長 Perkins 說他元旦四日連假都有來公司 Orz

總之我覺得能在 VIVOTEK 服國防役是非常幸運的
因為從小道消息指出
在關西同班的某些同袍
報到了一周還一個月後就直接決定回役
有地方是到職一個月後
就讓人寧願回部隊當兵也不想待四年
可見那地方有多水深火熱 XD
非常感謝所有 VIVOTEK 的同事長官
讓我能在這學習到非常多的技能與經驗

管理工作帶來不同的職涯經歷


隨著 R2 人數漸增
運氣不錯的被晉升成初階管理人員
自己的組最少的時候有三個組員
最多的時候則有七個組員
一直到最後離職前
我都還是擔任組長的職務
能夠接觸管理工作是我職涯中最特別的經驗

Perkins 在我剛進公司的第一年
有次面談時跟我提到
在面對把工作當作 routine 卻缺乏動力提升自己的人時
你會怎麼做?
當時的我屬於
「每個人應該都有選擇自己生活方式的自由,我不應干涉對方」這一派
P 老大說他以前也是這樣想的
但是後來他改變了
他當時的說法大概是這樣
「如果你的幫助或建議,能夠讓他有一點點改變的契機,那對他來說會是很大的影響」

有趣的是 P 老大並沒有告訴我一定要這樣想
但我在擔任管理職的過程中竟慢慢變成他口中的那一派
我喜歡分享我會的給其他人
我也喜歡回答其他人的問題
我更喜歡聽聽成員對於目前的工作有甚麼看法
並試著討論及給予他我能提出的建議
這是剛開始工作的我不會做的事情
以前的我覺得何必去改變別人的想法跟價值觀
現在我覺得如果他可以從我這邊得到一絲絲資訊
使得他自己能變得更好
那我會比他還要高興

練習說話也是擔任管理職的重要學習
面試以及一對一的面談都很需要
還有最難的就是說你不想說的話
做你內心會抗拒但又不得不做的事情時
我常跟成員說
擔任管理職帶給我最大的影響是
它就像一面鏡子
會幫助我發現以往沒有看過的自己
也算是某種讓自己離開舒適圈的一種方式吧

有幸參與敏捷轉型


在 2015 年的 1 月
R2 在 Diro 哥的帶領下開始導入敏捷開發
在好幾年前我們似懂非懂的嘗試過一點點
當然最後是失敗了
這次 Diro 哥勢在必行地做了很多準備
很幸運地我們算是有轉型過去
這三年中開拓了我的眼界
原來我們還有很多的可能性
革命尚未成功,同志仍須努力

最後要幫忙拉票一下


在 VIVOTEK 待了十年半
從來沒想過第一份工作就做了這麼久
我在這裡成家立業
還請了一段時間的育嬰留停
VIVOTEK R2 的同事們都很好相處
主管們對於各種意見也是以很開放的態度傾聽
除了內部自由發起的讀書會外
公司對於人的培養也很願意投資
無論是請外部講師到公司內訓
還是讓你到外面參加訓練課程或研討會
我本人就參加過資策會開的侯捷的課
以及到北京參加 QConf
只要是對於提升自我能力有幫助的
主管們都願意利用公司資源給予支持
歡迎有志人士可以跟 Diro 哥了解一下

我是因為禁不住內心對於舒適圈的恐懼感
以及想嘗試追尋更不一樣的刺激
所以選擇離開
但必須說如果可以再來一次
我還是會選擇 VIVOTEK 作為第一份工作的

天下無不散的筵席

我的國中導師在畢業紀念冊留下了這樣的句子

泉涸,魚相與處於陸,相呴以溼,相濡以沫,不如相忘於江湖。

這一段話一直到我當組長
第一個成員跟我說要離職後
我在感到很失落的當下才忽然懂了
如果真心的希望對方能過的更好
那就是在對方做了決定時
替他高興並且為他加油
雖然彼此可能不能再一起合作
但看到離開的那些成員都能更有發揮
這樣就很好了

希望 VIVOTEK 的各位都能越來越好,業績蒸蒸日上

2017/02/02

在 Database 裡面儲存樹的內容


前一陣子工作需要在 Database 裡面儲存一棵樹的資料
在 SlideShare 上看了一篇
Models for Hierarchical Data with SQL and PHP - by Bill Karwin, Percona Inc.
覺得蠻有趣的
特別用部落格整理一下
以下的圖片都來自原作者的 slides
SQL statements 的部分有些是作者 slides 內的
有些是我自己在 sqlfiddle 上試寫的
以 SQLite 支援的語法為主

作者介紹了四種實作
分別為 Adjacency List、Path Enumeration、Nested Sets 以及 Closure Table
並且很貼心的作了一張表來比較


作者以一個 bug 回報系統的討論區來作例子
可以想成一個節點就是一篇文章
你回覆某一篇你就成為該篇的子節點
(以下把節點稱作 Node)


Adjacency List


Adjacency List 算是大部分人第一時間會想到的方式
就是每一筆記錄一個 Node
然後用一個欄位來記 parent Node的 ID


新增,刪除,移動一個 Node, 或是移動子樹都很容易
-- 新增一個 Node 到 Node 5 下
INSERT INTO Comments (parent_id, author, comment)
VALUES (5,
        'Fran',
        'I agree!');

-- 刪除 Node 7
DELETE
FROM Comments
WHERE comment_id = 7;

-- 移動 Node 6 到 Node 3 底下 (若 Node 6 不是 leaf 則會移動整個 subtree)
UPDATE Comments
SET parent_id = 3
WHERE comment_id = 6;
查詢某一個 Node 的 children (只向下一個 level) 也不難
-- 取得 Node 2 的 children
SELECT c2.*
FROM Comments c1
LEFT JOIN Comments c2 ON (c2.parent_id = c1.comment_id)
WHERE c1.comment_id = 2;
但是要取得整顆子樹就不容易,因為必須遞迴地拿 (文章有介紹寫法,有興趣的可以去看)
因此刪除子樹也不容易

Path Enumeration


Path Enumeration 紀錄更多資訊,不像 Adjacency List 只記錄 parent 的 id
這個方法紀錄了從 root 到自己的完整路徑


新增,刪除,移動一個 Node, 或是移動子樹也不難
-- 新增一個 Node 到 Node 5 下
INSERT INTO Comments (author, comment)
VALUES ('Fran',
        'I agree');

UPDATE Comments
SET path =
    (SELECT path
     FROM Comments
     WHERE comment_id = 5) || last_insert_rowid() || '/'
WHERE comment_id = last_insert_rowid();

-- 刪除 Node 7
DELETE
FROM Comments
WHERE path LIKE
        (SELECT path
         FROM Comments
         WHERE comment_id = 7) || '%';

-- 移動 Node 6 到 Node 3 底下 (若 Node 6 不是 leaf 則會移動整個 subtree)
UPDATE Comments
SET path =
    (SELECT path
     FROM Comments
     WHERE comment_id = 3) || substr(path, instr(path, '6'))
WHERE path LIKE
        (SELECT path
         FROM Comments
         WHERE comment_id = 6) || '%';
與 Adjacent List 不同的是,查詢某一個 Node 的子樹不難
-- 取得 Node 2 的 subtree
SELECT *
FROM Comments
WHERE path LIKE
        (SELECT path
         FROM Comments
         WHERE comment_id = 2) || '%/%';
雖然投影片中說查一層 children 很難
但是我試了一下好像也還好
-- 取得 Node 2 的 children
SELECT *
FROM Comments
WHERE path LIKE
        (SELECT path
         FROM Comments
         WHERE comment_id = 2) || '_/';

Nested Sets


Nested Sets 蠻特別的,每一筆資料存著左右兩個數字
左數是一個比所有子節點的數字小的一個數 (每個子節點也是會有左右兩個數字)
右數則是一個比所有子節點的數字都大的一個數
所以 root 的左數一定是所有節點的左右數中最小的
反之 root 的右數則是所有節點的數字中最大的
頭暈了吧 XDDDDD
一圖勝萬言


查子樹很容易
-- 取得 Node 2 的 subtree
SELECT descendant.comment_id
FROM Comments parent
JOIN Comments descendant ON (descendant.nsleft BETWEEN parent.nsleft AND parent.nsright)
WHERE parent.comment_id = 2
    AND descendant.comment_id <> 2;
但是新增,刪除,移動一個 Node, 或是移動子樹都不容易
因為你會必須更動很多相關連的左右數
以新增一個 Node 為例
-- 新增一個 Node 到 Node 5 下
SELECT nsleft,
       nsright
FROM Comments
WHERE comment_id = 5;
-- 把結果存在 $nsleft_5, SQLite 沒有支援 local variable

UPDATE Comments
SET nsleft = CASE
                 WHEN nsleft >= ($nsleft_5 + 1) THEN nsleft + 2
                 ELSE nsleft
             END,
             nsright = nsright + 2
WHERE nsright >= $nsleft_5;

INSERT INTO Comments (nsleft, nsright, author, comment)
VALUES ($nsleft_5 + 1,
        $nsleft_5 + 2,
        'Fran',
        'I agree!');
slides 內也說明了一下查一層 children 的困難處
其實作者也把 SQL statements 寫出來了
只是真的不是很直覺,需要稍微在腦中想一下才知道他為什麼那樣寫

Closure Table


這是唯一用到兩張表的方法
一張表存 Nodes 的資訊
以 bug 回報系統來說,就是像作者,內文之類
另一張表存每一個 Node 到它自己所有的 descendants 的路徑
一樣一圖勝萬言


說真的我第一次看到這個方法時讚嘆不已
因為沒有研究過這個問題
所以沒想到有這樣的設計方式
投影片中更提到 TreePaths 這張表可以多存一個路徑長度的資訊
這樣在作一些查詢時會更容易一點


新增 Node 的時候要到 TreePaths 的表裡面建立相對應的路徑
-- 新增一個 Node 到 Node 5 下
INSERT INTO Comments(author, comment)
VALUES ('Fran',
        'I agree!');

-- 新增 paths, 複製指到 Node 5 的所有 paths 並把 descendants 換成新的
INSERT INTO TreePaths (ancestor, descendant, length)
SELECT ancestor,
       last_insert_rowid(),
       length + 1
FROM TreePaths
WHERE descendant = 5
    UNION ALL
    SELECT last_insert_rowid(),
           last_insert_rowid(),
           0; -- 加上一條自己指自己的 path
刪除也蠻簡單的
-- 刪除 Node 7
DELETE
FROM TreePaths
WHERE descendant = 7;

DELETE
FROM Comments
WHERE comment_id = 7;
利用 TreePaths 裡的 length 欄位
在查詢子樹或是一層的 children 時很方便
-- 取得 Node 2 的 children
SELECT c.*
FROM Comments c
JOIN TreePaths t ON (c.comment_id = t.descendant)
WHERE t.ancestor = 2
    AND t.length = 1;

-- 取得 Node 2 的 subtree
SELECT c.*
FROM Comments c
JOIN TreePaths t ON (c.comment_id = t.descendant)
WHERE t.ancestor = 2
    AND t.length > 0;
移動應該是最麻煩的
因為你要先刪掉所有相關的路徑
再重新建立移動後新的路徑
-- 移動 Node 6 到 Node 3 底下 (若 Node 6 不是 leaf 則會移動整個 subtree)
DELETE
FROM TreePaths
WHERE descendant IN
        (SELECT descendant
         FROM TreePaths
         WHERE ancestor = 6 )
    AND ancestor NOT IN
        (SELECT descendant
         FROM TreePaths
         WHERE ancestor = 6);

INSERT INTO TreePaths (ancestor, descendant, length)
SELECT supertree.ancestor,
       subtree.descendant,
       supertree.length + subtree.length + 1
FROM TreePaths AS supertree
JOIN TreePaths AS subtree
WHERE subtree.ancestor = 6
    AND supertree.descendant = 3;
最後是把整棵樹從 root 開始列出來所有 Nodes
SELECT n.*,
       p.ancestor AS parent
FROM TreePaths AS t
INNER JOIN Nodes AS n ON t.descendant = n.treeNodeId
LEFT JOIN TreePaths AS p ON p.descendant = n.treeNodeId
AND p.length = 1
WHERE (t.ancestor = 1)
    AND (p.ancestor IS NOT NULL
         OR n.treeNodeId = 1)
ORDER BY t.length;

2009/07/28

Javscript

不知不覺到公司也已經一年半過去了
最近因為支援組內某個人
所以又開始寫javascript
忽然今天想到
學javascript也是好久好久以前的事情
沒想到現在javscript可以作到當時看不到的事情
時代的快速前進忽然在這種奇怪的時候被感覺到
不過現在的那些library真的是相當強大啊XDD
(置入性廣告 你們看看funp那麼fancyXDD)

然後又再次回想到
會去學javascript還真是一堆巧合造成的
腦袋裡忽然湧現了好多人的臉
David, 忠穎, 盧小三的直屬Sam, Mouse等等
如果不是這些人的出現
也許我現在就會學的很慢吧
所以其實內心是蠻感謝這段遭遇的
雖然我不知道最後為什麼事情是這樣很奇怪的告一段落
也許盧公當初有跟我講過原委吧
但是我現在真的想不起來
只記得David不知道為什麼說我們有學長們的包袱
anyway, 多年以後回憶起那段日子
這些人其實抽離掉工作夥伴的身分後
也是還存在著好朋友的身分

不知不覺又開始回憶過去的時光
這是老了的徵兆嗎XDD

2008/02/04

掛狗牌的工程師

2008/01/30

邁入第三週
在上週四我從掛空白狗牌的工程師
正式升級成掛有名字狗牌的工程師
每天的生活還算ok
一板一眼 上班吃飯下班
完成被assign的工作 寫出要求的功能
de出找了一晚上的bug
都能令心情雀躍一下

這週一我的team leader Lloyd
在吃午飯時聊到他越來越晚出門
即使早起還是會在家裡慢慢摸
我說
"那不就要把每天早上可以做的事情寫下來
讓自己不要去做其他事情"
他回說
"應該是累了吧 穿襪子就慢慢穿 刷牙就慢慢刷"

聽完這句話的我只能陪苦笑
聽起來超苦的

晚餐時我問他
在台北有很多同學或朋友嗎
他說了比例後 補充但是在台北的沒有很要好
問他這週末在幹麻
他說睡覺 因為天氣不好
聽起來就是很苦命的工程師

講了這麼多
希望自己可以不要變成這麼苦的programmer啊....XD

Bug bash

2008/01/30

http://en.wikipedia.org/wiki/Bug_bash

禮拜一下午本來要做bug bash
結果bug回報的內部系統發生問題

改在今天一大早無預警的開始
反正就是想盡辦法比賽找bug

一開始實在是傻傻的
不大確定怎樣的情況要上bug
後來看了大家跟瘋子一樣的送出bug
看了一下內容 慢慢就進入狀況

看了一些國外programmers的blog談到bug bash
人家的程式果然夠大
有的bug bash超過一天(我們只做兩個多小時)
而且bug bash的時間內還有點心XD

bug bash初體驗
感受最深的就是
如果你是負責maintain那部份的人
看到大家瘋狂的丟bug給你
應該是苦笑吧
有人還戲稱
"你們在bug bash, 我在debug bash"

另外就是
為了確定我找到的bug是reproducible
我都會確認流程超級多次
這也是需要經驗的地方吧

總之 是一次不錯的經驗