今天一整天,就只改了一行程式。
對,就只有一行!
我很偷懶嗎?才不,今天可是超級「精實」。
那為什麼只改一行而已?改一行要那麼久嗎?
如果你是主管,你會怎麼評斷這位工程師?
如果你是位注重量化,把「人月」、「line of code」「function point」掛在嘴上,透過一些指標,這位工程師的一天簡直是災難吧!
先聽聽我今天做了什麼事
一早被指派這個工作後,先瞭解問題是什麼,可能的因素又有那些,接著就開始設計如何測試來確定是什麼原因造成的。等確定成因,大概就過了半天。半天,真的很快了。
接下來,就是修正這個錯誤。對,就是改那一行!真的不是我偷懶,有問題的就只有那一行,所以也只能改那一行。(我也很盡責的加上註解喔)。這大概花了幾分鐘。
這樣不就解決了嗎?你還有半天可以做別的事呀。這半天被你摸掉了喔。
才不是啦。公司的機器有十幾種models,而這個程式會被用在所有的models中,所以,除了出錯的那個機種外,我還必須一個一個機種去做regression test,以確定這樣的改法在別的機種上也可以正確運作。等這些機種都測完,一天也結束了。
所以,別再用那些奇怪的指標來衡量工程師了。有時,工程師做的事是一種ART!
就好像,你不該跟梵谷計較,在那幅星空中應該多畫幾顆星星才比較有價值!
2014/11/02
大法官
在片中,法律,對於擔任法官的父親,是正義;對於擔任律師的兒子,是工具。
兩位演員勞勃杜瓦(Robert Duvall)與小勞勃道尼(Robert Downey Jr.),真的演活了劇中的角色。另外,韋娜法米加(Vera Farmiga)在劇中很有戲的眼神,讓薩曼莎一角的浪漫不羈都活了起來,真的擄獲了我的心。
還有,Carla與Lauren都有咬頭髮習慣的動作與神情,真的是有趣的梗。
好了,談談我的感受,對於大部份的人子,父親,從小就像是大樹、就像是無所不能的超人。但隨著日子飛逝,人子逐漸長成大人,而人父也逐漸衰老。電影中最觸動我一幕是,法官父親在浴室狼狽的那一幕。
如果,你曾經看過父親年邁而脆弱的那一刻,你一定會警醒,那棵從小就庇護著你的大樹,已不再如你想像的巨大與堅強。那種警醒,會讓人很心痛,也會在你的心中烙下一個印痕,提醒著你有個時間終將到來,當那一刻到來,你不再有人可以依靠,可以幫你,可以再庇廕你。那種感覺,應該是為人子女的你我在心中會隱隱作痛的疤。
而在電影的最後一幕,律師走進父親的法庭,走上法官席,觸摸著父親坐了數十年的座椅,看著座椅旋轉。當座椅停下來,面對著他停下來時,我覺得在人子的心中,應該萌生出了一個決定!
2014/10/30
GCM推播訊息(notification)延遲問題
最近在開發Android APP,使用到GCM(Google Cloud Message),發現一個問題:
我們的server已經送出notification,可是Android phone/table有時很快(兩三秒)就收到推播訊息,有時則等超過10分鐘才收到。
雖然Google宣稱notification不保證即時送達,也不保證可以送達,不過我們還是希望在免費的服務下,能夠儘可能的即時送達
對有些應用而言,超過5分鐘就真的很久了
工程師個性使然,總是想找出是我們的server+APP有問題,還是其他因素造成。因為有時是即時就能收到,照理說應該不是server或APP的問題
找了andQlimax的po文,覺得他的測試與推論是合理的,也符合我所觀察到的狀況
手機/平板與GCM server間是透過TCP connection來進行通訊。當手機/平板連上網路時,Android就與GCM server建立連線。為了維持連線,手機/平板會定期送出heartbeat訊號到GCM server。andQlimax觀察到如果是使用3G/4G連線,則每28分鐘會送一次heartbeat;若是用WiFi則是15分鐘。(為什麼間距那麼大?這除了要考慮手機平板的耗電外,還有GCM server的負擔等等)
andQlimax認為一般電信服務商(3G/4G)或WiFi router(無線分享器...),就資源分配與使用效率等考量,通常不會無限維持這麼多的TCP connection(因為可以建立的connection數是有限的),因此這些設備(3G/4G:基地台; WiFi:無線分享器/HotSpot)會定期(例如每5分鐘)檢視那些connection是idle的(沒有傳送資料),就將這個connection關掉。
因為Android的heartbeat間距很長,所以手機平板與GCM server間的TCP connection會被關掉,因此當有訊息時,GCM server便無法透過原來建立的connection將訊息送到手機平板,必須等到手機端時間到要發heartbeat時,才會重新建立連線。
所以當connection還沒有被關掉,或是heartbeat週期很快又到了,手機平板就能很快的接收到推播訊息;若是connection被關了,那就得等到下一次送heartbeat時才能收到notification了。
andQlimax在很多論壇與管道都呼籲Google/Android應該修改heartbeat的傳送週期。不過看來到目前Google都尚未採納。
如果,真的有mission critical的應用,也許應考慮是不是用long-polling request等機制來作,而不依賴GCM。
我們的server已經送出notification,可是Android phone/table有時很快(兩三秒)就收到推播訊息,有時則等超過10分鐘才收到。
雖然Google宣稱notification不保證即時送達,也不保證可以送達,不過我們還是希望在免費的服務下,能夠儘可能的即時送達
對有些應用而言,超過5分鐘就真的很久了
工程師個性使然,總是想找出是我們的server+APP有問題,還是其他因素造成。因為有時是即時就能收到,照理說應該不是server或APP的問題
找了andQlimax的po文,覺得他的測試與推論是合理的,也符合我所觀察到的狀況
手機/平板與GCM server間是透過TCP connection來進行通訊。當手機/平板連上網路時,Android就與GCM server建立連線。為了維持連線,手機/平板會定期送出heartbeat訊號到GCM server。andQlimax觀察到如果是使用3G/4G連線,則每28分鐘會送一次heartbeat;若是用WiFi則是15分鐘。(為什麼間距那麼大?這除了要考慮手機平板的耗電外,還有GCM server的負擔等等)
andQlimax認為一般電信服務商(3G/4G)或WiFi router(無線分享器...),就資源分配與使用效率等考量,通常不會無限維持這麼多的TCP connection(因為可以建立的connection數是有限的),因此這些設備(3G/4G:基地台; WiFi:無線分享器/HotSpot)會定期(例如每5分鐘)檢視那些connection是idle的(沒有傳送資料),就將這個connection關掉。
因為Android的heartbeat間距很長,所以手機平板與GCM server間的TCP connection會被關掉,因此當有訊息時,GCM server便無法透過原來建立的connection將訊息送到手機平板,必須等到手機端時間到要發heartbeat時,才會重新建立連線。
所以當connection還沒有被關掉,或是heartbeat週期很快又到了,手機平板就能很快的接收到推播訊息;若是connection被關了,那就得等到下一次送heartbeat時才能收到notification了。
andQlimax在很多論壇與管道都呼籲Google/Android應該修改heartbeat的傳送週期。不過看來到目前Google都尚未採納。
如果,真的有mission critical的應用,也許應考慮是不是用long-polling request等機制來作,而不依賴GCM。
2014/09/17
書摘:托爾斯泰藝術論
促使人類進步的兩大重要因素:語言文字、藝術。
- 語言文字;傳達人們的思想與經驗
- 藝術:傳達感覺與情感
藝術是一種人類的活動,藉此將自己的感受有意識地傳達給他人
藝術感染力的強度取決於三條件:
- 所傳達之情感的特別度
- 所傳達之情感的清晰度
- 藝術家的真誠度
2014/09/15
Android APP無法取得GCM notification token
維護一支具有GCM notification功能的Android APP,因應客戶customization需要,必須更改package name以及修改manifest裡的root package定義,這會影響generated出來的R.java的package定義,因此,須再針對受影響的各程式更改import路徑
這樣的改法應該是最簡單的,比用refactor功能變更各package的name快多了 (之前也遇到一樣的需求,這樣改就OK了,也不會大幅改變svn裡的架構)
不過卻遇到了一個問題,當device送資料到server時,GCM register ID(token)竟是空的! trace一下程式,我有一個GCMIntentService class是繼承GCMBaseIntentService,原來override上層的onRegistered是會被呼叫的,現在程式一執行,這個callback function竟然一直沒有被叫用,難怪token會是空的。 可是,這又是那裡出錯了?改的東西好像也沒幾個,而且那些應該都不會影響到這部份的功能呀。
找了許多資料,也做了一些嘗試,找到了一個因素,就是這個GCMIntentService必須要在menifest所定義的root package,例如說,menifest定義的package是com.abc.app,則這個service也要在com.abc.app,不可以在com.abc.app.service等其他的package中,即使manifest對service的宣告是指向com.abc.app.service也不行! 所以,只好再用refactor功能,把這個GCMIntentService移到它該在的package中,這樣執行起來就OK了!
這樣的改法應該是最簡單的,比用refactor功能變更各package的name快多了 (之前也遇到一樣的需求,這樣改就OK了,也不會大幅改變svn裡的架構)
不過卻遇到了一個問題,當device送資料到server時,GCM register ID(token)竟是空的! trace一下程式,我有一個GCMIntentService class是繼承GCMBaseIntentService,原來override上層的onRegistered是會被呼叫的,現在程式一執行,這個callback function竟然一直沒有被叫用,難怪token會是空的。 可是,這又是那裡出錯了?改的東西好像也沒幾個,而且那些應該都不會影響到這部份的功能呀。
找了許多資料,也做了一些嘗試,找到了一個因素,就是這個GCMIntentService必須要在menifest所定義的root package,例如說,menifest定義的package是com.abc.app,則這個service也要在com.abc.app,不可以在com.abc.app.service等其他的package中,即使manifest對service的宣告是指向com.abc.app.service也不行! 所以,只好再用refactor功能,把這個GCMIntentService移到它該在的package中,這樣執行起來就OK了!
訂閱:
文章 (Atom)