tag:blogger.com,1999:blog-47642005004327735672024-03-12T18:41:04.468-07:00Tom's IT notebookIT is not Information Technology here, IT means EVERYTHINGTom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.comBlogger81125tag:blogger.com,1999:blog-4764200500432773567.post-51223279112925495132022-05-16T10:39:00.001-07:002022-05-16T10:56:05.934-07:00Database 選擇的 cheatsheet,太棒了!<img id="id_1af_fc44_b834_fe8b" src="https://lh5.googleusercontent.com/nx-W3epVKbygcrMDUxwlGDb7b88ysfxdGXA1ID4aZ0Z6O6WjCLAKTcGtVnLg2RHAxTQ" alt="" title="" tooltip="" style="width: 812px; height: auto;"><br><br> Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-61567785400973393772021-01-09T03:46:00.001-08:002021-01-09T03:47:49.074-08:00關於 SQL timeout 的錯誤判別<p><span style="font-family: verdana;"> 今天看到網路上一篇討論 SQL Timeout 原因的探討文章。</span></p><p><span style="font-family: verdana;"> 由於那篇文章的結論和我過去經驗完全不同,所以我懷疑是不是我過去仰賴的長期判斷經驗有誤,特別寫了個 TestCase 作為比較。</span></p><p><span style="font-family: verdana;"> 首先我先引用該文章作為調查起點的 <span style="color: #6aa84f;"><b>Exception</b></span> 內容:</span></p><p><span style="font-family: verdana;"> </span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-EFrmon_cNT0/X_mS7P_ll3I/AAAAAAAA3Dk/OJuqYCzs_70vbCtucn-RtfVByt5fP0omgCNcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: verdana;"><img alt="" data-original-height="567" data-original-width="697" src="https://lh3.googleusercontent.com/-EFrmon_cNT0/X_mS7P_ll3I/AAAAAAAA3Dk/OJuqYCzs_70vbCtucn-RtfVByt5fP0omgCNcBGAsYHQ/s16000/image.png" /></span></a></div><span style="font-family: verdana;"><br /></span><p></p><p><span style="font-family: verdana;"><span></span></span></p><a name='more'></a><span style="font-family: verdana;"> 我先講一下那篇文章的結論,作者認為應該是 Connection Pooling 機制,造成無法有效取得 Pool 中的 Connection 所造成。但我有印象,無法取得 Connection 並不是 <b><span style="color: #6aa84f;">SqlException </span></b>這種錯誤,而是 <b><span style="color: #6aa84f;">InvalidOperationException </span></b>這個錯誤。</span><p></p><p><span style="font-family: verdana;"> 而且根據他給的錯誤訊息,明白寫上 Execution Timeout,所以我認定應該是執行的命令超過指定時間造成。為了驗證我過去的認知,我寫了一段 Test case 去測試。</span></p><p><span style="font-family: verdana;"> 第一個案例很簡單,就是執行一個需要十秒才能完成的指令,但是我在 Timeout 上卻只給 1 秒,所以會立刻就爆 Timeout 錯誤。</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-KF0PNw0lTgA/X_mUgNzCH7I/AAAAAAAA3Dw/Qez3bNLf3go61AcbLU3ksNL-CZsht_iOACNcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: verdana;"><img alt="" data-original-height="437" data-original-width="1270" height="221" src="https://lh3.googleusercontent.com/-KF0PNw0lTgA/X_mUgNzCH7I/AAAAAAAA3Dw/Qez3bNLf3go61AcbLU3ksNL-CZsht_iOACNcBGAsYHQ/w640-h221/image.png" width="640" /></span></a></div><span style="font-family: verdana;"><br /> 第二個案例,就是故意耗盡 Connection Pool 的資源,利用 List 鎖住這些取而不用的 Connection 物件,避免被 GC 回收掉。</span><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-vMpDvv5NnsI/X_mVMOpP9jI/AAAAAAAA3D4/-zwbywQ2qsozWw6EaDD_4O8ukBWY5_OzwCNcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: verdana;"><img alt="" data-original-height="515" data-original-width="1222" height="270" src="https://lh3.googleusercontent.com/-vMpDvv5NnsI/X_mVMOpP9jI/AAAAAAAA3D4/-zwbywQ2qsozWw6EaDD_4O8ukBWY5_OzwCNcBGAsYHQ/w640-h270/image.png" width="640" /></span></a></div><span style="font-family: verdana;"><br /> 讓我們比對兩這產生的 Error log 吧。</span><p></p><p><span style="font-family: verdana;"> 擷取輸出的 log 如下:</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-r6iCHlsAABU/X_mXa7HNEXI/AAAAAAAA3EQ/tYF5wHNtB9YWTqI9P2iwZk3tOnG4lx2kACNcBGAsYHQ/image.png" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="654" data-original-width="891" src="https://lh3.googleusercontent.com/-r6iCHlsAABU/X_mXa7HNEXI/AAAAAAAA3EQ/tYF5wHNtB9YWTqI9P2iwZk3tOnG4lx2kACNcBGAsYHQ/s16000/image.png" /></a></div><br /><br /></div><span style="font-family: verdana;"><br /><br /></span><p></p><p><span style="font-family: verdana;"> 所以我的經驗是真的,想法沒錯。原文章的病灶應該是指令本身太過耗時,應該以效能優化來作解法。</span></p>Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-14052950012756640082017-10-14T08:26:00.003-07:002017-10-29T22:35:27.462-07:00阿里雙十一的高頻交易分享<br />
<div style="text-align: center;">
<a href="http://2.bp.blogspot.com/-3ukP9q6XFTU/WeIsgEKF4yI/AAAAAAAAmdM/izwZbKDZCEEs-JPdJDk8zHudj5yVVgHMQCK4BGAYYCw/s1600/S153677T1478880576510.jpg" imageanchor="1"><img border="0" height="480" src="https://2.bp.blogspot.com/-3ukP9q6XFTU/WeIsgEKF4yI/AAAAAAAAmdM/izwZbKDZCEEs-JPdJDk8zHudj5yVVgHMQCK4BGAYYCw/s640/S153677T1478880576510.jpg" width="640" /></a> </div>
<div style="-en-clipboard: true;">
</div>
<div style="-en-clipboard: true;">
即將發生的網路電商的大事件,莫過於越來越接近的大陸雙十一。屢創高峰的雙十一購物節,究竟阿里巴巴是怎麼在技術上克服這種巨量湧入的交易量呢?
</div>
<div>
<br /></div>
<div>
前陣子到中國東北剛好因為業務合作需要而結識了一位在杭州擔任阿里巴巴架構師的高手。晚餐大家在酒醉耳酣之際,我們聊起這件事,做經驗交流。 </div>
<div>
<br />
<a name='more'></a></div>
<div style="text-align: center;">
</div>
<div style="text-align: center;">
<a href="http://3.bp.blogspot.com/-uhFtCFECsXE/Wfa6EZZJcdI/AAAAAAAAmpc/lnRZt2OIGCISEFAt-vhG_4inuCryGXG0QCK4BGAYYCw/s1600/alcohol-492871_1920-1024x683.jpg" imageanchor="1"><img border="0" height="426" src="https://3.bp.blogspot.com/-uhFtCFECsXE/Wfa6EZZJcdI/AAAAAAAAmpc/lnRZt2OIGCISEFAt-vhG_4inuCryGXG0QCK4BGAYYCw/s640/alcohol-492871_1920-1024x683.jpg" width="640" /></a> </div>
<div>
</div>
<div>
首先,什麼使用 NoSQL、分散式快取、反向代理、CDN...這些應付巨量『訪問』的技術,已經是業界常識,<span style="color: #cc0000;"><u>我在乎的是『真正的交易行為』,消化那種客戶訂單所產生的帳務與數量變化的處理方式</u></span>。阿里在這一塊仍是依賴具有 ATOM 特性的 RDB(關聯式數據庫),牽涉到金額和訂單絕不能混亂的議題,使用 RDB 是可以想見的選擇,而 RDB 最被詬病的弱點,恰好就是平行處理與巨量請求,所以這次的請益得到的知識相當寶貴。
</div>
<div>
<br /></div>
<div>
聊了一整晚,我將幾項手法的重點歸納如下:
</div>
<div>
<br /></div>
<ul>
<li><h3>
<span style="color: blue;">地區數據分庫:</span></h3>
首先,為了分散全中國湧入的交易量,依地區將數據分庫來讓客戶可以在地區性最近的機房進行交易,這是最基本的起手式。也就是北上廣深各自存取不同的數據庫,分散交易量這是基本的概念。<br /><br /> 但是數據分庫後,彼此之間如何一致地同步呢?<br /><br /> 答案是當下不做同步,那商品的數量如何控制呢?由於雙十一要開賣的商品是在幾天前就已經上架完畢,只是關閉不顯現,<span style="color: #cc0000;">不同地區的商品數量其實是根據過去的交易紀錄分析預測出來做分配的,也就是配置在不同地區的同一件商品,數量從一開始就不同</span>,北京看到的可能是一萬件庫存,上海看到的是兩萬件,而廠商就是要準備總共三萬件供應品。<br /><br /> 所以其實會有那種現象,北京看到該商品已經售完沒有存貨的信息,但上海可能還能搶到。但這不會影響購物體驗,因為使用者並不會發覺有這樣的差異,除非這時候他能 VPN 到不同地區的商品頁面才有機會看到不一致的商品數量。</li>
<li><h3>
<span style="color: blue;">商品品類分庫:</span></h3>
除了地區外,較熱賣的商品類別和較為冷門的二線商品也不會在同一個數據庫內,例如大熱門的 3C 商品和保健運動類商品就會被分開。甚至佔據大量交易的可能還會細分許多,例如 3C 的筆電和手機可能就被放在不同的數據庫了,<span style="color: #cc0000;">從使用者挑選商品進購物車的當下,就已經被安排在不同的數據庫內做操作,不會彼此影響</span>。</li>
<li><h3>
<span style="color: blue;">訂單編號編碼邏輯:</span></h3>
許多開發人員都被訓練成依賴數據庫自動生成的 Identity 當作叢集(PK)唯一鍵值,但這種做法其實嚴重拖累效能。所以阿里內部會有自己的訂單編號生成算法,例如先以地區碼+商品代碼+時間戳記等等產生唯一的訂單編號,這樣<span style="color: #cc0000;">編號的產生就可以被分散到大量的 AP 服務器集群內,各自平行演算,不用消耗數據庫的能力</span>。</li>
<li><h3>
<span style="color: blue;">預先塞入預估總量的數據單量:</span></h3>
既然訂單編號可以透過阿里自訂的演算方式產生,那就可以在雙十一之前就預先產生好。因為雙十一的高峰期很容易預估,其實系統只要挺過那個高峰,後面就不用擔心了。所以他們會過去經驗預估這次的訂單數量,事先把雙十一的高峰時段會用到的訂單號產生後事先寫入數據庫內!對,剛不是說過訂單編號內有時間戳記的編碼嗎?所以要產生的範圍是可以鎖定只要產生午夜到凌晨三點這個區間的所有可用的訂單編號,將這些『空白的』預先 Insert 到數據庫內,等到客戶真正下單的時候,演算出客戶的訂單編號用 update 的方式回寫內容。<br /><br /> 為何要這樣做呢?<span style="color: #cc0000;">因為數據庫在檢查 insert 進來的 PK 必須唯一值的必須做 table lock 鎖住整張表,這一 lock 就會阻擋其他交易寫入</span>,所以預先塞好訂單可以做到訂單數據平行寫入。</li>
</ul>
<div>
<br /></div>
<div>
此外,阿里架構師也跟我們分享了在雙十一之前,他們要演練總共 160+ 備援方案,包含網路切換和機房移轉等例行性作業,達到雙十一萬無一失的準備作業,因為那個當下只要服務掉幾分鐘離線,就可能損失上億,對於中國這一流的網路電商服務,真的是佩服他們技術人員的準備與備戰的態度。
</div>
<div>
<br /></div>
<div>
以上分享,希望可以擴展國內的技術視野,希望台灣電商也能有半個雙十一交易量的機會,應用到這些技巧。
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-87534011053657063252015-09-26T08:58:00.003-07:002015-09-26T08:58:41.977-07:00我看 Java 的過去與未來<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-WExLv5u0x7M/Vga_427inAI/AAAAAAAAWnQ/RhkGY90dtxM/s1600/services_java_development_banner.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-WExLv5u0x7M/Vga_427inAI/AAAAAAAAWnQ/RhkGY90dtxM/s1600/services_java_development_banner.png" /></a></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
很多人總是拿 Java vs .NET,但這太容易引戰了,所以這邊我不要用兩相比較的方式,單純<span style="color: blue;">從『非技術』的『商業觀點』</span>談論我對 Java 的看法。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
我本身以微軟相關技術為主,但偶而也會寫寫 Java,因為程式語言就是工具,合適的時候就拿來用一用,更何況從 C# 轉 Java 遠比 Java 轉 C# 簡單得多,因為 C# 的語言特性較複雜。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
我自己會寫 Java 的幾個機會是:寫 Android App、寫 GAE app、寫公司產品 Java 版本的 SDK,不算是用在很核心的地方。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px; text-align: center;">
<span style="color: red;">聲明:以下看法單純從本人過去工作經驗的觀點做分享,難免偏頗絕非全貌,請自行斟酌真實性。</span></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<a name='more'></a><br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
我對這個語言的看法就是,他在處在一種前途未卜、渾沌未明的狀態,任何事件都有可能改變這個語言的發展趨勢,大概不上不下不明朗,但是七成偏悲觀。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
Java 無疑是 OOP 世界最佳的傳教者,大部份的人都是透過 Java 來認識 OOP,他導入的 <b><u>ByteCode 、虛擬機、垃圾回收機制</u></b>,絕對是影響近代語言發展的歷史性推手。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
歌功頌德完畢,還是得看看現實。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
Java 開放的特性,且沒有明顯的商業掛勾(<span style="color: #666666;">至少剛開始是這樣</span>),使得學術界對此非常友善,無論是學術研究、教育課程安排,都毫不避諱採用 Java,造成企業不太擔心人才斷層,在人力市場可以很安心地挑選需要的人才。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
許多先進的學術研究也多半會以 Java 為主,要玩各種主題可以發現資源非常豐富,幾乎不用擔心沒東西可玩。.NET 大多是等某些東西在 Java 已經紅翻天才移植過去,所以開源的發展總是慢半拍。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
Java 的社群很友善,可以明顯感受到一種無私奉獻的精神在跟你互動,我很喜歡這這種氛圍,兩相比較之下,其他門派的獎勵機制產生的 MVP 社群感受比較功利主義。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
以為 Java 免費資源多,成本低所以企業搶進嗎?</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<b><span style="color: blue;">錯了,Java 的商業 total solution 可是貴翻天是微軟 solution 的倍數起價!</span></b></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
最早透過 Java 獲得巨大利益的是 IBM,金融業因為大型主機被把持,幾乎都採購 WebSphere 來串 MQSeries,不用授權成本的 Java 成為 IBM 的指定語言。有 IBM 原廠的強力背書和支援,跟我之前談論 .NET 的論點一樣,當時 Java PG 薪資水漲船高,所有金融業都搶著要,IBM 整個賺翻天!</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
但金融業也不是天天過好年,近年整個經濟反轉,整併消失的銀行不在少數,那些以前不計較的 IT 投資,現在看到報價單是會心痛的!去 IBM 化的各種行動在金融業陸續展開,那幾年我拜訪許多銀行的 CIO,都知道『減少對 IBM 依賴』是他們被賦予的首要目標。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
想也知道,誰是次於 IBM 卻滿足降低成本,同時可以提供最強大有力技術支援的一線廠商(<span style="color: #666666;">不要總說 M$ 好貴,跟 IBM 相比,真的便宜太多</span>)?</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
這個消長頓時凍結了 Java PG 的需求量和薪資水準,而開始讓另一家敵對的技術做大。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
但是於此同時,Java 在學術研究界的聲望仍然高居不墜,很多框架繼續蓬勃發展,是技術人玩樂的天堂。反觀另一家雖然在就業市場開始翻身,但至今始終難以打入學術與教育界。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
在兩家技術各有擅長戰場的情況下,Google 選擇 Java 作為 Android 的官方開發語言,這真是一個奇異點,因為這個事件同時幫 Java 打入強心針、也引發危機。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
先說 Java 在我眼裡,是個發展越來越緩慢,越來越顯老態的語言(<span style="color: #666666;">我說的是語言特性本身,不是周圍的框架</span>),幾乎快跟 C/C++ 一樣不太會變動了。大家可以參考維基百科裡面的歷史章節,Java6 從 2005 年公開到 2011 年才有新的改變,到了 2014 年才開始納入對手 2008 年就有的語言特性:Lambda。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
IT 界一日數變,隔年如隔朝換代,這種緩慢的變化已經無法因應市場所需。原因當然跟 SUN 自己經營不善無力支持有關,<span style="color: #cc0000;">另一點就是 Java 本身的願景成為巨大的包袱:Write Once Run Everywhere</span>。任何異動要牽涉到的多方角力實在太多太廣,主事者又早已自顧不暇。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
而 .NET 卻只要顧好“跨自己家平台”就好,爆發性『瞻前不顧後』的發展速度連自家人都傻眼。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
事實上,Write Once Run Everywhere 早已變成空談,各家利用這免費的語言各自為政,iOS 完全無法執行 Java,PC 上寫的 Java 不能跑在 Android,反之亦然,而 Windows Phone 更想都別想。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
在 mobile first 的當下市場,就算其他裝置支援眾多,最大的行動市場大餅卻根本無法跨平台,真的是優勢盡失。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
反之,.NET 反而三大行動平台全都能跨,Java 的 slogan 在現今特別令人感覺諷刺。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
現在各大 IT 廠商覬覦 Java 的,已經沒人在乎什麼跨平台這件事,看上的是他的開發社群與累積龐大數量的 PG,降低許多推廣自家平台的門檻,所以大家都搶趁著 SUN 無力反擊時吃盡豆腐。 </div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
要知道創造一個全新的程式語言是非常吃力不討好的事情,推廣和教育訓練的成本都極高。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
前面為何說 Google 選擇 Java 作為 GAE + Android 的指定語言同時是替這語言引爆危機?第一,他造成 Java SDK 分裂讓跨平台這件事徹底崩壞。第二,他讓 Oracle 為了貪圖利益控告了 Google 侵權,要求巨額賠償。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
Oracle 這場官司,不知看在其他 IT 巨頭眼裡,還有多少敢指定 Java 為主要語言?連 Google 為了解套都開始研發屬於自己的新一代程式語言 Go,這對 Java 這個語言本身的發展蒙上非常不好的陰影,甚至連學術界都開始為之擔憂。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
如果你熟悉 Oracle 老闆 Ellison 的狂人個性,就會敬而遠之。Java 恐怕會因此被他玩死。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-E30sp8tpl_4/VgbAgMzgwUI/AAAAAAAAWnY/WzG1RwdYkag/s1600/201503180852535474580.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="256" src="http://3.bp.blogspot.com/-E30sp8tpl_4/VgbAgMzgwUI/AAAAAAAAWnY/WzG1RwdYkag/s400/201503180852535474580.jpg" width="400" /></a></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
目前看不出 Oracle 有打算向微軟一樣把 .NET 當作重要戰略棋子的方式對待 Java,所以目前我對這語言的發展傾向悲觀的看法。</div>
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
<br /></div>
<span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><span style="font-family: 'Helvetica Neue'; font-size: 14px;">
</span><br />
<div style="font-family: 'Helvetica Neue'; font-size: 14px;">
但這是一個已經累積足夠財富與資源的語言,即便他在我眼裡是正在走下坡,但還是很有利用的價值。</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-9921378781547758792015-01-27T07:39:00.001-08:002015-01-28T05:43:13.287-08:00[HACKING]宏碁江蕙門票銷售網分析<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-3dWWPot3kPE/VMer_7Xl2qI/AAAAAAAAU7k/MMkGTNEfnQY/s1600/banners.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-3dWWPot3kPE/VMer_7Xl2qI/AAAAAAAAU7k/MMkGTNEfnQY/s1600/banners.jpg" height="188" width="320" /></a></div>
<div>
<b><span style="color: #990000; font-size: large;"> 緣起:</span></b>原本我受朋友之託,要協助搶購將會追加的十場的演唱會門票,所以稍稍研究了一下該網站,想說能不能利用自己的專長之便偷點雞,確保自己開賣當日可以穩穩當當地不出差錯把票入手(<span style="color: #999999;">朋友原本說每張多加 NT$1,000 跟我轉購呢,看在四個孩子的份上...</span>)。</div>
<div>
<br /></div>
<div>
原本這篇文章是打算在搶票成功後第一時間公開,打算用諾曼地搶灘的勝利之姿洋洋灑灑解說,結果過了數日後整件事被我拋到雲霄(<span style="color: #999999;">我不懂台語,不聽台語歌,所以江蕙對我而言無意義</span>)。</div>
<div>
<br /></div>
<div>
開賣當天週日我就帶著全家到金山上泡天籟溫泉,當中午我躺在室外湯享受山海之色之際,<b>手機 LINE 的訊息不斷傳來:「<span style="color: blue;">搶到票沒?</span>」</b></div>
<div>
<br /></div>
<div>
<b><span style="color: red;">我心裡暗幹一聲,然後下午的泡湯過程,我心中的陰霾與失落慢慢滋生...。</span></b></div>
<div>
<a href="https://www.blogger.com/blogger.g?blogID=4764200500432773567" name="more"></a><br />
<a name='more'></a><br /></div>
<div>
本來也想說:算了,當沒這回事。當初研究這個售票網的過程記錄就讓他永久塵封在我的 Evernote 之中。</div>
<div>
<br /></div>
<div>
正巧今天看到宏碁慶功的大好消息,<span style="color: #141823;"><span style="font-size: 15px;"><span style="font-family: Helvetica;">想說</span></span></span><span style="background-color: white; color: #141823; font-family: Helvetica, Arial, 'lucida grande', tahoma, verdana, arial, sans-serif; font-size: 15px;">對於門票開賣當下完全忘了這回事而跑去泡湯的自己,講什麼馬後砲都是多餘的...</span></div>
<div>
<span style="background-color: white; color: #141823; font-family: Helvetica, Arial, 'lucida grande', tahoma, verdana, arial, sans-serif; font-size: 15px;"><br /></span></div>
<div style="text-align: center;">
<a href="http://www.inside.com.tw/2015/01/27/stan-shih-commends-technical-team-in-acer" target="_blank">宏碁雲端完售江蕙加場演唱會門票,施振榮肯定技術團隊</a></div>
<div>
<br /></div>
<div>
不過想想不寫有點可惜,還是拿出來聊聊好了。</div>
<div>
<br /></div>
<div style="text-align: center;">
<span style="color: red;">請注意:以下很多推論都純粹為本人猜測,未經實戰驗證,僅能當作茶餘飯後嗑瓜子閒聊之用。</span></div>
<div>
<br /></div>
<div>
首先這個售票網徹底改變了原本寬宏售票網的業務流程!這帖良藥應該才算真正解決售票網癱瘓的主因,而其他技術優勢其實只是點綴強化而已。用分區取代自行選位,由系統直接決定座位,是這次售票成功的真正關鍵(<span style="color: #666666;">我個人認為啦</span>)。</div>
<div>
<br /></div>
<div>
而且採行的預存購票清單的動作,把大量開賣期間會發生的網路 IO 操作分散在提前幾天,只保留最後一個訂單送出的動作,這也是業務流程的優化,而非技術問題,但卻真正解決了技術上無法解決的問題。而且大幅縮短了程式購票機器人和人類購票的速度差距。</div>
<div>
<br /></div>
<div>
<span style="color: blue;"><b> 這就是我常說的:技術不是萬能,有時候 User 改變一下僵化的業務流程和頭腦,往往遠比不斷責備、刁難 IT 來得有效。</b></span></div>
<div>
<br /></div>
<div>
1月20當天我也登入系統預購如下,所以接下來真正的問題是:<b><span style="color: #cc0000;">1/25 中午開賣,我要如何比別人搶更早送出訂單?</span></b></div>
<div>
<b><span style="color: #cc0000;"><br /></span></b></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-u-rqV_0YxnM/VMewb_eSvfI/AAAAAAAAU9I/bSTAJNq5_0k/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7_2015-01-20_%E4%B8%8B%E5%8D%8812_01_30.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-u-rqV_0YxnM/VMewb_eSvfI/AAAAAAAAU9I/bSTAJNq5_0k/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7_2015-01-20_%E4%B8%8B%E5%8D%8812_01_30.png" height="360" width="640" /></a></div>
<div>
<b><span style="color: #cc0000;"><br /></span></b></div>
<div>
<br /></div>
<div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-hNKjMeAO96o/VMesUV-QrmI/AAAAAAAAU7s/xONN0DC95bY/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%8812.01.42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-hNKjMeAO96o/VMesUV-QrmI/AAAAAAAAU7s/xONN0DC95bY/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%8812.01.42.png" height="177" width="640" /></a></div>
<div>
<br /></div>
<div>
<span style="color: #cc0000;">要搶快當然不能依賴『金手指』</span>,滑鼠狂點把電腦搞當機或是太激動搞到中風,這都不是上策。所以,<span style="color: blue;">就要靠程式自動化囉</span>!</div>
<div>
<br /></div>
<div>
要做自動化,就要認識我們的對手是什麼來頭,才好接招出招。首先透過瀏覽器本身的開發工具先探探敵手的出身背景,<b>讓我們閱讀一下 Response Header 看看敵手的基本資料</b>:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-POw1FevQ7d0/VMeso3VCIBI/AAAAAAAAU78/JqXUMYJX8AI/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%8812.12.14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-POw1FevQ7d0/VMeso3VCIBI/AAAAAAAAU78/JqXUMYJX8AI/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%8812.12.14.png" height="350" width="640" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Okay,從上述資訊,原來對手系出名門,是採用 .NET 2.0 runtime 的 ASP.NET,跑在 Windows 2008 Server 的 IIS,並且從 network 的清單內,可以找到幾個 .aspx 的 request。認識對手的流派,接著就是要觀其言行,<span style="color: blue;">我們接著看看他所夾帶的餅乾包了些什麼料?</span></div>
<div>
<br /></div>
<div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-sbpSYeCysjg/VMetASp2y0I/AAAAAAAAU8E/11aoIabVCSc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%8812.24.51.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-sbpSYeCysjg/VMetASp2y0I/AAAAAAAAU8E/11aoIabVCSc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%8812.24.51.png" height="142" width="640" /></a></div>
<div>
<br /></div>
<div>
如果讀者熟悉 ASP.NET 技術的話,應該會從上面的 cookie 清單發現一件事,就是<span style="color: blue;">少了最基本的『ASP.NET_SessionId』這個 cookie</span>。一般技術開發的 ASP.NET 網站,如果有透過 Server 來記憶特定使用者的資訊,就會自動產生這樣的 cookie。</div>
<div>
<br /></div>
<div>
基於 http Stateless 的特性,<b><span style="color: blue;">宏碁售票這個網站顯然是完全沒有使用到 Session</span></b>,也就是說基本上網站的伺服器根本不認識使用者,所以伺服器處理每一個 request 只能夠透過 client 端自己送上來的資訊做驗證。</div>
<div>
<br /></div>
<div>
所以上面的 cookie 放入加密過的亂碼字串就是這個用途。理論上<span style="color: blue;">只要我們能夠破解加解密的方式,就可以跟這個售票網宣稱自己的身份,伺服器只能全盤接受</span>。</div>
<div>
<br /></div>
<div>
其實這個售票網不依賴 Session 算是相當合理的設計,為了能應付擠爆大量的 request,前方負載平衡 NLB 的分流機制,不一定會把同一個使用者每次的 request 送往相同的伺服器,而且使用者人數一多,Session 是會大量消耗記憶體資源的。</div>
<div>
<br /></div>
<div>
而如果要做中控的 State Server 或 Distributed Cache(Session) 這些機制,不但拖垮效能耗費硬體資源,而且還要讓工程師煩惱如何做(反)序列化。而且購票網搶票,肯定很多網友開著網頁等待著,網站也不需要處理 Session expire 的麻煩,所以<span style="color: blue;"><b>直接規定捨棄 Session 機制算是個正確的 design decision</b></span>。</div>
<div>
<br /></div>
<div>
但是既然沒了 Session,所有的驗證與安全度只能依賴加密 token 的強健度。</div>
<div>
<br /></div>
<div>
因為 token 需要反解做驗證,可以推測上面用的“可能是”對稱式 AES 的加密法,不過要達到我搶票的目的,破解加密並非必要,可以忽略。</div>
<div>
<br /></div>
<div>
<b><span style="color: blue;"> 回到我們的目的:自動化。</span></b></div>
<div>
<br /></div>
<div>
這個網頁防堵自動化機器人攻進來的唯一防守門檻只有 captch 這個肉眼圖像辨識的機制,如果要走正規方式破解這關卡,不是做不到,但卻十分麻煩。但是剛剛我長篇大論對方沒有採用 Session 機制,就是為了替破解這個關卡鋪路。</div>
<div>
<br /></div>
<div>
因為伺服器沒有記錄任何資訊,只能全盤相信 client 端上傳的資訊,所以伺服器要驗證 captcha 的答案是否正確,正確解答肯定也是由瀏覽器告知的!</div>
<div>
<br /></div>
<div>
<b><span style="color: blue;"> 沒錯,就是 “ORDER_ValidateCode” 這個 cookie!</span></b></div>
<div>
<br /></div>
<div>
伺服器做的事情很簡單,只要把你送上來的 cookie 解密後,跟你手動輸入的字串做比對,兩者相同就是通過驗證!所以我們只要事先準備好一組已經知道答案的 ORDER_ValidateCode 的 Cookie 內容和解答就可以了!完全不需要理會網頁上 Server 最新產生的,<span style="color: blue;"><b>因為伺服器根本就不記得他剛剛產生給你的辨識圖樣是什麼</b></span>。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-bfqv1Hbi2QM/VMeshjvn4rI/AAAAAAAAU70/pWyO2n7VsV4/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.03.09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-bfqv1Hbi2QM/VMeshjvn4rI/AAAAAAAAU70/pWyO2n7VsV4/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.03.09.png" height="352" width="640" /></a></div>
<div>
<br /></div>
<div>
產生辨識圖樣的來源點:<a href="https://shop.jody-ticket.com.tw/pic.aspx?TYPE=ORDER">https://shop.jody-ticket.com.tw/pic.aspx?TYPE=ORDER</a></div>
<div>
<br /></div>
<div>
大家可以點擊上面的聯結進去隨便玩:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-ca07EvfqNZI/VMetfrwsV1I/AAAAAAAAU8M/IfyNiIi0NJo/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.06.30.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-ca07EvfqNZI/VMetfrwsV1I/AAAAAAAAU8M/IfyNiIi0NJo/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.06.30.png" height="480" width="640" /></a></div>
<div>
<br /></div>
如圖,我們就可以取得當 <span style="color: #cc0000;">ORDER_ValidateCode = JLzgjp/JUsQ=</span> 的時候,答案就是圖上的 <span style="color: #cc0000;">“TTC6”</span>。<br />
<div>
<br /></div>
<div>
如何破解圖像識別輸入的方法也找到了,接著就是,<b><span style="color: blue;">如何進入『真正的購票流程』</span></b>?</div>
<div>
<br /></div>
<div>
開賣之前,購票網只提供『預存自願單』這樣隔靴搔癢的鳥功能,這不合我們所用啊!<span style="color: blue;">我們必須提前知道如何進入真正的購票流程,才能在開賣當下的零秒差之下直接攻取我們要的票券!</span></div>
<div>
<br /></div>
<div>
不過,身為軟體工程師的你我,可以捫心自問,是不是開發趕工時,偶而會做些能偷懶就偷懶的取巧法?我們就來看看頁面上藏了什麼線索?</div>
<div>
<br /></div>
<div>
不看不知道,一看嚇一跳。網頁原始碼內,『預存志願單』的按鈕旁邊好像藏了些東西?</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-jnYCJ-U5P-k/VMeuF6lGxWI/AAAAAAAAU8Y/Ea7fTGg5zwE/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.19.55.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-jnYCJ-U5P-k/VMeuF6lGxWI/AAAAAAAAU8Y/Ea7fTGg5zwE/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.19.55.png" height="294" width="640" /></a></div>
<div>
<br /></div>
<div>
首先,真正下訂單的按鈕只是透過 CSS 在頁面上被藏起來(<span style="color: blue;">style=“display:none”</span>),移除掉該 style 就會顯現真正的下單按鈕:</div>
<div>
<br /></div>
<div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-_nXSiv-_odY/VMeutUQyCvI/AAAAAAAAU8g/p-B36aG5cVw/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.22.43.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-_nXSiv-_odY/VMeutUQyCvI/AAAAAAAAU8g/p-B36aG5cVw/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.22.43.png" height="396" width="640" /></a></div>
<div>
<br /></div>
<div>
不過顯示這個按鈕倒也沒什麼特別作用,好玩而已。最有趣的部分,在於『預存志願單』的 onclick 綁在 doPreSave(); 這樣的 javascript function 上,這支程式負責處理『預存』志願單這樣的功能。但是根據工程師有良心的命名習慣,有 do“Pre”Save,那是不是代表應該也有 doSave() 囉?</div>
<div>
<br /></div>
<div>
還真的有!而且就直接寫在頁面上放著,名稱這麼符合直覺,應該給他嘉獎鼓勵!</div>
<div>
<br /></div>
<div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-SMmYTLFy51M/VMeu3Rkhr3I/AAAAAAAAU8o/Vypcr2A3_0c/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.28.35.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-SMmYTLFy51M/VMeu3Rkhr3I/AAAAAAAAU8o/Vypcr2A3_0c/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.28.35.png" /></a></div>
<div>
<br /></div>
<div>
<b>就在 sign_up.html 頁面地 684 行的位置開始。</b></div>
<div>
<br /></div>
<div>
雖然該嘉獎這位命名規則直覺的工程師,但是把尚未用到的功能呈現在頁面上,曝露攻擊點....ㄎㄎㄎ。</div>
<div>
<br /></div>
<div>
真正的關鍵在 ajaxCall 那行,才是送出訂單跟伺服器溝通購買。跟doPreSave 之間的差異,只在於 PreSave 帶入 type=1 的參數,而真正的購買,帶入 <span style="color: blue;">type=3</span> 的參數</div>
<div>
ajaxCall 這支的實作寫在 master.js(line:146) 內。</div>
<div>
<br /></div>
<div>
不浪費時間,我們直接把 onclick 改綁到 doSave() 來看看網路上實際傳送 request 的模樣。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-mt5roV0iV4k/VMev0-U0bMI/AAAAAAAAU84/jMExBxWXCRc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7_2015-01-20_%E4%B8%8B%E5%8D%881_39_27.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-mt5roV0iV4k/VMev0-U0bMI/AAAAAAAAU84/jMExBxWXCRc/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7_2015-01-20_%E4%B8%8B%E5%8D%881_39_27.png" height="193" width="640" /></a></div>
<div>
<br /></div>
<div>
</div>
<div>
從 Form Data 看出伺服器在處理 type=3 的作業所需要的資料格式,只要到時候依樣畫葫蘆,讓程式在時間點到的時候發送相同的內容即可。</div>
<div>
<br /></div>
<div>
但由於伺服器有依賴開賣時間阻擋,所以提前發送並無效果,而伺服器和使用者的電腦之間又可能存在時差,誤差可能從秒到分鐘,為了精准判定伺服器的時間是否已達開賣時刻,可以一樣透過 UTK0195_.aspx 這支網頁,給 <span style="color: blue;">type=6</span> 取得目前伺服器倒數的毫秒數,只要等這個數字為 0 即可。</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-RUK2ldj1-w0/VMewAhrv_gI/AAAAAAAAU9A/rzpFbTduLr4/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.49.38.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-RUK2ldj1-w0/VMewAhrv_gI/AAAAAAAAU9A/rzpFbTduLr4/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7%2B2015-01-20%2B%E4%B8%8B%E5%8D%881.49.38.png" /></a></div>
<div>
<br /></div>
<div>
有了上面這些資訊,我們可以選擇直接在瀏覽器上嵌入一段自動化的 javascript 即可,這應該是最經濟簡便的做法,但要提前一直開著瀏覽器才可以。</div>
<div>
<br /></div>
<div>
不過走此方案的人,還要注意是否網頁有倒數結束自動重新刷新頁面的手法,這樣剛剛提前嵌入的 javascript 程式就會被清除掉喔!</div>
<div>
<br /></div>
<b><span style="color: blue;"> 結論:宏碁這次的專案成果其實品質相當不錯(雖然實際開賣時我不在場...Orz),沒有太多缺陷可以挑剔,也沒什麼重大漏洞,一些設計取捨看來也在情理之中,值得嘉許。</span></b><br />
<div>
<span style="color: blue;"><b><br /></b></span></div>
<div>
<span style="color: #cc0000;">PS. 根據留言的網友Zion(好像是Acer 的PM)表示,開賣當天的程式其實已經不是我先前看到的模樣,可能是說其實網站有多做一道防線,原本的 doSave 並無法直接使用。果然這篇文章沒有經過實戰驗證,不過就分享一下,當作示範外界有心人士可能會如何推敲目標網站的設計與運作。(^^)</span>
<br />
<div>
</div>
<br />
<div style="text-align: center;">
以上,就是我嘗試研究宏碁售票網站的過程,只要註明出處原始網址,歡迎轉載分享本文。</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-14036421922400284512015-01-11T06:54:00.001-08:002015-01-11T08:49:18.066-08:00「鍾馗抓鬼系列」log4net 檔案清空之謎<div>
身為多年 log4net 忠實用戶,最近接獲客戶報案,說 Rolling File Appender 會在跨日一過午夜就將 log 檔案內容清除,只留下 0 byte 的空殼。對方採用<a href="http://it.tomtang.idv.tw/2013/12/log4net-best-practice.html" target="_blank">我曾在 blog 推薦的多年調製而成的家傳祕方的組態設定</a>(<span style="color: #999999;">log4net.config</span>),竟然會遇到如此前所未聞的離奇事件!?</div>
<div>
<br /></div>
<div>
上網 google 搜尋是否有他人遇到類似狀況,卻毫無線索。太陽底下無鮮事,全天下沒有別人遇到的事情,通常也不該發生在我周遭,畢竟我樂透從沒中過(<span style="color: #999999;">不過我也都不買,這樣要中獎對老天爺來說應該是有難度</span>),但是客戶現場截圖又不得不讓我閉嘴,不敢過度質疑:<br />
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-BogN5wDh5l0/VLJprNdAD8I/AAAAAAAAU1c/lpAauV_rXvM/s1600/%E6%93%B7%E5%8F%962.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-BogN5wDh5l0/VLJprNdAD8I/AAAAAAAAU1c/lpAauV_rXvM/s1600/%E6%93%B7%E5%8F%962.jpg" /></a></div>
<br />
<a name='more'></a><br /></div>
<div>
</div>
<div>
如上圖,這張圖片是在 12/23 日截取,可以看到 ALL-XXX.log 在當天早上(10:16:27AM)是有內容的(258KB),但是只要跨日之後,<b>就會變成像 12/22 或是 12/21 那樣,內容清空只剩下 0 byte 的檔案</b>。</div>
<div>
<br /></div>
<div>
客戶有一百多台機器執行相同的程式,幾乎每天都發生類似的現象,但這現象也不是非常穩定,可能連續四五天但卻有一天的 log 內容可以倖存,發生率大約 90%。</div>
<div>
<br /></div>
<div>
我跟客戶領取他的程式經過數次測試模擬(<span style="color: #999999;">透過更改作業系統時間模擬</span>),皆無法重現這現象,我猜想或許跟環境因素有關,於是親自跑客戶的現場試圖親眼觀察該現象。然而沒想到的是,我們找了一台內部測試機器,經過調整作業系統時間的做法企圖捕捉這現象,竟然沒辦法重現!</div>
<div>
<br /></div>
<div>
懷疑是環境問題的我,來到案發的犯罪現場竟然還是抓不到任何線索?不得已之下,總是得稍微懷疑一下客戶做了什麼手腳,無論是否有特殊執行的排程程式、或是閒置磁碟空間是否足夠、是否有詭異的防毒軟體作怪...,死馬當活馬醫,皆無所獲。</div>
<div>
<br /></div>
<div>
唯一發現以前不知道的最新事實:<span style="color: #cc0000;">就是客戶有開發一個監控所有業務程式運作的 Deamon,這個 Deamon 只要發現這些 24 小時運作的程式如果發生意外 crash 結束執行,會自動重新啟動死掉的業務程式,所以一旦我手動關閉掉此樁懸案的主角,每五分鐘,該 Deamon 會把它重新呼喚起來恢復執行。</span></div>
<div>
<br /></div>
<div>
那是否因此有可能,該業務程式同時執行多個併行的實例,造成 log 檔案的寫入互相影響?不過當下我也無法立即透過這個解釋容量歸零的原因。</div>
<div>
<br /></div>
<div>
而這懸案的程式主角,客戶也在其中加入自我檢查,只要發現已經有啟動的實例,便會自我了斷,不給他重複執行的機會。</div>
<div>
<br /></div>
<div>
這個機制在我滑鼠點擊下反覆驗證,的確沒辦法保持兩個程序實例共同運作。</div>
<div>
<br /></div>
<div>
經過幾次反覆測試,跟在我自己家裡實驗的結果完全相同,沒有任何檔案清空的狀況!這下子好了,我 IT 生涯經歷過幾次鍾馗抓鬼的聊齋軼事看來又要增添一樁。<br />
<br />
<ul>
<li><a href="http://it.tomtang.idv.tw/2007/12/blog-post.html" target="_blank">「鍾馗抓鬼系列」靈光一閃,拔除肉中刺!</a></li>
<li><a href="http://it.tomtang.idv.tw/2010/08/backgroundworker.html" target="_blank">「鍾馗抓鬼系列」真相大白之 BackgroundWorker 研究 ( 只針對 ASP.NET )</a></li>
</ul>
</div>
<div>
每次出現這種聊齋事件,退隱江湖的念頭就會在我腦袋盤旋,不過每每總是在我拿出金盆裝滿水之前,老天爺總會在我腦中給我一條靈光乍現生路,讓我這幾年下來還能繼續在這個領域騙吃騙喝撐了好幾年。</div>
<div>
<br /></div>
<div>
「<span style="color: #cc0000;">永遠都要對客戶提供的資訊質疑!</span>」這些年來我跑各種支援任務,學到最血淋淋的經驗就是:<b><span style="color: blue;">儘信客戶,不如沒客戶</span></b>(<span style="color: #999999;">屁啦</span>)!</div>
<div>
<br /></div>
<div>
客戶端的這支 Deamon 程式的存在,是兩邊環境最大的差異,就算客戶咬定該 Deamon 只有在監控的業務程式 process 消失才會重新啟動新的 process。但假設這支 Deamon 有 bug,會不斷重複啟動呢?如果客戶之所以感受不到這個 bug 的存在,是因為業務程式自我了斷的第二道防線的作用呢?</div>
<div>
<br /></div>
<div>
終於,我根據這條線索重現了客戶所說的現象,請看影片演示:<br />
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="360" src="//www.youtube.com/embed/b1LOyR_no0o" width="640"></iframe></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
log4net 的 RollingFileAppender 跨日 rename 的機制其實會發生在<b><span style="color: blue;">兩個時機點</span></b>:</div>
<div style="text-align: left;">
</div>
<ol>
<li>已經運用中的 log4net 再下次寫入 log 的時候,判斷出上次寫入和這次寫入的日期不同,會先進行 rename 再開新的檔案才寫入。</li>
<li>log4net 剛接受組態的初始化,會先偵測既有的 log 檔案的最後修改日期是否相同,若不同會立刻進行 rename 再開新檔案。</li>
</ol>
<div>
所幸之前因為追蹤別的問題,我手上有留下一份客戶該程式的原始碼 copy,打開發現:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-0TjsGlXmk7k/VLKJJFQI15I/AAAAAAAAU1s/W2yiAEWPaPQ/s1600/2014-12-27-%E4%B8%8B%E5%8D%88-08-20-03.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-0TjsGlXmk7k/VLKJJFQI15I/AAAAAAAAU1s/W2yiAEWPaPQ/s1600/2014-12-27-%E4%B8%8B%E5%8D%88-08-20-03.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
很遺憾的, log4net 查覺出跨日而決定進行 rename 的動作比"阻擋的檢查點"還要早就發生。實際驗證,<i><span style="color: blue;">XmlConfigurator.ConfigureAndWatch(new FileInfo("log4net.config"));</span></i> 這行程式碼只要在跨日之後啟動立即就會進行 rename,<span style="color: #cc0000;">如果將上述兩個區塊的順序對掉,先讓"阻擋的檢查點"發生,之後才初始化 log4net 的組態設定,這個問題就可以解決</span>。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
客戶接受上述建議修改,問題終結,Case closed!</div>
<br />
<div style="text-align: left;">
</div>
<div>
<br /></div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-88630838813322447392014-07-25T23:20:00.004-07:002014-07-31T02:19:27.816-07:00百人 Pitch Demo Show 與會後記<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-JeO3Jp9cTRg/U9NG6gBSueI/AAAAAAAAT08/0kFLy4Q-vJg/s1600/logo2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-JeO3Jp9cTRg/U9NG6gBSueI/AAAAAAAAT08/0kFLy4Q-vJg/s1600/logo2.png" height="292" width="400" /></a></div>
『<a href="http://www.mobilehero.com/pitch/" target="_blank">十二小時百人 PITCH X STARTUP馬拉松</a>』,是個鼓勵創業人腳踏實地驗證自己想法的創新活動。因緣際會,某日晚上受帶衰胖胖之邀,跟其中一個參賽團隊『<a href="https://www.facebook.com/IronMan911.tw?fref=ts" target="_blank">鋼鐵人實作聯盟</a>』的成員聚會交流,順便交換彼此對這個 Business Model 的想法與回饋。<br />
<br />
而透過該團隊主要的 Coordinator - Sandy 的介紹,我才知道有這麼一個活動,而該週六就恰巧是馬拉松活動最後的決賽場! <br />
<br />
決賽場的地點是在台灣微軟,那地點我很熟,依照慣例,知道現場一定會有免費的糕點和無限暢飲的冷飲機,應該可以省去一頓午餐費用(<span style="color: #666666;">創業維艱、什麼都要省啊</span>),於是打定主意前往! <br />
<a name='more'></a><br />
其實我還蠻喜歡參加這類的創業、創新發表會的,可以讓自己僵化的大腦受到更多外來的刺激,活化一下腦細胞。過去我也多有現場參加 AppWork 的 Demo Show,從中觀摩學習。<span style="color: #cc0000;">只是自從 AppWork 的團隊主軸明顯偏向容易獲利生存的『電子商務』類型,讓人耳目一新、或是天馬行空的創意就減少許多,有點可惜</span>。<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.brain.com.tw/Upload/News/140719-01-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.brain.com.tw/Upload/News/140719-01-01.jpg" height="226" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
本圖片來自「<a href="http://www.brain.com.tw/" target="_blank">動腦新聞</a>」</div>
<div>
<br />
<br />
到了現場,沒想到那天見到的 Sandy 竟然是決賽場的主持人,嚇了我一跳!這次決賽場 DEMO 有許多科技媒體、潛在創投擔任評審,評分重點分四大類,除了第四點算是結論的總評,前三項我覺得很值得有創業意願的人多多思考:<br />
<ol>
<li>問題是否值得解決</li>
<li>團隊執行力</li>
<li>商業模式</li>
<li>投資意願</li>
</ol>
參賽的七個隊伍與他們的點子如下,我大概聊聊心中的想法: <br />
<br />
<div style="text-align: center;">
<a href="http://www.brain.com.tw/News/NewsPublicContent.aspx?ID=20447" target="_blank">這邊是動腦新聞的七個團隊的中立報導</a></div>
<h3>
瘋 APP: </h3>
知名程式教學論壇與程式交易「<a href="http://www.blueshop.com.tw/" target="_blank">藍色小鋪</a>」創辦人,提出一個換湯不換藥的媒合平台,也就是<b><span style="color: blue;">以行動 APP 為主題,提供企業和 APP 創作者合作交易的媒介</span></b>。企業常常要因為行銷活動而推出一些免費商品,像是電影上映,會有些以相關電影為主題的手機遊戲、桌布、網站活動要推出造勢。這類行銷活動多半用完就丟,屬於短期缺乏延續性的投資,所以成本能省就省,企業通常不會自己養人進行相關開發。而 APP 是目前當紅的行銷媒介,如何可以換湯不換藥地快速換皮推出各種 APP 來達到行銷目的,這個網站就想要做這樣交易媒介的平台。<br />
<br />
<b><span style="color: #cc0000;">個人覺得這樣的市場需求雖然存在,但是利基不大</span></b>,而且真正要實現換湯不換藥的快速推出 APP,恐怕有些過度理想化,每個行銷案都會有出人意外的客製,<span style="color: blue;">因為行銷案的生成順序其實是:廣告公司為客戶量身定做行銷企劃,在不斷被打槍修改調整後才會真正投入製作</span>,<span style="color: #cc0000;">從來就不是行銷公司先去元件市場,找某程式能提供那些設定變更外觀行為,然後在這樣的框架限制之下去跟客戶提案</span>。 <br />
<br />
自古以來,程式元件交易的概念一直存在幾十年了,但交易一直很難熱絡,其實就跟難以做到真正符合需求的客製化有關。我不認為這個現象因為平台轉到 APP 就會有任何改變。 <br />
<br />
這個 Pitch 看到很多值得我反省的負面例子。<br />
<div>
<br /></div>
<div>
為了在有限的時間內塞入最多內容,超快的語速反而讓底下的人根本無法吸收?到底是『為說而說』還是『為聽而說』?而且我聽到重複最多句的就是『跳過這張、略過』,投影片一堆字卻快速切過去,<span style="color: #cc0000;">為何事前不先過濾掉根本不打算講的投影片?為了趕時間把話講得不清不楚,卻把時間浪費在翻閱沒人來得及看清楚的投影片?</span> <br />
<br />
這讓我想到去年參加 Yahoo 黑客鬆的自己,值得好好反省:<b><span style="color: blue;">到底是『為說而說』還是『為聽而說』?</span></b><br />
<div>
<br />
<h3>
RightOn:Find the right people at right place。 </h3>
利用手機的 LBS,在正確的地點幫你找到正確的人。這個團隊提出的願景,是讓一群陌生聚會的社交活動,大家可以迅速找到這個陌生社交場合,自己需要認識的對象,並且能夠追蹤延續這樣新建立的人際關係。 </div>
<div>
<br />
這個問題在傳統的做法,就是在會場快速的交換名片,然後用高超的交際手腕把社交時間留給物色到的合作對象,甩開剛交換完名片,感覺沒什麼利用價值卻纏住你的路人甲。 <br />
<br />
這個團隊想解決的問題是確實存在著,也真的有這個價值去解決,但他們提出的 Solution 卻讓我非常無言以對。你可以想像一個聚會會場大家不面對面交流,卻低頭滑著手機瀏覽在這個會場有誰被定位在此,他們的工作頭銜和到此目的?如果一個社交場所進去看到這個光景,我會以為來到全國宅男自閉症會場,然後迅速離開。 <br />
<br />
而且不善面對面交流的人,就算透過這個定位 APP 找到現場有值得交流的人,難道他就有勇氣走過去做真正面對面的陌生交流(<span style="color: #666666;">我看最多就是發個 text message 過去吧</span>)?<span style="color: #cc0000;">這整個事情的 TA 本身定位就有問題</span>,我會修改這個團隊的 slogon 變成:</div>
<div>
<blockquote class="tr_bq">
<i> “Find the right people at right place BUT on the wrong way.” </i></blockquote>
<span style="color: #cc0000;"><b>為什麼會以 Place 為主去侷限了這個點子?</b></span>只因為想跟手機 APP 的 LBS 定位運用綁在一起?<span style="color: blue;">Find the right people 才是真正有價值的重點吧!</span>以 Place 為先決過濾條件非常本末倒置。 <br />
<br />
<b>如果顛倒過來,這個服務是:</b><span style="color: blue;">先幫我找到對的人,然後想辦法幫我安排對的地點讓我們面對面交流。這才是對我有價值的服務啊!</span> <br />
<br />
<b> 建議方向:Arrange somewhere to make you meet the right people。 </b><br />
<br />
<span style="color: #666666;"> 其實說穿了就是傳統相親、婚友社在做的事,只是看你能不能運用在商業社交上。</span><br />
<br />
<h3>
鋼鐵人實作聯盟: </h3>
Sandy 帶著他的團隊出場,氣勢非凡。也是所有團隊我唯一看到實際成品,而不是只有一堆 PowerPoint 簡報上的假想圖、模擬稿圖。這組的分數在執行力項目應該拿到高分,而創業這件事最重要的關鍵因素就是執行力,其他都是陪襯用的而已。 </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.brain.com.tw/Upload/News/140719-01-37.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.brain.com.tw/Upload/News/140719-01-37.png" height="266" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
本圖片來自「<a href="http://www.brain.com.tw/" target="_blank">動腦新聞</a>」</div>
<div>
<br />
<br />
果不其然,Sandy 他們拿到決賽最終優勝,前往日本出國爭光了!至於我對這個團隊的想法在前兩天晚上,跟當事者已經聊到很多(<span style="color: #666666;">而且對話中三不五時就提到保密協議...</span>),所以我這邊就不多說了。總之是個很有潛力的團隊,市場操作和商業模式有很多發揮空間,就看他們想不想得到、怎麼去玩。<br />
<br />
<h3>
切好好: </h3>
<b><span style="color: blue;">我很喜歡這個團隊的願景</span></b>,讓失業的家庭主婦可以找到經濟機會,幫其他忙碌的上班族準備健康的有機食材。對我來說,<span style="color: blue;">這是某種社會企業,真的解決一些社會問題:無法上班的家庭主婦的生產力浪費,忙碌上班族不健康的飲食</span>。<br />
<br />
可惜,叫好不叫座是社會企業創業的常態,<b>我非常希望他們能好好堅持,持續摸索出最佳經營方式突破新局。 </b><br />
<br />
<h3>
Smart77: </h3>
為了肢體殘障人士,而設計的智慧型拐杖,方便殘障朋友可以更加容易活動。這也是個改善弱勢、出發良善的創新發想,可惜<span style="color: #cc0000;">這個團隊的氣場和執行力給我感覺非常弱,連簡報過程都是透過評審的同情心,給予額外的時間施捨,才給他時間講完產品介紹</span>,幾乎無法讓人相信他們最後能推出真正的東西。<br />
<br />
<h3>
Find my star:</h3>
團隊原本想推出個方便追星族捕捉藝人最新動態的『人肉搜索 APP』。<a href="http://punnode.com/archives/21115" target="_blank">有些評論說擔心這個應用太 Powerful</a>,會成為『全民皆兵』用來追殺特定人物(<span style="color: #666666;">例如政治人物</span>)的人肉搜索平台,我本人倒是沒那麼看得起這個應用。可能因為我本身不是這個應用的 TA 吧,沒辦法有任何共鳴。 <br />
<br />
對我來說,這一樣是 LBS 而且接近 Square 的一個變形,我不認為他能單靠社群的力量自己維持,應該只會變成粉絲操作用的行銷平台而已。<span style="color: blue;">有商業價值,但對人肉搜索的擔憂我認為是多慮的</span>。 <br />
<br />
<h2>
結束轉淚</h2>
看完所有參賽隊伍,進入評審階段就是休息時間。我趕緊把握時間狂灌免費冷飲+免費糕點!<b><span style="color: blue;">不得不說,這次來對了,收獲非常大!</span></b></div>
<div>
<br /></div>
<div>
噢,不,我不是說這些吃吃喝喝啦!<br />
<br />
而是我從這七個團隊的發表獲得一個全新點子的啟發!而且就在進入休息時刻的當下,發生一個突發狀況,完完全全跟我切身之痛有關!而這七個隊伍提出的東西某部分剛好給出解答的線索!<br />
<br />
<b><span style="color: blue;"> 有時候遠看是一坨大便,換個角度發現他也可以是黃金啊! </span></b><br />
<br />
所以不等結果發表,我就迅速逃離會場,在路上把整個想法徹底整理來回檢視,跟人討論,初步獲得不錯的回饋!<br />
<br />
有時候很多疑問和想法就像是拼圖一樣,總是不完整缺了一角,在同一個房間繞來繞去就是找不到,總得多多走出去才發現柳暗花明的時刻。<br />
<br />
<div style="text-align: center;">
<b><span style="color: #cc0000;">所以帶衰胖胖,叫你出來參加活動你就該乖乖出來。</span></b></div>
</div>
</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-24027039118865184972014-06-06T05:00:00.000-07:002014-06-06T05:00:06.470-07:00軟體成功的 3 / 7 法則<div class="tr_bq">
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-KGCfxR_-KNU/U5GtFSmnn5I/AAAAAAAATP8/BKtfvUw1o6w/s1600/adaf5ce1dcff571689fe89daca1a8203.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-KGCfxR_-KNU/U5GtFSmnn5I/AAAAAAAATP8/BKtfvUw1o6w/s1600/adaf5ce1dcff571689fe89daca1a8203.jpg" height="240" width="320" /></a></div>
<br />
今年三月底,為了挽救公司的新產品,我臨危受命飛往馬來西雅。也是第一次我才一下飛機,透過越洋國際電話,就決定放生一位團隊同事。</div>
<br />
下令放生之前,我寫了封信,跟團隊談談我心中認為『成功的系統』的關鍵要素:<br />
<br />
<a name='more'></a><br />
<br />
<blockquote>
「嗨,
昨天『X系統』錯帳的事情,大家辛苦了。尤其感謝那些在公司待很晚、待命到問題解決的同事仁們。 </blockquote>
<blockquote>
我常覺得:『<b>人的成功,若是三分天才 + 七分的努力才能獲得</b>,<span style="color: blue;"><b>那軟體系統的成功,就是三分技術 + 七分的紀律與嚴謹驗證的態度。</b></span>』 </blockquote>
<blockquote>
<span style="color: blue;">技術再新再好,頂多創造三十分的價值。但是就算技術老舊,只要有紀律和不斷測試驗證,就能替使用者創造出七十分的價值。</span> </blockquote>
<blockquote>
去年有次晨會我就跟大家說過,<span style="color: red;">軟體就是比玻璃還要易碎的東西</span>,打破一個玻璃杯你還要花相當的力氣,但是<span style="color: red;">弄壞一個系統,你只要手指不小心在鍵盤上發抖一下,大小寫拼錯或是加減打反,就壞得一踏糊塗,不費吹灰之力</span>。 </blockquote>
<blockquote>
所以雖然人人都可以寫軟體,千萬不要以為寫好一個不出錯的軟體系統很容易。 </blockquote>
<blockquote>
我所知道<span style="color: red;">軟體界很優秀的人,都不是什麼技術很高、很會玩弄或破解什麼別人看不懂的技術</span>,而是<span style="color: blue;">那些態度嚴謹、永遠想著如何避免犯錯的人,這些大師創造出許多<b>軟體工程的方法論</b></span>,就是這些人知道人一定會出錯,所以想破頭在思考如何用流程來預防。 </blockquote>
<blockquote>
這次『X系統』的錯誤的原因,是在開發『Y功能』第二階段的期間, 3 / 19 日那天『X系統』的『Z程序』有附件內的修改:
將原本判斷財務金流增減的那段 IF 條件中的⋯⋯(略)。<br />
<br />
而移掉這個 IF 判斷的條件,卻造成這『Z程序』再也無法判斷『X系統』的財務金流,而讓所有的使用者的帳都損失。 </blockquote>
<blockquote>
這個出乎意料的順手改,所造成的問題之明顯,可以知道修改的人改完之後<b><span style="color: red;">絕對沒有測過</span></b>! </blockquote>
<blockquote>
我不是反對修改,原本就正常的東西你若有心想把它改得更好,我也很鼓勵!就像我們最近積極地 refactor 一樣。 </blockquote>
<blockquote>
<b>這件事最大的錯誤,不是『修改了本來正常的東西』,而是『改了卻沒有測』!沒有驗證!沒有讓任何人知道!</b> </blockquote>
<blockquote>
<b><span style="color: blue;">如果你太忙,不打算測,那我寧願你不要改!</span></b>
尤其改的還是 DB 內跟錢有關最重要的『Z程序』! </blockquote>
<blockquote>
我對這種嚴謹的要求,絕對不是現在給大家放馬後炮,當初要上 report pre-gen 這個改善校能的機制,前前後後跑了多少次驗證?
還專門寫了一支程式(略)每天跑各種查詢條件來跟 on-fly 的版本做交叉比對,確定好幾天都沒錯誤才敢給 User 使用?不只如此,而且還特意保留一個切換功能給大家在緊急的時候可以 runtime 切換 pre-gen / on-fly 兩種版本。 </blockquote>
<blockquote>
而且,pregen 還不是我自己開發的,上述我做這些都是為了幫別人把關驗證。你們對這整套系統前前後後有比我熟嗎?若沒有,那理應比我更小心更謹慎啊!怎麼可以比我不熟,卻還可以比我更鬆懈隨意呢? </blockquote>
<blockquote>
你盡力測但仍有 case 沒測到,這大家可以理解。但改了卻完全不測,認為自己不可能會修改錯的人,能力太強了,應該去 Google,不應該跟我們在這邊浪費生命。
這也是我當時讓 EXX 去找更好的發展的原因。 </blockquote>
<blockquote>
<b><span style="color: blue;">記住:你懂的技術再多再新,頂多創造三十分的價值。但是就算技術老舊,只要有紀律和嚴謹的態度,就能替使用者創造出七十分的價值。 </span></b></blockquote>
<blockquote>
我不想讓這件事造成以後大家都不敢修改任何東西,害怕 refactor 。 </blockquote>
<blockquote>
所以不要弄錯焦點,我不責怪修改,我要責怪的是『<span style="color: red;">改完卻不測</span>』!<br />
<div style="text-align: right;">
Best Regards」</div>
</blockquote>
<div style="text-align: right;">
<br /></div>
<div style="text-align: left;">
<br /></div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-75799337428089845972014-05-20T18:37:00.001-07:002014-06-05T19:24:14.809-07:00失控的加速<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-C_fRgle73-A/U3wCPwvManI/AAAAAAAATOc/IYhWwjouj8Q/s1600/21-10-40-24-867477385.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-C_fRgle73-A/U3wCPwvManI/AAAAAAAATOc/IYhWwjouj8Q/s1600/21-10-40-24-867477385.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
這一年多來,帶著團隊參與一間新創公司的產品開發,近一年的努力成果終於推向市場營運後,才幾個月不到,結束了。</div>
<div style="-webkit-text-stroke-width: 0px; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="font-weight: normal;">
<span style="color: black;"><br /> 如今還在收拾一些殘局的過程,看著這潮起潮落,我有些領悟。</span></div>
<div style="font-weight: normal;">
<span style="color: black;"><br /></span></div>
<div style="font-weight: normal;">
<span style="color: black;">
當然結束營運背後有諸多複雜的原因混雜,有些也不是我這種技術層級的黑手工頭可以知道的。但是針對 IT 開發這塊,我有個代價挺高的領悟:</span></div>
<div style="font-weight: normal;">
<span style="color: black;"><br /></span></div>
<span style="color: blue;">產品的系統特性,應交給市場幫你決定,而不是交給<b>系統架構師</b>來決定。</span><br />
<div style="color: black; font-weight: normal;">
<br />
<a name='more'></a><br /></div>
<span style="color: #cc0000; font-weight: normal;">如果你在做的是一個新形態的產品,需要市場教育的,我認為,系統架構師,不應該是初期就介入的角色。</span><br />
<div style="font-weight: normal;">
</div>
<div style="color: black; font-weight: normal;">
<br /></div>
<div style="font-weight: normal;">
除非,你做的是很成熟的市場和獲利模式,就是在紅海中分一杯羹的那種,市場的經驗容易套用,那就適合找個系統架構師來幫你好好規劃規劃!</div>
<div style="color: black; font-weight: normal;">
<br /></div>
<div style="font-weight: normal;">
但若不是!或是你對著市場一知半解,還在摸索之中,那麻煩你離系統架構師遠一點,少沾惹他們。</div>
<div style="color: black; font-weight: normal;">
<br /></div>
<div style="font-weight: normal;">
因為架構師在做的事情,就是幫你規劃一個架構,去做到同業競爭對手做不到的特色,或是超越對手的效能或規模化的特性。要做到這些優勢,必須套用某些最佳化策略,而這是有很強烈的假設前提的!
</div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
台灣因為房價高、坪數小,良好的室內設計特別重要,格局、擺設、動線、收納空間無一不需最佳化!再高級的室內設計師在做這些規劃設計時,也必須根據一些不可變動的假設來進行:打算生幾個孩子?會不會有長輩近來入住?居家活動以何者為重心?
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<span style="color: black;"> 但是不久後若這些假設前提改變了(</span><span style="color: #666666;">本來打算只生一個,卻不小心懷了三胞胎</span>),這時就會發現之前花了大成本的規劃不怎麼合用,但已經投了這麼多錢,打掉重練又捨不得,於是在這遷就中的兩難,日子勉強過,卻沒有因為當初的投資而獲得較好的生活品質。
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<br />
<div>
這並不是設計師的錯,但是做產品、做市場也常常遇到這樣的困境:因為我們面對的不確定性太強烈了。
</div>
<div>
<br /></div>
<div>
其實精實創業 Lean Startup 講的最小可行性產品 MVP 就是這個事實的體現!</div>
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<span style="color: black;"> 如果不是背後資源雄厚的新創公司,</span><span style="color: blue;">隨時對市場卑躬屈膝、保持最柔軟的身段才是生存的法則,任何剛性的假設條件都不該存在的</span>,否則市場會甩你個大巴掌,而你無法順勢彎曲,就只有鼻青臉腫的份。
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
這次真的鼻青臉腫了。
</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<span style="font-weight: normal;"><span style="color: black;"> 初期就引入某個假設下的最佳策略,然後</span><span style="color: #cc0000;">我們的車子跑得比誰都快,才發現方向根本錯了</span>,主推的商品線不受市場青睞,副線卻出乎意外地受歡迎。這時候想轉彎改變方向,才發現我們需要的迴轉半徑比誰都大,最後不管三七二十一硬是把方向盤用力一扳,</span><b>我們翻車了</b>。
<br />
<br /></div>
<div style="-webkit-text-stroke-width: 0px; font-family: Arial; font-size: medium; font-style: normal; font-variant: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="text-align: center;">
<b><span style="color: blue;">架構師,是在『市場方向對』的時候才進來幫你校調加速度的好夥伴。</span></b></div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-87824836537010172412014-01-15T22:23:00.001-08:002014-01-17T08:08:44.920-08:00[連載]新創公司歷險記-2:搬開技術絆腳石、加速執行<div class="separator" style="clear: both; text-align: center;">
<a href="http://cn.wsj.com/pictures/photo/Another_Lamborghini_Supercar/06.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://cn.wsj.com/pictures/photo/Another_Lamborghini_Supercar/06.jpg" height="212" width="320" /></a></div>
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
<span style="font-family: Arial;"> 繼<a href="http://it.tomtang.idv.tw/2013/11/1.html" target="_blank">上次才寫到開頭的歷險記</a>,第一週我先跟團隊達成『工作完成』定義的共識,避免錯誤的資訊混淆對實際狀況的掌握與判斷。</span><br />
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
但是,即使掌握正確的專案進度,避免浮報無知的樂觀,卻<span style="color: #cc0000;">沒辦法讓實際的開發速度加快</span>。採用了每週一輪的 spring,前兩週都無法達成目標,以當時的 deadline 來看,團隊的開發效率若沒有改善, 肯定無法對上有所交代。
</div>
<div style="font-family: Arial;">
<a name='more'></a><br /></div>
<div style="font-family: Arial;">
我仔細觀察造成開發效率低落的主要原因有幾項:
</div>
<div style="font-family: Arial;">
<ol>
<li><b><span style="color: #cc0000;">團隊浪費在 debug 的時間太多:</span></b>寫好一個功能,卻要花費三四倍的時間在除錯?</li>
<li><b><span style="color: #cc0000;">技能與工作分配嚴重矛盾:</span></b>個人專長無法與所負責的應用程式搭配。</li>
</ol>
<h3>
關於 #1:
</h3>
<div>
團隊當時還是<span style="color: #cc0000;"><b>使用老派原始 ADO.net 的開發方法,徒手撰寫大量資料庫存取的 DAO</b></span>(<span style="color: #666666;">Data Access Object</span>) 與 DTO(<span style="color: #666666;">Data Transform Object</span>),不但必須在資料庫改動時來回維護兩邊的接口,容易犯錯且工作量大,而且缺少強型別檢查,必須自己轉型,致使許多粗心大意的錯誤都要到執行階段才發現,令人不勝困擾。
</div>
<div>
<br /></div>
<div>
我立刻引進並介紹:<a href="http://msdn.microsoft.com/zh-tw/library/bb386976(v=vs.110).aspx" target="_blank">LinqToSql</a> 的技術,雖然跟 <a href="http://msdn.microsoft.com/zh-tw/library/bb399567(v=vs.110).aspx" target="_blank">EntityFramework</a> 相比,這已經是被汰換的技術,但由於我們資料庫的操作一律全部封裝到『預存程序』內,所以僅僅需要 Linq2Sql 自動產生 StoredProcedure 的代理界面,並且提供 strong-typed 的型別檢查,<span style="color: blue;">不但讓原本 DAO / DTO 的開發時間降低到趨近於 0</span>(<span style="color: #666666;">只剩下拖拉資料庫物件到 VisualStudio 內約只需要五分鐘</span>),<span style="color: blue;">更讓人為疏失消彌與無形,而且 IDE 自動幫我們在拖拉 code-gen 過程中,抓出『因為 table 改動造成既有的 spx 無法運作』的錯誤</span>!
</div>
<div>
<br /></div>
<div>
此技術的導入,省下團隊大量的開發時間,算是我至今採取最有幫助的手段之一。
</div>
<div>
<br /></div>
<div>
另外一個造成除錯時間過長的因素,是<span style="color: #cc0000;">團隊在程式中不寫 log,也不擅長</span>,大家都僅僅依賴 IDE 的中斷點和單步除錯來找問題,這種初學者除錯法尤其對 n-tier 架構的系統沒轍,而且測試出了問題後,<span style="color: #cc0000;">需要再花費大量時間放置中斷點、重新啟動系統、重複剛才出錯的操作,來來回回嘗試數遍才會找到問題的根源</span>。</div>
<blockquote class="tr_bq">
「<span style="color: #b45f06;">我剛剛打你的 service 怎麼沒有回傳資料?</span>」<br />
「<span style="color: #38761d;">應該是你沒有打進來吧?你檢查你打的 IP 位置對不對。</span>」<br />
「<span style="color: #b45f06;">IP 正確啊,是你的程式沒有回傳結果吧?</span>」<br />
「<span style="color: #38761d;">你關掉你的防毒軟體或是防火牆再試試看,或許被擋掉了?</span>」<br />
「<span style="color: #b45f06;">好,我關掉防毒軟體看看⋯⋯。</span>」<br />
<br />
<i>半小時後⋯⋯。</i><br />
<br />
「<span style="color: #783f04;"><b>Fxxk!我就知道我有打,明明就是你的服務執行到一半出 exception 了,只會回 null 給我!還叫我把防毒軟體關掉!</b></span>」
</blockquote>
<div>
<br /></div>
<div>
最後一句對話我戲劇化地渲染一下,<b><span style="color: blue;">我們其實是很溫柔的團隊</span></b>,就算是踢皮球也是用很溫柔的方式把皮球緩緩地親手交付到對方手中。
</div>
<div>
<br /></div>
<div>
不過因為沒有 log,自己寫的服務連別人到底有沒有打進來都搞不清楚,只能瞎猜原因和踢皮球,這樣的對話當時屢見不鮮,嚴重拖累團隊開發的效率。
</div>
<div>
<br /></div>
<div>
我當時立即決定<span style="color: blue;"><a href="http://it.tomtang.idv.tw/2013/12/log4net-best-practice.html" target="_blank">導入 log4net</a>,強迫所有人都要在程式被外部呼叫的進入點包覆完整的 log 機制</span>。</div>
<div>
<br /></div>
<div>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><i>Dear all:<br />目前系統已經開發至一個準備進入測試的階段, 請開始將您手上的系統加入 error <span class="il">log</span> 的機制.<br />尤其以 MVC website 部分.<br />凡是會被外界呼叫的進入點, 例如所有的 Controller 的 Action 都要加上 <span class="il">log</span><br />範例如下:</i></span></blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="color: blue;"><span style="font-family: microsoft jhenghei, sans-serif;">using System.Reflection;</span></span></span> </blockquote>
<blockquote class="tr_bq">
<span style="color: blue; font-family: 'microsoft jhenghei', sans-serif; font-size: x-small;">using </span><span class="il" style="color: blue; font-family: 'microsoft jhenghei', sans-serif; font-size: x-small;">log4net</span><span style="color: blue; font-family: 'microsoft jhenghei', sans-serif; font-size: x-small;">;</span></blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;">
public class XXXController {<br /><span style="color: blue;"> private static readonly ILog _logger = LogManager.GetLogger(typeof(<wbr></wbr>XXXController));</span><br /> public ActionResult XXXAction(string[] args) {<br /><span style="color: #0b5394; font-family: microsoft jhenghei, sans-serif;"> </span><span style="color: blue; font-family: microsoft jhenghei, sans-serif;"> _logger.DebugFormat("Invoking {0}...", MethodInfo.GetCurrentMethod().<wbr></wbr>Name);</span><span style="color: #0b5394; font-family: microsoft jhenghei, sans-serif;"><br /></span><span style="color: red; font-family: microsoft jhenghei, sans-serif;"> try {</span><span style="color: red; font-family: microsoft jhenghei, sans-serif;"><br /></span><span style="color: #6aa84f; font-family: microsoft jhenghei, sans-serif;"> // Do something 整個邏輯都包住在裡面</span><span style="color: red; font-family: microsoft jhenghei, sans-serif;"><br /></span><span style="color: red; font-family: microsoft jhenghei, sans-serif;"> } catch (Exception ex) {</span><span style="color: #0b5394; font-family: microsoft jhenghei, sans-serif;"><br /></span><span style="color: blue; font-family: microsoft jhenghei, sans-serif;"> _logger.Error(ex.Message, ex);</span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="color: blue; font-family: microsoft jhenghei, sans-serif;"> throw;</span><span style="color: #6aa84f; font-family: microsoft jhenghei, sans-serif;"> // 如果這個錯誤該讓外界知道</span><span style="color: blue; font-family: microsoft jhenghei, sans-serif;"><br /></span><span style="color: red; font-family: microsoft jhenghei, sans-serif;"> }</span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"><span style="color: #0b5394; font-family: microsoft jhenghei, sans-serif;"> return View();</span></span> </blockquote>
<blockquote class="tr_bq">
<span style="font-size: x-small;"> }<br />}</span></blockquote>
</div>
<div class="gmail_default" style="color: #0b5394; font-family: 'microsoft jhenghei',sans-serif; font-size: small;">
<br /></div>
<div>
記得當時我開會上說過:</div>
<div>
「<span style="color: #990000;">在正式營運的環境是沒機會讓你下中斷點,像現在這樣一步步找問題的!做 Production support 最怕兩件事:</span></div>
<div>
<span style="color: #990000;"> 第一是</span><span style="color: #cc0000;"><b>手上在查問題的原始碼和 production 正在跑的不是同一個版本</b></span><span style="color: #990000;">!</span></div>
<div>
<span style="color: #990000;"> 第二就是:</span><span style="color: #cc0000;"><b>『沒有 log』</b></span><span style="color: #990000;">!</span>」
</div>
<div>
<br /></div>
<div>
當時強制<a href="http://it.tomtang.idv.tw/2013/12/log4net-best-practice.html" target="_blank">引入 log4net </a>之後,剛開始大家還是沒有看 log 的習慣,也搞不清楚 log 會寫到哪裡,從哪邊看、怎麼看,像是還不適應拔掉奶嘴(<span style="color: #666666;">IDE 中斷點</span>)的開發寶寶。幾個月後,<span style="color: blue;">如今只看 log 而完全不依賴 IDE 找問題的已經大有人在</span>,在自己的開發機器以外的環境,也習慣看 log 和留下正確有意義的 log。<span style="color: blue;">這一步的效益雖然發酵地比較晚,但也在後期給團隊開發效率很大的幫助</span>。
</div>
<div>
<br /></div>
<div>
另外為了讓程式錯誤易於被察覺,盡可能透過 coding 技巧,<span style="color: blue;"><b>將原本會在執行階段才出錯的錯誤,盡可能引導到編譯階段就發生</b></span>。例如盡可能把大量的數值參數 int 的使用改為 enum,大量使用 generic 泛型編程來取代事後的轉型處理,還有...。</div>
<div>
<br /></div>
<div>
當然執意使用強型別將 runtime binding 引導至 compilation time,會大幅降低程式執行時期的彈性,使得許多異動都必須演變成“改程式”來達到,而不是“改設定 / 改插件”,<span style="color: blue;">但是為了對付眼前層出不窮的失誤,這是必要之惡</span>。
</div>
<div>
<br /></div>
<div>
每當有人跳腳對別人說:「<span style="color: #b45f06;">你昨天改了那個 DLL 內 XXX 類別,害我的程式今天就 build 不過。</span>」</div>
<div>
<br /></div>
<div>
我就會很寬心地安撫他:「<span style="color: #660000;">只要編譯時期能抓到的問題,哪怕是因此要從內改到外,都是小問題。</span><span style="color: red;">我最怕的,是程式執行後遇到才爆發的 runtime error</span><span style="color: #660000;">。</span>」
</div>
<div>
<br /></div>
<div>
再來就是 CI 的建立。由了前面強型別的界面檢驗,<span style="color: blue;">讓每日午夜的 automation build 自動幫我們找到所有整合的 broken point</span>,並作 automation deploy,<span style="color: blue;">讓團隊隨時都可以很輕易地進行 System Integration Test</span>,避免『忘了拉別人最新的 code 下來跑,別人測沒問題,自己測試就是不行』這種偷走時間的鬼打牆。
</div>
<div>
<br /></div>
<div>
最後,由於我們的 n-tier 架構,系統溝通之間需要透過 socket 進行,這部分我們雖然採用了強大的 <a href="http://zeromq.org/" target="_blank">ZeroMQ</a> 作為溝通管道,但是卻未經包裝成完善的 infrastructure,初期只用很原始的方式裸用,團隊必須自行處理 byte frame,缺乏組織過的資料封裝方式和完整的異常回報機制,導致開發雙方有大量口約定的協定必須處理,而且對於發生在彼岸的系統錯誤毫無所覺,所以後續我就<b><span style="color: blue;">全心投入 infrastructure 的建立,提供給團隊友善完整的開發基礎</span></b>。
</div>
<div>
<br /></div>
</div>
<div style="font-family: Arial;">
至於 #2 所提到,處理技能與負責項目的差距造成的困擾,就留到在下次再聊。 </div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-65527708044904932312013-12-19T17:41:00.000-08:002013-12-24T16:11:25.432-08:00網站效能不佳?談『如何判定系統變慢原因』的簡易 SOP<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-HZZ9kERdvWE/UrOf8hDS46I/AAAAAAAASqs/h_79z1igVoA/s1600/04.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-HZZ9kERdvWE/UrOf8hDS46I/AAAAAAAASqs/h_79z1igVoA/s1600/04.jpg" height="240" width="320" /></a></div>
<div>
<span style="font-family: inherit;"> 上次『<a href="http://it.tomtang.idv.tw/2013/12/blog-post.html" target="_blank">大禹治水</a>』提到,對於採用 Windows+ASP.NET+MSSQL 技術的網站服務,找出網站系統變慢、效能不佳的原因其實有一簡易 SOP 可以起手,減少無頭蒼蠅盲目亂撞的時間成本浪費,這篇就簡單介紹一下這簡易的 SOP。</span></div>
<div>
<br /></div>
<div>
符合<b>“簡易”</b>的這個特徵有<b>兩個</b>條件:</div>
<div>
<ol>
<li><b><span style="color: blue;">不用額外安裝任何第三方軟件或工具</span></b>,只使用作業系統內建的基本工具即可。</li>
<li><b><span style="color: blue;">與系統特性無關</span></b>,不需要先理解遇到麻煩的系統任何內部原理與商業邏輯。</li>
</ol>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: inherit;"> 所以任何任何人,都可依照這個 SOP,花個半天時間迅速判斷 80% 以上的網站效能瓶頸點。</span><br />
<span style="font-family: inherit;"></span><br />
<a name='more'></a><span style="font-family: inherit;"><br /></span></div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="orphans: auto; text-align: -webkit-auto; widows: auto;"> </span><span style="orphans: auto; text-align: -webkit-auto; widows: auto;"> </span><span style="font-family: inherit;">首先,當網站系統總是不太回應時,相信剛開始大家會做的第一步應該都一樣:<span style="color: blue;"><b>打開『工作管理員</b>(TaskManager)<b>』看一下 CPU / RAM 的使用狀況</b></span>。</span></div>
</div>
<div style="orphans: 2; text-align: -webkit-auto; widows: 2;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-uUFniobcQgQ/UrJLxELhKGI/AAAAAAAASpE/Usb5JFL6cmE/s1600/taskmanager01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" src="http://2.bp.blogspot.com/-uUFniobcQgQ/UrJLxELhKGI/AAAAAAAASpE/Usb5JFL6cmE/s1600/taskmanager01.png" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;">如果 <span style="color: #cc0000;"><b>CPU 或是記憶體使用率偏高</b></span>(<span style="color: #666666;">總是在 90% 往 100% 天花板上撞</span>)<b><span style="color: #cc0000;">,就要看是機器上的哪支程式吃掉</span></b>,對於多使用者的網站系統,<span style="color: blue;">通常不外乎是<b>網站服務</b>(IIS - w3wp.exe)或是<b>資料庫服務</b>(SQL Server - sqlservr.exe)</span>,若是其他非必要程式吃光了 CPU ,例如防毒軟體,就要請 MIS 妥善設定這類軟體或是直接關閉,這一樣可以透過工作管理員就輕鬆找到。</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-cvOhFHlnDVY/UrJQKJwvobI/AAAAAAAASpQ/nDGtJn7RL4s/s1600/taskmanager02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" src="http://4.bp.blogspot.com/-cvOhFHlnDVY/UrJQKJwvobI/AAAAAAAASpQ/nDGtJn7RL4s/s1600/taskmanager02.png" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;">最好多加入一些欄位輔助判斷,例如 PID 和執行緒數量,尤其<span style="color: blue;">如果你的網站內有許多子功能網站,且使用 IIS 應用程式集區而有多個 Worker Process,會需要 PID 幫你分辨是哪個子功能的網站過度忙碌</span>,而不需要依靠個別關閉來 try 出哪一個是占用資源的子網站。</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><span style="color: #cc0000;"><b>如果 CPU 看來平靜無波,有可能是對外的網路頻寬出了問題</b></span>,塞車是塞在外面。<span style="color: blue;">簡易的判定方式是直接在網站伺服器上打開瀏覽器觀看自己的網站</span>,如果非常通順,那就是對外網路頻寬的問題,從外部 ping 一下回應數據(<span style="color: #666666;">有些可能關閉不給 ping</span>),然後打電話給機房人員吧。</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><span style="color: #cc0000;">若不是網路問題</span>,不論 CPU 使用率高不高,即使從伺服器上看網站都非常慢,<span style="color: blue;">這時候就需要透過『<b>效能監視器</b>(Performance Monitor)』來觀看網站服務實際的狀況</span>。下圖是我前一陣子幫公司做壓力承載測試所截下的圖片:</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-_7cox3l65aY/UrJVoOHuSyI/AAAAAAAASp4/j-QxCQtB6xE/s1600/web00.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" src="http://4.bp.blogspot.com/-_7cox3l65aY/UrJVoOHuSyI/AAAAAAAASp4/j-QxCQtB6xE/s1600/web00.png" height="233" width="640" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;">一開始流量還沒灌進來時...</span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-E1S6n8UQxt0/UrJVhVYPoaI/AAAAAAAASpw/_mzCV3-fr6g/s1600/web01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" src="http://2.bp.blogspot.com/-E1S6n8UQxt0/UrJVhVYPoaI/AAAAAAAASpw/_mzCV3-fr6g/s1600/web01.png" height="234" width="640" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"> 上圖可以看出,不間斷地同時間有 100 個請求(<b><span style="color: blue;">Request Current</span></b>),來跟網站要資料。每個請求<b style="background-color: yellow;">大約會卡住三秒</b>之後才會回應(<b><span style="color: blue;">Request Execution Time</span></b>),說明了這時候如果有使用者連上網站,大約要等三秒之後才會開始看到網頁回傳。</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"> 不過以我的例子,<b>用戶會卡三秒,但是右邊卻顯示 CPU 閒置到不行,幾乎沒在做事</b>。原因是因為<b>瓶頸卡在後端的資料庫主機</b>上:</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-xyxxohO22bQ/UrJXmlZwOiI/AAAAAAAASqE/F5WBAkvl3yQ/s1600/DB01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" src="http://4.bp.blogspot.com/-xyxxohO22bQ/UrJXmlZwOiI/AAAAAAAASqE/F5WBAkvl3yQ/s1600/DB01.png" height="348" width="640" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;">16 核 80G RAM 的機器被我操爆了</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"> 請注意,我上面又特別<b>把“</b></span><span style="font-family: inherit;"><b>死結”的計數器打開</b>(<b><span style="color: blue;">Number of Deadlocks</span></b>)。這個數字如果出現,往往會造成 CPU 使用率偏低(<span style="color: #666666;">因為都在空等不做事</span>),但是系統會卡很久不做事,光從『工作管理員』這樣的基本工具會找不出效能瓶頸。</span><a href="http://it.tomtang.idv.tw/2010/08/sql-deadlock.html" style="font-family: inherit;" target="_blank">遇到 Deadlock ,是需要修改程式邏輯去解決的</a>。</div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"> 如果不管<b><span style="color: #cc0000;">資料庫或是網站服務都看不出 CPU 使用率飆高的現象,也沒有 Deadlock,但是 Request Execution Time 卻莫名其妙地拖高</span></b>,不要多想,<b><span style="color: blue;">一定有 BUG </span></b>造成執行緒等待某個外部訊號或資源而 Blocking!工程師快認命去修程式吧(<a href="http://it.tomtang.idv.tw/2010/08/backgroundworker.html" target="_blank">案例</a>)!</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"> 是不是被攻擊或是不當使用,差不多在這個步驟已經可以看出來。根據 Requests Current 數量是否異常地高,<b><span style="color: blue;">要找出被重度利用的點是哪裡,只要開啟 IIS 本身的紀錄即可</span></b>。</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-fU9hD3zbcWk/UrJdTV2BsUI/AAAAAAAASqU/6VgMuF-hUgk/s1600/iis01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" src="http://1.bp.blogspot.com/-fU9hD3zbcWk/UrJdTV2BsUI/AAAAAAAASqU/6VgMuF-hUgk/s1600/iis01.png" height="463" width="640" /></span></a></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"> 這個紀錄檔內會記載對方要求的網址,瀏覽器,作業系統這些 HTTP Header 內會有的東西,經過整理,很快就可以<b><span style="color: blue;">統計出最頻繁被索取的網址路徑,頻率最高的來源 IP</span></b>,做為進一步反制的參考依據。</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"> 以上基本款的 SOP 大概半天到一天的時間就可以釐清 80% 常見的網站效能問題,剩下 20% 屬於系統開發設計不良造成的瓶頸,屬於更進階個案的問題,但是透過額外的工具輔助依然可以找出癥結點,不過這就不符合“人人可做的簡易精神”了</span><span style="font-family: inherit;">。</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: inherit;"> <b><span style="color: blue;">今年 50 篇的部落格文章在這篇達成!</span></b>祝福大家新的一年,系統都可以頭好壯壯,不用依賴乖乖也能過個好年!</span></div>
<div id="wrchoverdiv" style="display: none;">
<div id="wrccontainer">
<div id="wrcheader">
<div id="wrctitle">
WebRep</div>
</div>
<div class="wrchorizontal">
</div>
<div id="wrccurrentvote">
currentVote</div>
<div class="wrchorizontal">
</div>
<div id="wrcrating">
</div>
<div id="wrcratingtext">
noRating</div>
<div id="wrcweighttext">
noWeight</div>
<div id="wrcflags">
<div class="wrcicon" id="wrcicon_shopping">
</div>
<div class="wrcicon" id="wrcicon_social">
</div>
<div class="wrcicon" id="wrcicon_news">
</div>
<div class="wrcicon" id="wrcicon_it">
</div>
<div class="wrcicon" id="wrcicon_corporate">
</div>
<div class="wrcicon" id="wrcicon_pornography">
</div>
<div class="wrcicon" id="wrcicon_violence">
</div>
<div class="wrcicon" id="wrcicon_gambling">
</div>
<div class="wrcicon" id="wrcicon_drugs">
</div>
<div class="wrcicon" id="wrcicon_illegal">
</div>
</div>
<div class="wrchorizontal">
</div>
</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-44692641417140260462013-12-14T00:54:00.002-08:002013-12-14T00:54:14.335-08:00我的 log4net 設定的 Best Practice <div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-E4o64ie1YL4/UqwA3Ah1RkI/AAAAAAAASoI/J_nlm20QJmk/s1600/o_log4netObjectRelations.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-E4o64ie1YL4/UqwA3Ah1RkI/AAAAAAAASoI/J_nlm20QJmk/s1600/o_log4netObjectRelations.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-size: x-small;">(圖片源自<a href="http://itrust.cnblogs.com/archive/2005/01/25/97225.html" target="_blank">”log4net面面觀之工作原理“</a>)</span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
一個系統是否容易追蹤與維護?出了問題容不容易快速查閱、釐清問題癥結?系統日誌(<span style="color: #666666;">System logging</span>)絕對佔著舉足輕重的角色。.NET 寫系統日誌的方案,最出名的大致上只有兩種:<a href="http://logging.apache.org/log4net/" target="_blank">log4net</a> 和 <a href="http://nlog-project.org/" target="_blank">NLog</a>。兩者之間沒什麼優劣比較,這種東西,精通其中之一就很夠用。<br />
<br />
<a name='more'></a><br /><br />
而<a href="http://it.tomtang.idv.tw/2006/11/my-work-log4net-gui.html" target="_blank">我身為 log4net 多年來的長期支持者</a>,對於這個強而有力的工具如何妥善地被運用有些心得在此分享,希望可以協助初階的開發人員快速掌握系統日誌的便利性。網路上關於 log4net 的介紹與使用已經很多,大家可以自己找來看,如果你還不熟悉這工具的用法,除了官方網站的英文文件外,以下幾篇還蠻值得參考、快速學習:<br />
<br />
<ul>
<li><a href="http://dragon.cnblogs.com/archive/2005/03/24/124254.html" target="_blank">log4net 使用指南(簡體)</a></li>
<li><a href="http://www.dotblogs.com.tw/yuanlin/archive/2012/05/30/72479.aspx" target="_blank">簡單記錄 log4net 的用法</a></li>
</ul>
<br />
假設你已經知道如何使用 log4net 了,但是<a href="http://logging.apache.org/log4net/release/config-examples.html" target="_blank">它的組態設定千變萬化</a>,怎麼樣才是個比較高階通用、方便容易使用的設定方式呢?我這邊要分享的就是這個經驗。<br />
<br />
首先,log4net 的設定檔有兩種主流載入法(<span style="color: #666666;">我曾在某公司還有看過非常不入流的第三種</span>):<br />
<br />
<ol>
<li>嵌入 app.config 或 web.config,跟 .NET 應用程式組態檔共存。<a href="http://dragon.cnblogs.com/archive/2005/03/24/124254.html" target="_blank">上面簡體的指南</a>就是介紹這種方式。</li>
<li>讀取外部檔案。<a href="http://www.dotblogs.com.tw/yuanlin/archive/2012/05/30/72479.aspx" target="_blank">上面的第二篇簡易教學</a>採用的就是這種方式。</li>
<li><strike><i><span style="color: #e06666;">在程式中用 StringBuilder 組好 xml 設定後,用 XmlReader 直接餵進去。小孩子千萬不要學壞!</span></i></strike></li>
</ol>
<div>
無論如何,我『<span style="color: blue;"><b>非常強烈</b>推薦</span>』採用第二種做法!原因如下:</div>
<div>
<ol>
<li><span style="color: blue;"><b>可以將公司內的 log4net 設定統一管理,採用相同的 Text pattern、filename、location convention。</b></span>我會在公司內透過 CI Server ,用統一規範過的 log4net.config 將所有生成的 application package 內的 log4net 設定覆蓋,達到一致性、去複雜化的效果。<span style="color: red;">如果 log4net 的設定藏在應用程式的組態檔內,這件事就非常困難</span>。<br />試想:若公司內有大大小小數十個系統,每個系統寫出的 log 格式、檔案命名、路徑各自發揮都不同,可是會讓維護人員真的動手查問題前先玩抓迷藏,花時間去找不同系統藏在不同地方的 log 檔,而且格式各不相同,解讀與理解困難。<br /></li>
<li><b><span style="color: blue;">常會有必要需要臨時動態調整 log 的設定,例如平時沒事的時候把過濾層級關到 WARN,只有出事的時候才想打開 DEBUG 層級。</span></b><span style="color: red;">如果把設定擺在應用程式組態內,一旦修改,會導致必須重新啟動應用程式,網站會將在線使用者登出,而服務必須重新下上,影響系統營運!而且有些錯誤只要一重開系統就會消失,等於束手無策!<br /></span></li>
<li><strike>廣告:可利用<a href="http://it.tomtang.idv.tw/2006/11/my-work-log4net-gui.html" target="_blank">我寫的 GUI Editor</a> 來視覺化編輯這個獨立的組態檔案。</strike></li>
</ol>
<div>
以上兩個理由,我想已經足夠說服大家將設定獨立於外部的重要性。至於從外部讀取組態的方式,基本上,我都是在程式的進入點就立刻做掉,我制定的文件規範範例如下:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-MfNXiYBCH6I/UqwShJZNdeI/AAAAAAAASoo/y_mfUhTFyW8/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-12-14+%E4%B8%8B%E5%8D%884.09.55.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-MfNXiYBCH6I/UqwShJZNdeI/AAAAAAAASoo/y_mfUhTFyW8/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-12-14+%E4%B8%8B%E5%8D%884.09.55.png" /></a></div>
<br />
<b><i><span style="color: blue;">ConfigureAndWatch</span></i></b> 的用途就是為了動態偵測組態檔案的變化,自動重新讀取而不用重新啟動系統。<br />
<br />
另外,最好在啟動的時候多塞入一個自定的 Global property(原因在後續介紹組態時會用到)如下:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-gsnfytmIPlg/UqwUy9QtLkI/AAAAAAAASo0/qG96-jR5CUo/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-12-14+%E4%B8%8B%E5%8D%884.13.31.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-gsnfytmIPlg/UqwUy9QtLkI/AAAAAAAASo0/qG96-jR5CUo/s1600/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7+2013-12-14+%E4%B8%8B%E5%8D%884.13.31.png" /></a></div>
<br /></div>
</div>
<div>
<br /></div>
<div>
再來是我多年經驗而推薦的設定內容(<a href="https://dl.dropboxusercontent.com/u/12401838/log4net.config" target="_blank">點此直接下載</a>):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-t-lhHN_lae0/UqwJ-eocRCI/AAAAAAAASoY/f8dENXO2ODM/s1600/log4netconfig.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-t-lhHN_lae0/UqwJ-eocRCI/AAAAAAAASoY/f8dENXO2ODM/s1600/log4netconfig.png" height="640" width="377" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
(<span style="color: blue;">圖有點小,請點擊上圖另開分頁看原圖</span>)</div>
<h4>
<span style="color: #cc0000;"><i> 解說:</i></span></h4>
</div>
<div>
<br />
<ol>
<li><b><span style="color: #990000;">依不同系統,動態產生該系統專屬的 log 檔與資料夾路徑:</span></b>如果一個通用的 log4net 組態可以不用為了錯開不同系統的 log 而個別客製化修改檔案路徑,就減少了許多管理與維護的麻煩。這裡運用了 log4net 可以生成自定屬性的方式,從 appname 的 property 中讀取目前的系統名稱組合出對應路徑與檔名。<br /></li>
<li><b><span style="color: #990000;">為了強化 log 內文字的讀取與解析,利用 tab 當作資料的分隔字符</span></b>,保留日後可以透過 ETL 解析統計的可行性。<a href="https://issues.apache.org/jira/browse/LOG4NET-166" target="_blank">但是自從 1.2.9 版本之後,log4net 不再支援組態檔內直接吃 tab 字元,而是必須透過編碼代表 [TAB]</a>。<br /></li>
<li><b><span style="color: #990000;">避免獨占檔案 IO:</span></b>基本上,log4net 在寫當下的 log file 是會獨占該檔案的所有權,其他人只能 read-only。這導致當有多個 processes “因故”會寫入同一個 log 檔案時(<span style="color: #666666;">我不鼓勵共用 log 檔</span>),只有一個會成功,其他 processes 都會失敗,導致其他程式的 log 遺失。或者希望在系統運行中想清除既有的 log 檔案內容或刪除檔案,也無法做到。採用 <b>MinimalLock</b> 策略可以避免上述問題,但請注意,雖然<span style="color: red;">這種方式會影響效能</span>,不過我還是偏愛採用。<br /></li>
<li><b><span style="color: #990000;">將不同 LEVEL 的 log 分開在不同檔案:</span></b>當系統發生錯誤,可以根據對應 level 的 log 檔快速找到問題點。平時對<span style="color: blue;">系統健康做檢查時,亦可直接檢視 Error.log 該檔案的大小就知道系統現在是否穩定</span>,不用實際打開 log 檔,讓系統管理更輕鬆。<br /></li>
<li><b><span style="color: #990000;">針對特定 class 或 namespace 底下的程式關閉 log,避免干擾:</span></b><span style="color: blue;">過多的資料等於沒有資料!</span>當一個系統每秒會產生1MB的 log,一天下來吃掉幾十 GB 的 log 檔案,問題的追蹤與維護就會變成大海撈針。將程式中平時不必要寫的 log 移除相關程式碼是不錯的方法,但是卻<b><span style="color: red;">不可逆</span></b>。 <span style="color: blue;">改用 logger level override 的方式,可以關閉特定程式碼輸出的 log,但是保留想關程式碼,在未來無法預期的哪一天需要用到時再打開</span>。</li>
</ol>
<div>
其實 log4net 的學問很廣,深入研究能夠精細調整的還有很多,尤其種類繁多的 Appender,是非常值得所有 .NET 程式設計師投資時間研究的工具。如果這篇文章能當作進階應用經驗傳承的引子,除了介紹與教學外,<span style="color: blue;">希望有更多人能分享這類的<b>實戰</b>經驗</span>。</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-75582877865932753572013-12-07T18:53:00.002-08:002013-12-24T16:08:15.455-08:00從『玩股網驚魂記』談大禹治水<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-WKbhj0b287c/UqPeiwAVdTI/AAAAAAAASjs/flJZcKKUUYQ/s1600/201101190620490109.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-WKbhj0b287c/UqPeiwAVdTI/AAAAAAAASjs/flJZcKKUUYQ/s1600/201101190620490109.jpg" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<a href="http://madchu.com/" target="_blank">楚狂人</a>的『<a href="http://www.wantgoo.com/" target="_blank">玩股網</a>』前陣子發文公告系統不穩的情形,這兩天他寫了篇『<a href="http://madchu.com/?p=4544" target="_blank">玩股網驚魂記</a>』說明了前因後果,看完後覺得可以當作一個個案解析的案例。<br />
<div>
<br /></div>
<div>
先談談文章所說最後發現玩股網無法正常運作的結論:被大量的 <a href="http://zh.wikipedia.org/wiki/%E7%BD%91%E7%BB%9C%E7%88%AC%E8%99%AB" target="_blank">Crawler(<span style="color: #666666;">網路爬蟲</span>)</a>抓資料導致伺服器過於忙碌。開頭原本說判斷這應該不是駭客攻擊,其實就結果來看,這也算是一種攻擊手法:<a href="http://zh.wikipedia.org/wiki/DDOS" target="_blank"><span style="color: #cc0000;">分散式服務阻斷式攻擊</span>(<span style="color: #666666;">DDoS</span>)</a>。</div>
<div>
<a name='more'></a><br /></div>
<div>
以這個結果來說,所謂前十大知名網站工程師竟然花了這麼多天,繞路這麼久才發現問題根源,令我眼睛脫窗。整個查案過程,我看到的是普遍台灣工程師在幹的『土法煉鋼法』:<span style="color: #cc0000;">也就是瞎子摸象、邊猜邊測邊找、從錯誤中排除可能</span>。</div>
<div>
<br /></div>
<div>
沒有透過善用工具,用系統化的方式找問題,完全依賴工程師過往的經驗;也就是工程師曾經遇過的狀況,列舉逐一做實驗排除,遇到不曾遇過的狀況就攤手。文章描述的期間可以看到<b><span style="color: #cc0000;">物力</span></b>(<span style="color: #666666;">平白浪費錢多買新的等級主機卻沒有對症下藥</span>)<span style="color: #cc0000;"><b>人力</b></span>(<span style="color: #666666;">工程師白花力氣熬夜加班卻只有苦勞沒有功勞</span>)與<b><span style="color: #cc0000;">營業損失</span></b>(<span style="color: #666666;">長達數周網站無法提供完整功能,影響客戶與事後補償</span>)。</div>
<div>
<br /></div>
<div>
由於玩股網採用的是 .NET 與微軟 Windows Server 技術平台,在此平台上如何有系統的找出系統問題,之後我打算另外寫<a href="http://it.tomtang.idv.tw/2013/12/sop.html" target="_blank">一篇文章分享個人 SOP 的做法流程</a>(<span style="color: #666666;">沒辦法,年底了要趕快湊齊部落格的年度目標的文章數量,拆成兩篇比較賺</span>),希望可以幫助其他公司與 IT 從業人員儘快鎖定問題根源,減少瞎子摸象、耗時耗力造成的經營損失。</div>
<div>
<br /></div>
<div>
但在此之前,我想先從<b>商業觀點</b>談談這個案例背後可能的<b>商業機會</b>!所謂<b>危機就是轉機,這件事在我看來怎麼樣都是玩股網個可以獲利的機會</b>!</div>
<div>
<br /></div>
<div>
目前他們的做法是阻擋這些來竊取資料的不明 IP,若以古代治水方法來說,採用的是<a href="http://zh.wikipedia.org/wiki/%E9%B2%A7%E7%A6%B9%E6%B2%BB%E6%B0%B4" target="_blank">大禹的父親 - “鯀”的治水法</a>:<b><span style="color: red;">阻擋</span></b>。</div>
<div>
<br /></div>
<div>
這方式就算奏效,也是<b><span style="color: #cc0000;">增加管理的複雜度,不堪其擾</span></b>。</div>
<div>
<br /></div>
<div>
其實想想,<span style="color: blue;">有這麼多 Crawler 來爬網站的資料,代表市場上有這樣的需求在</span>,為什麼,<b><span style="color: blue;">玩股網不乾脆開發一組 Web API 開放給外界用標準且正確的方法來撈資料?</span></b>而且,這組 API 可以跟外界收取月費<b>增加網站盈利</b>!</div>
<div>
<br /></div>
<div>
<b> 就算 API 是免費提供,對玩股網一樣有以下好處:</b></div>
<div>
<ol>
<li><b><span style="color: blue;">API 以獨立伺服器運作</span></b>,與一般使用者瀏覽的網站伺服器切割,<span style="color: blue;">無論是流量多大,被打爆的是 API 伺服器,不會影響一般上網的使用者</span>。</li>
<li><b><span style="color: blue;">易於管理</span></b>,對 API 的使用者提供申請認證,可以真正掌握資料使用量的大戶,<span style="color: blue;">分析潛在B2B 客戶,增加日後商業合作的談判籌碼</span>。</li>
</ol>
<div>
免費開放就有以上好處,若是收費,只要價錢合宜,也會有效引開爬蟲的流量。因為:</div>
</div>
<div>
<ol>
<li><b><span style="color: #cc0000;">寫爬蟲也是花力氣成本的:</span></b>寫爬蟲的人最討厭解析不規則的 HTML,也最怕網站不預期地改版網頁結構,導致爬蟲程式抓錯資料。如果官方提供標準格式的 API,將節省爬蟲的開發與維護成本,不用擔心哪天網頁改版。</li>
<li><b><span style="color: #cc0000;">商業依賴:</span></b>如果爬蟲作者的自己經營的服務重度依賴玩股網的資料,最怕無預警地 IP 被阻擋,導致自己的服務也停擺,如果付點小錢就可以保證資料取得的穩定性,這是非常划算合理的交易。</li>
</ol>
<div>
由於本人 IT 服務產業也是 Crawler 盛行的產業,<span style="color: blue;">上述的經營或是操作方式是確定有市場和可行性的</span>。</div>
<div>
<br /></div>
<div>
以上,是我認為<a href="http://www.wantgoo.com/" target="_blank">玩股網</a>可以思考的『<a href="http://zh.wikipedia.org/wiki/%E9%B2%A7%E7%A6%B9%E6%B2%BB%E6%B0%B4" target="_blank">大禹治水法</a>』,用『<span style="color: blue;">雙贏的思考</span>』、『<b><span style="color: blue;">導引取代阻擋</span></b>』,或許是一個更好的決策模式。</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-1873331086574528112013-11-30T03:08:00.000-08:002013-12-01T06:53:03.833-08:00[連載]新創公司歷險記-1:臨危受命,掌握資訊<div class="tr_bq">
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
</div>
<div style="font-family: Arial;">
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-UoWy_r5jKMw/UpnEZv45W5I/AAAAAAAASco/GIcw-RI2UFE/s1600/002140992.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-UoWy_r5jKMw/UpnEZv45W5I/AAAAAAAASco/GIcw-RI2UFE/s1600/002140992.jpg" height="320" width="285" /></a></div>
今年四月,正徘徊在職涯下一步的十字路口,當時剛好接到前同事電話力邀我加入一個剛成立半年的新創公司團隊,一起打造一個全新的新產品而努力。<br />
<br />
當時被原公司既有的營運系統基於管理上風險的考量,而搞得拳腳難伸的我,在與灰心喪志之下,很受<span style="color: blue;">眼前這個可以盡情嘗試各種全新技術與各種假設的創業機會所吸引,毅然訣然地揮別前公司</span>。</div>
<div style="font-family: Arial;">
<div>
<br /></div>
由於要能盡情試驗新技術、開發流程與團隊合作的模式,我加入的條件就是我必須擔任掌握這些權力的 <a href="http://think.tomtang.idv.tw/2013/10/team-lead.html" target="_blank">Team Lead(這篇)</a>。<br />
<div>
<br /></div>
然而真正置身此處,才發現事情也沒有想像中那般美好。<br />
<div>
<br />
<a name='more'></a><br /></div>
<div>
如今我們孵育的產品終於要推出市場接受真實的考驗。我一直想回顧與檢討這過程中我所採取的做法和決定,在產品推出的這個時間點,我想是最好不過。</div>
<div>
<br /></div>
<div>
一直在猶豫到底這個連載該放在我專談論<a href="http://think.tomtang.idv.tw/" target="_blank">「工作與雜想」的部落格</a>,或是<a href="http://newtom-it.blogspot.tw/" target="_blank">「IT見聞與思維」的這裡</a>,最後我決定以比較<b><span style="color: blue;">“技術性”</span></b>(<span style="color: #666666;">軟體工程、專案管理、技術性抉擇</span>)的方式來撰寫這個過程。</div>
<div>
<br /></div>
剛進來,就發現這個已經 RUN 了半年的新創公司已經陷入產品開發進度嚴重落後的慘況,團隊成員能力青澀,解決問題能力有限,而大量採用的新穎的新技術也造成團隊冗長的瞎子摸象的適應期,讓我第一天到任就加班到超過凌晨,只為了解決最初股東用展示版本的佈署(Deployment)。</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
原本我打算引入原公司無法實現的 SCRUM 開發方法,以及完整且全面性的『測試驅動開發』(TDD),在火燒屁股的專案時間限制下根本無法實現。<br />
<div>
<br /></div>
面對用不熟悉的技術而已經亂了陣腳的團隊,我判斷這時候再冒然導入 SCRUM 和 TDD 改變他們的做事方式,只會落得水土不服,導至更嚴重的混亂和團隊對朝令夕改的反感情緒。<br />
<div>
<br /></div>
當時團隊採用沒人熟悉的“全新”工具清單如下:</div>
<div>
<ul style="font-family: Arial;">
<li><b><span style="color: #cc0000;">全新沒用過的開發工具:</span></b>VisualStudio 2012</li>
<li><b><span style="color: #cc0000;">全新<span style="background-color: yellow;">超難用的開發機 OS</span>:</span></b>Windows 8</li>
<li><b><span style="color: #cc0000;">全新<span style="background-color: yellow;">超難用常用功能總是被藏起來</span>的辦公軟體:</span></b>Office 2012</li>
<li><b><span style="color: #cc0000;">全新沒人熟悉的版本控管工具:</span></b>GitHub(<span style="color: #666666;">之前大家都是喝 SVN 奶水長大的,我的<a href="http://it.tomtang.idv.tw/2013/08/svn-git.html" target="_blank">轉換新心得在此</a></span>)</li>
<li><b><span style="color: #cc0000;">全新的開發框架:</span></b>.NET 4.5 + ASP.NET MVC4</li>
<li><b><span style="color: #cc0000;">全新的 Web 溝通技術:</span></b>.NET SignalR + WebSocket</li>
<li><b><span style="color: #cc0000;">全新的<span style="background-color: yellow;">竟然把手機平板的操作搬給伺服器用的白痴設計</span> Server OS:</span></b>Windows Server 2012(<span style="color: #666666;">完全是為了 IIS8 有 WebSocket 功能</span>)</li>
<li><b><span style="color: #cc0000;">全新的 Socket 通訊技術框架:</span></b>ZeroMQ</li>
<li><b><span style="color: #cc0000;">全新的資料封裝技術框架:</span></b>Google ProtoBuf Message</li>
</ul>
<div style="font-family: Arial;">
公司 CEO 曾說:「<span style="color: blue;">專案採用新技術的比例最好低於 30%,否則很容易有許多無法預期的風險讓專案進度失控。</span>」</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
但<span style="color: red;">我們當時大概採納了 50%~60% 的新東西吧</span>?總之一團混亂下,我加入公司的第一週依計劃中的進度,部分系統就應該要衝 QAT 給 QA 測試,然後隔週股東從國外飛來台灣參訪看 DEMO。</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
哈,我搶著當 Team Lead 的行為就好像搶著把自己人頭擺上斷頭台上,還怕讓給別人咧~。</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
沒辦法多想怎麼導入我原本期望中的東西,當務之急是『<span style="color: blue;">掌握專案實際進度</span>』、『<span style="color: blue;">釐清工作順序</span>』、『<span style="color: blue;">確保計劃發生</span>』。<br />
<br />
SCRUM 裡面我能先借用的,就是 Daily stand-up meeting,只不過我改良成 Daily “sit-down” meeting⋯⋯XD。</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
我的 Daily meeting 的三大重點:</div>
<div>
<ol>
<li><span style="color: #990000; font-family: Arial;">回報「昨天我完成什麼」?</span></li>
<li><span style="color: #990000; font-family: Arial;">若昨天的項目沒有如期完成,原因為何?遇到什麼樣的阻礙、困難?</span></li>
<li><span style="color: #990000; font-family: Arial;">宣告「今天預計要完成什麼」?</span></li>
</ol>
<div>
<span style="font-family: Arial;"> 這讓我每天一早都可以更新最新的工作進度情報,並且儘早知道開發所遇到的障礙,急救的效果非常好。</span></div>
<div>
<span style="font-family: Arial;"><br /></span></div>
<div>
<span style="font-family: Arial;"> 但沒多久我就發現,團隊成員回報的“完成”,和我理解的“完成”差別很大,常常我聽到某人回報說“已經完成”,然後我派人接續後面的開發立刻壞掉,後面整合的人做不下去。</span></div>
<div>
<span style="font-family: Arial;"><br /></span></div>
<div>
<span style="font-family: Arial;"> 然後追問之下,得到類似以下的答覆:</span></div>
<div>
<span style="font-family: Arial;"><br /></span></div>
<div>
<span style="font-family: Arial;"> 「<span style="color: #783f04;">我完成的是</span><span style="color: red;">“程式碼撰寫”</span><span style="color: #783f04;">,但我</span><span style="color: red;">“還沒測試過”</span><span style="color: #783f04;">。</span>」</span></div>
<div>
<span style="font-family: Arial;"> 「<span style="color: #783f04;">我完成的是</span><span style="color: red;">“我目前能做的部分”</span><span style="color: #783f04;">,剩下沒做的是在</span><span style="color: red;">等 B 寫完,我才能繼續</span><span style="color: #783f04;">。</span>」</span></div>
<div>
<span style="font-family: Arial;"> 「<span style="color: #783f04;">我完成的是</span><span style="color: red;">“基本功能”</span><span style="color: #783f04;">,你</span><span style="color: red;">只能用我 hardcode 的測試資料來呼叫我</span><span style="color: #783f04;">。</span>」</span></div>
<div>
<span style="font-family: Arial;"> 「<span style="color: #783f04;">我完成的是</span><span style="color: red;">“正常使用的流程”</span><span style="color: #783f04;">,</span><span style="color: red;">還沒做“資料驗證”或是“錯誤處理”</span><span style="color: #783f04;">,你必須送正確的資料給我才行。</span>」</span></div>
<div>
<span style="font-family: Arial;"> 最經典的,</span><span style="font-family: Arial;">就是說:<b>“寫完了”</b>就下班,結果別人要進行整合時卻找不到那個東西,然後通電話追問,居然給我回答說:「<span style="color: #783f04;">我寫完啦,但是</span><span style="color: red;"><b>“還沒 commit 和 push”</b></span><span style="color: #7f6000;">。</span>」</span></div>
</div>
</div>
<div>
<span style="font-family: Arial;"><br /></span></div>
<div>
<span style="font-family: Arial;"> 會不會想丟筆、摔電話?</span></div>
<div>
<span style="font-family: Arial;"><br /></span></div>
<div>
<span style="font-family: Arial;"> 這讓我在掌握實際進度與工作派工上非常困擾,於是我利用一次晨會,非常慎重的跟團隊對“完成”兩字,作了明確的定義 - DoD(Definition of Done)。</span></div>
<blockquote>
<span style="font-family: arial, sans, sans-serif; font-weight: bold;"><span style="color: blue;">Completed = Deliverable</span></span></blockquote>
<blockquote>
<span style="font-family: arial, sans, sans-serif; font-weight: bold;"><span style="color: blue;">Partial completed = Partial Deliverable</span></span></blockquote>
<blockquote>
<span style="color: blue; font-family: arial, sans, sans-serif; font-weight: bold;">IF the part is unable to be delivered, the part doesn't existed (0%)</span></blockquote>
<blockquote>
<span style="font-family: arial, sans, sans-serif; font-weight: bold;"><span style="color: blue;">完成多少 = 交付多少</span></span></blockquote>
<blockquote>
<span style="font-family: arial, sans, sans-serif; font-weight: bold;"><span style="color: blue;">部分完成 = 部分交付</span></span> </blockquote>
<blockquote>
<span style="color: blue; font-family: arial, sans, sans-serif; font-weight: bold;">別人無法接手的部分 = 該部分視同完成度 0%</span></blockquote>
<span style="font-family: Arial, Helvetica, sans-serif;"> 也就是說,你交不出來的東西,別人無法接手,無法幫你修 BUG,我就當這東西不存在,當你混了一天什麼都沒做。什麼完成 50%、70%,只要別人看不到摸不著,就當你這數字喊爽喊虛的,是真實還是吹牛我分不出來,就毫無意義。</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"> 接著我採取每週一個 Sprint 的做法,透過 Google Doc 的雲端硬碟上的試算表做任務管理和進度控管,力求資訊共享、透明、準確,跟緊團隊緊追 Weekly goal 衝刺!</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-W2CksOYxKxk/UpnCwxPXddI/AAAAAAAAScc/sru_37Sq3Xc/s1600/%E5%BD%B1%E5%83%8F+2013-11-30+%E4%B8%8B%E5%8D%885.05+(1).jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-W2CksOYxKxk/UpnCwxPXddI/AAAAAAAAScc/sru_37Sq3Xc/s1600/%E5%BD%B1%E5%83%8F+2013-11-30+%E4%B8%8B%E5%8D%885.05+(1).jpg" height="193" width="400" /></a></div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif;"> 掌握正確的局勢與確保團隊說出做到的共識,只是起手式,而後面還有許多嚴苛的挑戰必須面對⋯⋯。</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<br />
<div style="text-align: center;">
<span style="color: blue; font-family: Arial, Helvetica, sans-serif;"><b>未完待續</b></span></div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><i>附錄,這過程中,我做出一些跟『人』相關的管理行動,在另一個針對工作雜想的部落格也略有所提:</i></span><br />
<br />
<ul>
<li><span style="font-family: Arial, Helvetica, sans-serif;"><a href="http://think.tomtang.idv.tw/2013/08/myup-in-air.html" target="_blank"><strike>第一次開除人就上手</strike>MY『UP IN THE AIR』</a></span></li>
<li><a href="http://think.tomtang.idv.tw/2013/06/jd-job-description.html" target="_blank">JD (Job Description) 是什麼?能吃嗎?</a></li>
<li><a href="http://think.tomtang.idv.tw/2013/10/team-lead.html" target="_blank">新創公司的 Team Lead 跟你想的不一樣!</a></li>
</ul>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-43162238715611493462013-11-08T20:27:00.000-08:002013-11-08T20:27:06.753-08:00YAHOO 2013 HACKDAY 附錄:兩分鐘的 Bubble DEMO 劇本稿<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-YKOCy5AMRNE/Un2qcwNvIPI/AAAAAAAASYI/LM-fAVZ2WGU/s1600/banner_Github.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-YKOCy5AMRNE/Un2qcwNvIPI/AAAAAAAASYI/LM-fAVZ2WGU/s1600/banner_Github.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
<span style="font-family: Arial;"> 科技幫助人溝通越來越快速、方便,但是人與人之間的溝通,還缺了一個重要的環節。</span><span style="font-family: Arial;">我們團隊所製作的 <a href="http://hacks.developer.yahoo.com/hack/yahoo-hack-taiwan/bubble/event_17/hack_990" target="_blank">Bubble Chat</a>,就是為了補足這遺落的環節。</span><br />
<div style="font-family: Arial;">
<br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">進入我們的 APP ,首先結合超級好用的 YahooMap,精準地呈現你所在地週圍,其他人透過這個 APP 所分享的生活大小事,心情喜怒哀樂。</span><br />
<div style="font-family: Arial;">
<br />
<a name='more'></a><br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">這邊我們看到週圍許多人正在附近分享許多圖片與訊息,我來看看:哇!是有人分享 YAHOO Hackthon 的照片啊。</span><br />
<div style="font-family: Arial;">
<br />
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="360" src="//www.youtube.com/embed/yZjHPf7zwGE" width="480"></iframe></div>
</div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">還有人分享各種心情。</span><br />
<div style="font-family: Arial;">
<br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">等到結束今天的活動,我赫然發現我的車被拖掉,我滿肚子大便想大聲說: X 我的車被拖掉了!</span><br />
<div style="font-family: Arial;">
<br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">Bubble Chat 除了成為你心情舒發的管道,更能幫你實際的解決問題。</span><br />
<div style="font-family: Arial;">
<br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">這個 APP 結合工人智慧語意分析,強大的 YQL,市政府完善的 Open Data API,立刻告訴我附近的拖釣場資訊!</span><br />
<div style="font-family: Arial;">
<br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">太神奇了!傑克!</span><br />
<div style="font-family: Arial;">
<br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">等等,這裡有剛剛有人分享了新東西!我們點開來看看!</span><br />
<div style="font-family: Arial;">
<br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">哇!是 LIVE Video Streaming!</span><br />
<div style="font-family: Arial;">
<br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">裡面正在轉播什麼活動?天啊!是我們雅虎黑客松活動現場!!!這個 APP 讓人人都可以透過手機變身為移動的現場轉播電視台,你隨時可以跟週圍的陌生人即時分享活生生的現場喜悅,不只是靜態冰冷的打卡、照片、文字!而是不限制接收對象的即時視訊廣播!</span><br />
<span style="font-family: Arial;"><br /></span>
<span style="font-family: Arial;"> 透過這個 APP,人人都可以是 LIVE 電視台!</span><br />
<div style="font-family: Arial;">
<br /></div>
<span style="font-family: Arial;"> </span><span style="font-family: Arial;"> </span><span style="font-family: Arial;">這就是我所說人與人溝通遺失的環節,在地分享,更關懷生活在你左右的左鄰右舍,而不是身在千里之外的網友。</span><br />
<div style="font-family: Arial;">
<br /></div>
<div style="text-align: center;">
<b><span style="font-size: large;"><span style="color: blue; font-family: Arial;">Bubble Chat,Chat Bubble。</span></span></b></div>
<div style="font-family: Arial;">
<br /></div>
<div style="text-align: center;">
<span style="font-family: Arial;"><b><span style="color: blue; font-size: large;">在地社群,在地品牌行銷,在地溝通網路的最佳橋樑。</span></b> </span></div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-6440396609859521102013-11-08T20:01:00.004-08:002013-11-08T21:00:24.043-08:00YAHOO 2013 HACKDAY 參賽記錄與心得<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-CsW4L3c3v2k/Un2IGsIy84I/AAAAAAAASSw/LyFLZaQK-LQ/s1600/2013-11-02+09.19.46.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="297" src="http://3.bp.blogspot.com/-CsW4L3c3v2k/Un2IGsIy84I/AAAAAAAASSw/LyFLZaQK-LQ/s1600/2013-11-02+09.19.46.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<span style="font-family: Arial;"> 剛好透過 <a href="http://www.inside.com.tw/" target="_blank">INSIDE</a> 網站宣傳得知 Yahoo 今年所舉辦『<a href="http://survey.bnext.com.tw/events/2013yahoo/index.html" target="_blank">駭客松(Hackthon)</a>』。</span><br />
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
我實在認為自認有熱情的開發者,一生中都應該至少來體驗一次這種 “<span style="color: blue;">燃燒生命、爆肝寫 Code</span>” 的活動!所以之前總是錯過這類活動的我,這次看到比賽消息,立刻在 FB 上揪團參加。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<b>由於這次競賽的要求跟過去以往不同,特別強調 UI / UX 設計,並且要求團隊中一定要有至少一個 Designer 參加</b>,所以造成這次比賽隊伍中,女性比例大幅提高,每隊通常會有一個女性參加(<span style="color: #666666;">本隊也是</span>),甚至有團隊是完全女性組成的四人隊伍。如果去網路上尋找過去幾屆的比賽作品,相比之下也會發現這屆 DEMO 的作品視覺上質感有大幅提升的效果。
<br />
<br />
<a name='more'></a><br />
<br />
<div style="text-align: center;">
<a href="http://hacks.developer.yahoo.com/hacks/yahoo-open-hack-taiwan-2012/event_5" target="_blank">去年 2012 DEMO 作品</a></div>
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
來看看此次比賽的決勝條件:
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
每隊須在指定的 24 小時內,運用 Open API(<span style="color: #666666;">鼓勵使用 Yahoo API</span>),開發出可執行的程式,應用範圍不限。</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
評分標準:
</div>
<div style="font-family: Arial;">
<ul>
<li>創意:30%</li>
<li>技術:25%</li>
<li>UI 設計:25%</li>
<li>執行度:25%</li>
</ul>
</div>
<div style="font-family: Arial;">
比賽前一周參加完比賽行前說明會,團隊相聚一起討論我們的開發主題,這個階段大概就耗掉三天的時間,把腦力激盪的各種莫名其妙的想法重組混合,整理出兩個主要提案,最後在團隊意見分歧、難分難捨中,經由投票表决,定下了此次開發的目標,<span style="color: blue;">一個在地化、智慧型、多媒體社群交流分享的手機 APP - 『<a href="http://hacks.developer.yahoo.com/hack/yahoo-hack-taiwan/bubble/event_17/hack_990" target="_blank">Bubble</a>』</span>。</div>
<div style="font-family: Arial;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-YKOCy5AMRNE/Un2qcwNvIPI/AAAAAAAASYE/htQ4ZeKcl44/s1600/banner_Github.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-YKOCy5AMRNE/Un2qcwNvIPI/AAAAAAAASYE/htQ4ZeKcl44/s1600/banner_Github.png" /></a></div>
<div style="font-family: Arial;">
<br /></div>
<h3>
關於團隊 GATE(DOWAY)
</h3>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
由於我是先組成團隊,再決定要開發的應用,所以一開始團隊的組成其實包括了可能需要的各類人才:
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<ul>
<li><span style="color: #cc0000;"><b>Gale:</b></span>我們的 UI / UX 設計師,除了卓越的美感與藝術天分,同時也擅長 WEB 端技術開發,包含 HTML / CSS / JQuery / Bootstrap … 等 Web UI 框架。</li>
<li><b><span style="color: #cc0000;">Alan:</span></b>我們的 Open Source 與 Open API 專家,對資料庫、統計、與 Big Data 應用頗有研究,是幫我們發想如何應用開放資料和開發串聯的重要智囊。</li>
<li><b><span style="color: #cc0000;">Eric:</span></b>精通各類 Adobe 開發技術,由於透過 Adobe AIR 可以快速開發,非常輕易地跨平台同時發佈 iOS / Android 的行動應用版本,我找來替可能進行的行動應用鋪路。</li>
<li><span style="color: #cc0000;"><b>Tom:</b></span>精通手機拍照和錄影剪輯記錄,負責記錄團隊的一舉一動並寫 blog…。哈,其實是負責所有伺服器端的程式開發與環境部署。</li>
</ul>
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
團隊名稱的是比賽事後穿鑿而成,理由應該很明顯吧,哈!
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
基本上,這個團隊的技能分布涵蓋範圍非常完整,團員也都是一時之選,<span style="color: blue;">幾乎各種未知可能的應用都能進行開發</span>!但是,<span style="color: #cc0000;">先組成團隊最大的缺點,是當開發主題定案時,工作量就瞬間傾倒在某人身上,其他人只能雙手一攤,無法協助分攤...</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
真的要在一天 24 hr 的時間內將一個應用 “從無到有” 做出來,絕不是件容易的事情。根據過去參賽者的經驗,事前的準備工作一定要做足!<span style="color: red;">開發的過程中最難掌控也最殺時間的活動是什麼?當然是 DEBUG!</span>為了不要再開發當天才開始查問題,賽前一天,團隊跟公司告假,開始測試各種技術的可行性,把需要的外部資源該買、該申請的都搞定。</div>
<div style="font-family: Arial;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-AvYw4y1lJoc/Un2uwMc3HbI/AAAAAAAASY0/GQsvealf2FA/s1600/Yahoo+2013+Hackday+GATE%2528DOWAY%25291.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="http://2.bp.blogspot.com/-AvYw4y1lJoc/Un2uwMc3HbI/AAAAAAAASY0/GQsvealf2FA/s400/Yahoo+2013+Hackday+GATE%2528DOWAY%25291.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
前一天(<span style="color: #666666;">週五</span>)晚上,線上刷卡到國外租買必要的伺服器時遇到開通的障礙,對方透過英語線上客服回覆我們:<span style="color: #cc0000;">要等到<b>“下週一”</b>工程師上班時段才能幫我們解決</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-SQOlT-lLiUs/Un2sjtZI4_I/AAAAAAAASYc/8iOwgRtJB-c/s1600/Yahoo+2013+Hackday+GATE%2528DOWAY%2529.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="http://1.bp.blogspot.com/-SQOlT-lLiUs/Un2sjtZI4_I/AAAAAAAASYc/8iOwgRtJB-c/s400/Yahoo+2013+Hackday+GATE%2528DOWAY%2529.jpg" width="400" /></a></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
隔天六日就要進行比賽的我們當場嚇得屁滾尿流!苦無對策之下,三更半夜,Eric 只好在家忍痛把已經循環利息繳不完的信用卡,<span style="color: blue;">在付費頁面連續刷卡刷到機器連線開通為止,不成功便成仁的場面極其壯烈,若非親眼所見,難以想像</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
刷信用卡刷到清晨三點才上床睡覺的他,隔天早上九點就跟我在會場集合,開始佈置我們的開發基地,面對接下來不眠不休的 36 小時。但是這時候有沙發的好位置都早已被占光了,我們被迫坐在靠近網路 switcher 設備旁邊的桌椅。</div>
<div style="font-family: Arial;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-PckNsNhfrrQ/Un2uxhQpexI/AAAAAAAASY8/YKsighf2XjA/s1600/Yahoo+2013+Hackday+GATE%2528DOWAY%25292.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="http://4.bp.blogspot.com/-PckNsNhfrrQ/Un2uxhQpexI/AAAAAAAASY8/YKsighf2XjA/s400/Yahoo+2013+Hackday+GATE%2528DOWAY%25292.jpg" width="400" /></a></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<strike><span style="color: #666666;"><br /></span></strike></div>
<div style="font-family: Arial;">
<span style="color: #666666;"> <strike>曾經我們商量要不要利用這個主場優勢,三不五時走過去把強隊的網路線踢掉⋯⋯</strike></span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/--t-pLdVDfRM/Un2rsbwyfPI/AAAAAAAASYQ/3dTlDA5UWAc/s1600/1374482023-3260140954_n.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="http://1.bp.blogspot.com/--t-pLdVDfRM/Un2rsbwyfPI/AAAAAAAASYQ/3dTlDA5UWAc/s400/1374482023-3260140954_n.jpg" width="400" /></a></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
比我們更晚來的人,只能做吧台旁沒有靠背的高腳椅,我還看到有人因為坐到屁股痛,像是跪算盤一樣跪在高腳椅上寫 code,真是悲情。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<span style="color: blue;">這次教訓告訴我下次搶位置一定要再提早半小時以上進會場</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
比賽現場提供豪華的吃喝玩樂,我就簡單貼些照片簡單介紹。一天供應四餐(<span style="color: #666666;">三餐+半夜泡麵宵夜</span>),玩到手酸不用錢的投籃機、手足球、撞球桌⋯⋯。前幾年還有 Wii 這些電動可以打,今年沒看到。
</div>
<div style="font-family: Arial;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-BkRIrCIAjpY/Un2vjt2EmYI/AAAAAAAASZI/9gqZngBsFXY/s1600/Yahoo+2013+Hackday+GATE%2528DOWAY%25293.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="http://2.bp.blogspot.com/-BkRIrCIAjpY/Un2vjt2EmYI/AAAAAAAASZI/9gqZngBsFXY/s400/Yahoo+2013+Hackday+GATE%2528DOWAY%25293.jpg" width="400" /></a></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
決定走 App 開發,所有的重擔都落在 Eric 身上。從剛開始和我串伺服器的資料,到拿到 Desginer 的圖開始套 UI,沒有休息的時刻,天性溫馴的他也脾氣暴躁了起來。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
由於 DEMO 要看 UI 的東西都必須真的有實際互動的視覺效果,沒辦法作假,不像我們後端可以為了定點展示(<span style="color: #666666;">我們的應用跟地圖地位有關</span>)先寫死假資料串流程,所以<b>幾度他測試測到怎麼資料都不會變,才領悟到我這邊是寫死的假資料,對我比出數次中指叫我吃大便~~</b>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
可憐的他去了廁所還竟然在馬桶上睡著,搞失蹤。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
由於後端開發這次 Loading 相對輕鬆,沒有時間壓力,為了多學點新東西,所以這次我經由 Alan 從旁指導,臨時決定捨棄熟悉且最有把握的 MS SQL Server,而改採用 NoSQL 的 <a href="http://www.mongodb.com/" target="_blank">MongoDB</a> 來增加開發上的一些困難度和額外的工作量。這種 NoSQL 的使用經驗之前我也用過類似的 <a href="http://memcached.org/" target="_blank">Memcached</a> 和 <a href="https://developers.google.com/appengine/docs/java/datastore/?hl=zh-tw" target="_blank">GAE 的 Datastore</a>,所以並沒有很陌生,<span style="color: blue;">但是感受到 MongoDB 在資料的運用上有較為靈活強化的功能,且部署使用極為輕便,是這次的一大收獲</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
第二天早上發現已經瀕臨崩潰的 Eric 開發進度不如預期,由於<b><span style="color: #cc0000;">上台 DEMO 只有短短兩分鐘的時間</span></b>,所以我和 Alan 開始根據兩分鐘內要 DEMO 的方式和劇本橋段進行討論,<span style="color: blue;">然後決定把所有 DEMO 沒機會展示的“非重點”功能全部砍掉!整個 APP 的開發方向徹底變成為了 DEMO 量身定做的道具而開發,而不是當做一個真正可用的產品!
</span></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
由於要在 DEMO 時呈現社群使用這個 APP 的假象,我立即開發亂數隨機撒出以假亂真偽資料的程式,並且開始排演串通每個隨機資料撒出的時機點。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
然而真正 DEMO 的時候,仍然遇到一些突發狀況,讓我無法及時在兩分鐘內強調完我們這個 APP 的強項而下台一鞠躬。不過從最後得獎得隊伍來看出評審的取向,我們本來就不可能獲得青睞,所以 DEMO 的失誤倒也不算關鍵。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
這次得獎的隊伍作品,許多會在我們當初腦力激盪會議中被歸類不實用而被屏除的點子,但這就是評審的取向。</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
道理很簡單,因為<span style="color: blue;">這個比賽是 Yahoo 為了招募人才而舉辦的活動</span>,他們要的並<b><span style="color: #cc0000;">不是</span></b>一個市場上可行性高的<b><span style="color: #cc0000;">“產品”</span></b>,而是<span style="color: blue;"><b>要</b></span>找能在最短時間內,套用最炫技術做出成品的<b><span style="color: blue;">高效率“開發人員”</span></b>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
事後檢討時,老婆說的一句話總結得很好:<br />
<blockquote class="tr_bq">
<b><span style="color: blue;">大家都知道,F1 賽車平常根本沒什麼用途,家用四門房車的實用性遠高於只能一個人乘坐的賽車。但是如果是造車子比賽,兩天時間做出一輛家用四門房車,和兩天做出一台 F1 等級的賽車,誰會贏?當然是做出賽車的那組啊!</span></b></blockquote>
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
沒錯,<span style="color: #cc0000;">我要對自己這個團隊說聲抱歉,是我在腦力激盪會議時主張砍掉那些華而不實的賽車點子,而強留下實用度較高的四門房車點子</span>。這是我賽後心得,自己該學習面對的教訓與經驗。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
雖然我們採用 Adobe 的 AIR,但結局我們沒有拿到 Mac 的 AIR,<b><span style="color: blue;">但是卻呼吸到 Hacker 的 AIR!
</span></b></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
與一群能力高強、各有專長的朋友在高度專注與高效率配合下,在極短的時間內從無到有完成一個可用的軟體,這種過程真是非常愉快,<b>是我在工作職場上許久都不曾有的爽快感受!</b>我們這個團隊,有信心迎接未來的各類 HackDay 比賽! </div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<br />
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="360" src="//www.youtube.com/embed/kFr7WFzKkSg" width="480"></iframe></div>
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial; text-align: center;">
<a href="http://hacks.developer.yahoo.com/hacks/yahoo-open-hack-taiwan-2013/" target="_blank">本屆比賽所有 DEMO 作品</a></div>
<div style="font-family: Arial; text-align: center;">
<br /></div>
<div style="font-family: Arial; text-align: center;">
<a href="http://hacks.developer.yahoo.com/hack/yahoo-hack-taiwan/bubble/event_17/hack_990" target="_blank">我們的參賽作品:Bubble</a><br />
<br />
<a href="http://it.tomtang.idv.tw/2013/11/yahoo-2013-hackday-bubble-demo.html" target="_blank">兩分鐘 DEMO 稿</a></div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-82219345871759953042013-10-16T18:46:00.000-07:002021-04-23T04:41:41.120-07:00新創公司的 Team Lead 跟你想的不一樣!<!--?xml version="1.0" encoding="UTF-8" standalone="no"?--> <br /><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-uUwLXHwDgPA/Ul9BMJuPBVI/AAAAAAAASCw/lbqt3kySI8I/s1600/team-leader.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-uUwLXHwDgPA/Ul9BMJuPBVI/AAAAAAAASCw/lbqt3kySI8I/s1600/team-leader.jpg" /></a></div><div style="font-family: Arial;"> 前幾天一位前同事到家裡做客,邊玩邊聊,談到他最近在工作遇到的挫折。<div><br /></div> 這位前同事跟我一樣都離開前公司後,帶著一些理想加入了新創公司。先前我一直鼓吹他要積極爭取新公司新團隊內 Team Lead 的角色,但<span style="color: #cc0000;">自認淡薄名利、不想爭權奪利,只想好好做事的他,覺得誰當 Team Lead 都一樣,所以並沒有把我當時的建議當回事</span>。如今,在這個依然<b>沒有 Team Lead</b> 的新創公司內,他遇到了團隊合作中<b>無法跨越的磨合障礙</b>。<div><br /></div> 這個新團隊的組成各有各的來源與背景,大家帶來的做事方式、文化、習慣與見解各不相同。而其中兩人洽巧是同氣連枝的夫妻檔,難以溝通和差異頗大的做事方式讓他配合起來苦不堪言。<div><br /></div> 對原本堅信透過實事求是、良好的溝通就能達成共識的他,我直白的說:「<span style="color: #783f04;">我的經驗告訴我,溝通不是萬能。你們需要的,就是一個拍板定案的 Team Lead 。</span>」<div><a name='more'></a><br /></div> 「<span style="color: #38761d;">但是公司 Manager 說:Team Lead 要等第一階段上線後,看誰的表現好,再決定由誰擔任。</span>」<div><br /></div><b><span style="color: red;"> 真是大錯特錯!</span></b><div><br /></div> 已經陷入群龍無首局面這樣糟糕的團隊,管理階層還想把問題拖到上線後才處理?這樣的思維,代表管理層把 Team Lead 這個位置當作一個 promote 的獎勵手段。無功不受祿,對於才剛成立尚未有戰功的新團隊,用這樣的思維當然會找不到 Team Lead 的合適人選!<span style="color: blue;">這時間點該立即找到的人選,該是願意挺身而出為成敗負全責的人擔任</span>!也只有願意替成敗負全責的人,才有拍板定案的權力!<div><br /></div> <span style="color: blue;">這時候的 Team Lead ,未必他的薪水就該拿的比其他人多,單純只是承擔更多的責任和壓力,所以不必用 promote 的眼光看待這個職位</span>,這需要事先跟其他團隊人員溝通清楚,避免破壞團隊合諧的誤會。<br /></div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 為何在這當下,我不贊成繼續採用『溝通』這個方法? </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 前同事最初其實是為了一個程式開發的方法來徵詢我的建議,因為現在團隊內出現的異議就是必須在執行速度快或是易於維護支援做個取捨。80%的狀況我都是以後者為重,因為大多數的應用,事實上速度根本就沒有那麼重要。但是一次耗費過多時間的維護支援,造成的停業損失可能一次就把速度上的獲利優勢連本帶利全部吐出來。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 相信『良好溝通可以解決爭議』的前同事,為了一個我看來極端雞毛蒜皮的小事,花了好幾天做 POC 收集數據和網路資訊想要在團隊中證明自己的論點。<span style="color: #cc0000;">新創公司最珍貴的資源:時間。就這樣奢侈地流失掉了</span>。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 曾經也相信過『良好溝通可以解決爭議』的我,阻止他繼續浪費時間:</div><div style="font-family: Arial;"> 「<span style="color: #783f04;">這件事的真相本來就是同時有好有壞,你花再多時間去證明你說的優點真的存在,也沒辦法否定他說的缺點不存在。</span><b><span style="color: #990000;">僵持不下的根本原因,在於你們兩人『內心』中對這些優點和缺點的配重不同</span></b><span style="color: #783f04;">!大家都承認這些優缺點並存,但是在你的內心,兩者的重要性比重是 3:7,對方則是看作 7:3,這才是問題的癥結。這就是所謂的『成見』,你收集再多資料也沒用。</span>」 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 『成見』是來自於當事者過去經歷過的『事實』所堆積,<span style="color: blue;">唯一要能打破成見,也只能以毒攻毒,依賴的也是『新的親身經歷的事實』</span>。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 所以,不斷地在空中噴口水比劃是無法產生事實,只有先做出決定、執行、才能產生新的事實!<span style="color: #cc0000;">而尷尬的就是:誰來做出這個決定?因為這個團隊,沒有 Team Lead</span>。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 「<span style="color: #783f04;">你知道其他人為何不願意配合你覺得明明就比較好的方式去做事情嗎?因為你改變他們的習慣,卻又不替他們負責!這跟只出一張嘴指東道西有何不同?他們用熟悉的老方法,東西可以做出來,雖然很醜又很花力氣,新技術又快又漂亮但沒經驗,但是遇到沒見過的障礙不知如何解決時,誰負責?如果你只給建議卻不負責,當然他們肯定不配合你!</span>」 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 「<span style="color: #38761d;">但上頭又不指定 Team Lead,我又不是 Team Lead,事情也不是我說了算,為何要負責?這應該是要經過大家都認同的決定⋯⋯。</span>」 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 不多說,到此我相信這個團隊內耗空轉的問題已經很明顯了。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> <span style="color: blue;">決定不論好或不好,都要有下一步才會前進</span>。擔任 TL 的角色並不代表他所做的決定都是明智且正確的,他只是<span style="color: blue;">不斷地勇於承擔,快速下決定、修正、再決定、修正,並且能以同理心支持和理解團隊</span>。這是我自己擔任 Team Lead 之後的心得:<span style="color: blue;">溝通雖然重要,但遠比不上承擔責任重要</span>。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> <b>溝通不見得能讓事情前進(<span style="color: #666666;">請參考我國立法院</span>),但承擔責任肯定會! </b></div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 送行前,我要他好好想一個問題: </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 「<span style="color: #783f04;">你說不論誰當 TL 你都無所謂。那如果這個 Team 最後決定要用的技術和做事方式和你理想不同,你願意開開心心地選擇入境隨俗融入嗎?還是會鬱鬱寡歡,不能接受?如果你是後者,代表你無法忍受事情發展跟你想要的不同,那憑什麼說『誰當 TL 都無所謂』?憑什麼把決定權交給別人?交給你所謂的『大家的共識』?</span>」 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 因為知道自己是這樣的人,所以當初現在這間公司找上我的時候,擔任 Team Lead 是我加入的必要條件。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 在電梯門口,我再次鼓吹前同事到管理層面前,主動毛遂自薦去擔任 Team Lead 一職。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial; text-align: center;">在強調一次:</div><div style="font-family: Arial; text-align: center;"><span style="color: blue; font-size: large;">溝通不見得能讓事情前進,但承擔責任肯定會! </span></div>Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-53874227287994618302013-10-06T09:53:00.001-07:002013-10-06T09:53:37.198-07:00Yahoo 2013 Tech Conference 與會小記 這次榮幸獲 Yahoo HR 的安排參加這場 2013 Tech Conference。看到活動邀請函上寫著『<span style="color: #cc0000;">無限供應的自助餐點</span>』,抱著白吃白喝看熱鬧的心情,在 9 / 12 日當天晚上,來到了南港軟體園區的雅虎辦公室。<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-GaWX8JqWP_g/UlF_TFaDQJI/AAAAAAAAR-Y/uTt49JcpjcU/s1600/2013-09-12+18.57.26.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://4.bp.blogspot.com/-GaWX8JqWP_g/UlF_TFaDQJI/AAAAAAAAR-Y/uTt49JcpjcU/s1600/2013-09-12+18.57.26.jpg" height="298" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<a name='more'></a><br /><br />
<div class="separator" style="clear: both; text-align: left;">
一進會場,看到會場中央,人群在兩個長桌旁活像一群螞蟻緊緊圍繞著,眼看著所謂『無限量』供應的自助餐點也快被搶光殆盡,我趕緊加入這群螞蟻群中猛攻。</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-T4GgplbM57A/UlGNVUBySqI/AAAAAAAAR_c/F6Xdy4K6OYQ/s1600/Yahoo-06.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://2.bp.blogspot.com/-T4GgplbM57A/UlGNVUBySqI/AAAAAAAAR_c/F6Xdy4K6OYQ/s1600/Yahoo-06.jpg" /></a><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-C-LSvDghbdo/UlGNeMmzCNI/AAAAAAAAR_k/6a660AnozWg/s1600/Yahoo-07.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://2.bp.blogspot.com/-C-LSvDghbdo/UlGNeMmzCNI/AAAAAAAAR_k/6a660AnozWg/s1600/Yahoo-07.jpg" /></a><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
然而冷不防地,螞蟻群中有個熟面孔立馬認出我中飽私囊的醜態,嚇得我連躲避都來不及。原來前同事在下班之後變身為 <a href="http://www.meetup.com/Taiwan-R/" target="_blank" wrc_done="true">Taiwan R Group</a><span class="wrc_icon wrc12" rating="{"icon":"green2-16.png","rating":1,"weight":2,"flags":{"shopping":null,"social":true,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span><span class="wrc_icon wrc12" rating="{"icon":"green2-16.png","rating":1,"weight":2,"flags":{"shopping":null,"social":true,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span> 籌辦單位的 Officer!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-PA0tx85YsfE/UlF_Ofs51AI/AAAAAAAAR-I/8FMyPb-JKIs/s1600/2013-09-12+18.58.31.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://4.bp.blogspot.com/-PA0tx85YsfE/UlF_Ofs51AI/AAAAAAAAR-I/8FMyPb-JKIs/s1600/2013-09-12+18.58.31.jpg" height="300" width="400" /></a><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
這次的 Conference 主題是 Big Data,而跟 Big Data 有高度相關的 R (<span style="color: #666666;">一種 Data-mining 和統計分析演算法的實踐技術</span>)也在獲邀之列。R Group 由中研院的研究員所主導,藉由這次機會幸運地跟幾位中研院的研究員交換名片,原來 R Group 每週一晚上都有技術研討會,大家有機會可以多去參加,</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
我特別跟中研院院士確認,如果當天研討跟 Yahoo 一樣會有食物招待,一定要通知我到場。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
雖然好吃的醜態被前同事撞個正著,但是往正面想:人多好辦事。我們兩聯手收刮食物,充分發揮 1 + 1 > 2 的效果。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-3lFPjPZldxs/UlF_WWwqVfI/AAAAAAAAR-g/RdP6BB2IB5Y/s1600/2013-09-12+18.59.35.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://1.bp.blogspot.com/-3lFPjPZldxs/UlF_WWwqVfI/AAAAAAAAR-g/RdP6BB2IB5Y/s1600/2013-09-12+18.59.35.jpg" height="400" width="298" /></a><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
當天技術研討會的議程如下:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<h3 style="background-color: white; color: blue; font-family: 華康黑體, 微軟正黑體, 黑體, 黑体; font-size: 16px; line-height: 24px; margin: 0px 0px 10px; min-height: 22px; overflow: hidden; padding: 0px; text-align: justify;">
<span style="font-family: arial, helvetica, sans-serif;">講題一:How Yahoo! Dance with Big Data – Ecommerce Yahoo! Taiwan</span></h3>
<span style="background-color: white; color: dimgrey; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;"><span style="font-family: arial, helvetica, sans-serif;">* Ecommerce Data Solutions/Products Introduction
<br />* Data Solution Design and Planning<br />* Hadoop Application</span></span><br />
<br style="background-color: white; color: #666666; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;" />
<span style="background-color: white; color: #666666; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;"><span style="color: dimgrey;"><span style="font-family: arial, helvetica, sans-serif;">講者介紹:<br /><br /><u><strong>Wennie Hwang</strong></u> (E-Commerce Engineering Director, Yahoo!)</span></span></span><br />
<span style="background-color: white; color: dimgrey; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;">Wennie has been contributed herself in the Ecommerce industry since 1999. She led an engineering team to build up a B2B Auction platform for Autotradecenter, which was acquired by Adesa in 2011 with 210 million USD. Her work in Cyberlink as an online Marketing and Sales Director was driving numbers using numbers. Part of her efforts in Yahoo! for the past two years was to drive the Big Data analysis for the Ecommerce stakeholders and provide value added features and product offerings to the consumers.</span><br />
<br style="background-color: white; color: #666666; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;" />
<h3 style="background-color: white; color: blue; font-family: 華康黑體, 微軟正黑體, 黑體, 黑体; font-size: 16px; line-height: 24px; margin: 0px 0px 10px; min-height: 22px; overflow: hidden; padding: 0px; text-align: justify;">
<span style="font-family: arial, helvetica, sans-serif;">講題二:The Big Data architecture in Yahoo!</span></h3>
<span style="background-color: white; color: dimgrey; font-family: arial, helvetica, sans-serif; font-size: 13px; line-height: 20px; text-align: start;">講者介紹:</span><br />
<br style="background-color: white; color: dimgrey; font-family: arial, helvetica, sans-serif; font-size: 13px; line-height: 20px; text-align: start;" />
<u style="background-color: white; color: dimgrey; font-family: arial, helvetica, sans-serif; font-size: 13px; line-height: 20px; text-align: start;"><strong>Tim Tully</strong></u><strong style="background-color: white; color: dimgrey; font-family: arial, helvetica, sans-serif; font-size: 13px; line-height: 20px; text-align: start;"> </strong><span style="background-color: white; color: dimgrey; font-family: arial, helvetica, sans-serif; font-size: 13px; line-height: 20px; text-align: start;">(Distinguished Architect, Yahoo!)</span><br />
<span style="background-color: white; color: #666666; font-family: arial, helvetica, sans-serif; font-size: 13px; line-height: 20px; text-align: start;"><span style="color: dimgrey;">Tim Tully is Distinguished Architect at Yahoo! and is an experienced big data expert. At Yahoo!, he has designed the Yahoo! Data technology platform, including data warehousing, aggregation, visualization, instrumentation, ETL and anything else involving analytics. Currently, he leads the architecture of multi-petabyte solutions at Yahoo on Hadoop and other big data ecosystems, and is responsible for bringing Spark and Shark from UC Berkeley to Yahoo. He is also a Winner of prestigious Yahoo! Individual Superstar award for 2011.</span></span><br />
<br style="background-color: white; color: #666666; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;" />
<span style="background-color: white; color: dimgrey; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;">Tim Tully 任職於美國Yahoo!。他是在 Big Data 裡面相當資深的 Distinguished Architect。Tim設計了從頭到尾的 整個Yahoo! Data platform,包含 data warehousing, aggregation, visualization, instrumentation, ETL 以及任何有關資料分析的部份。現在他的工作主要是主導 Yahoo! Data platform,像是 Hadoop 跟其他 big data ecosystem 的發展,並且跟 UC Berkeley 合作將 Spark跟 Shark 帶入 Yahoo! Platform. Tim Tully同時也是 Yahoo! 2011 年的 Individual Super Star 的得主。</span><br />
<br style="background-color: white; color: #666666; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;" />
<h3 style="background-color: white; color: blue; font-family: 華康黑體, 微軟正黑體, 黑體, 黑体; font-size: 16px; line-height: 24px; margin: 0px 0px 10px; min-height: 22px; overflow: hidden; padding: 0px; text-align: justify;">
<span style="font-family: arial, helvetica, sans-serif;">講題三:Spark and Shark: High-speed Analytics over Hadoop Data</span></h3>
<div style="background-color: white; color: blue; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; padding: 0px; text-align: start;">
<span style="color: dimgrey; font-family: arial, helvetica, sans-serif;">In this talk, we present two emerging, popular open source projects: Spark and Shark. Spark is an open source cluster computing system that aims to make data analytics fast — both fast to run and fast to write. It outperform Hadoop by up to 100x in many real-world applications. Spark programs are often much shorter than their MapReduce counterparts thanks to its high-level APIs and language integration in Java, Scala, and Python. Shark is an analytic query engine built on top of Spark that is compatible with Hive. It can run Hive queries much faster in existing Hive warehouses without modifications. </span></div>
<span style="background-color: white; color: #666666; font-family: arial, helvetica, sans-serif; font-size: 13px; line-height: 20px; text-align: start;"><span style="color: dimgrey;"><br />These systems have been adopted by many organizations large and small (e.g. Yahoo, Intel, Adobe, Alibaba, Tencent) to implement data intensive applications such as ETL, interactive SQL, and machine learning.</span></span><br />
<br style="background-color: white; color: #666666; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;" />
<span style="background-color: white; color: #666666; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;"><span style="font-family: arial, helvetica, sans-serif;"><span style="color: dimgrey;">講者介紹:<br /><br /><u><strong>Reynold Xin</strong></u><strong> </strong>(PhD Candidate, UC Berkeley)<br />Reynold Xin 是 Big Data 界最頂尖的 UC Berkeley AMP Lab 的學生,他是 Shark 的作者以及 Spark 的核心開發者。他所主導的 Shark Project 是 SQL on Spark 的一個 Open Source 的實現,在相容於 Hive 的狀況下,性能最高可以達到 Hive 的一百倍。也因為這樣的突破,Shark 獲得了SIGMOD 2012 的 Best Demo Award。在就讀 Berkeley之前,他曾經在 Google 跟 IBM 任職過,他的興趣是資料管理系統,分散式系統,<wbr></wbr>以及大規模資料處理的演算法設計。</span></span></span><br />
<div class="separator" style="clear: both; text-align: left;">
<span style="background-color: white; color: #666666; font-family: CustomFont, 微軟正黑體, 蘋果儷黑體, 新細明體, Arial; font-size: 13px; line-height: 20px; text-align: start;"><span style="font-family: arial, helvetica, sans-serif;"><span style="color: dimgrey;"><br /></span></span></span></div>
<div class="separator" style="clear: both; text-align: start;">
<span style="font-family: inherit;"><span style="line-height: 20px;"> 其實,這次的研討會根本是藉由 Yahoo 在大資料應用領域火力展示在做新血招募!我相信現場有許多人跟我一樣,看到技術成果都相當 exciting,趨之若鶩。</span></span></div>
<div class="separator" style="clear: both; text-align: start;">
<span style="font-family: inherit;"><span style="line-height: 20px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-pT_4RfquFus/UlGUrGOOtHI/AAAAAAAASAU/Bq-YOyn8DKU/s1600/Yahoo-05.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://2.bp.blogspot.com/-pT_4RfquFus/UlGUrGOOtHI/AAAAAAAASAU/Bq-YOyn8DKU/s1600/Yahoo-05.jpg" /></a><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: start;">
<span style="font-family: inherit;"><span style="line-height: 20px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: start;">
<span style="font-family: inherit;"><span style="line-height: 20px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;"><span style="line-height: 20px;">這次三位講者的合影:</span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;"><span style="line-height: 20px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/--pyypCIrgHI/UlGIHMamX0I/AAAAAAAAR_M/lD5zwMBC4eM/s1600/yahoo-01.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://2.bp.blogspot.com/--pyypCIrgHI/UlGIHMamX0I/AAAAAAAAR_M/lD5zwMBC4eM/s1600/yahoo-01.jpg" /></a><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
最後一講可供下載的投影片:</div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="356" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/26265033" style="border-width: 1px 1px 0; border: 1px solid #CCC; margin-bottom: 5px;" width="427"> </iframe> </div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-mtXsCFvzBAk/UlGNxN7AmAI/AAAAAAAAR_s/Y9018eUiA68/s1600/Yahoo-04.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://2.bp.blogspot.com/-mtXsCFvzBAk/UlGNxN7AmAI/AAAAAAAAR_s/Y9018eUiA68/s1600/Yahoo-04.jpg" /></a><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="margin-bottom: 5px;">
<br /></div>
<div class="separator" style="clear: both; text-align: start;">
<span style="font-family: inherit;"><span style="line-height: 20px;"> 果不其然,活動結束,HR 們蜂擁而上,穿梭在與會中之間,訪談與會者收集個資。</span></span></div>
<div class="separator" style="clear: both; text-align: start;">
<span style="font-family: inherit;"><span style="line-height: 20px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-JNyPADUaLEg/UlGOETKuBJI/AAAAAAAAR_0/DU0qzKRayAg/s1600/Yahoo-03.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://4.bp.blogspot.com/-JNyPADUaLEg/UlGOETKuBJI/AAAAAAAAR_0/DU0qzKRayAg/s1600/Yahoo-03.jpg" /></a><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-V5uCN0yR0ZI/UlGOOFN1n0I/AAAAAAAAR_8/k7zba3bqSOI/s1600/Yahoo-08.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://4.bp.blogspot.com/-V5uCN0yR0ZI/UlGOOFN1n0I/AAAAAAAAR_8/k7zba3bqSOI/s1600/Yahoo-08.jpg" /></a><span class="wrc_icon wrc13" rating="{"icon":"green3-16.png","rating":1,"weight":3,"flags":{"shopping":null,"social":null,"news":null,"it":null,"corporate":null,"pornography":null,"violence":null,"gambling":null,"drugs":null,"illegal":null}}"></span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-GU5UUzeNl18/UlGUa78agSI/AAAAAAAASAM/4ffcbTRxJwU/s1600/Yahoo-02.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" wrc_done="true"><img border="0" src="http://2.bp.blogspot.com/-GU5UUzeNl18/UlGUa78agSI/AAAAAAAASAM/4ffcbTRxJwU/s1600/Yahoo-02.jpg" height="426" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: start;">
<span style="font-family: inherit;"><span style="line-height: 20px;"><br /></span></span></div>
<div id="wrchoverdiv">
<div id="wrccontainer">
<div id="wrcheader">
<div id="wrctitle">
WebRep</div>
</div>
<div class="wrchorizontal">
</div>
<div id="wrccurrentvote">
currentVote</div>
<div class="wrchorizontal">
</div>
<div id="wrcrating">
</div>
<div id="wrcratingtext">
noRating</div>
<div id="wrcweighttext">
noWeight</div>
<div class="wrchorizontal">
</div>
</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0115台灣台北市南港區25.053315 121.6074089999999624.995769000000003 121.52672799999996 25.110861 121.68808999999996tag:blogger.com,1999:blog-4764200500432773567.post-11624031941098579712013-08-24T09:25:00.003-07:002013-08-24T12:11:57.913-07:00你這是負責任或推責任?談『系統程式交接』<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-HGw-DxZuKYw/UhjC7GOyqeI/AAAAAAAARtA/27pQIICp-bI/s1600/o1392212664.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="141" src="http://4.bp.blogspot.com/-HGw-DxZuKYw/UhjC7GOyqeI/AAAAAAAARtA/27pQIICp-bI/s400/o1392212664.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.wretch.cc/blog/markleeblog/24273856" target="_blank">原圖取自馬克的部落格</a></div>
<span style="font-family: Arial;"><br /></span>
<span style="font-family: Arial;"> 我最感到幸運的,是這一路上遇到幾個願意帶我的師傅。其中一個待我相當嚴苛(<span style="color: #666666;">當時我常常心裡有很多抗拒</span>),然而現在回想起來,卻也從他身上學到、領悟許多。其中他讓我體悟到影響至深、最重要的一點,不是技術,而是某些做事態度,<span style="color: blue;">尤其是『程式交接』這件事</span>。</span><br />
<div style="font-family: Arial;">
<br />
<a name='more'></a><br /></div>
<div style="font-family: Arial;">
所有工作職務交接,複雜度與困難度最高的前幾類型,我相信軟體程式絕對是其中之一。由於軟體程式天生的易變性與複雜度,身在這個領域中,一定能領悟維護前人留下的系統是多麼困難的一件事情(<span style="color: #666666;">不管有沒有文件都一樣,因為文件不可信</span>)。<span style="color: #cc0000;">『垃圾』、『遺產』、『打掉重練』這些常用詞句在這個領域盛行之程度,完全可以反映這個領域要能成功的完成『交接』是多麼困難的一件事情</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
所以,軟體公司最重要的資產是『<span style="color: blue; font-weight: bold;">人</span>』,<span style="color: blue;">工程師的流動率絕對不只是影響薪資開銷,而是會連帶影響公司現有系統的價值</span>,原本可以維護修改的系統只因為一個關鍵人員流失,就變成沒人敢動的不動產(<span style="color: #666666;">所以除了作案子打帶跑或是販賣工程師人力的資訊公司以外,其實一般軟體公司都不太受 22K 風氣影響,老板通常會盡可能想辦法留住人員</span>)。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
記得這個師傅開始帶我時,很快就丟給我一個前人的遺產(<span style="color: #666666;">Legacy component</span>):「<span style="color: #b45f06;">Tom,這支程式以後交給你<b>負責</b>。</span>」
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
「<span style="color: #38761d;">好。</span>」除了程式碼,這東西什麼文件都沒有。但當時我想都沒想,就傻傻地答應了。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
反正一個客戶普遍用了幾年的元件,凍結了多年未動,應該沒啥大事啦~。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
沒想到,接下這遺產沒幾天,客戶就遇到問題。師傅打開程式碼專案 review,指著被報出問題的那段程式碼嚴厲地對著我說:「<span style="color: #b45f06;">Tom,這地方寫什麼鬼?為什麼可以這樣寫!?</span>」
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
「<span style="color: #38761d;">那又不是我寫的啊⋯。</span>」
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
師傅雙眼緊盯著我:「<span style="color: #b45f06;">那天我說這東西交給你『<b>負責</b>』對吧?而你也答應了。那你現在這樣回答,</span><span style="color: #cc0000;">是在『推卸責任』還是在『負責任』?</span><span style="color: #b45f06;">不管這是不是你寫的,你接下了,這些就全部都是你的 code!</span>」
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
「<span style="color: #38761d;">ㄜ ⋯⋯。</span>」小丸子的三條線。</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
「<span style="color: #b45f06;">我再問你一次:這裡為什麼可以這樣寫?</span>」師傅的眼神更嚴厲了。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
「<span style="color: #38761d;">給我一點時間研究一下,等下回答你。</span>」我立刻埋首,花了不知多少時間,trace 整份程式碼,就算沒有全懂,也把這來龍去脈搞清楚七八成。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
這次經驗之後,我知道不管接手什麼東西,我都不能以:「<span style="color: #38761d;">這當初不是我做的。</span>」這樣的理由來搪塞,唯一能做的,只有兩件事:<span style="color: blue;">要就<b>徹底把它從頭到尾看懂</b>、要就<b>把難懂部分用自己能理解的方式重寫</b></span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<b><span style="color: blue; font-size: large;"> 目標只有一個:讓自己百分百掌握接手的這個東西。
</span></b></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
最近帶的團隊,雖然沒有人員流失的問題,但因為工作模式與任務導向的改變,所有人都面臨要接手其他人產出的程式。當天分派好所有模組的領養人,我就把上面的故事講給所有組員聽,之後強調:<br />
<br />
「<span style="color: #38761d;">我要說的,是從現在開始,你只有想辦法怎麼讓自己扛起來,沒有藉口說:這是某某某寫的,我不清楚。不懂?就去問原作者問到懂。</span>」
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
很慶幸從那天起,目前接手的組員表現狀況都算良好⋯,<b>除了一個某元件外</b>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
系統內目前有個構造精巧,複雜度極高的核心元件,最近頻頻被爆出許多邏輯的漏洞。然而這個元件的歸屬權已經易手,但<b>原作者因為擔心此次的修正難度太高,所以又接回去自己修正完後歸還</b>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
接班人跟我反應:「<span style="color: #741b47;">那東西內部現在變得非常亂,有些地方我真的看不懂為什麼要這樣寫,這樣的東西我真的不敢接手維護。</span>」
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
曾經我表達過:<span style="color: blue;">真的怎麼都看不懂的地方就用你能懂的方式改寫,否則你怎麼樣都無法負起責任,最後只會有受害(被迫承擔)的感受</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
但這其中參雜了『<span style="color: #cc0000;">接班人是否要尊重原作者的堅持和設計?</span>』的人際問題(<span style="color: #666666;">若原作者已離職當然就沒這樣的顧慮</span>)。</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
事實上這次的修正,原作者已經因為擔心接班人無法勝任而帶回去自己處理,<span style="color: #cc0000;">這已經很明顯地暴露這東西的『交接障礙』</span>,雙方其實都心知肚明。真正的交接,不該是有出問題就只能靠原作者處理再歸還。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
當然,對工程師而言,自己寫出的程式就像自己懷胎生下的孩子,若看到被別人改成不是自己期望的樣子,有時難免會有些感受上的失落或不舒服。但是既然決定好責任的交接,就該<span style="color: blue;">真正放手才能讓另一方真正扛起</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
每次程式交接,若接班人可以從原作者那邊理解、接收到 70% 的知識,這已經是非常優秀難得的狀況(<span style="color: #666666;">過去經驗大部份只看到 50% 以下</span>),剩下 30% 是真的極困難理解。<span style="color: #cc0000;">若每個接班人都不透過『重構』來解決那 30% 無法維護的部分,那再下一任的接班人就只剩下 49%(</span><span style="color: #999999;">70% * 70%</span><span style="color: #cc0000;">)對手上東西不到一半的理解度</span>!更遑論再下一任的接班人,或是那些從剛開始接手就低於 70% 理解度的東西了!
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<span style="color: #cc0000;"> 東西會演變成遺產或是只能打掉重練的演化,就是依循著這樣的交接品質而來的!
</span></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
身為接班人,我們唯一能做的,<span style="color: blue;">就是想辦法讓手中的 70% 透過自己理解的方式重構來提升到 100%,這樣下一次的交接,至少還能再保持 70% 的知識傳承出去</span>,如此問心無愧後,剩下就看下一任有沒有那個肩膀和他自己的造化了。<br />
<br />
若每次交接都能做到這樣,<span style="color: blue;">系統的知識就能保持在 100% -> 70% -> 100% -> 70% -> 100% 這樣的健康循環</span>,而不是<span style="color: #cc0000;">變成 100% -> 70% -> 49% -> 34% -> ... 打掉重練的遺產,這樣的循環</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
為了隨時培養系統的接手人員,我設計了一份投影片範本,讓每個系統的 owner 負責完成,並一這份投影片對所有人進行教育訓練。這份投影片範本在此分享給大家作為參考,也歡迎大家給予各種回饋與補充意見:
<br />
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="true" frameborder="0" height="389" mozallowfullscreen="true" src="https://docs.google.com/presentation/d/13CWCxsSjEwsy95JJGKFC2ZuW_zvXq-os2CMaYYJsRqc/embed?start=false&loop=false&delayms=3000" webkitallowfullscreen="true" width="480"></iframe>
</div>
<div style="text-align: center;">
<br /></div>
<div style="font-family: Arial;">
<div style="text-align: center;">
<span style="color: blue;">對於如何做好『系統程式交接』,你們會怎麼做呢?歡迎大家分享討論。 </span></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
不好意思,工商服務一下。</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
目前我所在的團隊正招募 DB Developer 成員:</div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<span style="background-color: white; font-family: Roboto, arial, sans-serif; line-height: 18px; text-align: -webkit-auto;"><span style="color: blue;">熟悉 MSSQL 2005 以上版本的 DB Developer</span></span></div>
<div style="text-align: center;">
<span style="color: blue;"><br style="background-color: white; font-family: Roboto, arial, sans-serif; line-height: 18px; text-align: -webkit-auto;" /></span><span style="background-color: white; font-family: Roboto, arial, sans-serif; line-height: 18px; text-align: -webkit-auto;">地點:<span style="color: blue;">台北市永春捷運站附近</span></span></div>
<div style="text-align: center;">
<span style="color: blue;"><br style="background-color: white; font-family: Roboto, arial, sans-serif; line-height: 18px; text-align: -webkit-auto;" /></span><span style="background-color: white; font-family: Roboto, arial, sans-serif; line-height: 18px; text-align: -webkit-auto;"><span style="color: #cc0000;"><b>新創公司、工作富挑戰性、待遇優渥</b></span></span></div>
<div style="text-align: center;">
<span style="color: #cc0000;"><b><br style="background-color: white; font-family: Roboto, arial, sans-serif; line-height: 18px; text-align: -webkit-auto;" /></b></span><span style="background-color: white; font-family: Roboto, arial, sans-serif; line-height: 18px; text-align: -webkit-auto;"><span style="color: #38761d; font-size: large;"><b>生涯規劃、轉職的最佳選擇,有興趣的請傳訊或 <a href="mailto:tomtang0406@gmail.com" target="_blank">MAIL</a> 給我</b></span></span></div>
</div>
<br />
<div id="wrchoverdiv" style="display: none;">
<div id="wrccontainer">
<div id="wrcheader">
<div id="wrctitle">
WebRep</div>
</div>
<div class="wrchorizontal">
</div>
<div id="wrccurrentvote">
currentVote</div>
<div class="wrchorizontal">
</div>
<div id="wrcrating">
</div>
<div id="wrcratingtext">
noRating</div>
<div id="wrcweighttext">
noWeight</div>
<div id="wrcflags">
<div class="wrcicon" id="wrcicon_shopping">
</div>
<div class="wrcicon" id="wrcicon_social">
</div>
<div class="wrcicon" id="wrcicon_news">
</div>
<div class="wrcicon" id="wrcicon_it">
</div>
<div class="wrcicon" id="wrcicon_corporate">
</div>
<div class="wrcicon" id="wrcicon_pornography">
</div>
<div class="wrcicon" id="wrcicon_violence">
</div>
<div class="wrcicon" id="wrcicon_gambling">
</div>
<div class="wrcicon" id="wrcicon_drugs">
</div>
<div class="wrcicon" id="wrcicon_illegal">
</div>
</div>
<div class="wrchorizontal">
</div>
</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-63577139175123864532013-06-28T23:12:00.000-07:002021-04-23T04:41:41.922-07:00JD ( Job Description ) 是什麼?能吃嗎?<!--?xml version="1.0" encoding="UTF-8" standalone="no"?--> <br /><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-3yqKTlSCf9Y/Uc56RIMYR_I/AAAAAAAARZM/bdekkQ2BdQM/s320/jobdescription.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-3yqKTlSCf9Y/Uc56RIMYR_I/AAAAAAAARZM/bdekkQ2BdQM/s1600/jobdescription.jpg" /></a></div><div style="font-family: Arial;"> JD,Job Description ,是應徵招募職缺時重要的參考資訊、也是一個公司營運方向的重要體現。讓我們來看個我手上最近拿到的範例:</div><div style="font-family: Arial;"><br /><div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 54pt;"><span style="color: #666666; font-size: x-small;"><i><b><span lang="EN-US">1.<span style="font-family: 'Times New Roman';"> </span></span><u></u></b><span lang="EN-US"><b>BU Team Lead</b><u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 72pt;"><span style="color: #666666; font-size: x-small;"><i><u></u><span lang="EN-US"> a.<span style="font-family: 'Times New Roman';"> </span></span><span lang="EN-US">Product technical owner<u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 72pt;"><span style="color: #666666; font-size: x-small;"><i><u></u><span lang="EN-US"> b.<span style="font-family: 'Times New Roman';"> </span></span><u></u><span lang="EN-US">Provide technical support to project/incident<u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 72pt;"><span style="color: #666666; font-size: x-small;"><i><u></u><span lang="EN-US"> c.<span style="font-family: 'Times New Roman';"> </span></span><span lang="EN-US">Provide mentorship and guidance to fellow team members<u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 72pt;"><span style="color: #666666; font-size: x-small;"><i><u></u><span lang="EN-US"> d.<span style="font-family: 'Times New Roman';"> </span></span><u></u><span lang="EN-US">Assist to manage/review release process<u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 54pt;"><span style="color: #666666; font-size: x-small;"><i><b><u></u><span lang="EN-US">2.<span style="font-family: 'Times New Roman';"> </span></span><u></u></b><span lang="EN-US"><b>Technical Architect</b><u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 72pt;"><span style="color: #666666; font-size: x-small;"><i><u></u><span lang="EN-US"> a.<span style="font-family: 'Times New Roman';"> </span></span><span lang="EN-US">Review project/incident design by request<u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 72pt;"><span style="color: #666666; font-size: x-small;"><i><u></u><span lang="EN-US"> b.<span style="font-family: 'Times New Roman';"> </span></span><u></u><span lang="EN-US">Code review by request<u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 72pt;"><span style="color: #666666; font-size: x-small;"><i><u></u><span lang="EN-US"> c.<span style="font-family: 'Times New Roman';"> </span></span><span lang="EN-US">Establish the code standard<u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 54pt;"><span style="color: #666666; font-size: x-small;"><i><b><u></u><span lang="EN-US">3.<span style="font-family: 'Times New Roman';"> </span></span><u></u></b><span lang="EN-US"><b>Production Support</b><u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 72pt;"><span style="color: #666666; font-size: x-small;"><i><u></u><span lang="EN-US"> a.<span style="font-family: 'Times New Roman';"> </span></span><span lang="EN-US">Analyze sticky incident<u></u><u></u></span></i></span></div><div style="background-color: white; font-family: arial, sans-serif; margin-left: 72pt;"><span style="color: #666666; font-size: x-small;"><i><u></u><span lang="EN-US"> b.<span style="font-family: 'Times New Roman';"> </span></span><u></u><span lang="EN-US">Support/guide the team for urgent case</span></i></span></div><div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: 14px; margin-left: 72pt;"><span lang="EN-US" style="font-size: 11pt;"><br /></span></div></div> 然而以上條列式的敘述,在上層和下層的解讀卻截然不同。上層開出一個職位,對這個職位所能發揮的功能是有所期望的,所寫下的描述是希望擔任這個位置的人<span style="color: blue;">『至少』</span>能做到的事。而下層的人面對這樣的工作描述,則認為:<span style="color: red;">沒有寫在上面以外的部分,不屬於我的權責範圍,與我無關。</span><br /><div><a name='more'></a><br /></div> 當一個公司大部分的員工,心態都屬於後者,這間公司就已經僵化,很難有機會繼續進化。<span style="color: red;">因為任何的『創新』或『改變』的項目,一定都不可能被寫在現任員工所持有的那份 JD 文件之內,後者的力量大了,所有的改變和推行就很難發生</span>,有志難伸者只好陸續求去,留下的,只有比例越佔越高的 JD 保命 (<span style="color: #999999;"> save ass </span>) 的擁護者。而這間公司的發展前途越趨暗淡,是可以被預料的。<br /><div><br /></div> 今年四月,我剛離開一個情感寄託很深、工作三年半的公司。其中一個原因跟 JD-Driven 的管理與工作文化有關。</div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 來到新的工作環境,帶領一個剛成軍 1Q 的工作團隊,我相當看好其中一個團員的潛力,希望能 promote 他來接手我的權責。在徵詢他的意願的過程中,他提到:「<span style="color: #b45f06;">我需要知道這個 "Assistant" Team Lead,到底該做什麼?</span>」 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 「<span style="color: #0b5394;">你該做的,就是我所做的所有事情。</span>」心中並沒有明確 JD 想法的我,簡單回答。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 「<span style="color: #b45f06;">那我必須知道,你做的所有事情包含哪些?</span>」這位同仁又追問。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 突然間,這個問題讓我當下仔細思考 JD 存在的意義。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 讓我們回頭來看看整件事的因果關係: </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 老闆和股東為何要成立一間『營利』商業公司的原因?肯定是為了『賺錢、贏得市場』,絕不是為了燒錢取暖。<b>所以,<span style="color: blue;">CEO 的 JD 是什麼?讓公司成功獲利! </span></b></div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> CEO 為了達成這個目標,他心中有策略,根據心中的策略,他判斷需要什麼樣能力的幫手,於是創造了第二批的 JD(s),例如 PM ( <span style="color: #666666;">專案經理</span> )、HR ( <span style="color: #666666;">人力資源主管</span> )、RD ( <span style="color: #666666;">研發主管</span> ) …etc。而這時候的<span style="color: #783f04;">第二批 JD(s) 會以<b>功能導向</b>的描述為主</span>,而<b>最初衷的原始目標:『讓公司獲利』,這項目經常會在這階段的 JD 文件中被抹去</b>。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 而第二批 JD 所招募進來的人,會為了讓自己做事方便、加快效率,產生第三批 JD(s),這之後同樣也都只有功能性描述。但絕不能忘記,<span style="color: blue;">這所有 JD(s) 的源頭都來自最原始的目標:<b>讓公司成功獲利</b></span>。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 然而,常常我們看著手上 JD 文件的描述,忘了這一切的因果,而 JD 反而成為與公司初衷矛盾與對抗的產物。因為,<b>市場可能會改變,CEO 可能會誤判或是需要調整策略,原來的功能性描述自然可能就不再適用</b>。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 但是若我們抓緊原本 JD 的初衷,這些條文式的規範就不會是困擾和問題。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 因此,當下我是這樣回答同仁他的疑惑:</div><blockquote class="tr_bq"><span style="color: blue;"> 我們的目標就是讓手上這個產品推上線,並且成功地在市場上成功獲利。雖然這件事跟公司所有人都有關,但是你把這個當做是你自己的責任,而你手邊剛好有幾個幫手 ( Team members ) 能從旁協助你,在這樣的前提下,<b><u>你覺得你必須採取什麼樣的行動來達成這個目標,那些行動就是你該做的事情</u></b>。</span></blockquote><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 的確,我會決定必須要從中 promote 一個 assistant team lead,也是因為要達到上述目標而認為這是自己必須採取的行動,並不是因為任何 JD 告訴我說應該要培訓或是 promote 某人。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 看這位同仁點點頭,我想他應該是理解我所說的。事後證明,他也的確表現得非常不錯,高於我的預期。 </div><div style="font-family: Arial;"><br /></div><div style="font-family: Arial;"> 所以,各位讀者,你手上那份 JD 的文件是什麼?能拿來吃嗎?<span style="color: blue;">不如丟掉這份包袱,把公司的願景和目標當做你自己的 JD 吧! </span></div>Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-54367054330177863802013-06-15T21:19:00.002-07:002013-06-15T21:27:35.445-07:00架構師 vs 創業者<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-wC7AxmTHnpc/Ub070iqtOTI/AAAAAAAARYI/fO-srZq2Kdk/s1600/09152205jfp5.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-wC7AxmTHnpc/Ub070iqtOTI/AAAAAAAARYI/fO-srZq2Kdk/s1600/09152205jfp5.jpg" /></a></div>
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
<span style="font-family: Arial;"> 今年初,我以系統架構師的頭銜離開了前公司,來到了一個才 start-up 三個月左右的新創公司當 Team Lead,帶著五、六個人的開發團隊力挽狂瀾、力保三個月後能讓該公司的新創產品能順利上線。</span><br />
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
這段時間我算是忙到昏天暗地,每天工作時間超過十二小時,甚至還有做到清晨四點下班,然後早上十點又繼續上班。可以說沒什麼體力心力寫部落格,任其荒廢了好一段時間。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
這段時間,我不斷受到內心或是外在所謂『架構師』和『創業家』角色之間的拉扯。但想想自己當初跳脫上一間公司的角色來到這裡,諸多原因之一,就是我想認真學習如何成為一個『創業者』!
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<span style="color: blue;"> 但是,架構師和創業家在思維上是很衝突的。</span><br />
<a name='more'></a><span style="color: blue;">
</span></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
架構師的使命是預測系統瓶頸和設計可以符合未來趨勢進行擴充與成長的架構,並且追求高度一致性的架構美學和可維護性,某種程度說來,<span style="color: blue;">架構師是種『期望在沒有資源限制下,做出盡善盡美的系統』的主導性角色</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
而<span style="color: blue;">創業者追求的是,在有限的資源內以低成本來快速回應市場需求,在兼顧股東期望、穩扎穩打下逐步改進產品來適應市場</span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
於外,手握任務指派和帶領團隊權責的我,常常處在現任架構師、專案經理和公司 CEO 拉扯的中間。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
對公司而言,Team Lead 必須緊緊牢扣承諾給股東的上線時程,因為這關係到公司能不能贏得投資者的信賴和持續挹注資金的意願,也是 CEO 和專案經理關注的重點。對架構師而言, Team Lead 應該要依照他不斷分析到的系統弱點、與既定的架構作施工,系統的完善是他在乎的。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
於內,我內心常常也是自我對話,到底現在該不該做這個架構,還是只要先讓功能可以運作就好?現在選擇不做,是不是未來就更不可能回頭做?
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<span style="color: blue;"> 但是資源永遠不夠用,這時候就必須面對取捨。
</span></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
在一次多方會談,CEO 提到:「<span style="color: #990000;">不是所有的問題都一定要透過技術來解決。</span>」
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
的確,<span style="color: red;">技術人員最容易有的盲點,就是把一切的問題變成『技術問題』</span>。如果這個問題是可以透過營運面 ( <span style="color: #666666;">Operation</span> ) 來解決,那就不該因這樣的問題而卡住系統上線的時間。這的確也符合『<a href="http://newtom-read-watch.blogspot.tw/2013/03/blog-post.html" target="_blank">精實創業 Lean Startup</a>』的哲學。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
對創業者而言:<span style="color: blue;">有時候,『避開』問題比『解決』問題更務實得多。
</span></div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<span style="color: #b45f06;">擔心資料被大量查詢而拖累主交易系統?</span>身為架構師的自己可能會思考如何開發 CACHE 機制並且保持資料同步的複雜設計,而創業者決定多花點錢買獨立的設備隔離在外,就算被查到爆量也不影響主交易系統。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<span style="color: #b45f06;">擔心同時間大量使用者湧入登入系統?</span>身為架構師會思考如何獨立出 Login Server 並且設計 SSO ( <span style="color: #666666;">Single-SignOn</span> ) token 串聯其他系統,分散登入作業的負擔。創業者則決定簡單加上隨機亂數延遲來錯開同時間的登入請求。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<span style="color: #b45f06;">擔心記憶體不足?</span>架構師思考分散式快取 ( <span style="color: #666666;">Distributed-Cache </span>) 的機制和開發。創業者說多給你一萬塊幫我多插幾條 RAM 就好。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
就如我們在開發時遇到如果強制跑在 64 位元模式會出現一些執行錯誤的狀況,過去若我以架構師的身份,應該會花時間做各種實驗找出問題的癥結點,面對然後解決它。然而身為無論如何要讓產品推上線的創業者的 Team Lead 角度,我決定不花任何時間釐清原因,而選擇先以 32 位元模式讓系統得以正常運作,以便進行後續開發。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
現在選擇避開,當然日後仍有可能必須<a href="http://newtom-it.blogspot.tw/2013/03/blog-post.html" target="_blank">回頭血債血還</a>,而且問題可能被埋得更深,可能會有利息效應,<span style="color: blue;"><b>但這是創業者必須承擔的風險</b></span>。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
為何我們買房子寧願承擔房貸的利息,也不選擇全部以自備款交易?其中一個原因是期待未來收益會多過利息的支付,這是一個機會成本的選擇。而我們能否真的擴張營運到需要回頭解決 64 位元的問題,卻也是個未知數。
</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
如果我在學習如何把自己轉換成一個創業者,勢必未來有更多和過往的自己互相衝突的地方。 </div>
<br />
<div id="wrchoverdiv" style="display: none;">
<div id="wrccontainer">
<div id="wrcheader">
<div id="wrctitle">
WebRep</div>
</div>
<div class="wrchorizontal">
</div>
<div id="wrccurrentvote">
currentVote</div>
<div class="wrchorizontal">
</div>
<div id="wrcrating">
</div>
<div id="wrcratingtext">
noRating</div>
<div id="wrcweighttext">
noWeight</div>
<div id="wrcflags">
<div class="wrcicon" id="wrcicon_shopping">
</div>
<div class="wrcicon" id="wrcicon_social">
</div>
<div class="wrcicon" id="wrcicon_news">
</div>
<div class="wrcicon" id="wrcicon_it">
</div>
<div class="wrcicon" id="wrcicon_corporate">
</div>
<div class="wrcicon" id="wrcicon_pornography">
</div>
<div class="wrcicon" id="wrcicon_violence">
</div>
<div class="wrcicon" id="wrcicon_gambling">
</div>
<div class="wrcicon" id="wrcicon_drugs">
</div>
<div class="wrcicon" id="wrcicon_illegal">
</div>
</div>
<div class="wrchorizontal">
</div>
</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-17035011001104620732013-04-09T17:56:00.003-07:002013-04-09T18:01:24.988-07:00一個打十個的葉問很強,但我要殺很大的瑤瑤!<span class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-hdm-vnC4kVg/UWSkeLbujZI/AAAAAAAAQ4o/VdI4pXBE4Q8/s1600/49bb5c45e94e0.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="295" src="http://3.bp.blogspot.com/-hdm-vnC4kVg/UWSkeLbujZI/AAAAAAAAQ4o/VdI4pXBE4Q8/s320/49bb5c45e94e0.jpg" width="320" /></a></span>
<br />
<span class="separator" style="clear: both; text-align: left;">
<b>傳說中葉師傅是個以一打十的功夫英雄、深居簡出,是個頂尖的人才</b>。</span>
<br />
<span class="separator" style="clear: both; text-align: left;"><br /></span>
<span class="separator" style="clear: both; text-align: left;">
</span>
<span class="separator" style="clear: both; text-align: left;">
求才若渴的老闆,三顧茅廬尋訪多年、重金禮聘,花費 <b>9999K</b> 終於請出葉師傅到我們公司上班。老闆欣喜若狂,認為嘔心瀝血總算讓這麼一等一的高手出任敝公司職務,公司前途光明,發展不可限量。</span><br />
<span class="separator" style="clear: both; text-align: left;"><br /></span>
<span class="separator" style="clear: both; text-align: left;">
</span>
<span class="separator" style="clear: both; text-align: left;">
「<span style="color: #7f6000;">這位老闆,先說好,沒有以一對十的場面我可是不幹的。</span>」葉師傅醜話說在前頭。</span>
<br />
<span class="separator" style="clear: both; text-align: left;"></span><br />
<a name='more'></a><span class="separator" style="clear: both; text-align: left;"><br /></span>
<span class="separator" style="clear: both; text-align: left;">
</span>
<span class="separator" style="clear: both; text-align: left;">
老闆笑容可掬、點頭如搗蒜,極為謙恭地將葉師傅帶到公司櫃台說:</span><br />
<span class="separator" style="clear: both; text-align: left;">
「<span style="color: #274e13;">葉師傅,<b>我們現在正缺的職位,是公司櫃台業務小姐。本來需求是需要個年輕女孩</b>,但是以您葉師傅的能力之強大,我覺得破個例應該不是問題。由於敝公司客戶都是電玩界宅男,麻煩葉師傅您<u>戴上這頂假髮和假睫毛,畫上口紅、配上這瞳孔放大片和臉部遮瑕膏,這兩袋水球掛在您胸前</u>,其實還是可以出任這個職務絕<b>沒有問題</b>!</span>」</span>
<br />
<span class="separator" style="clear: both; text-align: left;"><br /></span>
<span style="text-align: left;"> 葉師傅聞之大驚:「<span style="color: #7f6000;">一對十的場面呢!?</span>」</span><br />
<span style="text-align: left;"><br /></span>
<span style="text-align: left;"> 「<span style="color: #274e13;">每個櫃檯業務小姐常常必須同時處理十個客訴服務電話,每天也必須至少讓十個電玩宅男簽下本公司的定型化契約變成忠實客戶。</span>」老闆面貌嚴肅、不苟言笑。</span><br />
<span style="text-align: left;"><br /></span>
<span style="text-align: left;"> 「<span style="color: #7f6000;">⋯⋯。</span>」</span><br />
<span style="text-align: left;"><br /></span>
<span style="text-align: left;"> 下一秒,老闆渾身是血地趴在地上,手上的假髮散亂成一團,葉師傅拂袖而去,頭也不回⋯⋯。</span><br />
<span style="text-align: left;"><br /></span>
<br />
<div style="text-align: left;">
<span style="text-align: left;"> 在這案例中,葉師傅雖然是百年難得一見的人才,但是花了再多時間力氣把他打扮成女人⋯⋯。</span></div>
<div style="text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><a href="http://1.bp.blogspot.com/-eZg85GHnVJw/UWSsV5RxriI/AAAAAAAAQ4w/bJPeFp5ZRCk/s1600/122731052_541n.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-eZg85GHnVJw/UWSsV5RxriI/AAAAAAAAQ4w/bJPeFp5ZRCk/s1600/122731052_541n.jpg" /></a></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><span style="text-align: left;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><span style="text-align: left;"><b><span style="color: #cc0000;">他的工作表現也不可能勝過只花 22K 就請來剛畢業的瑤瑤。</span></b></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><a href="http://4.bp.blogspot.com/-YLbutDmbL5o/UWStQ21JfYI/AAAAAAAAQ44/6Ccwq8foD0A/s1600/49e9bc7d07181.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-YLbutDmbL5o/UWStQ21JfYI/AAAAAAAAQ44/6Ccwq8foD0A/s1600/49e9bc7d07181.jpg" /></a></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;">(宅男表示,瑤瑤完勝)</span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> 老實說,上述這個虛構的案例實在誇張了些,其道理也確實顯而易見,怎麼看都像是浪費篇幅、騙稿費講些大家從小到大都知道的廢話,實在不需要人提醒。</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> 但不知為何,上述現象常常在 IT 界出現。仿佛進入應該以理智邏輯分析出發的科技業,人的判斷反而不理智了。<span style="color: #cc0000;"><b>常常一個公司因為開發出一套效能極佳的產品或核心技術,就傾向把這套到所有的應用上,不管合不合適</b></span>。</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><b> 例如目前正在上演這場鬧劇的:Microsoft。</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> 由於 Windows 桌上作業系統的功能強大與成功,所以兩三年前,微軟的智慧型手機在 Windows Mobile 6.5 版本前,完全複製與套用桌上型的作業系統操作界面與設計,而且不管客戶使用者如何反饋,打死不變,只做各種補強的小調整來勉強符合,<span style="color: #cc0000;">這就好比硬是逼著葉師傅上妝逼演霸王別姬那般</span>。</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><a href="http://1.bp.blogspot.com/--89uoK5EdcA/UWSwxog-C8I/AAAAAAAAQ5A/_ELFHev9j0Y/s1600/201303121912391808367.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="http://1.bp.blogspot.com/--89uoK5EdcA/UWSwxog-C8I/AAAAAAAAQ5A/_ELFHev9j0Y/s400/201303121912391808367.jpg" width="400" /></a></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> 如今行動市場拱手讓人,事實擺在眼前,才真的願意『打掉重練』,不再為難可憐的葉師傅⋯⋯。</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><b> 但是,這場悲劇並未結束,因為歷史又重演了⋯⋯。</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> Windows Phone 7 之後起用了新人瑤瑤,總算小有起色,沒想到微軟竟然拿瑤瑤趕跑原本鎮守桌面穩若泰山的葉師傅!?更甚者,瑤瑤還擔任起伺服器作業系統版本的代言人!我在 Windows 2012 Server 上看到那該死的磚畫面,簡直傻眼!難不成微軟認為有人會在觸控手機或是平板電腦上安裝伺服器版本的作業系統!?</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><a href="http://4.bp.blogspot.com/-eiecPu4xolg/UWSzHqPQDiI/AAAAAAAAQ5Q/pWjqK7DWOc8/s1600/62826d27jw1e236qfxg75j.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="http://4.bp.blogspot.com/-eiecPu4xolg/UWSzHqPQDiI/AAAAAAAAQ5Q/pWjqK7DWOc8/s400/62826d27jw1e236qfxg75j.jpg" width="400" /></a></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><span style="color: #cc0000;">(這張圖說明微軟的腦殘真是太中肯了)</span></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> 我遠端桌面連線到伺服器上竟然還要為了捉到右上角那個點來“滑出”我要的設定選單⋯⋯。</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> 除了微軟,<b>這種決策在各處也不斷上演</b>。<b>例如把『非同步平行化巨量交易引擎』硬是套在商業需求已經強調需要的循序處理邏輯上</b>。<span style="color: blue;">不斷地耗費力氣修整這個工具來應付不合適的應用場景,就像是在葉師傅身上戴上假睫毛和假髮,讓他看起來像個女人</span>。</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> 有一天你的工程師看到葉師傅明明是個身強體健的男兒身,怎麼身上裝了兩袋水球?<span style="color: blue;">這到底是不是 BUG 還是某種『特殊考量』?該不該修</span>?然後他發現這個葉師傅胸口不只是水球,連口紅假睫毛都有!於是他見怪不怪,一律全部當作過去歷史的『特殊考量』,既使他發現原來胸口還藏有<b><span style="color: #cc0000;">第三個小水球</span></b>(<span style="color: #666666;">這是真的 BUG</span>),他也不會理會、更不可能膽敢動手修正。</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> <b>更淒慘的是</b>,當看過這麼多『特殊考量』的設計,再<span style="color: #cc0000;">看到葉師傅身上那根帶把的東西跟上述這些特殊考量格格不入,怎麼看都像是多出來的累贅,於是他把這帶把的當作 BUG,一刀閹割了下去⋯⋯</span>。</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"> 從此,葉師傅失去了以一擋十的男子氣概,同時又是業績遜色差強人意的櫃台小姐,最終變成眾人唾棄的第三性公關,成為社會邊緣人⋯⋯。</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="text-align: left;"><br /></span></div>
<br />
<div id="wrchoverdiv" style="display: none;">
<div id="wrccontainer">
<div id="wrcheader">
<div id="wrctitle">
WebRep</div>
</div>
<div class="wrchorizontal">
</div>
<div id="wrccurrentvote">
currentVote</div>
<div class="wrchorizontal">
</div>
<div id="wrcrating">
</div>
<div id="wrcratingtext">
noRating</div>
<div id="wrcweighttext">
noWeight</div>
<div id="wrcflags">
<div class="wrcicon" id="wrcicon_shopping">
</div>
<div class="wrcicon" id="wrcicon_social">
</div>
<div class="wrcicon" id="wrcicon_news">
</div>
<div class="wrcicon" id="wrcicon_it">
</div>
<div class="wrcicon" id="wrcicon_corporate">
</div>
<div class="wrcicon" id="wrcicon_pornography">
</div>
<div class="wrcicon" id="wrcicon_violence">
</div>
<div class="wrcicon" id="wrcicon_gambling">
</div>
<div class="wrcicon" id="wrcicon_drugs">
</div>
<div class="wrcicon" id="wrcicon_illegal">
</div>
</div>
<div class="wrchorizontal">
</div>
</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-20037107850082422932013-03-14T08:03:00.003-07:002013-03-14T08:03:40.076-07:00『東西沒壞就不要修』?淺談軟體的技術破產<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/--DsPG5MQfbA/UUHk-vlz9cI/AAAAAAAAQk8/VytKmHKo19o/s1600/1184252316.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="http://4.bp.blogspot.com/--DsPG5MQfbA/UUHk-vlz9cI/AAAAAAAAQk8/VytKmHKo19o/s400/1184252316.jpg" width="400" /></a></div>
<div style="font-family: Arial;">
<br /> 只要在軟體開發圈子混一段時間,尤其已經有系統 run 在 production 環境上,十之八九會聽到這句廣為流傳的經驗談:「<span style="color: red;">東西沒壞就不要修。</span>」<div>
<br /></div>
這句話,常常被反對重構(<span style="color: #666666;">refactoring</span>)者掛在嘴上。<div>
<a name='more'></a><br /></div>
朋友在看到我上一篇『<a href="http://newtom-it.blogspot.tw/2013/02/bottomup-topdown.html" target="_blank">TopDown or BottomUp</a>』的文章,對我說:「<span style="color: blue;">這年頭能找到願意重構的人真是太少了。</span>」<div>
<br /></div>
常有人以為做軟體工程跟蓋房子這種建築工程相似,若是這樣,想像你所居住的房子像是個搖搖欲墜、像是比薩斜塔的危樓,主結構樑柱都腐爛破損,但遮風避雨的主要功能還是有,要住人也是可以,偶爾漏水放個水桶也過得去。但住在這樣的房子,你真的覺得可以『不用修』嗎?<div>
<br /></div>
覺得這個例子很誇張嗎?但事實上在軟體圈內,在光鮮豔麗的使用者操作介面背後,系統經常就是這樣充滿壁癌的海砂屋重新油漆粉刷牆壁而成,原來你以為的樑柱內其實是沙拉油桶堆立起來的模樣,<span style="color: red;">這間房子之所以還能使用,只是剛好達到一個巧妙的平衡,只要多加一點或少一點,就可能瞬間坍塌</span>。而負責維護這間危樓的人,自然會充滿著「東西沒壞就不要修」的想法。<div>
<br /></div>
『<a href="http://www.ithome.com.tw/itadm/article.php?c=71807" target="_blank">技術債</a>』這個詞在軟體工程界已經行之有年,但是在台灣,似乎只有很小圈子內知道這個概念,而高層一點的管理者、專案經理,根本不知道這些債常常都是為了他們而欠下的,而欠債還債,這種原本天經地義的事情,卻往往變成呆帳。<div>
<br /></div>
高層主管總是抱怨、或是不理解,為何他想改一個功能,或是加上一個新需求,工程師會如此面有難色,掙扎很久,然後報出一個出乎他意料很多的人日成本?尤其該系統活得越久,後面提出修改的人日成本就會越來越高,做出來的穩定性也越來越差。<div>
<br /></div>
因為技術債的利息正在發酵。<span style="color: blue;">當東西越來越難改的時候,就代表已經欠下『技術債』</span>。</div>
<div style="font-family: Arial;">
<br /><div>
技術債的產生,通常是開發人員受迫於專案壓力下妥協的產物,可能是挖東牆補西牆,因而破壞了建築結構;可能是便宜行事,臨時改用不合規格的劣質建材;也可能是臨時挖出一條地圖上看不到的地道或水路,讓專案需要的物資通行。</div>
<div>
<br /></div>
而當底下的工程師開始說出經典名言:「沒有壞的東西就不要修。」代表債臺高築已經瀕臨破產邊緣,<span style="color: red;">因為工程師已經失去可以安心修改調整的自信心</span>。</div>
<div style="font-family: Arial;">
<br /></div>
<div style="font-family: Arial;">
<span style="color: blue;">一個系統剛建立時,往往是結構分明、邏輯最直覺清晰易懂的時候</span>。隨後歷經各種需求調整,如果不是跟隨調整整個架構設計,往往會變成『硬塞進去』的異類,<span style="color: red;">將不同的邏輯放入同一個系統內,開始逐漸形成所謂的『例外』</span>。隨著這種架構上『例外』的增加,系統越來越艱澀難懂,任何一個修改的需求提出,工程師不再有把握能夠正確預測與知道所需的代價成本。這個時候,充滿無力感的工程師會陸續離職,新人進來缺乏交接也更不可能勝任,終於變成 legacy system,老闆最後只能<b><span style="color: red; font-size: large;">打掉重練</span></b>。<div>
<br /></div>
<div>
<span style="color: blue;">時常『重構』,是維持系統新鮮活力的必要活動</span>,隨時保持系統整體的設計方向是符合商務直覺,盡可能消除『例外』的設計,達到一致性,才能真正減輕工程師的生理與心理負擔,保持需求修改的直覺與穩定性,同時減少不開心的工程師流動率。</div>
<div>
<br /></div>
<div>
<span style="color: #666666;">內心 OS:推行重構最難的魔障,往往是看不到乾淨易懂的程式碼的業務單位⋯⋯。</span></div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-26384474566063141032013-02-05T19:37:00.002-08:002013-02-06T01:42:09.914-08:00軟體開發適合 BottomUp 或 TopDown?<div class="separator" style="clear: both; text-align: center;">
<a href="http://blogs.dickinson.edu/cop17durban/files/2011/10/top_down_bottom_up2.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;" wrc_done="true"><span style="font-family: inherit;"><img border="0" src="http://blogs.dickinson.edu/cop17durban/files/2011/10/top_down_bottom_up2.jpg" /></span></a></div>
<div style="text-align: left;">
<span style="font-family: inherit;"> 在進行軟體開發的系統設計,有兩種迥然不同的思維模式,<b>一種是由下到上的 BottomUp,也就像是蓋房子一樣,由地基規劃打底開始,逐步往上;另一種是由上至下的 TopDown,由需求主導,逐步向底層延伸</b>。甚至,微軟曾經為了不得罪兩邊的支持者,提出了折衷的 MiddleOut 從中間往兩邊延展的模式,但落得兩邊都不討好的下場,所以這個含糊其辭的異教論我就不在此討論了。</span></div>
<br />
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 十年前當 XML base 的 WebService 初試啼聲,彷若帶來一道曙光,是 IT 界整合的創世救星的年代,那時候各種系統整合的名詞蜂擁而出,開始有 SOA(<span style="color: #666666;">Service-Oriented Architecture:服務導向架構</span>)、 BPM(<span style="color: #666666;">Business Process Management</span>)或是 ESB(<span style="color: #666666;">Enterprise Service Bus:企業服務匯流</span>)⋯⋯等令人眼花繚亂的名詞,當年我負責協助金融業導入相關技術產品與專案,就遇到究竟該 TopDown or BottomUp 僵持不下的爭論。</span></div>
<div>
<a name='more'></a><span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 上述專案導入由於與利益掛鉤,所以廠商都會想盡辦法勸客戶以 Infrastructure(<span style="color: #666666;">基礎建設</span>)的角度去採購與施工,<b>本來客戶只是需要一條柏油路讓資料可以從 A 送達到 B ,但是廠商會以宏觀的觀點告訴客戶直接投資一個四通八達的捷運系統,未來資料要從 ABCDE⋯到⋯XYZ 二十六個英文字母都不是問題</b>。而且為了要應未來『不可預期的延展性』,所以各種可搭配的彈性或高效能(<span style="color: #666666;">承載量</span>)產品就會順便引進,本來百萬的小案子就被拱成千萬之譜,然後廠商會感謝客戶 CIO 的慧眼獨具,這筆一次性投資之後在未來幾年(<span style="color: #666666;">倒底是幾年?</span>)內成本平攤後會比選擇每次都蓋一條小馬路來的划算。於是乎,著眼於這樣的利益導向,BottomUp 幾乎是既定的策略。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="color: blue; font-family: inherit;"><b> 但是 BottomUp 真的能『完全』滿足每個專案所要的需求嗎?</b></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 很快每個專案就會發現,<span style="color: #cc0000;">本來打算花一百萬開條馬路直接到我家門口又快又方便,現在花了一千萬搞了個捷運系統,結果為了因應大家共同使用的需求,所以他們把捷運站蓋在離我家有點遠的幾個重大十字路口,從捷運站下車之後我還得自己走一段路回家⋯⋯</span>,更別說為了遵照捷運路線規則,中間我還多出換車和轉線的麻煩(<span style="color: #666666;">這時候原導入廠商就會回頭現身提出各種收費的客制化服務,又是一筆商機)</span>,對每個專案的負責人而言,公司這筆投資有點隔靴搔癢啊。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 當然若不趕時間且平時用量夠大的話,還是會感謝這個節運系統的存在,他畢竟省下了自己開馬路的成本,而且提供了可預期的一定水準與服務品質(<span style="color: #666666;">每次招標來的廠商幫你蓋條馬路的品質風險是很難預估的</span>),只需要每次多花點小錢解決離開捷運站後轉乘其他交通工具的開銷,處理最後一哩的問題,但這卻不是 Performance Critical Mission 適合的解決方案。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="color: blue; font-family: inherit;"><b> 相信當你時間趕不及的時候,還是會選擇直接跳上計程車直達目的吧?</b></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 基本上,BottomUp 的設計是嘗試以中立的立場,不偏袒任何應用的方式(<span style="color: #666666;">離各種相關應用平均距離相同</span>),儘量提供可以被重複使用的服務端點(<span style="color: #666666;">捷運站</span>)。如果你家的系統就那麼寥寥沒幾種,甚至主力系統就一種,搭建這樣的基礎建設反而是拖累自己。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 講完系統整合面,<b>用 BottomUp 做單一軟體或系統的開發也常會遇到些障礙</b>。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">身為非 UI 的工程師,當拿到 UI MockUp 和需求描述,過去最常做的事情就是先從最底層的資料庫設計開始著手,接下來才開始往上堆疊應用程式開發。而且<b>為了彰顯自詡為“經驗豐富的資深工程師”這樣的角色,所以我們會在底層琢磨許久,預測未來效能的瓶頸</b>,提供可以滿足各種 NFR 的高超設計:<span style="color: #cc0000;">多執行緒、平行作業、記憶體快取、自動資料同步還原、資料切割壓縮封存、負載平衡與高可用性⋯⋯,什麼鬼都有</span>。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="color: blue; font-family: inherit;"><b> 過早的最佳化,不如不要最佳化。</b></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 事實上,這時候我們已經迷失在實作的細節之中,而罔顧了真正的商業需求。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 當打造了完一個<b>偉大框架的萬能底層</b>之後,我們告訴商務應用層開發人員:<span style="color: #783f04;">我們底層提供了這個 API 的第三個參數可以讓你決定是否啓用記憶體快取機制,如果這邊你需要提高讀取效能就帶入 true。若你想要重新同步記憶體快取的內容和資料庫的資料,你呼叫另一個 API 就可以做到。如果你收到系統例外,打上面這個 API 就會自動切換到另一個備援節點⋯⋯</span>。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 是的,上面這個情境代表我們已經開始玷污了商務應用層的開發,藉由暴露過多底層特性而導致商務層不再維持抽象,而是緊緊綁死底層提供的各項超能力。而這樣<b><span style="color: #cc0000;">打破抽象原則的開發通常是一種 BottomUp 思維不經意犯下的錯誤,而且極為普遍</span></b>,因為大部份的開發還是停留在底層完工後才有 API 可以呼叫,才能編譯這樣的思考模式,所以上層應用開發人員很自然會對底層所有的設計概括承受。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 沒多久前,公司同事才因為這種責任分層問題找我討論。他的觀點:<span style="color: #783f04;">我只是負責提供 service 的人,我就盡量把所有能參數化的東西都公開透明化給上層,應用開發人員自己去組合出他要的,這樣出了問題他也容易自己 debug</span>。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 就除錯而言,封裝和抽象的確會造成無法第一時間就直接找到 root cause(<span style="color: #666666;">問題根源</span>)的阻礙,也容易造成線上系統出問題會讓一整條開發人員起床聯合問診的情況⋯。但,<b>我還是認為這是必要之惡,也是該付的代價</b>。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 那位同事的做法,等同是把責任轉嫁給 service 的使用者,並且要求對方必須了解底層的特性,並俱備跟自己不相上下的使用知識,這無疑是增加對方腦力的負擔(<span style="color: #666666;">人家還得同時搞懂商業需求的邏輯呢</span>)。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 透過抽象和封裝把責任切割好,底層的人若擔心半夜被叫<strike>起床尿尿</strike>,就會自覺要把更多內部就該處理好的事情做好,例如該有的監控稽核 tracing log⋯,而不是把責任往上拋。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"><b> 講了這麼多關於 BottomUp 對系統開發造成的弊端,那 TopDown 呢?</b></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 其實 TopDown 是現在我認為更為適合的系統開發方式,而且可以搭配另外兩套實施論:DDD(<span style="color: #666666;">Domain-Driven Development:領域驅動開發</span>)和 TDD(<span style="color: #666666;">Test-Driven Development:測試驅動開發</span>)。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 一切從商務需求出發,搭配 DDD 可以在應用邏輯層開發時,就使用符合商務語意的命名原則來設計物件和方法,並且以簡單明瞭又直觀的方式撰寫邏輯,易於閱讀與維護。但是欠缺底層不就如空中閣樓那般,實務上如何編譯?這是剛好可以順水推舟地導入 TDD 的測試先行概念,利用尚未真正實作而會失敗的 Test Case 來彌補缺口。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 而且由於不綁底層實作(<span style="color: #666666;">沒東西可綁</span>),所以 Unit-Tesing(<span style="color: #666666;">單元測試</span>) 導入常遇到的許多阻礙就迎刃而解,也順其自然地達到<b>去耦合</b>的特性。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 由於我們先放棄了底層實作,意味著我們不去思考效能瓶頸與最佳化等議題,只單純以商務邏輯的描述下去開發,透過 TDD 來要求功能結果的正確性。所以之後我們一定會回頭面對必須重構來達到效能速度⋯⋯等 NFR 的需求。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 大部份事先琢磨底層的人其實都想避開未來重構這個麻煩,所以總是期望未卜先知預期將來的一切狀況做好事前設計與準備,但這本來就是過度理想的幻想。反而不願意重構這樣的念頭成了死不認錯、不肯大改的心理抗拒因素。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 透過 TopDown 導入 TDD,為的就是迎接不可避免的重構。如果當初 TDD 做得扎實,現在就可以義無反顧地為重構放手一搏,重新建構符合商務需求卻又俱有最佳效能的底層。</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> <span style="color: #cc0000;">單純 TopDown 讓專案失敗的機率其實很高</span>,因為它雖然確保東西符合功能需求,但是一旦經歷壓力測試就會爆發各種 NFR 的疑慮,偏偏沒有 TDD 的狀況下修改底盤牽扯疊覆其上</span><span style="font-family: inherit;">的模組範圍極廣,因此風險也極高,幾乎是上線日前最無法妥協的事,也代表時程延誤,專案經理要殺頭。 </span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> 所以<b><span style="color: blue;">走 TopDown 不只是容易搭配 TDD,也一定要搭配 TDD!</span></b>這樣才能作出容易理解、易於維護且修改風險低,可以健康成長系統。</span></div>
<div id="wrchoverdiv" style="display: none;">
<div id="wrccontainer">
<div id="wrcheader">
<div id="wrctitle">
WebRep</div>
</div>
<div class="wrchorizontal">
</div>
<div id="wrccurrentvote">
currentVote</div>
<div class="wrchorizontal">
</div>
<div id="wrcrating">
</div>
<div id="wrcratingtext">
noRating</div>
<div id="wrcweighttext">
noWeight</div>
<div id="wrcflags">
<div class="wrcicon" id="wrcicon_shopping">
</div>
<div class="wrcicon" id="wrcicon_social">
</div>
<div class="wrcicon" id="wrcicon_news">
</div>
<div class="wrcicon" id="wrcicon_it">
</div>
<div class="wrcicon" id="wrcicon_corporate">
</div>
<div class="wrcicon" id="wrcicon_pornography">
</div>
<div class="wrcicon" id="wrcicon_violence">
</div>
<div class="wrcicon" id="wrcicon_gambling">
</div>
<div class="wrcicon" id="wrcicon_drugs">
</div>
<div class="wrcicon" id="wrcicon_illegal">
</div>
</div>
<div class="wrchorizontal">
</div>
</div>
</div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0tag:blogger.com,1999:blog-4764200500432773567.post-1773732010420466622013-01-09T01:19:00.002-08:002013-03-14T08:11:17.116-07:00『微軟私有雲建置及管理規劃營』課後報告<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.technologyguide.com/assets/1908.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="http://www.technologyguide.com/assets/1908.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin-bottom: 0.714285em; padding: 0px;">
當單機軟體服務已經幾乎被淘汰,網路服務已經成為顯學,所有的應用幾乎都要求 web 化,網路應用服務供應商如何自己建置,或找到穩定、經濟、合用的伺服器 Hosting 環境,已經成為燃眉之急的要務。</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin-bottom: 0.714285em; padding: 0px;">
雲端這個詞正夯,有人認為這只是個行銷名詞,跟過去網業虛擬主機或是主機代管並無差異。為了釐清這樣的誤解,微軟替現在的『雲端運算』做了如下的定義:<b><span style="color: blue;">虛擬化</span>和<span style="color: blue;">可攜性</span></b>。</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin-bottom: 0.714285em; padding: 0px;">
</div>
<a name='more'></a><br />
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin-bottom: 0.714285em; padding: 0px;">
<b><span style="color: #990000;">在這個定義下的雲端運算可以為企業 IT 帶來什麼效益?</span></b></div>
<ul style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; list-style-position: outside; margin: -0.428571em 0px 0.714285em 2em; padding: 0px;">
<li style="border: 0px; margin: 0px; padding: 0px;">IT 服務的快速回復</li>
<li style="border: 0px; margin: 0px; padding: 0px;">AP 的運算資源可以依需要而靈活的增減調度</li>
<li style="border: 0px; margin: 0px; padding: 0px;">不適任硬體更換極為容易</li>
<li style="border: 0px; margin: 0px; padding: 0px;">硬體資源分配的全新觀點 - 適量的資源(right sizing)</li>
<li style="border: 0px; margin: 0px; padding: 0px;">私有雲和公有雲相得益彰</li>
</ul>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
走上虛擬化,將作業系統綁死的硬體層抽象化後,的確可以輕易又快速地將所有服務轉移到其他不同機器起死回生,並且在高用量時候隨意地配給這台虛擬機器任意多的記憶體和 CPU 資源,或是複製任意數量的伺服器並啟動來應對,等到服務量縮減後再歸還給其他機器使用,不必再為了硬體採購時的規格和未來營運的估計傷透腦筋。</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
<br data-mce-bogus="1" /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
雖然虛擬化在這波雲端運算中扮演關鍵技術,但是該技術已經百家爭鳴,並且價格低廉極為容易取得(<span style="color: #444444;">Oracle 的 VirtualBox 和微軟的 VirtualPC(Server) 都是免費的</span>),所以決定真正的勝出關鍵,其實是整個虛擬化環境的安排。這個虛擬化環境必須確保服務可以全年無休絕不間斷,並且能夠容錯轉移,甚至異地備援,甚至能替企業以『利潤中心』的商業角度,替提供的服務與應用計價和計算營運成本。如果企業因為資料機密考量,想要自己建設『私有雲』,要達到上述的目的將是個浩大的工程。</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
<br data-mce-bogus="1" /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
不像其他雲端服務商只願意提供環境租貸服務,微軟佛心來著,因為知道有些企業因為營業秘密、或是政府法令限制,所以無法將應用遷移到境外雲端機房,所以將自家的雲端技術產品提供給一般企業採購(<b>也就是 <a href="http://www.windowsazure.com/zh-tw" target="_blank">Windows Azure</a></b>),讓一般企業也有機會建置出高穩定且可用的『私有雲』環境。然而有了軟體只是第一步,讓企業擁有使用計價、虛擬機隨選隨用、高速佈署的能力,<span style="color: blue;">但是要做到『高可用性』,機房本身的設備和環境設計才是最困難的地方,必須要經過縝密的妥善規劃</span>。</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
<br data-mce-bogus="1" /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
微軟講師在課堂上調侃競爭對手,說微軟本身是少數同時經營線上服務又提供雲端環境的企業,旗下有 XBOX Live、MSN、Office 365...自稱穩定性有目共睹,暗扁競爭對手只賣環境給外人卻不用自家的東西。有趣的是,講師這番話猶言在耳,微軟的<a data-mce-href="http://tech.weiphone.com/2013-01-01/Microsoft_s_mistakes_cloud_storage_game_interrupted_pay_542700.shtml" href="http://tech.weiphone.com/2013-01-01/Microsoft_s_mistakes_cloud_storage_game_interrupted_pay_542700.shtml" style="border: 0px; color: #047ac6; margin: 0px; padding: 0px;"> XBOX Live 就傳出服務中斷數小時的災情</a>,真是情何以堪。</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
<br data-mce-bogus="1" /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
無論如何,這堂課談如何規劃機房環境的內容仍然相當精彩實用,例如如何計算 FD(Fault Domain):某個設備錯誤或損壞而造成集體陣亡的虛擬機叢集。這個東西的定義當然是看觀點的 scope ,微軟官方雲端環境計算 FD 的基準是看 UPS (<span style="color: #444444;">不斷電系統</span>)節點,也就是連接到同一個不斷電系統的機器群就視同一個 FD,微軟機房至少都會準備兩組以上的 FD ,所以 Failure over(容錯轉移)是只要設備異常是發生在一個 UPS 的範圍內(<span style="color: #444444;">含</span>),都能做到服務不間斷的移轉。</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
<br data-mce-bogus="1" /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
當然,如果整個機房跳電,或是機房所在地發生大地震、火山爆發,整個環境就變成唯一的 FD 了...。(<span style="color: #444444;">據此推論,之前 XBOX Live 服務中斷不是遇到核彈攻擊就是大海嘯之類的...?</span>)</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
<br data-mce-bogus="1" /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
不過 <a href="http://www.windowsazure.com/zh-tw" target="_blank">Windows Azure</a> 的 FD 轉移的機制,微軟提供了一項<b><span style="color: blue;">令我印象極為深刻的 Live Migration</span></b> (<span style="color: #444444;">活色生香地轉移?</span>),這是據我所知其他廠商做不到的 Failure over 技術。因為其他廠商能提供的,多半就是 A 實體宿主機器掛掉時,自動把使用者或程式服務導向 B 實體宿主機器,雖然使用者不會看到網站無法顯示的錯誤,但這過程通常會讓使用者突然被登出,因為 B 機器上不會有 A 機器上之前儲存的使用者資料。</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
<br data-mce-bogus="1" /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
然而<span style="color: blue;"> Live Migration 可以完全抄寫 A 實體機上的記憶體內容,轉移到 B 實體機上,讓執行到一半的工作得以繼續完成</span>。然而要擁有這項神奇的能力,<b>先決條件是這兩個 FD 的宿主實體機器的硬體配備和設定必須完全一致</b>。也就是說,<span style="color: red;">如果 A 用的是 INTEL CPU,而 B 用的是 AMD CPU,因為兩邊的 CPU 指令集根本不同,所以記憶體抄寫的內容根本無法在不同硬體上執行</span>,轉移過去還是個<b>死屍</b>罷了,無法<b>活色生香</b>。</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
<br data-mce-bogus="1" /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin: 0px; padding: 0px;">
不可否認地,這場研討會看到許多 <a href="http://www.windowsazure.com/zh-tw" target="_blank">Windows Azure</a> 的實際戰力展示,的確比起 Amazon(亞馬遜)、Google App... 有著不輸人的優勢,且對以 .net 技術開發的服務特別有善。從這次課程我也學習到原來完善的機房建置與規劃設計要考慮哪些因素,才是真正做好萬全準備!</div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin-bottom: 0.714285em; padding: 0px;">
<br /></div>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin-bottom: 0.714285em; padding: 0px;">
<strong>課程內容</strong><strong><span lang="EN-US">:</span></strong></div>
<table border="0" cellpadding="0" cellspacing="0" style="cursor: default; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 1em; width: 652px;"><tbody>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="ZH-CN">時間</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="ZH-CN">主題</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="ZH-CN">主講者</span></strong></div>
</td></tr>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="EN-US">09:00-09:30</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">報到</span></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<br /></div>
</td></tr>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="EN-US">09:30-10:40</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">從</span><span lang="EN-US">ITIL</span><span lang="ZH-CN">看私有雲運算環境規劃</span></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">資深技術支援經理</span></div>
<div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">張聖民</span></div>
</td></tr>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="EN-US">10:40-12:00</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">微軟私有雲基礎架構規劃</span></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">技術支援經理</span></div>
<div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">李耀文</span></div>
</td></tr>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="EN-US">12:00-13:10</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">午餐時間</span></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<br /></div>
</td></tr>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="EN-US">13:10-14:30</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">微軟私有雲營運管理架構規劃</span></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">企業支援服務經理</span></div>
<div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">林聖斌</span></div>
</td></tr>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="EN-US">14:30-14:50</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">中場休息</span></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<br /></div>
</td></tr>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="EN-US">14:50-15:10</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">微軟私有雲的延伸</span><span lang="EN-US"> - </span><span lang="ZH-CN">混合雲應用探討</span></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">技術支援經理</span></div>
<div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">李耀文</span></div>
</td></tr>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="EN-US">15:10-16:10</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">私有雲參考架構的實踐</span><span lang="ZH-CN">微軟</span><span lang="EN-US">Datacenter Service</span></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">企業資訊架構顧問</span></div>
<div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">周浩汶</span></div>
</td></tr>
<tr><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="142"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<strong><span lang="EN-US">16:10-16:30</span></strong></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="321"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<span lang="ZH-CN">問題與討論</span></div>
</td><td style="cursor: text; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; margin: 8px; padding: 0.2em 2em 0.2em 0em;" valign="top" width="189"><div style="border: 0px; line-height: 1.428571em; margin-bottom: 0.714285em; padding: 0px;">
<br /></div>
</td></tr>
</tbody></table>
<div style="border: 0px; font-family: Helvetica, Arial, 'Droid Sans', sans-serif; font-size: 14px; line-height: 19.983333587646484px; margin-bottom: 0.714285em; padding: 0px;">
<br /></div>
Tom Tanghttp://www.blogger.com/profile/04219845118263176962noreply@blogger.com0