<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1298974142445162186</id><updated>2012-02-12T12:05:27.963+08:00</updated><category term='生活'/><category term='還少一本書'/><category term='旅遊'/><category term='Mobile'/><category term='軟工'/><category term='agile'/><category term='exception handling'/><category term='軟體架構'/><category term='HCI'/><category term='Eclipse'/><category term='其他'/><category term='持續整合'/><category term='軟體設計'/><category term='Programming'/><title type='text'>搞笑談軟工</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default?start-index=101&amp;max-results=100'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>311</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-6901907452233662978</id><published>2012-02-12T05:00:00.000+08:00</published><updated>2012-02-12T10:25:51.717+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='旅遊'/><title type='text'>2010冬遊日本關西Day1大阪隨便亂走(上)</title><content type='html'>&lt;p&gt;February 11 19:50~22:28&lt;/p&gt;  &lt;p&gt;2010年11月底12月初Teddy和Kay到日本關西大阪、京都、奈良玩了八天，原本想說回國之後寫個遊記介紹一下當地的風景，不過寫遊記也是很累人的，後來這個task就逐漸被Teddy給遺忘，今天想不到什麼料就來補記一下Teddy腦海中殘存的記憶片段。按照慣例Teddy的遊記還是以「大易輸入法」的形式呈現：一堆圖，少少的字。&lt;/p&gt;  &lt;p&gt;八天的行程大致如下：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Day 1：台北到大阪 &lt;/li&gt;    &lt;li&gt;Day 2：大阪到奈良 &lt;/li&gt;    &lt;li&gt;Day 3：奈良 &lt;/li&gt;    &lt;li&gt;Day 4：奈良 &lt;/li&gt;    &lt;li&gt;Day 5：奈良 &lt;/li&gt;    &lt;li&gt;Day 6：奈良到京都 &lt;/li&gt;    &lt;li&gt;Day 7：京都 &lt;/li&gt;    &lt;li&gt;Day 8：京都回台北 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;從桃園機場第二航廈搭長榮班機到關西機場，下圖是桃園機場第二航廈的天花板，當時有很多漂亮的紙傘，應該不是為了接漏水吧…XD。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-z5D6526vXnU/TzZ7zw1tk2I/AAAAAAAAA8U/HEhmBO_WC8I/s1600-h/01%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="01" border="0" alt="01" src="http://lh5.ggpht.com/-sVJ46A2OoX0/TzZ75FjmN7I/AAAAAAAAA8c/KGOQ2_NYu_g/01_thumb%25255B1%25255D.png?imgmax=800" width="510" height="295" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;快到關西機場前從飛機窗戶往外拍的照片。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-qCBqtegq49c/TzZ8AHKW2uI/AAAAAAAAA8k/5Qb1jrsa2sQ/s1600-h/02%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="02" border="0" alt="02" src="http://lh3.ggpht.com/-VC6If3pk4II/TzZ8C3qF16I/AAAAAAAAA8s/D27lLVWpoNk/02_thumb%25255B1%25255D.png?imgmax=800" width="515" height="289" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;在關西機場看到這隻「鹿男」，原來2010年是奈良成為日本首都1300年的紀念。也就是說1300年前奈良曾經是日本的首都，後來遷都到京都。往後的幾天到處到看到這隻鹿男的身影，尤其是在奈良的時候。不知為何看了到他很想捏他的臉…XD。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-mpQgy1OutvY/TzZ8JGswfWI/AAAAAAAAA80/jyJ706mHCzM/s1600-h/03%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="03" border="0" alt="03" src="http://lh6.ggpht.com/-PZdqWHUNwEo/TzZ8MRoaoLI/AAAAAAAAA88/Snic7GhLmbI/03_thumb%25255B2%25255D.png?imgmax=800" width="275" height="517" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;後來在機場買了一人花了1500日圓買了大阪出差一日劵(大阪出張きっぷ)，從機場搭「南海電鐵」到「南海難波站」，換「御堂筋線」到「本町」換「中央線」搭到「谷町四丁目」（因為住在那附近的Super Hotel），全程共約50分鐘。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-GuWD9CvUipc/TzZ8P6A-cGI/AAAAAAAAA9E/rsubr_rUdhU/s1600-h/04%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="04" border="0" alt="04" src="http://lh3.ggpht.com/-J-VChTrrE2c/TzZ8SqO-l0I/AAAAAAAAA9M/S0M1msXUohw/04_thumb%25255B1%25255D.png?imgmax=800" width="484" height="224" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;挺熱鬧的站名與價目表&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-t3O3x1HgfZg/TzZ8XHWGo4I/AAAAAAAAA9U/xjxvr5Otkuc/s1600-h/05%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="05" border="0" alt="05" src="http://lh4.ggpht.com/-cvDsxRSOeyQ/TzZ8am6LBCI/AAAAAAAAA9c/DUkHuzaqzW8/05_thumb%25255B1%25255D.png?imgmax=800" width="487" height="328" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;在機場買了這些票&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-AaSBwLyK5ow/TzZ8kYT-2vI/AAAAAAAAA9k/pSY350IdZdc/s1600-h/06%25255B8%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="06" border="0" alt="06" src="http://lh4.ggpht.com/-IldLBxb-H38/TzZ8oJYF7XI/AAAAAAAAA9s/c2Ifxp8VYMc/06_thumb%25255B4%25255D.png?imgmax=800" width="503" height="286" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;要搭這輛很像戴了頭盔的火車，被它撞到應該會滿慘的…XD&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-Lrec61O0iwU/TzZ8vx8n3GI/AAAAAAAAA90/dMFAs9Hv86U/s1600-h/06%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="06" border="0" alt="06" src="http://lh3.ggpht.com/-lXOCfCyq2iY/TzZ8y00FQrI/AAAAAAAAA98/Vc6uIvZPPsI/06_thumb%25255B1%25255D.png?imgmax=800" width="497" height="283" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;火車內部長這樣子&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-tFaYu8fyEJ4/TzZ82hzyOhI/AAAAAAAAA-E/AmkCIjX6p3I/s1600-h/08%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="08" border="0" alt="08" src="http://lh3.ggpht.com/-1m5j37uHPdM/TzZ85xJpX1I/AAAAAAAAA-M/CD2Ho8y4gNk/08_thumb%25255B3%25255D.png?imgmax=800" width="507" height="300" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;天下茶屋…很有意思的地名，有賣茶嗎？&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-qBFvy-IlVDM/TzZ9G4kYGzI/AAAAAAAAA-U/bfOTKj-V7QU/s1600-h/09%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="09" border="0" alt="09" src="http://lh3.ggpht.com/-RYnkf_r4Vn4/TzZ9KOKQ3rI/AAAAAAAAA-c/dIolUymiebU/09_thumb%25255B1%25255D.png?imgmax=800" width="516" height="294" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;難波站的旅客中心&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-BC3jOULrnXs/TzZ9QSq5hXI/AAAAAAAAA-k/An8RGSAlqYM/s1600-h/10%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="10" border="0" alt="10" src="http://lh3.ggpht.com/-frUbuIEAno0/TzZ9SilOTqI/AAAAAAAAA-s/v2XAPnmUFGU/10_thumb%25255B3%25255D.png?imgmax=800" width="319" height="252" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;先從阿波座到本町&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-3zE-_pWcOcM/TzZ9WuKJ8iI/AAAAAAAAA-0/vZBXWdrJEXE/s1600-h/10%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="10" border="0" alt="10" src="http://lh5.ggpht.com/-VC0l2uGMhXU/TzZ9Y4eTioI/AAAAAAAAA-8/K5LY86eawNg/10_thumb%25255B1%25255D.png?imgmax=800" width="527" height="215" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;再從本町到谷町四丁目&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;到了谷町四丁目之後就先到Super Hotel放行李，房間長這樣&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-6r2idqVLqjw/TzZ9g6UdxoI/AAAAAAAAA_E/kd0rXcUZ_dU/s1600-h/12%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="12" border="0" alt="12" src="http://lh3.ggpht.com/-3v6gUgeHFPA/TzZ9kODAylI/AAAAAAAAA_M/yGj6SXHVFpc/12_thumb%25255B1%25255D.png?imgmax=800" width="530" height="298" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-Te-_EyVJ1TU/TzZ9qkHK95I/AAAAAAAAA_U/vaus_3Rpov8/s1600-h/13%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="13" border="0" alt="13" src="http://lh6.ggpht.com/-5V8t9Lg_kwM/TzZ9tKiH6LI/AAAAAAAAA_c/Ly6cPAW_tMQ/13_thumb%25255B1%25255D.png?imgmax=800" width="539" height="303" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-4blRnDDbqBc/TzZ9z_8kxII/AAAAAAAAA_k/DmcDXlcgwhk/s1600-h/14%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="14" border="0" alt="14" src="http://lh4.ggpht.com/-8wTCASbfKmg/TzZ92lxjkmI/AAAAAAAAA_s/rlnfkAb9A2U/14_thumb%25255B1%25255D.png?imgmax=800" width="547" height="330" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;放好行李之後就到道敦崛、心齋橋閒逛。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-S-0IdKBKCss/TzZ96UZTWoI/AAAAAAAAA_0/-jbR0ncg8vo/s1600-h/15%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="15" border="0" alt="15" src="http://lh3.ggpht.com/-8cYRG2sG8yQ/TzZ99JX4iuI/AAAAAAAAA_8/0GTO8RGrAcA/15_thumb%25255B2%25255D.png?imgmax=800" width="769" height="170" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;路過一個賣場&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/--l7zrEghUdA/TzZ-FaBYsgI/AAAAAAAABAE/-7Uu6kbWK3k/s1600-h/16%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="16" border="0" alt="16" src="http://lh6.ggpht.com/-vbYV9ue0WNw/TzZ-JmCF0zI/AAAAAAAABAM/KUVoLyqXXkQ/16_thumb%25255B1%25255D.png?imgmax=800" width="575" height="320" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-dSIw7_x8eas/TzZ-SX9wGPI/AAAAAAAABAU/vst0-d66elA/s1600-h/17%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="17" border="0" alt="17" src="http://lh6.ggpht.com/-VZD6fp2dZq4/TzZ-XK_H0lI/AAAAAAAABAc/cWrFQ6gBzz0/17_thumb%25255B1%25255D.png?imgmax=800" width="579" height="330" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;書直接擺在路邊賣&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-ZI0Sz7SsjZk/TzZ-feKFV-I/AAAAAAAABAk/r5EeevN9fIo/s1600-h/18%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="18" border="0" alt="18" src="http://lh4.ggpht.com/-IktRiyOY6xw/TzZ-jGvJ4YI/AAAAAAAABAs/8UBxC7orA88/18_thumb%25255B1%25255D.png?imgmax=800" width="587" height="325" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;亂走走到了這裡&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-kIS4ZXhcjA8/TzZ-lYm48gI/AAAAAAAABA0/pC-Pw-iCEuA/s1600-h/19%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="19" border="0" alt="19" src="http://lh6.ggpht.com/-GddPVLauTN0/TzZ-nt5d9NI/AAAAAAAABA8/kk5x9nfOPbY/19_thumb%25255B1%25255D.png?imgmax=800" width="585" height="198" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;大阪在整修水岸，有些已經完工的地方在河（水溝？）岸有步道可以散步，感覺還滿好的。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-5MfPdrpDx_E/TzZ-uTEFn4I/AAAAAAAABBE/0BlK-WnigZY/s1600-h/20%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="20" border="0" alt="20" src="http://lh6.ggpht.com/-DUTm7qyXfqs/TzZ-x1xUEyI/AAAAAAAABBM/vtBA3Rem394/20_thumb%25255B1%25255D.png?imgmax=800" width="597" height="338" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;這是路邊的廟嗎？&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-D3VpY_ebUAg/TzZ-47h5gVI/AAAAAAAABBU/lvkMQP0qSyU/s1600-h/21%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="21" border="0" alt="21" src="http://lh4.ggpht.com/-v_XL1WZiMjU/TzZ-82SiZ5I/AAAAAAAABBc/dOUsxhVdRVQ/21_thumb%25255B1%25255D.png?imgmax=800" width="607" height="328" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;終於走到了第一個目標：道敦崛。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-BodfcKxPzjU/TzZ_FNOrfRI/AAAAAAAABBk/NM57rxf1fuo/s1600-h/22%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="22" border="0" alt="22" src="http://lh4.ggpht.com/-a8OJa8ba54Y/TzZ_JXMsSgI/AAAAAAAABBs/dCW4O1bTbPg/22_thumb%25255B1%25255D.png?imgmax=800" width="616" height="338" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;中間這位仁兄，鄉民們不覺得很眼熟嗎？很像「馬因酒」先生。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-JMmk4KDgecY/TzZ_RHwLWJI/AAAAAAAABB0/orj8LKbfH6A/s1600-h/23%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="23" border="0" alt="23" src="http://lh5.ggpht.com/-8SlBF0slSbY/TzZ_Va218HI/AAAAAAAABB8/RogUxjVHucA/23_thumb%25255B1%25255D.png?imgmax=800" width="616" height="348" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;第二個目的地到了&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-yF0XVqqAKq4/TzZ_c9yNvFI/AAAAAAAABCE/VPKA_zxJ_98/s1600-h/24%25255B12%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="24" border="0" alt="24" src="http://lh5.ggpht.com/-WW8KVfGtemw/TzZ_jen56_I/AAAAAAAABCM/LQdSufwjydU/24_thumb%25255B6%25255D.png?imgmax=800" width="622" height="349" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;這隻螃蟹好像也是景點，不過應該是用吃的，而不是用看的&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-tY9wIjO7ls0/TzZ_q91FzQI/AAAAAAAABCU/hxzE0uUY7u4/s1600-h/25%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="25" border="0" alt="25" src="http://lh6.ggpht.com/-D4pn2SJox40/TzZ_uaQevUI/AAAAAAAABCc/8LhrnUlSWvw/25_thumb%25255B1%25255D.png?imgmax=800" width="635" height="380" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;人很多&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-MXN0h8ANC-A/TzZ_yF2ALLI/AAAAAAAABCk/DKinwd6xHhM/s1600-h/26%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="26" border="0" alt="26" src="http://lh5.ggpht.com/-P3b3zNV9ufY/TzZ_03S__3I/AAAAAAAABCs/Md_nwbW5h2I/26_thumb%25255B1%25255D.png?imgmax=800" width="787" height="167" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;在河邊散步還滿有fu的&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-3wYBvS-aDZY/TzZ_9Bc5EeI/AAAAAAAABC0/KSVx71myja0/s1600-h/27%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="27" border="0" alt="27" src="http://lh3.ggpht.com/-q32v4VYkXjo/TzaACjIuV2I/AAAAAAAABC8/IvQ8rSqZW-o/27_thumb%25255B2%25255D.png?imgmax=800" width="728" height="411" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;這一家的章魚燒據說蠻好吃的&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-qgkK48BvfBU/TzaAKnADrvI/AAAAAAAABDE/WItk6uMKluQ/s1600-h/28%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="28" border="0" alt="28" src="http://lh5.ggpht.com/---9kPATQfuo/TzaAQtfQmCI/AAAAAAAABDM/uBkn251wYnY/28_thumb%25255B1%25255D.png?imgmax=800" width="686" height="396" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;有幾種不同的口味&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-AJ7chcFJGvs/TzaAWmjwx5I/AAAAAAAABDU/oDkNG2VbU1o/s1600-h/29%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="29" border="0" alt="29" src="http://lh3.ggpht.com/-kDl36parOtQ/TzaAZx9VQ3I/AAAAAAAABDc/uM20VPxvlwE/29_thumb%25255B2%25255D.png?imgmax=800" width="301" height="387" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;買了一份來吃，覺得好像還好，有點水水的口感。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-gMn_eoByr2I/TzaAc9Or6XI/AAAAAAAABDk/mlKouSQm__c/s1600-h/30%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="30" border="0" alt="30" src="http://lh5.ggpht.com/-23NxrOdE7ds/TzaAfmFwBdI/AAAAAAAABDs/GBlMq9-78Hw/30_thumb%25255B1%25255D.png?imgmax=800" width="495" height="256" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;這一家拉麵店好像也滿有名的&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-xJMgrly-__4/TzaAn1DTZMI/AAAAAAAABD0/wT8ONdDpwhE/s1600-h/31%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="31" border="0" alt="31" src="http://lh5.ggpht.com/-nHgUMfrV8AQ/TzaAq5cjlzI/AAAAAAAABD8/1JJB5yyicEc/31_thumb%25255B1%25255D.png?imgmax=800" width="501" height="281" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;逛到現在還沒吃晚餐，看到一家一蘭拉麵，就吃這個吧。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-6kFnhhOzJlM/TzaAzL2iBDI/AAAAAAAABEE/8RdT4mkV1ro/s1600-h/32%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="32" border="0" alt="32" src="http://lh6.ggpht.com/-NhqhIFPWGNM/TzaA1-KYr7I/AAAAAAAABEM/DestM4t7Z9A/32_thumb%25255B1%25255D.png?imgmax=800" width="505" height="280" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;一人一個座位，還是有小隔間那種的，透過座位前方的小格子廚師會把麵送進來。在門口要先用販賣機購買要吃的拉麵，進門的時候有人會把票收走&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-Jz72ltJc2OY/TzaA8vTGGiI/AAAAAAAABEU/Q6GIBkZrTO4/s1600-h/33%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="33" border="0" alt="33" src="http://lh3.ggpht.com/-XfU1e-OATeU/TzaBAKdsRUI/AAAAAAAABEc/DoEwNsDaKaM/33_thumb%25255B2%25255D.png?imgmax=800" width="505" height="288" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;忘了點什麼口味的拉麵了…Orz…印象中味道還不錯。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-9u9cfcXwP8k/TzaBHZMMtnI/AAAAAAAABEk/QeOHUrPIS8U/s1600-h/34%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="34" border="0" alt="34" src="http://lh3.ggpht.com/-_9ITU-TMAh4/TzaBKbg3jgI/AAAAAAAABEs/m0wfGbD3M2Y/34_thumb%25255B1%25255D.png?imgmax=800" width="518" height="289" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;廚師工作環境，竹簾後方就是顧客。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-qynPg85TFe8/TzaBS7JFsNI/AAAAAAAABE0/19_Izgvb8TY/s1600-h/35%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="35" border="0" alt="35" src="http://lh5.ggpht.com/-w6uB6G0_xAg/TzaBWZkBrGI/AAAAAAAABE8/O7hVC_yBLZg/35_thumb%25255B1%25255D.png?imgmax=800" width="530" height="337" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;回旅館之前記得找一家藥妝店買點東西帶回台灣。附近的藥妝店還滿多家的，有時間的話記得先比價一下，同樣的東西在不同的店面價錢不太一樣。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-Ghq5yuRvbMk/TzaBfHP10eI/AAAAAAAABFE/1g2SmVVL7BE/s1600-h/36%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="36" border="0" alt="36" src="http://lh6.ggpht.com/-DrABe6AAXRc/TzaBidOKFDI/AAAAAAAABFM/684io0wDnks/36_thumb%25255B3%25255D.png?imgmax=800" width="538" height="307" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;採買完畢之後先回到旅館休息一下，等一下還要去逛大阪城，下回待續。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：寫遊記比寫軟工文章還花時間啊…Orz。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-6901907452233662978?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/6901907452233662978/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=6901907452233662978' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6901907452233662978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6901907452233662978'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/2010day1.html' title='2010冬遊日本關西Day1大阪隨便亂走(上)'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-sVJ46A2OoX0/TzZ75FjmN7I/AAAAAAAAA8c/KGOQ2_NYu_g/s72-c/01_thumb%25255B1%25255D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-897158003545303408</id><published>2012-02-11T11:38:00.001+08:00</published><updated>2012-02-11T23:52:42.497+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（14）：好問題</title><content type='html'>&lt;p&gt;February 11 10:08~11:36&lt;/p&gt;  &lt;p&gt;昨天有一位鄉民在部落格上留言問Teddy一個關於採行Scrum（廣義的說應該是agile methods）的大問題，由於這個問題很具代表性，有心想要採行Scrum的團隊應該都會遇到類似的問題，所以特別 &lt;strike&gt;蓋一樓&lt;/strike&gt; 寫一篇來回答。以下是鄉民的留言：&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;您好:&lt;/p&gt;  &lt;p&gt;可以請教個關於scrum的實務問題嗎?    &lt;br /&gt;因為其進行方式是由列出story     &lt;br /&gt;然後就按照重要性     &lt;br /&gt;分解出task進行開發     &lt;br /&gt;且成員的安排也強調無分析師、架構師&lt;/p&gt;  &lt;p&gt;那麼是否就完全不需要全面性的系統分析、系統設計的階段？    &lt;br /&gt;關於物件或Table都是有人需要就新增？&lt;/p&gt;  &lt;p&gt;如此在分工進行下    &lt;br /&gt;不會造成相同或相近的東西重複出現嗎？&lt;/p&gt;  &lt;p&gt;雖然知道觀念上有持續整合與重構    &lt;br /&gt;但還是好奇每個人在開發一個功能時     &lt;br /&gt;怎麼能知道是否要共用、修改現有的物件或table     &lt;br /&gt;還是另外增加一個？&lt;/p&gt;  &lt;p&gt;因為是嘗試敏捷式開發的新手    &lt;br /&gt;觀念上若有誤，還請提供一點思考方向&lt;/p&gt;  &lt;p&gt;謝謝&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;在回答之前Teddy先聲明一下以下的回答是Teddy個人的經驗，並不保證和Scrum或是其他agile methods書本中所建議的方法完全一致（先撇清一下責任…XD）。&lt;/p&gt;  &lt;p&gt;Q：那麼是否就完全不需要全面性的系統分析、系統設計的階段？&lt;/p&gt;  &lt;p&gt;A：當一個新的專案開始的時候，基本上還是需要花「相對來講」比較多一點的時間在做所謂的系統分析、系統設計的工作，但是儘量要避免變成傳統waterfall所謂的「&lt;font color="#0000ff"&gt;全面性&lt;/font&gt;的系統分析、系統設計（big up-front design）」。這樣講可能還是太抽象了，因為依據傳統的作法，專案一開始如果沒有花時間「徹底的」做需求分析與軟體架構設計，那等專案開始之後在去改需求或是架構所付出的成本是很高的。這個問題Teddy在之前部落格的文章中有提過，請參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/03/sprint.html" target="_blank"&gt;萬事起頭難：如何開始第一個 Sprint？&lt;/a&gt;」、「&lt;a href="http://teddy-chen-tw.blogspot.com/2011/06/iteration-0.html" target="_blank"&gt;Iteration 0 要幹麼？&lt;/a&gt;」、「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/04/blog-post_17.html" target="_blank"&gt;你的軟體架構有多軟&lt;/a&gt;」看看能不能解答鄉民們的疑惑。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Q：關於物件或Table都是有人需要就新增？&lt;/p&gt;  &lt;p&gt;A：這個問題的答案基本上Yes，有需要就新增。Teddy很少遇到developer跑來問Teddy說；「我可不可以新增某某物件？」這樣的問題，通常會遇到的問題比較類似「這個問題套個XXX pattern合不合適？」或是「這個物件我這樣設計好不好？」。換句話說，developer大部分的情況都是自己有了一個想法之後，如果需要找人 &lt;strike&gt;背書&lt;/strike&gt; 確認，才會 &lt;strike&gt;跑&lt;/strike&gt; 走過來找Teddy討論。如果某個工作是採用pair programming的方式施工，那麼很多時候developers自己就可以把問題搞定，不需要動用到Teddy…XD。&lt;/p&gt;  &lt;p&gt;但是資料庫的table就需要小心謹慎一點（因為改table比改code要麻煩啊…XD）。假設在某個sprint中的某個story所實作的功能需要動到資料庫，那麼在sprint planning meeting時，這個story就會有一個設計database schema的task。認領這個task的developer要先設計出第一個版本出來。如果是設計一個或多個全新的tables，那麼設計好第一個版本之後，這個developer會再找其他人幫他看一下設個設計有沒有問題，有時候甚至整個team需要開個會，花1-2小時的時間來一起確認這些新的schema有沒有問題。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Q：如此在分工進行下，不會造成相同或相近的東西重複出現嗎？&lt;/p&gt;  &lt;p&gt;A：會，而且機率還可能不低…Orz。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Q：每個人在開發一個功能時，怎麼能知道是否要共用、修改現有的物件或table還是另外增加一個？&lt;/p&gt;  &lt;p&gt;A：在sprint planning meeting估算story點數與task時數的時候，從每一個developers所出的牌就可以相當程度的解決這個問題。假設有一個developer對於某個task出了13點，另一個出了5點，經過討論之後，原來要完成這個task的某些工作已經有共用的物件可以用，所以就不需要花那麼多的時間去施工。關於資料庫表格的新增或是修改也是經由估算點數的活動來達到溝通與「情報交換」的目的。&lt;/p&gt;  &lt;p&gt;當然光是靠sprint planning meeting的互動還是不夠的，因為有很多細節是要等真正coding開始的時候問題才會浮現出來。所以像是持續的pair programming與朝向shared code的目標努力就顯得很重要。請參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2009/11/teddy-pair-programming.html" target="_blank"&gt;Teddy的Pair Programming之旅&lt;/a&gt;」、「&lt;a href="http://teddy-chen-tw.blogspot.com/2011/12/pair-programming.html" target="_blank"&gt;Pair Programming 成本太高，嗎？&lt;/a&gt;」、「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/pair-programming.html" target="_blank"&gt;Pair Programming 沒人性？」&lt;/a&gt;、「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/03/shared-code.html" target="_blank"&gt;Shared Code：讓我們變成博格人吧&lt;/a&gt;」。&lt;/p&gt;  &lt;p&gt;這樣就沒事了嗎？當然不可能，還是會遭遇相同或相近的東西重複出現的問題，此時就只能靠最後的法寶：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Developer要養成做新功能的時候如果懷疑所需要的物件或是table是否已經存在，就快速問一下其他team members。 &lt;/li&gt;    &lt;li&gt;當發現有重複的物件或資料時，安排時間實施refactoring（可在retrospective meeting中提出）把重複的東西合併（當然一定要有自動化測試做起refactoring才不會心虛）。 &lt;/li&gt;    &lt;li&gt;定期安排refactoring或code review的活動來改善軟體設計（改善程式碼的品質）。 &lt;/li&gt; &lt;/ul&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;寫到這邊不免又想起之前寫過的幾篇文章：「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/01/scrum.html" target="_blank"&gt;Scrum 是一種制度&lt;/a&gt;」、「&lt;a href="http://teddy-chen-tw.blogspot.com/2011/03/blog-post_12.html" target="_blank"&gt;傻的願意相信&lt;/a&gt;」、「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/scrum.html" target="_blank"&gt;Scrum 不會幫你解決問題&lt;/a&gt;」、「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/02/scrum-2.html" target="_blank"&gt;Scrum 不會幫你解決問題（2）&lt;/a&gt;」，還沒看過的鄉民趕快去看一下吧。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：肯問問題就是好現象。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-897158003545303408?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/897158003545303408/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=897158003545303408' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/897158003545303408'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/897158003545303408'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/scrum-14.html' title='Scrum 是什麼（14）：好問題'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-374511779902533855</id><published>2012-02-10T12:20:00.000+08:00</published><updated>2012-02-10T12:20:54.172+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>影片上架：Scrum 經驗分享之使用Java與C/C++之跨平台軟體開發</title><content type='html'>&lt;span style="background-color: #f6f6f6;"&gt;&lt;span style="font-family: inherit;"&gt;February 10 12:13~12:20&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: white; line-height: 17px; text-align: left;"&gt;2012年1月7日舉辦的&lt;/span&gt;&lt;span style="background-color: #f6f6f6;"&gt;「&lt;/span&gt;&amp;nbsp;&lt;span style="background-color: white; line-height: 17px; text-align: left;"&gt;Scrum 經驗分享：使用Java與C/&lt;/span&gt;&lt;wbr style="background-color: white; line-height: 17px; text-align: left;"&gt;&lt;/wbr&gt;&lt;span class="word_break" style="background-color: white; display: inline-block; line-height: 17px; text-align: left;"&gt;&lt;/span&gt;&lt;span style="background-color: white; line-height: 17px; text-align: left;"&gt;C++之跨平台軟體開發&lt;/span&gt;&lt;span style="background-color: #f6f6f6;"&gt;」&lt;/span&gt;&lt;span style="background-color: white; line-height: 17px; text-align: left;"&gt;影片已經由ezScrum團隊放到Youtube，有興趣的鄉民請自行餵食。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: inherit;"&gt;上半場：&amp;nbsp;&lt;a href="https://www.youtube.com/watch?v=K7BZHgbPY9w"&gt;https://www.youtube.com/watch?v=K7BZHgbPY9w&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: inherit;"&gt;下半場： &lt;a href="https://www.youtube.com/watch?v=Ib-YcnrKJpI"&gt;https://www.youtube.com/watch?v=Ib-YcnrKJpI&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;再次感謝ezScrum團隊&lt;span style="font-family: inherit;"&gt;花費時間剪輯影&lt;/span&gt;片並上載。&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: inherit;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="background-color: #f6f6f6; text-align: -webkit-auto;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-family: inherit;"&gt;&lt;span style="background-color: #f6f6f6; text-align: -webkit-auto;"&gt;友藏內心獨白：那個講著一直晃來晃去看到快暈船了...XD。&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 17px; text-align: -webkit-auto;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-374511779902533855?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/374511779902533855/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=374511779902533855' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/374511779902533855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/374511779902533855'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/scrum-javacc.html' title='影片上架：Scrum 經驗分享之使用Java與C/C++之跨平台軟體開發'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-1010288794795860856</id><published>2012-02-10T05:00:00.000+08:00</published><updated>2012-02-10T05:00:06.992+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體架構'/><title type='text'>Quality Attribute Scenarios（4）：Availability General Scenarios</title><content type='html'>&lt;p&gt;February 07 22:40~23:44&lt;/p&gt;  &lt;p&gt;為了幫助使用者寫出QAS，書中針對六種quality attributes個別訂定了一個所謂的「general scenario」，開發人員可以把這個general scenario看成是用來產生QAS的範本。今天先看一下availability general scenario（課本80-81頁），各位鄉民還記得一個QAS包含那六個元素嗎？&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="713"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="199"&gt;元素&lt;/td&gt;        &lt;td valign="top" width="512"&gt;可能的內容&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="199"&gt;Source&lt;/td&gt;        &lt;td valign="top" width="512"&gt;系統內部或系統外部&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="199"&gt;Stimulus&lt;/td&gt;        &lt;td valign="top" width="512"&gt;Fault的種類：omission, crash, timing, response&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="199"&gt;Artifact&lt;/td&gt;        &lt;td valign="top" width="512"&gt;系統處裡器，通訊通道，永久儲存體，行程（process）&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="199"&gt;Environment&lt;/td&gt;        &lt;td valign="top" width="512"&gt;正常操作或降級模式&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="199"&gt;Response&lt;/td&gt;        &lt;td valign="top" width="512"&gt;系統要能夠增測到fault發生，並且執行以下一種或多種動作：(1)通知相關人等或是其他系統；(2)將產生fault來源的元件或系統關閉，隔離或移除；(3)暫時停止系統服務一小段時間；(4)在正常或是降級模式中繼續提供服務&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="199"&gt;Response Measure&lt;/td&gt;        &lt;td valign="top" width="512"&gt;(1)系統需要花多少時間從fault中復原；(2)系統可得性；(3)系統從降級模式到正常模式所需花費的時間；(4)修復時間&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;有了上面這個表格，鄉民們就可以替自己的軟體架構定義出很多個availability QAS（非功能需求）。再舉例子之前先說明一下上面這個表格中的內容：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Source：Stimulus的來源可能來自系統內部或是系統外部，例如，一個資料庫應用系統，source可能是系統的使用者介面元件（系統內部），或是來自於外部的資料庫系統。 &lt;/li&gt;    &lt;li&gt;Stimulus：fault的種類一共有四大類，      &lt;ul&gt;       &lt;li&gt;omission：忽略，系統無法回應一個要求 &lt;/li&gt;        &lt;li&gt;crash：系統持續遭遇到ommission這種fault（翻成白話文，系統持續無法回應要求，就等於當機啊） &lt;/li&gt;        &lt;li&gt;timing：系統太早或太晚回應需求（timing不對） &lt;/li&gt;        &lt;li&gt;response：系統回應會應錯誤的答案 &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Artiface：需要高度可得性的系統或元件 &lt;/li&gt;    &lt;li&gt;Environment：當fault發生時系統的狀態，這個狀態很可能會影響到系統處理fault的策略，例如當系統已經是處於降級模式時，又不斷的遇到很多fault（可能是遭受攻擊），那麼此時系統可能會決定暫停服務一小段時間。 &lt;/li&gt;    &lt;li&gt;Response measure：用來評量這個availability QAS是否合格的標準，例如當fault發生時系統必須要在0.1ms回復正常，或是當系統當機時，平均修復時間必須少於五分鐘。 &lt;/li&gt; &lt;/ul&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;接下來舉兩個簡單的例子&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="907"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="161"&gt;Quality Attribute&lt;/td&gt;        &lt;td valign="top" width="90"&gt;Source&lt;/td&gt;        &lt;td valign="top" width="128"&gt;Stimulus&lt;/td&gt;        &lt;td valign="top" width="119"&gt;Artifact&lt;/td&gt;        &lt;td valign="top" width="137"&gt;Environment&lt;/td&gt;        &lt;td valign="top" width="125"&gt;Response&lt;/td&gt;        &lt;td valign="top" width="145"&gt;Response Measure&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="161"&gt;Availability &lt;/td&gt;        &lt;td valign="top" width="90"&gt;Database          &lt;br /&gt;(external system) &lt;/td&gt;        &lt;td valign="top" width="128"&gt;connection closed (omission)&lt;/td&gt;        &lt;td valign="top" width="119"&gt;Application (process)&lt;/td&gt;        &lt;td valign="top" width="137"&gt;Normal operation&lt;/td&gt;        &lt;td valign="top" width="125"&gt;create a new connection and continue to operate&lt;/td&gt;        &lt;td valign="top" width="145"&gt;No downtime&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="161"&gt;Availability &lt;/td&gt;        &lt;td valign="top" width="90"&gt;Database          &lt;br /&gt;(external system) &lt;/td&gt;        &lt;td valign="top" width="128"&gt;no response (crash)&lt;/td&gt;        &lt;td valign="top" width="119"&gt;Application (process)&lt;/td&gt;        &lt;td valign="top" width="137"&gt;Normal operation&lt;/td&gt;        &lt;td valign="top" width="125"&gt;switch to the replicated database, inform DBA, and continue to operate&lt;/td&gt;        &lt;td valign="top" width="145"&gt;No downtime&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;參考上表依樣畫葫蘆，花點時間腦力激盪一下就可以訂出很多的availability QAS。&lt;/p&gt;  &lt;p&gt;看到這邊鄉民們是不是在想，&lt;font color="#0000ff"&gt;這樣不是很麻煩嗎&lt;/font&gt;？沒錯，是很麻煩，但是誰叫你要開發high availability的系統呢，想 &lt;strike&gt;賺錢&lt;/strike&gt; 做出好東西就不要怕麻煩啊…XD 。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：好多細節Teddy也都忘了，邊寫邊複習。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-1010288794795860856?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/1010288794795860856/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=1010288794795860856' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1010288794795860856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1010288794795860856'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/quality-attribute-scenarios4availabilit.html' title='Quality Attribute Scenarios（4）：Availability General Scenarios'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-8038392287749395336</id><published>2012-02-09T05:00:00.000+08:00</published><updated>2012-02-09T08:46:11.187+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>不要省小錢花大錢：導入Scrum需要先上課嗎？</title><content type='html'>&lt;p&gt;February 08 10:09~11:12&lt;/p&gt;  &lt;p&gt;前幾天有一位鄉民在Facebook上問Teddy一個問題：&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;鄉民：請問一定要受過訓才可以導入Scrum嗎？不能看書找資料就自己試試看喔 @@a&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;俗話說的好：「只要是我喜歡，有什麼不可以？」所以，當然可以啊，法律又沒規定導入Scrum一定要先受過訓或上過課。&lt;/p&gt;  &lt;p&gt;但是，就好像Teddy在「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/02/scrum-2.html" target="_blank"&gt;Scrum 不會幫你解決問題（2）&lt;/a&gt;」提到的，自己試有一個風險，就是試到最後團隊變成「&lt;font color="#0000ff"&gt;Scrum皮，Waterfall骨&lt;/font&gt;」，然後團隊成員開始覺得這個Scrum也沒有「傳說中的那麼好啊」，導入Scrum前會發生的問題，導入之後還是依然存在啊。於是團隊成員又切換回原本的 &lt;strike&gt;靜音模式&lt;/strike&gt; 求生模式，眼不見為淨，還是傻傻加班，把生活融入工作中比較實在。&lt;/p&gt;  &lt;p&gt;Teddy覺得台灣人有一個習慣，尤其是開發軟體的人（Teddy自己也有這樣的問題），就是「不找顧問，什麼都想自己試」。當然如果自己能力很強那也無可厚非，都那麼強了幹嘛找人幫忙或是去外面上課。但怕就怕在團隊的能力還不是很強的時候，要靠自己找書嘗試結果萬一不幸失敗，就會怪罪這個方法不好。&lt;/p&gt;  &lt;p&gt;當團隊能力還不是很強但卻又不想上課或是找人輔導可能有兩個原因：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;沒錢，或是公司想省錢。 &lt;/li&gt;    &lt;li&gt;找不到合適的課程或是導入顧問，以前被騙太多次了所以還是自立自強自己慢慢摸吧。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Teddy三年多前剛開始在幫別人導入Scrum的時候也是靠自己看書，過了快半年之後剛好Bass來台灣開Certified ScrumMaster的課，&lt;font color="#0000ff"&gt;短短兩天要價新台幣四萬塊&lt;strike&gt;根本是搶錢嘛&lt;/strike&gt;&lt;/font&gt;，這可能是很多人一個月的薪水。因為Teddy幾年前也曾花了別人好幾萬去上了CxxI的課，好痛苦，上完之後覺得自己好像不會開發軟體了…Orz，所以原本對這種Certified XXX的課沒什麼好感。再加上Teddy去上課之前也是覺得，自己都已經看過那麼多軟體工程方面的書了，agile methods的書也看了不下十本，還有必要花四萬塊去上課嗎？把這四萬「省下來」拿去出國旅遊那該多好…XD。&lt;/p&gt;  &lt;p&gt;後來因為有善心人士幫Teddy付學費結果Teddy就去上了，一上之後不得了，真的學到很多東西（&lt;font color="#ff0000"&gt;最主要是有人可以讓你當場發問，這一點是看書得不到的&lt;/font&gt;），覺得這四萬塊真的很值得。&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;「不花錢」並不代表「省錢」，&lt;/font&gt;有時候花錢的目的是為了省錢，或是更積極一點來看，花錢是為了要賺錢。這是什麼邏輯？假設有一個六個人的團隊，平均每個人月薪就算五萬塊好了，公司對這個團隊每個月所付出的人力成本等於：&lt;/p&gt;  &lt;p&gt;6 X 5 X 1.6 = 48 萬 （乘上1.6是因為公司還有勞健保、房租、水電、設備、行政等成本）&lt;/p&gt;  &lt;p&gt;假設請顧問花兩天到公司去教Scrum收費十萬台幣（支出10萬）&lt;/p&gt;  &lt;p&gt;這10萬要怎麼撈回來？&lt;/p&gt;  &lt;p&gt;48 * N = 10 ==&amp;gt; N = 0.20833333&lt;/p&gt;  &lt;p&gt;只要上過課之後，一個月之內可以幫團隊減少21%左右的時間浪費（省下很多自己嘗試Scrum的時間），那就夠本了。如果把時間拉長來看，之後的每個月所省下的時間成本是很可觀的，因此請顧問或去外面上課所花的錢絕對是值得的。&lt;/p&gt;  &lt;p&gt;但是，Teddy剛剛講的故事有一個前提，那就是請來的顧問或是外面上課的講師要有真材實料，不能只是出張嘴的那一種。所以，這就衍生了Teddy之前所說的第二個問題，就算公司或個人想付費學習，但是在台灣要去那裡找好的顧問或是開課單位呢？如果所託非人不是又等於把錢丟到大海了。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;Teddy之前有介紹過北科大軟體研發中心的ezScrum團隊（ &lt;a title="http://scrum.tw/" href="http://scrum.tw/"&gt;http://scrum.tw/&lt;/a&gt;）有提供Scrum導入與agile practices教育訓練服務（例如測試自動化、持續整合、如何撰寫需求分析、&lt;strike&gt;agile workspace室內裝潢&lt;/strike&gt;）。ezScrum團隊的Scrum導入服務不是說上個課露個臉講師就閃人了，而是還可以提供「&lt;font color="#0000ff"&gt;&lt;strike&gt;駐唱&lt;/strike&gt; 駐點服務&lt;/font&gt;」，派人跟團隊一起實施若干個sprint等團隊上手之後，再讓團隊的Product Owner、Scrum Master獨立作業。&lt;/p&gt;  &lt;p&gt;另外，預告一個Scrum教育訓練課程，預計在&lt;font color="#0000ff"&gt;今年四月十四號與四月二十一號兩個禮拜六開課&lt;/font&gt;（工業局「數位內容產業發展躍進計畫」有補助部分學費…XD），上課講師也是北科大軟體研發中心的成員…還有Teddy也會去插花幾個小時，有需要的鄉民們可以開始存錢了…XD。&lt;/p&gt; &lt;!--&lt;br /&gt;&lt;p&gt;最後，如果鄉民們的公司真的&lt;strike&gt;本錢很粗&lt;/strike&gt;…嗯嗯…很景仰Teddy的話（快吐了…），最近這幾個月Teddy還處於打工模式，也是可以提供Scrum與agile practices的顧問服務（跳跳…選我，選我…XD）。&lt;/p&gt;&lt;br /&gt;--&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p align="left"&gt;奇怪，這篇是被置入性行銷的廣告文嗎？&lt;/p&gt;  &lt;p align="left"&gt;錯，是好東西要跟好朋友分享啦。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：錢真難賺。    &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-8038392287749395336?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/8038392287749395336/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=8038392287749395336' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8038392287749395336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8038392287749395336'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/scrum.html' title='不要省小錢花大錢：導入Scrum需要先上課嗎？'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-7859712240905589491</id><published>2012-02-08T05:00:00.000+08:00</published><updated>2012-02-08T05:00:02.343+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體架構'/><title type='text'>Quality Attribute Scenarios（3）：Availability</title><content type='html'>&lt;p&gt;February 07 18:16~19:10&lt;/p&gt;  &lt;p&gt;在這系列第一集的時候Teddy提到Software Architecture in Practice, 2nd 這本書介紹availability、modifiability、performance、security、testability、usability這六種QAS，今天先介紹一下availability的定義，下一集在介紹availability QAS。&lt;/p&gt;  &lt;p&gt;Availability中文翻作可用性，這是一個經常可以聽到的非功能需求，尤其是現在網路與雲端計算很熱門，一個雲端應用的availability就變得很重要。那麼到底什麼是availability？如果用簡單的白話文來說明，&lt;font color="#0000ff"&gt;availability就是某樣東西或是服務，當你想要用它的時候，是否立即就可以使用&lt;/font&gt;。例如，當Teddy想用Facebook、Gmail、或是Dropbox的時候，這些服務是否還活得好好的。如果這些服務三不五時就當機，使得使用者想用的時候卻無法使用，我們就說這個服務的availability很低。&lt;/p&gt;  &lt;p&gt;從軟體架構的設計面來看，要設計一個availability很高的系統，所必須考量的因素有兩點：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;System failure types：有哪些情況會導致system failure。當一個系統無法依據它的&lt;font color="#0000ff"&gt;規格書&lt;/font&gt;所規範的條件來提供服務的時候，我們就說這個系統失效（system failure）。這邊有一個很重要的「眉角」要注意，那就是系統是否發生failure是要依據他的&lt;font color="#0000ff"&gt;規格書&lt;/font&gt;&lt;font color="#000000"&gt;所記載的服務條件來判斷&lt;/font&gt;。舉一個大家都知道的例子，如果鄉民們跑去搭台灣高鐵，今天高鐵誤點59分鐘，請問可否退票？答案是不行，因為人家的規格書寫了，誤點超過60分鐘才可以退票，所以就算是「只」誤點59分59秒也不算system failure，因此無法退票。 &lt;/li&gt;    &lt;li&gt;The consequences of a system failure ：當一個系統失效所造成的後果有多麼嚴重，是只要重開機一下耽誤個使用者幾分鐘而已，還是會造成幾百萬…美元的損失，或是會 &lt;strike&gt;毆傷運將&lt;/strike&gt; 搞出人命。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;在談到availability還有一個觀念要弄清楚，那就是failure和fault的差別。Fault就是系統的缺陷或是可以簡單想成bug，當系統中有缺陷的時候，就有可能造成系統失效導致無法提供服務。但是fault只要被妥善處理之後，就不會造成failure。換句話說，從使用者的角度來看，使用者只觀察的到failure但看不到fault。當一個fault可以被使用者所觀察到，那麼就表示這個fault變成了failure，也就是說這個fault造成系統失效。&lt;/p&gt;  &lt;p&gt;鄉民們可能會問，幹嘛區分這些有的沒的觀念？因為要提升系統的availability，就是要降低系統失效的機會；要降低系統失效的機會，就要想辦法讓系統不會有fault，或是退而求其次，當fault發生的時候，要想辦法去處理它使其不會造成系統失效，這樣系統才可以繼續運作下去，availability才會高。 &lt;/p&gt;  &lt;p&gt;最後談到如何評量一個系統的availability，公式如下：&lt;/p&gt;  &lt;p&gt;availability = mean time to failure / (mean tim to failure + mean time to repair)&lt;/p&gt;  &lt;p&gt;假設一個系統的mean time to failure (MTTF) 是2年（兩年當機一次）而mean time to repair (MTTR) 是一小時，那麼：&lt;/p&gt;  &lt;p&gt;MTTF in hours = 2 * 365 * 24 = 17520 (系統跑了17520個小時才會當機一次)&lt;/p&gt;  &lt;p&gt;Availability= MTTF/(MTTF+MTTR) = 17520/17521=99.99429%&lt;/p&gt;  &lt;p&gt;Unavailability = 0.00571%&lt;/p&gt;  &lt;p&gt;一年當中有多少小時無法使用該系統&lt;/p&gt;  &lt;p&gt;U= 0.00571% * 365 * 24 = 0.62195 小時/年&lt;/p&gt;  &lt;p&gt;最後的最後還有一個觀念，叫做scheduled downtime，排定的停機時間，這個時間一般來講是不算入一個系統的availability之內。例如，一個系統每半年要停機2小時來備份資料。在這段停機的時間中，由於系統已經對外公告「暫停營業」，所以不會算入availability的計算之中。&lt;/p&gt;  &lt;p&gt;先有這樣的觀念之後，之後談availability QAS才會有fu…XD。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：mean time to failure要怎麼算啊？&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-7859712240905589491?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/7859712240905589491/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=7859712240905589491' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7859712240905589491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7859712240905589491'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/quality-attribute-scenarios3availabilit.html' title='Quality Attribute Scenarios（3）：Availability'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-6301863753897658462</id><published>2012-02-07T10:40:00.001+08:00</published><updated>2012-02-07T10:40:18.991+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（13）：為什麼不建議使用focus factor？</title><content type='html'>&lt;p&gt;February 07 09:26~10:39&lt;/p&gt;  &lt;p&gt;寫了「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/02/scrum-12focus-factorunplanned-items.html" target="_blank"&gt;Scrum 是什麼（12）：不要再用focus factor與unplanned items了&lt;/a&gt;」之後有鄉民問Teddy是不是會再寫一篇談「不再用focus factor的原因」？Teddy以為看完「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/02/scrum-12focus-factorunplanned-items.html" target="_blank"&gt;Scrum 是什麼（12）：不要再用focus factor與unplanned items了&lt;/a&gt;」之後鄉民們就應該會瞭了，沒想到…那就再寫一篇解釋一下吧，正愁沒東西可寫…XD。&lt;/p&gt;  &lt;p&gt;Focus factor原本的目的是用來協助團隊觀察自己有多投入在工作當中，focus factor的值介於0到1之間（跟機率一樣…XD），0表示某人（或某個團隊）在某個sprint中完全沒有投入或參與專案。1表示某人（或某個團隊）在某個sprint中全部的工作天（假設一天工作八個小時）都在參與這個專案。可想而知，focus factor 1幾乎是不可能的，因為在江湖上走跳總是會有需要參與武林大會（參加各種大大小小的meeting）、路見不平，拔刀相助（幫助同事解決問題或是喬 &lt;strike&gt;代誌&lt;/strike&gt; 事情）、走累了在路邊喝杯茶或是喝碗酒（下午茶時間）、到處打探消息（以實體或虛擬的方式閒扯蛋）、以及傳遞消息（打電話，寫e-mail）等種種活動。以上這些活動都會導致於團隊成員不可能一天八小時都投入在直接與專案開發有關的活動當中，所以正常來講，&lt;font color="#0000ff"&gt;focus factor有0.6~0.7就算是不錯的了&lt;/font&gt;。&lt;/p&gt;  &lt;p&gt;古早以前Teddy剛開始實施Scrum的時候，在sprint planning meeting開始時，會決定團隊的focus factor，假設說鄉民們的團隊有六個全職開發人員，團隊的focus factor為0.65，一個sprint長度是兩周，那麼這個sprint可以使用的工作小時就是：&lt;/p&gt;  &lt;p&gt;（6 人）X （10天）X （8小時）X（0.65）= 312 小時&lt;/p&gt;  &lt;p&gt;有了這個時間，就可以估算這個sprint可以完成多少個stories。等一下…講到這邊鄉民們應該會有一個問題，這個focus factor等於0.65是怎麼來的？說實話，當初都是Teddy「憑感覺」訂出來的。基本上是參考上一個sprint所訂的focus factor，然後看看上個sprint是否全部的stories都有做完，如果有，那麼可以考慮把這個sprint的focus factor稍稍調高一點點，如果沒有則可以考慮是否調降。有時候當sprint planning meeting快結束的時候，發現最後一個story可能還差個幾小時才能夠完成，此時甚至可以「偷偷」把focus factor調高一點點，耶，原本不夠的那幾個小時不就跑出來了。&lt;/p&gt;  &lt;p&gt;鄉民們仔細想一下，Scrum團隊每個sprint所要觀察與生產力直接相關的數值，其實只要看estimated velocity與actual velocity就好了，例如：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;當estimated velocity比actual velocity大很多的時候，例如原本預估這個sprint可以做完49 story points，但是實際上只完成了38 story points，此時團隊就應該要檢討為什麼有一些原本排入的工作無法完成（被抓去開太多無意義的會，遇到太多不預期或是很難解的bugs等等）。這個現象如果以focus factor的角度來看，相當於團隊把&lt;font color="#0000ff"&gt;focus factor估太高&lt;/font&gt;了，但實際上團隊並沒有足夠的時候投入工作當中，所以有一些story無法完成。&lt;/li&gt;    &lt;li&gt;相反地，當estimated velocity比actual velocity小很多的時候，例如原本預估這個sprint可以做完21 story points，但是實際上卻完成了36 story points。這個現象如果以focus factor的角度來看，相當於團隊把&lt;font color="#0000ff"&gt;focus factor估太低&lt;/font&gt;了，但實際上團隊還有充裕的時間可以完成更多的工作。&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;所以，直要直接觀察estimated velocity與actual velocity便可看出團隊的專注力與生產力，以及是否遭遇到什麼「人力不可抗拒的因素」，多了一個focus factor反而增加麻煩。這個觀念有點像是iPhone手機只有用一個實體按鈕就可以搞定全部的事情，何必像「他牌手機」搞到三個甚至是四個按鈕呢（以上言論，不代表&lt;strike&gt;本人&lt;/strike&gt;本台立場）。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;寫到這邊最後還剩下一個問題，不使用focus factor之後，要如何估算每個sprint有多少小時可以使用？這個問題Teddy在「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/05/story-point.html" target="_blank"&gt;如何估算 story point？&lt;/a&gt;」中已經提到過了，這裡再簡短說明一下。基本上每個人每天實際可以投入工作的時間直接以&lt;font color="#0000ff"&gt;五個小時&lt;/font&gt;來估算就好了，所以上述那個例子用這種方法來估算的話，該sprint的工時就變成：&lt;/p&gt;  &lt;p&gt;（6 人）X （10天）X （5小時）= 300 小時&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：這樣解釋應該夠清楚了吧。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-6301863753897658462?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/6301863753897658462/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=6301863753897658462' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6301863753897658462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6301863753897658462'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/scrum-13focus-factor.html' title='Scrum 是什麼（13）：為什麼不建議使用focus factor？'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-7052043292635768065</id><published>2012-02-06T05:00:00.000+08:00</published><updated>2012-02-06T19:46:16.074+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟工'/><title type='text'>Software Tester有前途喔</title><content type='html'>&lt;p&gt;February 05 17:08~18:11&lt;/p&gt;  &lt;p&gt;自從去年（2011）12月正式升級為無業遊民之後，Teddy就去訂閱了104人力銀行的配對日報。從配對日報的內容，Teddy觀察到一個很有趣的改變，就是出現了好幾個要找「軟體測試工程師」或是「軟體測試自動化工程師」的職缺。記得若干年前這樣的職缺幾乎不曾出現，Teddy大膽假設這種職缺的釋出代表著一個現象：&lt;font color="#0000ff"&gt;台灣的軟體開發工作與軟體產品變多了，所以漸漸的軟體測試工作需要專職的人來負責&lt;/font&gt;。&lt;/p&gt;  &lt;p&gt;在某次的Scrum分享活動中，Teddy問了現場的來賓們，有誰的公司裡面有專職的測試工程師，結果只有四個人舉手。這四個人分別來自於兩家不同的公司，所以只有兩家公司有有專職的測試工程師。再細問下去，請問公司的程式設計師和測試工程師的比例是多少 ？詳細答案Teddy已經忘了，大概是1:0.1或是1:0.01之類的比率吧…XD。&lt;/p&gt;  &lt;p&gt;江湖上傳言，台灣軟體公司有做到程式設計師和測試工程師達到1:1比例的，可能只有X勢公司。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;問題來了，如果市場上既存的測試工程師職缺不多，相對的懂測試或是有測試經驗的人自然也不多。現在台灣的軟體開發團隊與公司雖然慢慢認識到專職測試人員的重要性，但是卻苦惱於無法從就業市場找到夠多符合需求的人才。&lt;/p&gt;  &lt;p&gt;如果鄉民們是一位程式設計師 ，請問你會想轉去做tester嗎？Teddy相信絕大多數的回答應該是No。為什麼 ？答案很簡單，從軟體開發的各種不同角色來看，test似乎是處在很低階的一環：&lt;/p&gt;  &lt;p align="center"&gt;技術經理 或 專案經理 &amp;gt; SA &amp;gt; SD &amp;gt; Programmer &amp;gt; Tester &amp;gt; 工讀生&lt;/p&gt;  &lt;p&gt;也許大部分的人都有這樣的想法：基於人往高處爬，水往低處流的道理，只有tester「升等」為programmer，哪有programmer「降級」為tester的道理呢（總不會有商務艙不坐，跑去搭經濟艙吧）。其實一個團隊的組成，每個角色都很重要，從事軟體開發活動，並不是每個人都要成為programmer才是唯一的出路，或是每個programmer一定要變成所謂的SA才不會被淘汰。以Teddy的經驗，真正程式寫得好的人，測試也會做的不錯，這是相對來講這種人畢竟是少數，所以也不能把他們全部都調去當tester。而測試做的好的人，並不一定要人人都是coding高手。很多好的tester需要具備良好的協調力、細心、耐心、大膽假設，小心求證的特質。所以，如果鄉民們也是從事軟體開發工作，喜歡寫程式但是總覺得要變成所謂的「高手」還有一大段距離。或是說&lt;font color="#0000ff"&gt;會寫程式但是又不是那麼喜歡寫程式&lt;/font&gt;（這是什麼樣的矛盾情結…Orz），如果還想繼續待在軟體這一行，除了轉作 &lt;strike&gt;不三不四的&lt;/strike&gt; 專案經理或是業務之外，測試這個領域也是大有可為的。&lt;/p&gt;  &lt;p&gt;Teddy在2009年去上Certified ScrumMaster課程的時候，上課講師就有提到，Scrum Master這個角色就很適合由資深的tester或是所謂的test manager來當任，技術能力非常強但是做起事來卻硬梆梆的資深programmer或是SA反倒不見得合適這樣的工作。&lt;/p&gt;  &lt;p&gt;也許目前software tester這個工作在台灣還不識很受到重視，但是如果軟體愈來越受重視的這個趨勢不變，相信再過個幾年software tester一定會很搶手，相對的待遇應該也不會太差，現在卡位正是時候…XD。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p align="left"&gt;友藏內心獨白：某人的名言：不需要tester，程式設計師自己測就好了…Orz。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-7052043292635768065?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/7052043292635768065/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=7052043292635768065' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7052043292635768065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7052043292635768065'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/software-tester.html' title='Software Tester有前途喔'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-1283351527633163193</id><published>2012-02-05T05:00:00.000+08:00</published><updated>2012-02-08T11:37:45.798+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（12）：不要再用focus factor與unplanned items了</title><content type='html'>&lt;p&gt;February 02 13:37~14:58&lt;/p&gt;  &lt;p&gt;不曉得有多少鄉民跟Teddy一樣都是讀&lt;font color="#0000ff"&gt;Scrum and XP from the Trenches: How we do Scrum&lt;/font&gt;這本書 &lt;strike&gt;長大&lt;/strike&gt; 來學習Scrum的。這本書寫得很好，但是書中有兩個做法，focus factor與unplanned items，經過Teddy實際實施過後的經驗，再加上2009年去上Certified ScrumMaster課程時親自詢問授課講師所得到的答案，Teddy會建議不要使用。&lt;/p&gt;  &lt;p&gt;關於focus factor的解釋請參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/05/story-point.html" target="_blank"&gt;如何估算story point？&lt;/a&gt;」這篇，Teddy今天想談的是unplanned items。&lt;/p&gt;  &lt;p&gt;這一切的一切，還是要從某鄉民兩個小時之前在Facebook上與Teddy的對話說起：&lt;/p&gt;  &lt;p&gt;鄉民：關於bug的問題，如果是外面的人發現的bug，要算在下一個sprint的task嗎?&lt;/p&gt;  &lt;p&gt;Teddy：這要看Product Owner如何安排。&lt;/p&gt;  &lt;p&gt;鄉民：我們是在當下的sprint加入一個fix bug task，所velocity會變低。&lt;/p&gt;  &lt;p&gt;Teddy：我以前儘量不會一收到bug report就馬上去改它，而是會在某個sprint安排一個bug fix的story, 裡面包含所有要fix的bug。這個修bug的story也是要估算story point的，所以不會有作了task但是導致velocity降低的問題。&lt;/p&gt;  &lt;p&gt;鄉民：可是如果bug fix task算unplanned item的話，就不算在velocity裡了說。&lt;/p&gt;  &lt;p&gt;Teddy：我之前去上Certified ScrumMaster課的時候，上課講師告訴我，任何的task一定要歸屬某一個story。所以我上過課之後，就把unplanned item給取消了，不再採用了。&lt;/p&gt;  &lt;p&gt;鄉民：有這種事...&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;Unplanned item就是在sprint planning meeting中沒有被規畫到的工作都可以放到這裡面的某種容器，採用unplanned item有幾個目的：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;應付需要立即處裡的突發狀況：例如使用者臨時回報需要立即修復的重大的bug，修這個bug的task沒地方貼只好把它放在所謂的unplanned item這的分類裡面。 &lt;/li&gt;    &lt;li&gt;不先完成不行的工作：例如，開始實作某個story的時候發現需要先修改另一個既有功能否則做不下去；或是要先安裝一個測試環境才可以完成整個story。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;一個sprint的unplanned item數量越多，的確會造成團隊的velocity（每個sprint實際完成的story point稱之為velocity）下降&lt;/font&gt;。有人覺得這是採用unplanned item的好處，因為當團隊的velocity下降，在retrospective meeting時團隊就應該要檢討原因並訂出改善的方法，以便日後慢慢減少每個sprint發生unplanned item的次數。但是很多人可能會把unplanned item當成一個「&lt;font color="#0000ff"&gt;後門&lt;/font&gt;」，反正就算是sprint planning meeting忘了列出的工作到時候只要丟到unplanned item就好了，或是忽略品質的重要性，想說反正有人回報bug就丟到unplanned item就好了。&lt;/p&gt;  &lt;p&gt;拿掉unplanned item其實會讓整個Scrum的流程變得比較簡單（&lt;font color="#0000ff"&gt;原本的Scrum其實根本沒有unplanned&amp;#160; item這種東西&lt;/font&gt;），也可以強迫團隊重視流程的問題。例如：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;應付需要立即處裡的突發狀況：與其反射性地將所有接收到使用者回報的bug立即放到unplanned item中修正而搗亂了原本開發的步驟，拿掉unplanned item之後團隊會先思考，這個bug如果可以等到下個sprint在處裡，那就不要現在立即處理。如果真的一定要立即處理，可以選擇：      &lt;ul&gt;       &lt;li&gt;寫一個bug fix task然後把這個task貼到某個story裡面（通常是較要性比較高的story這樣才會優先被施工）。 &lt;/li&gt;        &lt;li&gt;如果修這個bug很花時間，或是需要好幾個task才可以修完，可能需要考慮新增一個story。雖然Scrum強調「sprint開始之後儘量不要調整story」，但是如果遇到非處裡不可的情況還是應該要隨機應變一下，可以把重要性比較低的story暫時移除讓bug fix的story插隊一下。 &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;不先完成不行的工作：看看這些沒被規畫到但是又非得完成的task和哪一個story有關，就貼在那個story上面。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;總之，每一個task一定要屬於某一個story就對了。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;看到這邊鄉民們可能會說，這樣子不是換湯不換藥嗎？不管有沒有unplanned item這個分類，這些未被規劃的工作還是會讓velocity降低啊。沒錯，這就是重點：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;如果團隊的velocity經過好幾個sprint之後都還不能穩定下來，就表示某種&lt;font color="#0000ff"&gt;警訊&lt;/font&gt;。還記得Teddy說過「&lt;font color="#0000ff"&gt;&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/scrum.html" target="_blank"&gt;Scrum 本身不能幫你解決問題，但是可以幫你把問題暴露出來&lt;/a&gt;&lt;/font&gt;」，問題既然暴露出來了，團隊就需要找出問題並謀求改善之道。 &lt;/li&gt;    &lt;li&gt;既然有沒有unplanned item這個分類都可以把問題暴露出來，那當然是拿掉unplanned item這個分類會比較簡單啊。 &lt;/li&gt; &lt;/ul&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：古人有云：盡信書不如無書。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-1283351527633163193?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/1283351527633163193/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=1283351527633163193' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1283351527633163193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1283351527633163193'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/scrum-12focus-factorunplanned-items.html' title='Scrum 是什麼（12）：不要再用focus factor與unplanned items了'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-4170424573262612971</id><published>2012-02-04T23:42:00.000+08:00</published><updated>2012-02-04T23:43:05.415+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='其他'/><title type='text'>搞笑談軟工成立Facebook社團</title><content type='html'>&lt;p&gt;February 04 23:27~23:40&lt;/p&gt;  &lt;p&gt;Teddy發現鄉民們很少在搞笑談軟工部落格上面留言，倒是有一些鄉民很看得起Teddy把Teddy加入Facebook好友，透過Facebook問了Teddy一些問題。既然鄉民們比較習慣透過Facebook留言，那乾脆Teddy就在Facebook上幫搞笑談軟工成立一個社團好了，網址如下：&lt;/p&gt;  &lt;p&gt;&lt;a title="https://www.facebook.com/groups/268206229913141/" href="https://www.facebook.com/groups/268206229913141/"&gt;https://www.facebook.com/groups/268206229913141/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;歡迎鄉民們加入，有任何問題只要能幫上忙Teddy會盡量回答，也歡迎鄉民們一起幫忙答覆。&lt;/p&gt;  &lt;p&gt;PS：請不要在Facebook上面跟Teddy借錢，這一點幫不上忙...XD。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;有藏內心獨白：好像早就應該在Facebook上成立社團了說。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-4170424573262612971?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/4170424573262612971/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=4170424573262612971' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/4170424573262612971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/4170424573262612971'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/facebook.html' title='搞笑談軟工成立Facebook社團'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-1612547111509976624</id><published>2012-02-04T05:00:00.000+08:00</published><updated>2012-02-04T05:00:02.787+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體架構'/><title type='text'>Quality Attribute Scenarios（2）：會不會太理論了一點？</title><content type='html'>&lt;p&gt;February 02 09:16~10:33&lt;/p&gt;  &lt;p&gt;有讀過「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/02/quality-attribute-scenarios1.html" target="_blank"&gt;Quality Attribute Scenarios（1）：簡介&lt;/a&gt;」的鄉民們不曉得是否有一個疑問：｢這個方法真的可以在業界被使用嗎，會不會太理論了一些？｣其實Quality Attribute Scenarios（QAS）的目的就是&lt;font color="#0000ff"&gt;以撰寫劇本（scenario）的方式來具體化原本很抽象的非功能需&lt;/font&gt;求，這一點其實跟agile methods採用stories來描述（功能）需求的精神是很類似的。幫鄉民們複習一下，為什麼agile methods要建議用stories來描述需求而非使用use cases？&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;一個story可以想像成是一個use case的某條執行路徑，也就是說一個use case是某個功能（需求）的一般性（較抽象）的敘述。 &lt;/li&gt;    &lt;li&gt;敏捷方法要求團隊要在較短的週期（2-4周）釋出軟體，如果用use case來描述需求可能會無法在一次開發週期中完成這個use case，因此就把需求寫成更小且更具體的story。 &lt;/li&gt;    &lt;li&gt;假設一個use case被切成四個stories，每個sprint完成兩個stories，那麼經過兩個sprints之後原本可能有點抽象的一個use case就完成了。因此Teddy會覺得story比use case更容易「操作（operational）」。需求的可操作性是一個很重要的特性，如果需求寫得太抽象，那敏捷開發團隊很難在短時間內完成該需求。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;套用相同的精神，如果在描述非功能需求時只是說「這個系統需要具備高可用性（high availability）」，這樣的非功能需求對於任何的開發團隊而言都是很難施工的（non-operational）。所以如果把非功能需求寫成scenario（鄉民們可以把scenario和story想成同意字）那麼開發團隊就比較容施工與派工，對於客戶而言也可以根據所寫出來的QAS來驗收系統的非功能需求（不然要如何驗收一個系統是否滿足high availability？）。&lt;/p&gt;  &lt;p&gt;就好像story有類似「As a user, I can do xxx so that I can yyy」這樣的固定格式，QAS所規定的六個元素（Source of stimulus、Stimulus、Environment、Artifact、Response、Response measure）也只是幫忙開發人員可以方便寫出QAS。雖然課本（&lt;font color="#0000ff"&gt;Software Architecture in Practice, 2nd&lt;/font&gt;）的QAS是用畫圖的方式表示，但是真正在寫QAS的時候並不一定要畫類似下面的圖，可以用類似下列表格的形式來撰寫：&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="894"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="103"&gt;Quality Attribute&lt;/td&gt;        &lt;td valign="top" width="97"&gt;Source of stimulus&lt;/td&gt;        &lt;td valign="top" width="127"&gt;Stimulus&lt;/td&gt;        &lt;td valign="top" width="109"&gt;Environment&lt;/td&gt;        &lt;td valign="top" width="72"&gt;Artifact&lt;/td&gt;        &lt;td valign="top" width="172"&gt;Response&lt;/td&gt;        &lt;td valign="top" width="212"&gt;Response measure&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="107"&gt;Availability&lt;/td&gt;        &lt;td valign="top" width="98"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="125"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="113"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="76"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="169"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="208"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="110"&gt;…&lt;/td&gt;        &lt;td valign="top" width="98"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="123"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="116"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="79"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="167"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="205"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="112"&gt;…&lt;/td&gt;        &lt;td valign="top" width="98"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="122"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="118"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="81"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="166"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="203"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="113"&gt;Robustness&lt;/td&gt;        &lt;td valign="top" width="97"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="122"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="120"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="83"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="165"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top" width="206"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;或是寫成story的形式，例如：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;圖(b)：As a boundary component, when a callee throws an exception at runtime, I will transform the exception semantics according to the upper layer’s aspect so that the upper layer can has a meaningful context to handle the exception. 至於Response Measure可以寫在story的how to demo這個欄位。 &lt;/li&gt;    &lt;li&gt;圖(c)：As a application controller, when a callee thorws an exception at runtime, I will perform state-recovery so that the system can continue to run. 同樣的，把Response Measure寫在story的how to demo欄位。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-DpF1WMI-esI/Tyn8Fr1F8XI/AAAAAAAAA8E/oSZnDaDmcM8/s1600-h/QAS-1%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="QAS-1" border="0" alt="QAS-1" src="http://lh6.ggpht.com/-ec5353-yNm8/Tyn8GmtCk7I/AAAAAAAAA8M/MclvDw8eowQ/QAS-1_thumb%25255B2%25255D.png?imgmax=800" width="537" height="348" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：搞軟體的人好像變來變去都是那幾招，只是試圖用不同的講法來包裝，還挺會搞行銷的。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-1612547111509976624?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/1612547111509976624/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=1612547111509976624' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1612547111509976624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1612547111509976624'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/quality-attribute-scenarios2.html' title='Quality Attribute Scenarios（2）：會不會太理論了一點？'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/-ec5353-yNm8/Tyn8GmtCk7I/AAAAAAAAA8M/MclvDw8eowQ/s72-c/QAS-1_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-1935364341622409849</id><published>2012-02-03T05:00:00.000+08:00</published><updated>2012-02-03T05:00:01.232+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 不會幫你解決問題（2）</title><content type='html'>&lt;p&gt;February 02 12:000~01:05&lt;/p&gt;  &lt;p&gt;沒想到這個主題會讓Teddy寫第二集，希望不要有第三集...Orz。&lt;/p&gt;  &lt;p&gt;剛剛某位鄉民在Facebook上問Teddy幾個問題：&lt;/p&gt;  &lt;p&gt;鄉民：看了Teddy你寫的「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/sustainable-pace.html" target="_blank"&gt;Sustainable Pace&lt;/a&gt;」，我發現目前我所參與的Scrum團隊一直找不到sustainable pace。Task總是做不完，或是需要經常加班才做的完。採用Scrum到現在已經超過半年了，大家都很累想說每個sprint的story估鬆一點，但是Product Owner（PO）不肯就範。&lt;/p&gt;  &lt;p&gt;Teddy：Scrum Master可能要跟PO溝通一下，因為 &lt;strike&gt;真相只有一個(請奏樂)&lt;/strike&gt; &lt;font color="#0000ff"&gt;事實擺在眼前&lt;/font&gt;，以往的經驗已經告訴團隊說每個sprint所安排的story太多了，能否先試著拿掉一兩個story看看。Scrum有一個重點是Scrum團隊（包含PO，Scrum Master與Developer）是否能夠從每個sprint中得到&lt;font color="#0000ff"&gt;回饋&lt;/font&gt;。如果每個sprint的story都無法完成或是要靠加班才能夠勉強做完，而團隊（可能是PO）又不正視這個問題，Scrum Master也不去協調，那很有可能導致Developer採行犧牲quality來讓story或是task「&lt;font color="#0000ff"&gt;看起來好像做完&lt;/font&gt;」但實際上可能事後bugs一堆，這樣又回到傳統開發模式的老路子。&lt;/p&gt;  &lt;p&gt;鄉民：但是我們的上層主管規定我們一定要在原本規劃的deadline之前完成全部的story啊，所以這個sprint拿掉story等於下一個sprint的工作量就增加了。所以除非上層主管的想法改變，否則現狀是無法改變了。&lt;/p&gt;  &lt;p&gt;Teddy內心獨白：敢問你們是在run Scrum還是waterfall ？Scrum應該是time boxing而鄉民所說的情況卻是feature boxing。&lt;/p&gt;  &lt;p&gt;Teddy：是啊，如果大老闆訂出一個「不可能完成的時程」又沒有人敢說出真話，那大家只好配合&lt;font color="#0000ff"&gt;演戲&lt;/font&gt;給老闆看（說真的，Teddy覺得台灣人還滿有演戲天分的），&lt;font color="#0000ff"&gt;假裝&lt;/font&gt;&lt;font color="#000000"&gt;大家都很拚讓專案&lt;/font&gt;可以在時限內完成。最後會回到Teddy經常說的：「Developer只能靠加班來保護自已」，反正老闆時程亂定，Developer無論如何有效率的工作也不可能在規定的時程內完成，所以大家就開始搞「&lt;font color="#0000ff"&gt;看起來很忙&lt;/font&gt;」那一套（請參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/06/blog-post_16.html" target="_blank"&gt;加班，加班，我愛你&lt;/a&gt;」）。&lt;/p&gt;  &lt;p&gt;… &lt;/p&gt;  &lt;p&gt;(該位鄉民又問了N個問題之後)&lt;/p&gt;  &lt;p&gt;Teddy：請問你們team的Scrum Master有受過如何當任Scrum Master的訓練嗎？&lt;/p&gt;  &lt;p&gt;Teddy：哈~~~~真是不好意思，我們只有上過內部training，並沒有很正式的訓練，而且Scrum Master是engineer兼任的...@.@&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;這位鄉民一共問了Teddy好幾個問題，最後Teddy得到一個結論，該鄉民的團隊根本是「&lt;font color="#0000ff"&gt;Scrum皮，Waterfall骨&lt;/font&gt;」。&lt;strike&gt;來人啊，拖出去斬了&lt;/strike&gt;。嗯嗯，此時Teddy不免又要mobile01上身...&lt;font color="#ff0000" size="5"&gt;幫不了你&lt;/font&gt;。&lt;/p&gt;  &lt;p&gt;各位鄉民們請讓Teddy再拜託一下，把Scrum套在一個waterfall的專案，那還是waterfall啊，並不會變成agile。雖然Teddy還是相信如果骨子裡是waterfall，但是套用Scrum的專案管理框架，還是能得到一些好處。例如，因為有sprint planning meeting所以每個sprint所要開發的功能整個團隊都會比較清楚。另外，有了task board與Daily Scrum Meeting整個團隊的進度也會變得比較透明。但是，但是，但是（這不是打錯字，而是Teddy連說三個but…XD），至於團隊可以改善到哪個程度，說真的只要靠團隊自己來努力。如果公司文化與老闆的信仰就是waterfall，&lt;font color="#0000ff"&gt;而Scrum Master又不是老闆的兒子或女兒或三等親之內的親戚&lt;/font&gt;，不夠力去改變這一切，那就只能做多少算多少了。&lt;/p&gt;  &lt;p&gt;最後，請各位試著不要換氣跟著Teddy大聲地朗誦一遍：「&lt;font color="#0000ff"&gt;Scrum 不會幫你解決問題，只能幫你把問題暴露出來&lt;/font&gt;」，「&lt;font color="#0000ff"&gt;Scrum 不會幫你解決問題，只能幫你把問題暴露出來&lt;/font&gt;」，「&lt;font color="#0000ff"&gt;Scrum 不會幫你解決問題，只能幫你把問題暴露出來&lt;/font&gt;」。&lt;/p&gt;  &lt;p&gt;唸完收工...^_^。&lt;/p&gt;  &lt;p align="center"&gt;***    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;友藏內心獨白：是不是應該要規定一下，鄉民們在Facebook上一天最多只能問一個問題...XD。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-1935364341622409849?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/1935364341622409849/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=1935364341622409849' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1935364341622409849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1935364341622409849'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/scrum-2.html' title='Scrum 不會幫你解決問題（2）'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-7604993658648692745</id><published>2012-02-02T00:13:00.001+08:00</published><updated>2012-02-02T11:58:59.296+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Agile Workspace</title><content type='html'>&lt;p&gt;February 01 22:48~February 02 00:12&lt;/p&gt;  &lt;p&gt;寫了好多Scrum與agile practices的文章，昨天晚上突然想到有一個很重要的東西沒講，那就是「敏捷團隊的工作環境」。前一陣子剛好去某家公司參觀（&lt;font color="#ff0000"&gt;2/2 11:54補充，剛剛應邀請Teddy去參觀該公司的善心人士要求，在此公布該公司名稱Waveface, &lt;/font&gt;&lt;a href="http://waveface.com"&gt;&lt;font color="#ff0000"&gt;http://waveface.com&lt;/font&gt;&lt;/a&gt;），發現他們的工作環境算是非常接近Teddy心目中理想的agile workspace，今天就借花獻佛跟鄉民們分享一下。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-22CpGIoy2WI/TylksjVULvI/AAAAAAAAA70/8jGei35LTGY/s1600-h/Agile%252520workspace%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="Agile workspace" border="0" alt="Agile workspace" src="http://lh3.ggpht.com/-aGTtMixKUtc/TylkwckA20I/AAAAAAAAA78/0EanN9OgLls/Agile%252520workspace_thumb%25255B1%25255D.png?imgmax=800" width="517" height="532" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;沒有照片鄉民們只好將就一下看看Teddy憑記憶手工打造的草圖，在上圖的工作環境中，是沒有任何的辦公室隔間的，整個空間除了右邊兩間會議室之外，由六張大桌子組成三個工作區間。每一張大桌子可以容納三個人，六張大桌子就可以坐的下十八位員工。每張桌子雖然坐三個人，但是每個人的空間要夠大到可以同時容納兩個人一起pair programming。&lt;/p&gt;  &lt;p&gt;圖的上方標明為「吧&lt;strike&gt;台&lt;/strike&gt;檯」的區域，是一圈靠著窗戶所圍成的吧檯桌面，可以坐得下好幾個人（Teddy沒仔細算可以坐得下多少人）。會議室是用玻璃隔間的，所以會議室的玻璃隔間牆面都可以拿來當作白板或是task board。此外，上圖左下方的整個牆面吊了一個看起來像是訂做的超大白板，同樣可以當作task board。左方的牆面也都貼滿了stories/tasks。&lt;/p&gt;  &lt;p&gt;左上方的牆面前方可以擺放一個移動白板或是flip chart，形成一個小區域討論空間。另外右方會議室前面的空間形成另一個較大的討論空間，適合拿來舉辦daily scrum meeting。在右方入口處有一個茶水間，整個辦公室正前方有一個投影布幕，可以拿來&lt;strike&gt;看電影&lt;/strike&gt;...嗯嗯...開會討論（當然兩個會議室也都各有一個投影機。）。&lt;/p&gt;  &lt;p&gt;寫到這邊Teddy想到少畫了一個機房，好像是位於右方會議室與茶水間的中間。另外像是影印機、印表機、與文具放在哪裡就不是那麼的重要了。還有一點，一個agile team一定要有build server（建構機器或是持續整合機器），可以在工作區域角落找一個單獨的小桌子擺放或是放在機房中。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;以上是Teddy記憶中該公司的大致工作環境（這樣應該沒有洩漏到人家的公司機密吧…XD），整個空間給人的感覺滿好的。一個理想的agile workspace除了上述的元素以外應該還要有：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;休息空間，能有沙發或是廚房可以煮點東西會更好。 &lt;/li&gt;    &lt;li&gt;圖書空間，存放公用的書籍、雜誌或資料。開發軟體不可能不看書吧，所以有一個公用的圖書空間很重要。 &lt;/li&gt;    &lt;li&gt;集中式置物櫃，給員工存放個人物品。 &lt;/li&gt;    &lt;li&gt;測試空間，可以擺放多台測試機器。&lt;font color="#0000ff"&gt;測試空間非常重要，尤其是開發跨平台系統的團隊。&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;個人臨時（私密）空間，又稱為hot-desk area，提供員工需要打電話、回email、臨時處理較私密的事情，或是當員工需要獨自安靜思考與工作時使用。 &lt;/li&gt;    &lt;li&gt;高速有線與無線網路。 &lt;/li&gt;    &lt;li&gt;可移動式且可上鎖的小置物櫃，每人一個。 &lt;/li&gt; &lt;/ul&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p align="left"&gt;友藏內心獨白：搞agile也要懂一點室內設計...XD。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-7604993658648692745?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/7604993658648692745/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=7604993658648692745' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7604993658648692745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7604993658648692745'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/agile-workspace.html' title='Agile Workspace'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-aGTtMixKUtc/TylkwckA20I/AAAAAAAAA78/0EanN9OgLls/s72-c/Agile%252520workspace_thumb%25255B1%25255D.png?imgmax=800' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-6121556778365570668</id><published>2012-02-01T06:00:00.000+08:00</published><updated>2012-02-01T23:01:43.112+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體架構'/><title type='text'>Quality Attribute Scenarios（1）：簡介</title><content type='html'>&lt;p&gt;January 31 14:42~17:06&lt;/p&gt;  &lt;p&gt;Scrum、軟體設計與物件導向基本觀念在一月份談得差不多了，接下來換換口味，談點軟體架構的議題。關於軟體架構有一個重要的觀念，那就是「&lt;font color="#0000ff"&gt;軟體架構要解決的問題，絕大部分都&lt;font color="#ff0000"&gt;不是&lt;/font&gt;功能面需求（functional requirements）的問題，而是所謂的非功能需求（non-functional requirements）的問題&lt;/font&gt;」。事實上，如果功能需求是唯一的需求，那麼軟體系統是可以沒有任何的結構，一整坨像義大利麵一樣糾纏不清都沒問題（所謂的monolithic system）。但是實際上一個軟體系統除了功能需求以外，還會有所謂的非功能需求，像是modifiabiflity（容易修改）、dependability（穩定可靠）、performance（執行效率）、time-to-market（及時上市）等等。為了要兼顧這些非功能需求，於是各式各樣的系統架構因此應運而生。&lt;/p&gt;  &lt;p&gt;現在問題來了，如果鄉民們正在設計軟體架構，要如何滿足一個系統的眾多非功能需求 ？學過architecture patterns的鄉民可能會說，很簡單啊，就是套用patterns就好了。在很幸運的情況下，也許剛剛好有現成的architecture patterns可以解決手邊的問題。但是很多情況是，套用了某個（或某些）patterns的確解決了若干個非功能需求，但是卻還是遺留了其他的非功能需求需求沒有被解決，此時該如何應對 ？舉個實際的例子，鄉民們的系統套用了plug-ins architecture，解決了extensibility（擴充性）與modifiability（修改性）這兩個主要的非功能需求，但如果這個系統是24x7全年無休的系統，像是availability（可用性）這個重要的非功能需求就沒有直接被plug-ins architecture給涵蓋。所以看起來需要有比architecture patterns還要更基本的東西來幫助開發者應付非功能需求。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;在&lt;font color="#0000ff"&gt;Software Architecture in Practice, 2nd&lt;/font&gt;這本書中介紹一個方法來處理上述問題，這個方法叫做&lt;font color="#0000ff"&gt;Quality Attribute Scenarios&lt;/font&gt;（QAS），中文姑且稱之為「品質屬性劇本」。Quality attributes就是non-functional requirements，兩者是同義詞（Teddy之前有提到過作軟體的人很喜歡搞同義字，請鄉民們多包涵...XD）。&lt;/p&gt;  &lt;p&gt;傳統上若只是用quality attributes來定義系統的非功能需求會有三個問題：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Non-operational：光是說「這個系統需要很高的可用性（availability）」只提及了availability這個quality attribute，太過於抽象且沒有定義何謂「很高的可用性」，因此這樣的quality attribute定義對於開發人員而言是「無法操作（無從下手去滿足它）」的。 &lt;/li&gt;    &lt;li&gt;Overlapping attribute concerns：在判斷或是討論一個系統品質好壞的時候，通常要先申明是用何種角度來評論才有意義。例如，系統當機這件事情，從availability、security、usability這三種quality attributes來看，各有不同的因應之道。因此，針對某個事件來討論系統品質的時候，必須要清楚說明是從哪一個quality attribute的角度來看這件事。 &lt;/li&gt;    &lt;li&gt;缺少共通語彙：不同quality attributes領域的人可能會有用不同的字彙來敘述相同的一件事情，例如搞performance的人會說events到達一個系統，搞security的人會說系統收到很多attacks，搞availability的人會說系統產生了failures，搞usability的人會說系統收到user input。這些說法其實可能指的都是同一件事，但是卻用不同的語彙。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;上述前兩個問題可以用QAS來解決。在介紹QAS長什麼樣子之前，還要先說明一個觀念，假設說鄉民們的系統被要求要具備high availability，那麼當設計系統的時候就要明確定義出來，在何種情況下需要達到high availability。例如，「電腦硬體當機」系統還是要可以運作。這個「電腦硬體當機」事件在QAS的術語就叫做stimulus，總之把stimulus當成event或是某種條件（condition）來看待就好了。&lt;/p&gt;  &lt;p&gt;接下來說明一個QAS所包含的六個元素：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Source of stimulus：產生這個stimulus的人（一個電腦系統、人類或是其他任何軟體元件）。 &lt;/li&gt;    &lt;li&gt;Stimulus：當這個stimulus到達系統的時候，系統必須加以回應。 &lt;/li&gt;    &lt;li&gt;Environment：這個stimulus發生時的系統環境狀況，例如系統可能已經過載，或是電腦剛剛開機。 &lt;/li&gt;    &lt;li&gt;Artifact：接收到這個stimulus的人。 &lt;/li&gt;    &lt;li&gt;Response：當這個stimulus到達系統（被artiface收到）的時候系統所做出的反應。 &lt;/li&gt;    &lt;li&gt;Response measure：當系統產生response（反應）的時候，該response必須是要能夠被測量的，如此一來這個用QAS所描述的非功能需求才可以被測試。 &lt;/li&gt; &lt;/ul&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;最後舉個例子，下圖是兩個關於robustness的QAS，圖(b)可以解讀為「在runtime的時候callee（某個被呼叫的元件）丟出一個exception，當這個exception被boundary component所收到的時候，系統必須將這個exception轉成上層元件所了解的意義（通常會丟出一個新的exception）。驗證方法為所有經過boundary component的exception其語意都必須要是上層元件所了解的意義」。&lt;/p&gt;  &lt;p&gt;圖(c)可以解讀為「在runtime的時候callee（某個被呼叫的元件）丟出一個exception，當這個exception被application controller所收到的時候，系統必須執行狀態回復的動作，確保當例外發生之後整個系統的狀態是正確的以便系統可以繼續執行。驗證方法為檢查這個應用程式的workspace（工作區）的資料都已經被回復成正常的狀態」。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-6JfbOwnexTA/TyevJtKkZuI/AAAAAAAAA7k/xLK0CAFbr7U/s1600-h/QAS-1%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="QAS-1" border="0" alt="QAS-1" src="http://lh4.ggpht.com/-qA0ox7eQLSI/TyevK1LdxLI/AAAAAAAAA7s/vVRhi37XrYo/QAS-1_thumb%25255B2%25255D.png?imgmax=800" width="720" height="466" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;在書中介紹availability、modifiability、performance、security、testability、usability這六種QAS，日後有時間再逐一介紹。不過話說回來，就算是沒時間也要介紹，不然快沒東西可寫了...XD。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：這篇太紮實了，寫得有點久。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-6121556778365570668?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/6121556778365570668/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=6121556778365570668' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6121556778365570668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6121556778365570668'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/02/quality-attribute-scenarios1.html' title='Quality Attribute Scenarios（1）：簡介'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/-qA0ox7eQLSI/TyevK1LdxLI/AAAAAAAAA7s/vVRhi37XrYo/s72-c/QAS-1_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-5707399932033214253</id><published>2012-01-31T06:00:00.000+08:00</published><updated>2012-01-31T06:00:05.499+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體設計'/><title type='text'>什麼是物件導向（4）：Inheritance</title><content type='html'>&lt;p&gt;January 30 19:27~20:45&lt;/p&gt;  &lt;p&gt;終於來到物件導向觀念介紹的最後一集inheritance（繼承），且看課本第57頁的定義：&lt;/p&gt;  &lt;p&gt;If class B interits class A, then both the operations and the information structure described in class A will become part of class B. &lt;/p&gt;  &lt;p&gt;接著課本解釋幾個與inheritance相關的名詞：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Generalization&lt;/strong&gt;：一般化，把好幾個不同的classes共同的特性抽離出來集中放到一個class中，然後讓原本的那些classes去繼承這個新的class。這種過程叫做generalization。感覺有點botton-up的方式來建構繼承架構。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Specialization&lt;/strong&gt;：特殊化，這個名詞一聽就知道跟generalization相反，也就是說假設鄉民們要新增一個class到現有的系統中，先找到一個既存的class其功能與資料和這個準備新增的class類似，然後讓這個準備新增的class去繼承原有的這個class，然後在這個新的class身上增加專屬於他自己的行為或資料。&lt;font color="#0000ff"&gt;一個被特殊化的class其行為已經跟他的祖先不同了，換句話說，特殊化違反了&lt;/font&gt;&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/4.html" target="_blank"&gt;&lt;font color="#0000ff"&gt;Liskov Substitution Principle&lt;/font&gt;&lt;/a&gt;&lt;font color="#0000ff"&gt;。&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Ancestors&lt;/strong&gt;：祖先，在一個繼承架構中，某個class A之上的所有classes稱之為A的祖先。Ancestors又稱作superclasses（父類別）。。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Descendants&lt;/strong&gt;：後代，在一個繼承架構中，某個class A之下的所有classes稱之為A的後代。Descendants又稱作subclasses（子類別）。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Direct descendant&lt;/strong&gt;：直屬後代，直接繼承自某個class A的那個class稱之為class A的direct descendant或是child。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Direct ancestor&lt;/strong&gt;：直屬祖先，若class A為class B的direct descendant，則class B就稱為class A的direct ancestor或是parent。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Abstract classes&lt;/strong&gt;：祖先類別在設計的時候，其主要目的若是要讓其他類別繼承，則我們通常稱這樣的祖先類別為abstract classes。關於這一點雖然課本上這樣解釋，但是實務上我們會說一個無法產生instance的class就稱之為abstract class。 &lt;/li&gt;    &lt;li&gt;     &lt;div align="left"&gt;&lt;strong&gt;Concrete class&lt;/strong&gt;：和abstract classes相反，一個類別其設計之主要目的就是要讓人產生instance，則稱此類別為concrete class。實務上只要是能產生instance的類別都稱之為concrete classes。&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p align="left"&gt;這在邊Teddy先插花補充一的觀念，雖然在課本中並沒有提到，但是現在鄉民們可能都知道inheritance分成兩種：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Implementation inheritance&lt;/strong&gt;：實作繼承，子類別繼承父類別的介面以及實作。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Interface inheritance&lt;/strong&gt;：介面繼承，子類別只繼承父類別的介面。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;接下來回到課本的內容，課本提到使用inheritance的四種時機：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Reuse&lt;/strong&gt;：透過implementation inheritance重複使用祖先類別中的行為與資料。剛開始學OO的人會認為reuse是使用繼承的主要目的，當年Teddy也是這樣認為，後來慢慢懂事之後，才發現如果光是為了reuse而使用繼承並不是一個好主意。且看GoF的Design Patterns第20頁告訴鄉民們：&lt;font color="#0000ff"&gt;Favor object composition over class inheritance&lt;/font&gt;。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Subtyping&lt;/strong&gt;：一個類別（class）被視為某個型別（type）的實作就稱為subtyping（所以interface inheritance就是一種subtyping）。課本第64頁有講到一個重點：Subtyping normally occurs if the inheritance performs only an extension, rather than overriding something already defined in the ancestor. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Specialization&lt;/strong&gt;：前面已經解釋過，一個類別被特殊化之後，其行為已經跟他的祖先不相容了。有時候使用特殊化目的是因為後代類別與祖先類別大部分的行為都很相似，但是有少數幾個行為不同（可能後代增加新的行為，或是移除祖先的某些行為）。因為特殊化違反了&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/4.html" target="_blank"&gt;&lt;font color="#000000"&gt;Liskov Substitution Principle&lt;/font&gt;&lt;/a&gt;&lt;font color="#000000"&gt;，所以使用特殊化的程式通常會看到instacne of 之類的判斷式（無法做polymorphism）。&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Conceptual&lt;/strong&gt;：概念化，因為「概念上」某個類別屬於另外一種類別的後代，所以就使用了繼承。例如，人和狗都是一種動物，所以人和狗都繼承自動物這個類別。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;這四種使用繼承的理由並非互斥的，例如，可能因為reuse的原因而套用subtyping或是specialization。&lt;font color="#0000ff"&gt;根據課本的說法，subtyping是一種使用繼承比較好的理由。&lt;/font&gt;&lt;font color="#000000"&gt;但是如果依據Design Patterns的說法：&lt;font color="#0000ff"&gt;Favor object composition over class inheritance&lt;/font&gt;&lt;font color="#000000"&gt;，吃飽沒事就不要用（實作）繼承了，但是介面繼承多用倒是無妨&lt;/font&gt;。&lt;/font&gt;&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：今天中午吃得好飽。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-5707399932033214253?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/5707399932033214253/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=5707399932033214253' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/5707399932033214253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/5707399932033214253'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/4inheritance.html' title='什麼是物件導向（4）：Inheritance'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-8702011556068421838</id><published>2012-01-30T06:00:00.000+08:00</published><updated>2012-01-30T06:00:01.252+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（11）：不信邪之流程改善精神</title><content type='html'>&lt;p&gt;January 29 22:21~23:24&lt;/p&gt;  &lt;p&gt;Teddy在「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/scrum-9retrospective-meeting.html" target="_blank"&gt;Scrum 是什麼（9）：Retrospective Meeting&lt;/a&gt;」這一篇介紹了三種流程改善的思考方向，其實說到底廣義的流程改善也好，或是狹義的實施Scrum與agile practices也罷，都需要有一種「&lt;a href="http://teddy-chen-tw.blogspot.com/2011/03/blog-post_12.html" target="_blank"&gt;傻的願意相信&lt;/a&gt;」外加「不信邪」的精神。「傻的願意相信」的觀念Teddy已經提過好幾次了，大意是說書上教授的軟體工程方法，鄉民們自己要先「傻傻地願意相信」這些是可以奏效的方法，先嘗試照著去做，而不要在學會之前就先急著去否定這些方法。&lt;/p&gt;  &lt;p&gt;然而，傻地願意相信只是第一步，因為有時候就算是真的傻傻地照著書本上所教的方法去做，實務上還是會遇到很多困難，導致於無法達到書本上所說的那種效果。例如，幾乎所有軟體工程與敏捷方法的書都告訴鄉民們「要寫自動化測試，要寫自動化測試」，老師在講鄉民們有沒有在聽 ？沒有嘛（翻桌）。不過這也不能怪鄉民們，實務上團隊就是沒有編列「testers」這種標準配備啊，自動化測試要叫誰寫 ？好吧，山不轉路轉，沒有testers就請programmers自己寫吧。問題又來了，programmers要嘛就是說不知道怎麼寫自動化測試，要嘛就是直接嗆說不爽寫，還有些PM（專案經理）會跳出來阻擋，理由是「寫code都來不及了哪有時間寫什麼自動化測試啊」。&lt;/p&gt;  &lt;p&gt;正所謂「天將降大任於斯人也，必先苦其心志，勞其筋骨，餓其體膚，空乏其身，行拂亂其所為（&lt;font color="#0000ff"&gt;難怪Scrum Master當久了很容易起肖&lt;/font&gt;），所以動心忍性，增益其所不能。」 遇到這些阻礙也當屬正常現象，請安心服用。所以，「傻的願意相信」的下一步，就是要有「不信邪」的精神。老子/老娘就不信沒有tester就寫不了自動化測試；有了這樣的覺悟，假以時日團隊自然會找出改善之道。&lt;/p&gt;  &lt;p&gt;約十天前Teddy在寫「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/single-code-base.html" target="_blank"&gt;Single Code Base&lt;/a&gt;」時，把Extreme Programming Explained: Embrace Change, 2nd這本書關於Single Code Base的解釋又讀了一次，在68頁作者寫了一段話讓Teddy感觸良多：&lt;/p&gt;  &lt;p&gt;If you have a legitmate reason for having multile versions, &lt;font color="#0000ff"&gt;look at those reasons as assumptions to be&lt;/font&gt;&lt;font color="#0000ff"&gt; challenged&lt;/font&gt; rather than absolutes. It might take a while to unravel deep assumptions, but &lt;font color="#0000ff"&gt;that unraveling may open the door to the next round of improvement&lt;/font&gt;.&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;當Teddy在開發團隊中扮演Scrum Master角色的時候，心中日思夜想的事情都是如何改善團隊的軟體開發流程。為什麼這個sprint產生的bugs特別多，為什麼bugs沒有被自動化單元測試與自動化功能測試給找出來，為什麼有一個版本的安裝程式根本無法執行，為什麼與平台相依的專案（native projects）無法在持續整合系統上面自動被建構，為什麼... ？&lt;/p&gt;  &lt;p&gt;這麼多為什麼，也許都可以用一句「人力不足」或是「時程太趕」來交代過去，但是這樣的話就談不上什麼向上提升，只能祈禱不要向下沉淪就該偷笑了。&lt;/p&gt;  &lt;p&gt;「基礎practices達成度」、「進階practices達成度」、「消除浪費」這三點已經幫Scrum團隊樹立了許多改善的方向或是目標，然而要如何接近這些目標每個團隊卻是要依據自己的現況與組織的文化自行調整。達成目標的過程可能很漫長，但只要抱持著不信邪的精神，Teddy相信改善的效果總是會逐漸顯現。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p align="left"&gt;友藏內心獨白：清宮劇裡面不是常常都說要「想輒」嗎，沒輒的時候還是要想輒，這就是一種改善的精神...XD。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-8702011556068421838?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/8702011556068421838/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=8702011556068421838' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8702011556068421838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8702011556068421838'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/scrum-11.html' title='Scrum 是什麼（11）：不信邪之流程改善精神'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-5820186730405056607</id><published>2012-01-29T00:20:00.001+08:00</published><updated>2012-01-29T00:20:32.974+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（10）：時程估算</title><content type='html'>&lt;p&gt;January 28 23:03~January 29 00:20&lt;/p&gt;  &lt;p&gt;Scrum的大小活動大致上算是都交代過一遍了，今天談一 下幾天前學妹在Facebook上問Teddy的一個問題：時程估算。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;學妹：最近我們常常被問到關於時程估計的問題，尤其是之前沒有run過Scrum的團隊，他們會想知道假設客戶一個案子來了，要怎麼去估算時間跟報價呢。我們用自己的經驗回答了，但總覺得回答得不夠有說服力。很想請教學長在這方面有沒有相關經驗可以跟大家分享呢? 謝謝!!&lt;/p&gt;  &lt;p&gt;Teddy：很簡單啊，請問你問題的人跟Teddy聯絡...不是啦，這個問題不容易回答，基本上agile是建議不要採用「固定費用的合約」，但是實務上目前很難能夠被客戶接受。再加上如果團隊沒有run過Scrum不知道自己的「速度（生產力）」那就更難估了。你都怎麼回答別人？&lt;/p&gt;  &lt;p&gt;學妹：這問題其實是上次學長講座結束後，後續留資料跟我們接觸的廠商訪談時候提出來的XD。首先，我們是講說通常一個有經驗的scrum團隊開發速度會趨穩定，這時候可以根據這樣的速度做估計。如果沒有經驗的話，會請他們用Commitment Based的方式，變成邊做邊調整，並且預留buffer，可是留buffer又牽扯到報價的問題。而且對方是表示對他們接案為主的小公司來說，這樣真的滿難的。所以討論到最後，對方說可能先從自己有興趣沒時程壓力的案子先run看看。我自己覺得我們回答的不好，所以最近才在想這個問題有沒有好的做法 ~&amp;quot;~&lt;/p&gt;  &lt;p&gt;Teddy：要回答這樣的問題其實也很簡單，&lt;font color="#0000ff"&gt;最保險的作法就是看他們原本怎麼估，就怎麼估&lt;/font&gt;。然後用SCRUM想辦法在估算的時程內把案子做出來。以這種方式多做幾次就會越估越準，不用說去找什麼「沒有時程壓力的案子來試SCRUM」。&lt;/p&gt;  &lt;p&gt;學妹：哈哈哈 這樣一說突然覺得很有道理耶XD 突然想起學長寫的「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/scrum.html" target="_blank"&gt;Scrum 不會幫你解決問題&lt;/a&gt;」這篇。我想我自己也陷入那種想用Scrum幫大家解決所有問題的迷思了XDDD 謝謝學長，我會再多想想的!!&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;Teddy覺得學妹原本的回答已經很得體了。時程估算在軟體開發中本來就是一件困難的事情，問什麼 ？很簡單，因為變數太多了啊。有什麼變數？&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;需求會變 &lt;/li&gt;    &lt;li&gt;開發團隊成員會變 &lt;/li&gt;    &lt;li&gt;技術會變 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;但也不能說因為變數太多所以就什麼也不估。估算的結果通常有兩種：「不準」以及「非常不準」。對於一個剛開始想要採用Scrum的團隊，如果客戶還是只願意用傳統的固定價格合約的方式來進行專案，那麼案子還是可以做。也沒甚麼好害怕或是擔心的，採用Scrum並不是進京趕考「一試定終身」，也不是做數學四則運算考題，第一次就要算出所謂的「正確答案」才算是成功。Scrum（所有的敏捷方法）都是一種逐步改善的過程，先把箭射出去了，再看看箭離標靶有多遠，然後修正後再射箭...縱然標靶本身並非是固定不動的（活動標靶），但依此精神長久下去所射出的箭總是慢慢地往標靶靶心靠近。&lt;/p&gt;  &lt;p&gt;沒錯，「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/scrum.html" target="_blank"&gt;Scrum 不會幫你解決問題&lt;/a&gt;」，江湖上沒有什麼大還丹或是天山雪蓮之類的補品，吃一口就可以平白增長數十年功力。只有「&lt;a href="http://teddy-chen-tw.blogspot.com/2011/03/blog-post_12.html" target="_blank"&gt;傻的願意相信&lt;/a&gt;」，勇敢誇出第一步，然後邊走邊修正（果真如Kent Beck大叔所說的，軟體開發就跟開車是一樣的道理）。&lt;/p&gt;  &lt;p&gt;Robert L. Glass在Facts and Fallacies of Software Engineering第31頁寫了一段大家都知道的事實：&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Most software estimates are performed at the beginning of the life cycle. This makes sense until we realize that estimates are obtained before the requirements are defined and thus before the problem is understood. Estimation, therefore, usually occurs at the wrogn time.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Scrum能帶來的好處，是&lt;font color="#0000ff"&gt;把「計畫」這兩個字從名詞變成動詞&lt;/font&gt;。Scrum團隊隨時都在計畫，隨時都在調整，眼睛隨時都盯著標靶前進。Teddy前面提到的三個影響需求估算的變數，第一點「需求會變」這幾乎是無法改變的事實，所以Kent Beck大叔又告訴我們要「擁抱改變」。在Scrum的設計中，專屬的Product Owner與Scrum Master，舉辦Sprint Planning Meeting、Daily Scrum、Sprint Demo等活動，以及自動化測試、refactoring等作法，都算是用來「擁抱改變」的方法。&lt;/p&gt;  &lt;p&gt;至於另外兩點變動因素「團隊成員會變」與「技術會變」，還是要靠「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/sustainable-pace.html" target="_blank"&gt;Sustainable Pace&lt;/a&gt;」以及「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/03/shared-code.html" target="_blank"&gt;Shared Code&lt;/a&gt;」與「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/pair-programming.html" target="_blank"&gt;Pair Programming&lt;/a&gt;」等實務作法，讓提升團隊合作的能力，並且讓團隊成員有餘力可以讀書與自我成長（Sustainable Pace是很重要的）。     &lt;br /&gt;&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;講了一堆，其實講再多鄉民們不願意去嘗試也沒用。軟體是動手做出來的，開發軟體是一種逐步改善的活動，所以，不要怕第一次估算沒做好就裹足不前。因為這就跟追女朋友一樣，不開口機會永遠是零。考慮東，考慮西的，最後又回到原本每天加班的老方法上面。團隊是否一開始就可以馬上實施「正統的Scrum」並不是重點，重點是這一狗票的敏捷方法（例如XP與Scrum）與敏捷實務作法（例如自動化測試、持續整合、Pair Programming等等）有那一些是可以拿來改善軟體開發流程，能用多少就算多少。而且要記得「&lt;font color="#0000ff"&gt;開發軟體是一種逐步改善的活動&lt;/font&gt;」，不是說那一天心血來潮隨便挑一個敏捷實務作法來試一下乎弄過去就沒事了，而是要依據團隊與專案現況，挑選合適的實務作，對症下藥方能見效。但這藥也不能亂吃，吃錯了藥輕則花錢消災，重則可能要終生洗腎，不可不慎。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：這整篇哪裡有提到時程要如何估算啊？&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-5820186730405056607?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/5820186730405056607/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=5820186730405056607' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/5820186730405056607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/5820186730405056607'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/scrum-10.html' title='Scrum 是什麼（10）：時程估算'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-8537268404831028718</id><published>2012-01-28T06:00:00.000+08:00</published><updated>2012-01-28T06:00:00.053+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='生活'/><title type='text'>動手整理資料（2）：Synology DS411 儲存空間設定</title><content type='html'>&lt;p&gt;January 26 12:35~14:38&lt;/p&gt;  &lt;p&gt;&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/1synology-ds411.html" target="_blank"&gt;上一集&lt;/a&gt;提到Synology DS411開箱與安裝硬碟的步驟，接下來要設定如何使用這些硬碟。首先連到Synology的官方網站找到DS411的軟體下載畫面，如下圖所示。要先安裝Synlolgy Assistant這個軟體，沒想到這個軟體居然有提供Windows、Mac、與Linux等三個版本，真是「揪感心」。剛好Teddy最近買了一台MacBook Air，就下載Mac版來試看看。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-qAA0ZJHye2M/TyDlJkZNABI/AAAAAAAAA2M/yLq0AJFNXWc/s1600-h/HD-01%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-01" border="0" alt="HD-01" src="http://lh3.ggpht.com/-BghXjX41C7Q/TyDlKzEr4aI/AAAAAAAAA2U/e3-6aMaVE8o/HD-01_thumb%25255B3%25255D.png?imgmax=800" width="662" height="688" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;下載之後安裝完畢執行Synology Assistant會看到如下畫面，注意「狀態」那一欄顯示「DSM未安裝」，DSM是DiskStation Manager的縮寫，應該是一個web-based application，要先安裝這個軟體才可以透過瀏覽器去管理DS411。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-u7ZT5xf1Z0w/TyDlLyRtfDI/AAAAAAAAA2c/40TFeoe6FQI/s1600-h/HD-02%25255B8%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-02" border="0" alt="HD-02" src="http://lh4.ggpht.com/-Tc6q9v-Uw9k/TyDlMhZ5N6I/AAAAAAAAA2k/o4VEbBLlBQs/HD-02_thumb%25255B6%25255D.png?imgmax=800" width="642" height="409" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;點選上個畫面中的安裝按鈕，就會出現下面這個畫面，按下瀏覽按鈕選擇從Synology官網下載的DSM 3.2檔案按下一步（目前DSM最新版本為3.2，4.0版已經舉辦了beta發表會。）。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-2H4M1KyeA5k/TyDlN2_Fo_I/AAAAAAAAA2s/j0v5_aB9k0s/s1600-h/HD-03%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-03" border="0" alt="HD-03" src="http://lh6.ggpht.com/-fUigzeOfVO0/TyDlPO3JUwI/AAAAAAAAA20/serB1r1tt3M/HD-03_thumb%25255B3%25255D.png?imgmax=800" width="637" height="459" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;預設管理者帳號是admin，在這個步驟可以設定管理者密碼以及DS411的名稱。這個名稱就是設定完成之後透過Windows的網芳尋找電腦時會看到的電腦名稱。最後有一個要注意的選項「安裝後建立Synology Hybrid Raid (SHR)儲存空間」，這個選項預設是打勾的。如果選擇了這個選項，系統預設會把所有安裝的硬碟作成一個號稱「可以兼顧資料保護與儲存容量的」單一個存儲空間，但是Teddy看了老半天還是沒搞懂SHR的運作原理，再加上Teddy的四顆硬碟只有disk 1與disk需要作RAID 1，其他兩顆硬碟不需要做RAID，所以就不選擇這個SHR（但是Teddy第一次安裝的時候不曉得者個選項是做什麼的，所以還是選擇了SHR…Orz）。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-MX7S_xsOUo0/TyDlQViat-I/AAAAAAAAA28/l8K0BNHCt1U/s1600-h/HD-04%25255B7%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-04" border="0" alt="HD-04" src="http://lh5.ggpht.com/-CzulzTOaz28/TyDlRgLeVPI/AAAAAAAAA3E/CujLYdwpXSQ/HD-04_thumb%25255B3%25255D.png?imgmax=800" width="642" height="463" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;接著是網路設定，這應該不用說明了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-WM7zgNHVm-E/TyDlTN8yXjI/AAAAAAAAA3M/8oIdr2U0Uzs/s1600-h/HD-05%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-05" border="0" alt="HD-05" src="http://lh3.ggpht.com/-tErdJiEf1BU/TyDlUeetBFI/AAAAAAAAA3U/vTAVX3_gVAI/HD-05_thumb%25255B2%25255D.png?imgmax=800" width="646" height="466" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;基本設定完成，等系統自動設定與安裝完DSM就可以開始使用了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-sAn3sYHiXow/TyDlVWNaFyI/AAAAAAAAA3c/S6VJdbvEqJ0/s1600-h/HD-06%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-06" border="0" alt="HD-06" src="http://lh4.ggpht.com/-TgpG2DzDDYE/TyDlWXC6O5I/AAAAAAAAA3k/sBcRni5RQR4/HD-06_thumb%25255B2%25255D.png?imgmax=800" width="642" height="516" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;安裝完成，按下「登入DiskStation」。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-j5zWg7q1KCg/TyDlXpx5sbI/AAAAAAAAA3s/5hq3FOfe-B0/s1600-h/HD-07%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-07" border="0" alt="HD-07" src="http://lh4.ggpht.com/-C4zuyA53zVk/TyDlYsDpXLI/AAAAAAAAA30/39VHYm_Hi6s/HD-07_thumb%25255B2%25255D.png?imgmax=800" width="637" height="512" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;輸入帳號（admin）以及剛剛設定的密碼。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-BooZYe9QQeI/TyDlZ4wk9fI/AAAAAAAAA38/OQEihd7T9uA/s1600-h/HD-08%25255B9%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-08" border="0" alt="HD-08" src="http://lh4.ggpht.com/-a56H-L8xmTw/TyDlb5AMnCI/AAAAAAAAA4E/gCLvqlfpr-M/HD-08_thumb%25255B5%25255D.png?imgmax=800" width="610" height="447" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;第一次登入所看到的畫面。由於Teddy在之前的設定步驟中在還搞不清楚狀況的情況下選擇了使用SHR，所以系統一安裝好就自動新增儲存空間。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-L718Si4MlQg/TyD0vIqvRiI/AAAAAAAAA4M/-l8ilJA5kdw/s1600-h/HD-09%25255B9%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-09" border="0" alt="HD-09" src="http://lh4.ggpht.com/-SqjRWJgj3Oc/TyD0wpb9RZI/AAAAAAAAA4U/2KOR6LVXnJY/HD-09_thumb%25255B5%25255D.png?imgmax=800" width="612" height="612" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;從下面這個畫面可以看到Teddy的四顆硬碟被組成一個很大的「儲存空間1」。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-1dsQ0dQp4cY/TyD0zB-6kQI/AAAAAAAAA4c/QeMkXt7paA8/s1600-h/HD-09%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-09" border="0" alt="HD-09" src="http://lh5.ggpht.com/-62JCUYZ4L6g/TyD00dDn6VI/AAAAAAAAA4k/AK1DTeVdA1E/HD-09_thumb%25255B2%25255D.png?imgmax=800" width="591" height="446" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;但是SHR規劃出來的儲存空間並非Teddy所要的，所以把這個儲存空間給刪除了，重新建一個。使用DSM提供的「儲存空間管理員」，選擇「自訂」選項來新增儲存空間。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-CkGgQHDGR1k/TyD01ITPgjI/AAAAAAAAA4s/q_O5TTm2qxM/s1600-h/HD-11%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-11" border="0" alt="HD-11" src="http://lh3.ggpht.com/-FRWEVbheiQY/TyD02fWl5RI/AAAAAAAAA40/THv60ELNybw/HD-11_thumb%25255B1%25255D.png?imgmax=800" width="554" height="462" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Teddy選擇了第二個選項，不過寫到這邊才發現好像應該要選第一個選項…XD。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-s-TcAcl6w4c/TyD03OFoA5I/AAAAAAAAA48/BK2WjOw6FXg/s1600-h/HD-13%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-13" border="0" alt="HD-13" src="http://lh4.ggpht.com/-5eZIyx22_7o/TyD04diaEgI/AAAAAAAAA5E/O6lROE-cUA4/HD-13_thumb%25255B1%25255D.png?imgmax=800" width="553" height="462" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;選擇第一個選項，建立新的磁碟群組。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-p4nHqdR-V4s/TyD05MJ3YBI/AAAAAAAAA5M/DzJ8yMa2tKo/s1600-h/HD-14%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-14" border="0" alt="HD-14" src="http://lh3.ggpht.com/-dhqGOHFLqrs/TyD06QH5naI/AAAAAAAAA5U/ZQh6s7fFAKI/HD-14_thumb%25255B1%25255D.png?imgmax=800" width="565" height="474" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;選擇硬碟。由於Teddy只有disk 1與disk 2要做RAID 1，所以就選擇前兩部硬碟就好了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-SXsiRIdq5iQ/TyD07vz15cI/AAAAAAAAA5c/3_JfALkagTU/s1600-h/HD-15%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-15" border="0" alt="HD-15" src="http://lh6.ggpht.com/-PP2O28DktqY/TyD081me7SI/AAAAAAAAA5k/5CkWHhZRJwI/HD-15_thumb%25255B2%25255D.png?imgmax=800" width="568" height="475" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;選擇RAID 1。看到這個畫面Teddy就有一個疑問，如果只有兩台硬碟，那麼選擇SHR和RAID 1會有什麼不同呢 ？還沒有時間去網路上爬文，不過總是覺得如果SHR是Synology所提供的特異功能，也許在安裝與設定畫面上應該要想辦法表現出到底哪裡和傳統的RAID有何不同之處。附帶一提，如果只是要單純使用單一台硬碟，那麼在這一個步驟選擇Basic選項就可以了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-Cbz3iMAGjKI/TyD09wiiPRI/AAAAAAAAA5s/CI7dDtgUhQg/s1600-h/HD-16%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-16" border="0" alt="HD-16" src="http://lh6.ggpht.com/-KgEhrJJ_wmE/TyD0_ErBOZI/AAAAAAAAA50/toyzwsx2Y3M/HD-16_thumb%25255B1%25255D.png?imgmax=800" width="573" height="478" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;是否進行硬碟檢查，預設是要檢查。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-RWkY8J5bHDk/TyD1AGZAsCI/AAAAAAAAA58/tXRfZjNCcnY/s1600-h/HD-17%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-17" border="0" alt="HD-17" src="http://lh3.ggpht.com/-Sx35bfsoGRU/TyD1BRFRgMI/AAAAAAAAA6E/l6iSzbMNCyo/HD-17_thumb%25255B1%25255D.png?imgmax=800" width="586" height="489" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;設定儲存空間配置容量。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-9tuLXzgigOE/TyD1CEMfUcI/AAAAAAAAA6M/bfLLtQnwo1U/s1600-h/HD-18%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-18" border="0" alt="HD-18" src="http://lh6.ggpht.com/-xiGNqDH0jdY/TyD1DLyNVVI/AAAAAAAAA6U/2IhfAnkiYCU/HD-18_thumb%25255B2%25255D.png?imgmax=800" width="593" height="495" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;再次確定剛剛所有設定值，按下套用之後就會開始建立儲存空間。請注意建立儲存空間之後原本硬碟中的資料會消失。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-Ijbheodow7A/TyD1EHsdl5I/AAAAAAAAA6c/F21-uKjpvpA/s1600-h/HD-19%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-19" border="0" alt="HD-19" src="http://lh6.ggpht.com/-buRNR2Qqdho/TyD1FkUj5OI/AAAAAAAAA6k/VDxCHIbxs_k/HD-19_thumb%25255B2%25255D.png?imgmax=800" width="604" height="501" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;開始非常，非常漫長的等待，兩顆3TB硬碟作RAID 1足足等了10個小時。不知道如果不要檢查硬碟的話是不是速度會快一點 ？&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-9vlMwS5ks9c/TyD1Gou_ueI/AAAAAAAAA6s/ea35iW9CCpg/s1600-h/HD-20%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-20" border="0" alt="HD-20" src="http://lh5.ggpht.com/-O5WHZuOF5IQ/TyD1HWgLqbI/AAAAAAAAA60/fEXMeV1GSYk/HD-20_thumb%25255B1%25255D.png?imgmax=800" width="608" height="291" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Teddy最後設定完成三個儲存空間的畫面，儲存空間1是RAID 1，儲存空間2和3是Basic。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-RvUSSa9c6JI/TyD1IT3QuSI/AAAAAAAAA68/Btzqv0-ISsI/s1600-h/HD-21%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-21" border="0" alt="HD-21" src="http://lh6.ggpht.com/-ployvnhGEfU/TyD1JSOMDkI/AAAAAAAAA7E/itxzYcU89I8/HD-21_thumb%25255B1%25255D.png?imgmax=800" width="634" height="301" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;設定儲存空間有一點像是「格式化硬碟」的感覺，還需要新增「共用資料夾」才可以透過網路從別台電腦來存取DS411上面的資料。設定共享資料夾的方法容後再稟。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-RFAMwYd4iAI/TyD1Lp4rR7I/AAAAAAAAA7M/hzTvlVGKH-g/s1600-h/HD-22%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="HD-22" border="0" alt="HD-22" src="http://lh3.ggpht.com/-hWPjMwaJ8s4/TyD1M_Iv28I/AAAAAAAAA7U/D-I7s45oouw/HD-22_thumb%25255B3%25255D.png?imgmax=800" width="677" height="510" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;看到者邊不知道鄉民們是否會有一個疑問：為什麼不全部作RAID 1或是用SHR就好了，這樣不是簡單多了嗎。因為Teddy比較膽小，之前曾經聽江湖傳言說有作成RAID X的硬碟因為電腦上面RAID controller壞掉導致硬碟上面的資料無法讀取。也許這樣的機率很低，或是只要把硬碟搬到另一台相同硬體的電腦就可以讀取了，但是萬一發生了總是很麻煩。而且做成RAID 1之後可用空間就只剩下一半，所以Teddy拿了兩台硬碟作RAID 1，把最重要的資料，例如相片，文件等放到RAID 1上面，其他比較不重要的資料，例如用電視卡錄下來的電視節目，網路上抓下來的Linux軟體ISO檔等，就放在一般儲存空間就好了。&lt;/p&gt;  &lt;p&gt;然後，重點來了，這些放在DS411上面的所有資料，都會用軟體再複製一份到 &lt;strike&gt;雲端&lt;/strike&gt; Teddy的桌機中，這樣子一來應該算是很保險了（不要叫Teddy做什麼異地備援啊...）。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：不知道DS411的RAID是有硬體支援還是透過軟體模擬的 ？&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-8537268404831028718?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/8537268404831028718/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=8537268404831028718' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8537268404831028718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8537268404831028718'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/2synology-ds411.html' title='動手整理資料（2）：Synology DS411 儲存空間設定'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-BghXjX41C7Q/TyDlKzEr4aI/AAAAAAAAA2U/e3-6aMaVE8o/s72-c/HD-01_thumb%25255B3%25255D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-8910965922366554988</id><published>2012-01-27T00:29:00.001+08:00</published><updated>2012-01-27T00:31:41.358+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體設計'/><title type='text'>什麼是物件導向（3）：Polymorphism</title><content type='html'>&lt;p&gt;January 26 23:01~January 27 00:23&lt;/p&gt;  &lt;p&gt;Polymorphism，中文翻譯成「多形」，說真的這個概念當年Teddy學OO的時候搞了好久才弄懂，後來看了「課本」的定義之後，覺得寫得還滿好的，請參考Object-Oriented Software Engineering: A&amp;#160; Use Case Driven Approach第55頁：&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;Polymorphism means that the sender of a stimulus does not need to know the receiving instance’s class. The receiving instance can belogin to an arbitrary class.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;再看一下55頁中另一段類似的解釋&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;If an instance sends a stimulus to another instance, but does not have to be aware of which class the receiving instance belongs to, we say that we have polymorphism.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;翻成白話文就是說：一個訊息（message or event or stimulus）的意義是由接收者（接收到這個訊息的物件）來解釋，而不是由訊息發出者（sender）來解釋。所以，在runtime時只要接受者換成不同的物件或是instance，系統的行為就會改變。具有這樣的特性就稱之為polymorphism。還是不懂，對，很正常。不過在看一個活生生的例子鄉民們就應該懂了。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;Teddy（sender，等一下準備送出信息的物件）走在路上看到前方有兩位名人，分別是「林志玲」與「阿美姐」（等一下準備接收訊息的兩個物件），於是大喊一聲「美女請留步（訊息）」。理論上Teddy期待只有「林志玲」會「回頭」（訊息接收者的行為），沒想到「阿美姐」也回頭了...XD。所以說，一個訊息的解釋是由接收者來決定的，而不是送出者。如果一個系統具有這樣的特性，那麼我們就說這個系統具備多型的行為。&lt;/p&gt;  &lt;p&gt;舉個程式的例子：&lt;/p&gt;  &lt;p&gt;List&amp;lt;String&amp;gt; list = new LinkedList&amp;lt;String&amp;gt;();&lt;/p&gt;  &lt;p&gt;list.add(“This is a book”);&lt;/p&gt;  &lt;p&gt;從上面這一行程式來看，我們可以說寫程式的人送了一個add這個訊息給list這個instance。從靜態程式碼來看，鄉民們一定知道list.add(“This is a book”)的行為，但是如果list這個instance不是像上面程式一樣寫死new LinkedList&amp;lt;String&amp;gt;();，而是runtime時傳入的任意符合List介面的某個instance，那麼程式的行為就無法只從靜態的程式碼得知了，而且add(“This is a book”);訊息的解釋也只能看runtime時list instance指到哪一個instance而定。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;一般常用的靜態型別程式語言例如Java、C#，要做到polymorphism必須透過繼承，不管是implementation inheritance或是interface inheritance。有些動態型別程式語言，如果Teddy沒記錯的話像是Smalltalk（如果有錯請留言或來信幫忙更正），可以不需要靠繼承來達到polymorphism，但是在runtime如果接收者沒有支援某個訊息的話，則是會出現runtime errors。&lt;/p&gt;  &lt;p&gt;總之，其實Teddy想講的重點是，這些老外厲害的地方，就是可以用很簡短的句子寫出某些觀念或是名詞的定義。因為除非真正了解所要描述的觀念或是名詞，否則是無法寫出這樣的定義出來。當年Teddy背下這個定義（因為考試會考啊…Orz）到現在都還依稀記得。什麼，你問Teddy記下這些定義有何用 ？Teddy也說不上來，也許哪一天鄉民們去面試不小心考了polymorphism這一題，而鄉民們恰巧看到這篇文章所以把書中的定義給寫了出來，但是主考者可能看不懂...Orz。不過這都不是重點，就以&lt;font color="#0000ff"&gt;「純欣賞」&lt;/font&gt;的角度為能夠寫出這麼精簡定義的作者們拍拍手就好了...XD。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：這幾天好冷，寫到手都凍僵了。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-8910965922366554988?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/8910965922366554988/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=8910965922366554988' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8910965922366554988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8910965922366554988'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/3polymorphism.html' title='什麼是物件導向（3）：Polymorphism'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-3870987405368889710</id><published>2012-01-26T06:00:00.000+08:00</published><updated>2012-01-28T08:59:02.590+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='生活'/><title type='text'>好用的UHU萬用黏土（2）：照片牆篇</title><content type='html'>&lt;p&gt;January 23 23:01~23:58&lt;/p&gt;  &lt;p&gt;前一篇提到萬用黏土的止漏用途，今天介紹一下最近幾天Kay發現的新用途，拿來把照片框固定在牆上。&lt;/p&gt;  &lt;p&gt;話說又是幾年前在好友的辦公室中看到好友將他到世界各國旅遊的照各洗了一張，然後訂做一些相框把照片掛滿整面牆，整個感覺非常好。於是Teddy和Kay也想有樣學樣一下，但是想歸想，由於Teddy太懶於是這件工作就落在Kay身上。基本上這個「story」可以細分為五個「tasks」：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;挑選要洗出來的照片 &lt;/li&gt;    &lt;li&gt;洗照片 &lt;/li&gt;    &lt;li&gt;買相框 &lt;/li&gt;    &lt;li&gt;把照片放到相框中並決定相框放到牆上的位置 &lt;/li&gt;    &lt;li&gt;把相框度定在牆上 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;為了省錢（其實是偷懶）於是相框就直接買IKEA現成的，Kay花了很多時間在選照片，然後拿去Costco印（比較便宜不過感覺印出來的照片顏色有點說不上來的奇怪）。最後只剩下一個問題，要怎麼把相框固定在水泥牆上啊 ？不想要用釘子，如果買3M的無痕掛勾又不好看，沒想到最後Kay居然想到可以用萬用黏土來固定相框。先看一下sprint demo…啊，不對，是最後的成品（請忽略照片右方很雜亂的吧檯桌面，沒時間隱藏了）。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-1ElAvitnkaU/Tx2F7b4YFHI/AAAAAAAAA0c/sPE6ndIMu5M/s1600-h/UHU-A%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="UHU-A" border="0" alt="UHU-A" src="http://lh3.ggpht.com/-7IRHGoL_87U/Tx2F9wnCYlI/AAAAAAAAA0k/tqVTkWY8ozI/UHU-A_thumb%25255B2%25255D.png?imgmax=800" width="614" height="284" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;耶，說好的「照片牆」怎麼只有這一小塊啊？要怪只能怪Teddy和Kay去的國家不夠多，不過這不是重點啦，我們是套用agile的incremental growth精神，先試作一小片照片牆，留點以後擴充的空間。Teddy可以肯定的說，這種設計應該是有符合open-closed principle：加新 &lt;strike&gt;功能&lt;/strike&gt; 照片的時候應該不需要移動舊照片的位置吧。如果真的要動到舊照片，只能說是為了套用refactoring...XD。&lt;/p&gt;  &lt;p&gt;言歸正傳，接下來說明一下如何利用萬用黏土把照片黏到牆上，首先準備海綿寶寶若干隻，不對，是萬用黏土若干小塊。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-PmaX0Q7aXZ0/Tx2GAUM_oDI/AAAAAAAAA0s/S8b4Pu9-l6E/s1600-h/HUH-B%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="HUH-B" border="0" alt="HUH-B" src="http://lh3.ggpht.com/-mAazuJk_A2E/Tx2GBsi3T2I/AAAAAAAAA00/u03aPi_hb-w/HUH-B_thumb%25255B1%25255D.png?imgmax=800" width="231" height="328" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;然後用手把這些萬用黏土&lt;font color="#0000ff"&gt;反覆揉捏&lt;/font&gt;，依據產品使用說明，反覆揉捏可以增強黏土延展性使黏著效果更佳。揉捏完畢之後把黏土黏到相框背面，如下圖所示。請注意，原本Teddy只黏了上下左右四個角落，隔夜起床之後發現相框抵抗不了地心引力的誘惑有點向下沉淪的現象，所以還是建議鄉民們依據相框的大小酌量增加黏土的分量。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-T9lavqg35xU/Tx2GFWty5jI/AAAAAAAAA08/HU9QN3Biowo/s1600-h/UHU-C%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="UHU-C" border="0" alt="UHU-C" src="http://lh6.ggpht.com/-xSt23DXDHWM/Tx2GGnQaqNI/AAAAAAAAA1E/Dw1qtw1pxOk/UHU-C_thumb%25255B1%25255D.png?imgmax=800" width="237" height="268" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;然後把相框貼到牆上，用力在相框四周敲打一下使相框可以透過萬用黏土固定在牆面上（下面這張照片由於個資法的關係未經由本人同意只好打上「馬賽克」）。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-tzTNdtmGCkY/Tx2GKcgGHGI/AAAAAAAAA1M/RgHFkerfFJM/s1600-h/UHU-D%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="UHU-D" border="0" alt="UHU-D" src="http://lh6.ggpht.com/-G0EK9SxNhPs/Tx2GL8-xiiI/AAAAAAAAA1U/fOXsx3p1efI/UHU-D_thumb%25255B1%25255D.png?imgmax=800" width="240" height="278" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;下圖是地心引力大於萬用黏土黏著力的證明。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-xdQLU45yPhk/Tx2GPBWMTFI/AAAAAAAAA1c/zwyAnTTQSvY/s1600-h/UHU-E%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="UHU-E" border="0" alt="UHU-E" src="http://lh3.ggpht.com/-A-sksrhUGEA/Tx2GQMUlgnI/AAAAAAAAA1k/vzxlULaDHIw/UHU-E_thumb%25255B1%25255D.png?imgmax=800" width="361" height="126" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;如果想取下照片框也是很容易的，稍微用力就像是在拔蘿蔔一樣就可以拔起來了。請參考下圖，照片框拔起來之後萬用黏土可能會黏在牆上，用手可以輕易的把萬用黏土清除，基本上不會留下什麼痕跡。照片中牆上的刮痕是Teddy前一陣子不小心刮到的，與萬用黏土無關，特此聲明...XD。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-wFkOcBg0_kE/Tx2GU5Kq4kI/AAAAAAAAA1s/UdhuRf-nUks/s1600-h/UHU-F%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="UHU-F" border="0" alt="UHU-F" src="http://lh3.ggpht.com/-w10U_gq6c48/Tx2GWSaEZDI/AAAAAAAAA10/QrNyZAYevJE/UHU-F_thumb%25255B1%25255D.png?imgmax=800" width="361" height="214" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;下圖是移除萬用黏土之後的牆面。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-8Bwt8-ezsTw/Tx2GalQKHOI/AAAAAAAAA18/_RbLkTUCBpo/s1600-h/UHU-G%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="UHU-G" border="0" alt="UHU-G" src="http://lh4.ggpht.com/-pssU_v6BK5Y/Tx2GcHhy8_I/AAAAAAAAA2E/cK2-WyWmj-w/UHU-G_thumb%25255B1%25255D.png?imgmax=800" width="354" height="208" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;&amp;#160;&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;雖然照片是固定不動的，但整個過程不知道為什麼有種在施作task board的感覺...Orz。&lt;/p&gt;  &lt;p align="center"&gt;&amp;#160;&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：大過年的寫點別的，總不能每天都在練（軟）功吧。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-3870987405368889710?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/3870987405368889710/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=3870987405368889710' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/3870987405368889710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/3870987405368889710'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/uhu2.html' title='好用的UHU萬用黏土（2）：照片牆篇'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-7IRHGoL_87U/Tx2F9wnCYlI/AAAAAAAAA0k/tqVTkWY8ozI/s72-c/UHU-A_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-1117423627752769753</id><published>2012-01-25T06:00:00.000+08:00</published><updated>2012-01-25T06:00:04.234+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='生活'/><title type='text'>好用的UHU萬用黏土（1）：止水篇</title><content type='html'>&lt;p&gt;January 23 21:46~22:38&lt;/p&gt;  &lt;p&gt;幾年前Teddy還在念書的時候有一陣子很喜歡買文具，有一次在學校的文具店看到一種德國製的「 UHU萬用黏土」，看了一下產品背面的介紹：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;產品特點：可隨意黏貼於任何場所，防震，防水，防風吹。可重複使用，黏性不變。 &lt;/li&gt;    &lt;li&gt;主要用途：黏貼海報圖畫或輕巧事務；固定物品位置如電話、電線；填補裂縫、窗緣；黏起灰塵或衣物之毛屑。 &lt;/li&gt;    &lt;li&gt;使用方法：黏貼兩面必須乾淨無油汙，依黏著面積取適量黏土，同時柔捏多次後，再黏貼施壓至物品黏牢為止。 &lt;/li&gt;    &lt;li&gt;售價：68元新台幣。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;說真的這個東西Teddy當年一看到就覺得真的太神奇了，「&lt;font color="#0000ff"&gt;防震，防水，防風吹。可重複使用，黏性不變&lt;/font&gt;」這種東西要去哪裡找啊。當時雖然沒有立即的需要，還是買了一個帶回家「保存」。目前手邊只剩下一點點還沒用完的萬用黏土，拍張照片給鄉民們參考一下。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-C37S-NESPVg/Tx11--tehJI/AAAAAAAAAzs/QPnQY__Ulps/s1600-h/UHU-1%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="UHU-1" border="0" alt="UHU-1" src="http://lh4.ggpht.com/-BEiJjPiLEMU/Tx12AtA8leI/AAAAAAAAAz0/oSJD6lPTl2M/UHU-1_thumb%25255B2%25255D.png?imgmax=800" width="294" height="334" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;買回家之後一直沒有機會拿出來使用，一直到大概1-2年前，家中浴室洗臉台下方的排水管接頭漏水，於是賢慧的Teddy拿了防水膠帶繞了排水管接頭幾圈試圖想止水。雖然漏水的現象有改善但是光靠防水膠帶無法很緊密的把漏水給全部止住，此時Teddy想起以前賣的萬用黏土，正所謂養兵千日，用兵一時，趕快拿出來止漏。沒想到效果非常的好，經過了這麼久的時間排水管漏水的問題都沒有再發生過。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-AvWVE3GwxNw/Tx12Fly99EI/AAAAAAAAAz8/xk2OZ_XQNjg/s1600-h/HUH-2%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="HUH-2" border="0" alt="HUH-2" src="http://lh6.ggpht.com/-ygLwDTkiWrI/Tx12Hp3ma7I/AAAAAAAAA0E/gWxb5zU9RAE/HUH-2_thumb%25255B3%25255D.png?imgmax=800" width="377" height="331" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;排水管接頭處已經用黑色的防水膠帶包覆起來&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-Klvmzg-hKkI/Tx12NAFuniI/AAAAAAAAA0M/sd9nqwWJdcE/s1600-h/HUH-3%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="HUH-3" border="0" alt="HUH-3" src="http://lh3.ggpht.com/-Vou6fu1Q_sY/Tx12Oi5fYdI/AAAAAAAAA0U/lgDf_GtulaE/HUH-3_thumb%25255B3%25255D.png?imgmax=800" width="396" height="231" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;近看可以看到一圈黃色的萬用黏土&lt;/p&gt;  &lt;p align="center"&gt;&amp;#160;&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;以上用來修補排水管接頭漏水的小技巧提供給鄉民們參考一下。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：不知道為什麼現在看這個萬用黏土腦中就會浮出海綿寶寶的畫面...XD。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-1117423627752769753?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/1117423627752769753/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=1117423627752769753' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1117423627752769753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1117423627752769753'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/uhu1.html' title='好用的UHU萬用黏土（1）：止水篇'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/-BEiJjPiLEMU/Tx12AtA8leI/AAAAAAAAAz0/oSJD6lPTl2M/s72-c/UHU-1_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-1741448665930439985</id><published>2012-01-24T06:00:00.000+08:00</published><updated>2012-01-24T16:17:26.005+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='生活'/><title type='text'>動手整理資料（1）：Synology DS411 開箱</title><content type='html'>&lt;p&gt;January 23 16:26~18:36&lt;/p&gt;  &lt;p&gt;過年前幾乎家家戶戶都要大掃除，打掃「真實世界」的住家雖然辛苦但是卻只要願意出賣勞力一般來講都可以有不錯的成果。但是說起要打掃「虛擬世界」的住家，也就是電腦中的資料，那可就不是光靠付出勞力就可以搞定的。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;數位化的資料越來越多，資料備份的問題也越來越令人頭大。早些年只要買個2.5吋的USB外接硬碟，然後利用類似SyncFree或是SecondCopy這種軟體將本機硬碟的資料與外接硬碟同步也就很好用了。但是隨著數位相機與智慧型手機的普及，隨便拍出來的高畫質影像（720p or 1080p）大小都是以GB起跳。數位照片的數量也越來越多，反正不管看到什麼先拍下來再說啦（這是一種爆料心態嗎？），不喜歡再刪掉就好了。所以，除了大容量資料備份以外，還要考慮到資料分享的方便性。&lt;/p&gt;  &lt;p&gt;Teddy家裡有一台電腦二十四小時都不關機，專門拿來當mail server與檔案伺服器之用（Teddy內心獨白：沒事幹嘛自己搞一台mail server…Orz）。由於這台電腦只是一台用了應該超過四年的普通PC，當然不可能有什麼RAID硬體支援。Teddy會定期將這台電腦上面的資料備份至另一台Ubuntu桌機，這樣至少就有兩份資料，不用怕哪一天突然硬碟壞掉造成資料遺失。但是，隨著「多媒體資料」越來越多，檔案伺服器的硬碟已經不夠放了（已經升級過幾次硬碟），因此有些資料便被Teddy搬移到硬碟空間比較大的Ubuntu電腦中。&lt;/p&gt;  &lt;p&gt;這樣做之後原本也相安無事，但是日子一久，Teddy開始搞不清楚到底哪裡的資料是最新的，那些資料備份了沒有，以及備份到哪裡去了（迷之音：學弟，SyncFree修好沒啊）。&lt;/p&gt;  &lt;p&gt;原本Teddy是很不願意花錢買一台專屬的NAS（Network-attached storage）來當作檔案伺服器，為什麼 ？因為一台4Bay（可以接四台硬碟）的NAS不包含硬碟最便宜的也都要一萬元起跳，有的甚至要超過二萬，那為什麼不去Px Home買一台9999的一般電腦回來，還可以接6個SATA硬碟不是更划算。但是後來想一想現在雲端儲存與個人雲端儲存越來越流行，Teddy個人電腦都不知道換過幾台了但卻沒買用家用NAS，所以就冒著生命危險狠下心來上禮拜五下午在Px Home上面買了Synology DS411外加三顆3TB硬碟（這個產品組合比分開買DS411與硬碟要便宜個幾百塊）當作自己的新年禮物。&lt;/p&gt;  &lt;p&gt;Synology DS411的主要規格:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;CPU：1.6 GHz（不知道是哪家公司的，好像是ARM的CPU不過Teddy不確定） &lt;/li&gt;    &lt;li&gt;記憶體：DDR3 512MB &lt;/li&gt;    &lt;li&gt;硬碟：四台3.5吋或2.5吋SATA II &lt;/li&gt;    &lt;li&gt;網路：一個GB乙太網路 &lt;/li&gt;    &lt;li&gt;最大儲存容量：12TB（四顆3TB硬碟） &lt;/li&gt;    &lt;li&gt;功耗：27.7W （運作中），13.2W（硬碟休眠） &lt;/li&gt;    &lt;li&gt;重量：2.23 KG（應該是不含硬碟的重量吧） &lt;/li&gt;    &lt;li&gt;支援下載協定：BT/eMule/HTTP/FTP/NZB &lt;/li&gt; &lt;/ul&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;下定之後隔天下午一點多左右拿到包裹，打開之後看到一台Synology DS411和三顆WD綠標的3TB硬碟，至於價錢就...&lt;font color="#0000ff"&gt;莫再提&lt;/font&gt;，想知道的鄉民們自己上Px Home上面找吧…XD。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-vOOYRr6k-po/Tx08Lz1JbJI/AAAAAAAAAv8/fYCTQcmvOz4/s1600-h/DS411-1%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-1" border="0" alt="DS411-1" src="http://lh6.ggpht.com/-RfbwE1C2InE/Tx08NgVqJkI/AAAAAAAAAwE/YSG3EziDH94/DS411-1_thumb%25255B2%25255D.png?imgmax=800" width="387" height="227" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;先把DS411的箱子打開，上面有一張DSM 4.0 beta的廣告傳單，可惜活動已經辦完了，無緣參加。不過Teddy的學弟有去參加這個活動，有興趣的鄉民們可以參考「&lt;a href="http://dbi1463.pixnet.net/blog/post/27747245" target="_blank"&gt;這裡&lt;/a&gt;」。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-EgzqPBmSqmQ/Tx08S3u46fI/AAAAAAAAAwM/qhWQGjS0rZA/s1600-h/DS411-2%25255B5%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-2" border="0" alt="DS411-2" src="http://lh5.ggpht.com/-D6Ks8MAQ4E0/Tx08U2eEAKI/AAAAAAAAAwU/qE3CpU7WnD8/DS411-2_thumb%25255B3%25255D.png?imgmax=800" width="380" height="338" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;箱子打開之後看到主機一台，電源線一條，另外還很貼心的附上很多螺絲以及一條網路線。有附網路線這一點依該要先給它拍拍手，雖然一條網路線沒多少錢，但是如果等你東西都裝好之後才發現少了一條網路線，那就很傷腦筋了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-Hcpi3tLt7Do/Tx08bV00x_I/AAAAAAAAAwc/UyC3flDsY3s/s1600-h/DS411-3%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-3" border="0" alt="DS411-3" src="http://lh5.ggpht.com/-Q5LPDBm_noU/Tx08dUcuasI/AAAAAAAAAwk/4YQ8sUgwHFU/DS411-3_thumb%25255B1%25255D.png?imgmax=800" width="446" height="232" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;主機的正面，有一個塑膠保護套開機之前記得拿下來。這台主機的機身是沒有通風口的，所以應該是靠前方進風口與後方的兩個風扇來散熱。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-FIxUuPidnLk/Tx08knoYSaI/AAAAAAAAAws/zb-pYwNsW0o/s1600-h/DS411-4%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-4" border="0" alt="DS411-4" src="http://lh6.ggpht.com/-3VSJ5bEuNNw/Tx08m54dmaI/AAAAAAAAAw0/8zRsDptoFK0/DS411-4_thumb%25255B1%25255D.png?imgmax=800" width="282" height="307" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;機身後方可以看到兩個風扇，一個1GB乙太網路孔，兩個USB 2.0與一個e-SATA。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-e1RxirGt5pU/Tx08sa3sa4I/AAAAAAAAAw8/nfbuqCy3DOg/s1600-h/DS411-5%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-5" border="0" alt="DS411-5" src="http://lh6.ggpht.com/-45I5iVYuqwY/Tx08tnnar0I/AAAAAAAAAxE/OMiIbSv2iGs/DS411-5_thumb%25255B1%25255D.png?imgmax=800" width="282" height="293" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;用手扭開機身背面四個角落的螺絲資後的照片，可以看到有四個硬碟插槽。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-yIs3w73J78U/Tx08xl2mXiI/AAAAAAAAAxM/N1shXP2KeYg/s1600-h/DS411-6%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-6" border="0" alt="DS411-6" src="http://lh5.ggpht.com/-Ziwycj1-gtE/Tx08zEenzGI/AAAAAAAAAxU/9kykV9HOjM8/DS411-6_thumb%25255B1%25255D.png?imgmax=800" width="282" height="298" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;把機殼也拆開可以隱約看到主機板放在最下方。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-msFbDKDd5vc/Tx084VicxnI/AAAAAAAAAxc/HhK6w0pK-fw/s1600-h/DS411-7%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-7" border="0" alt="DS411-7" src="http://lh6.ggpht.com/-WLqeyngrUzA/Tx086NksbbI/AAAAAAAAAxk/rrBNXpC2aYA/DS411-7_thumb%25255B1%25255D.png?imgmax=800" width="345" height="311" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;安裝硬碟時必須把硬碟架抽出來，這個硬碟架是塑膠材質的，感覺有點省成本的嫌疑。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-oEjmfUGa3sw/Tx08-7eAR6I/AAAAAAAAAxs/rDDdb8ich80/s1600-h/DS411-8%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-8" border="0" alt="DS411-8" src="http://lh6.ggpht.com/-XvOWo8d_CHs/Tx09ABbI0VI/AAAAAAAAAx0/7IrQ9dAu6Ik/DS411-8_thumb%25255B1%25255D.png?imgmax=800" width="246" height="279" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;WD 3.0 TB綠標硬碟，這應該是目前市面上最便宜的3.0TB硬碟了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-2GC1v5ytQls/Tx09GPrChGI/AAAAAAAAAx8/OLDe1JibfZU/s1600-h/DS411-9%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-9" border="0" alt="DS411-9" src="http://lh6.ggpht.com/-rb2Ik49x-hM/Tx09HumuJ_I/AAAAAAAAAyE/Jl1T-lo-F_Y/DS411-9_thumb%25255B1%25255D.png?imgmax=800" width="257" height="283" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;放進去之後雙邊都鎖上螺絲，這是整個安裝過程中唯一需要用到螺絲起子的步驟。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-4vM8dzSDzS4/Tx09LQC5taI/AAAAAAAAAyM/biS8Md6j1qU/s1600-h/DS411-10%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-10" border="0" alt="DS411-10" src="http://lh5.ggpht.com/-iwzpBvx5XtU/Tx09Mbc-bCI/AAAAAAAAAyU/ICpxdQlgcrU/DS411-10_thumb%25255B1%25255D.png?imgmax=800" width="306" height="121" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;產品中已經附了很多螺絲，直接拿出來鎖就好了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-amBXq1QfuvA/Tx09Q7UExQI/AAAAAAAAAyc/XlGyOq4xfOQ/s1600-h/DS411-11%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-11" border="0" alt="DS411-11" src="http://lh3.ggpht.com/-zHd-crNafU0/Tx09SvlnoDI/AAAAAAAAAyk/IoIgHCqTh6o/DS411-11_thumb%25255B1%25255D.png?imgmax=800" width="317" height="312" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;鎖好後翻過來背面長成這樣子。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-midCibg8I7w/Tx09XD6ms1I/AAAAAAAAAys/7ppEjWbKvjs/s1600-h/DS411-12%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-12" border="0" alt="DS411-12" src="http://lh4.ggpht.com/-jokpQYM4GrE/Tx09Yt5ovPI/AAAAAAAAAy0/JQ4lneorvmw/DS411-12_thumb%25255B1%25255D.png?imgmax=800" width="265" height="313" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;把硬碟鎖好之後輕輕往主機一推就完成硬碟安裝了。好像還有一顆螺絲可以把硬碟架和主機鎖在一起但是Teddy偷懶沒鎖。在安裝最下面那顆硬碟的時候由於會卡到風扇的電源線因此稍微比較不容易安裝，這一點要注意一下。另外，這四顆硬碟的編號應該是從上往下分別是Disk 1, 2, 3, 4，但是機殼背後卻沒有標號。要是萬一哪一天硬碟不小心壞掉，電腦軟體告訴你Disk 3壞掉了，你把機殼猜開後還不知道要拔哪一顆硬碟勒。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-jAMeMvrn3-U/Tx09c_4kn6I/AAAAAAAAAy8/7MAQKesoBmw/s1600-h/DS411-13%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-13" border="0" alt="DS411-13" src="http://lh6.ggpht.com/-6PE6WtRoFW8/Tx09efPvMeI/AAAAAAAAAzE/86BHT-cUoOk/DS411-13_thumb%25255B1%25255D.png?imgmax=800" width="252" height="333" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;最後插上電源開機，主機正面最左邊那一顆是Status的燈，Status旁邊那一顆是LAN。右邊那四顆是HDD1,2,3,4的燈。中間那個亮藍色光的按鈕是電源開關。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-Q1lMVlzygEw/Tx09iaGi2aI/AAAAAAAAAzM/SEdCnWWN57o/s1600-h/DS411-14%25255B3%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-14" border="0" alt="DS411-14" src="http://lh4.ggpht.com/-ObWcDD1swfs/Tx09jsM466I/AAAAAAAAAzQ/GeeeILa1SoU/DS411-14_thumb%25255B1%25255D.png?imgmax=800" width="335" height="313" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;機器裝好之後回頭一看地板，只能用「杯盤狼藉」來形容...Orz。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-MGTZ9gvZgfc/Tx09ppPEdBI/AAAAAAAAAzc/Ntx4vDDYOU0/s1600-h/DS411-15%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="DS411-15" border="0" alt="DS411-15" src="http://lh4.ggpht.com/-acVzgSHF0xM/Tx09rrwgTaI/AAAAAAAAAzk/HmlXg_j6eXg/DS411-15_thumb%25255B2%25255D.png?imgmax=800" width="422" height="253" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="center"&gt;&amp;#160;&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;硬體開箱與安裝到此結束，之後就用用軟體從遠端去設定DS411的硬碟模式（是否使用RAID）與分享目錄及帳號權限。今天先講到這裡，軟體設定等Teddy搞熟了之後再跟鄉民們報告。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：為了打掃虛擬世界花了快30張小朋友，這...過完年之後某人看到這台不知有何反應...XD。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-1741448665930439985?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/1741448665930439985/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=1741448665930439985' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1741448665930439985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1741448665930439985'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/1synology-ds411.html' title='動手整理資料（1）：Synology DS411 開箱'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/-RfbwE1C2InE/Tx08NgVqJkI/AAAAAAAAAwE/YSG3EziDH94/s72-c/DS411-1_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-2674922421890289197</id><published>2012-01-23T06:00:00.000+08:00</published><updated>2012-01-23T06:00:02.969+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體設計'/><title type='text'>什麼是物件導向（2）：Object, Class, Instance</title><content type='html'>&lt;p&gt;January 21 22:58~January 22 00:10&lt;/p&gt;  &lt;p&gt;鄉民們看到這篇的日子應該是大年初一，先跟大家說聲新年快樂。&lt;/p&gt;  &lt;p&gt;這次要介紹在物件導向技術中三個經常容易搞混的名詞，分別是object、class、instance。首先看一下Object-Oriented Software Engineering這本書對於這三個名詞的定義：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Object&lt;/strong&gt;：An object is characterized by a number of &lt;font color="#0000ff"&gt;operations&lt;/font&gt; and a &lt;font color="#0000ff"&gt;state&lt;/font&gt; which remembers the effect of these operations.（p.44）&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Class&lt;/strong&gt;：A class represents &lt;font color="#0000ff"&gt;a template&lt;/font&gt; for several objects and describes how these objects are structured internally. Objects of the same class have the same definition both for their operations and for their information structures.（p.50）&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Instance&lt;/strong&gt;：&lt;font color="#0000ff"&gt;An instanceis an object created from a class&lt;/font&gt;. The class describes the (behavior and information)structure of the instance, while the current state of the instance is defined by the operations performed on the instance.（p.50）&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;以下為上述定義翻成白話文再加上一點Teddy個人補充的資料：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Class是用來定義object的一種東西，class的內容包含了動作（operations）與資料（data）。&lt;/li&gt;    &lt;li&gt;動作（operations）、方法（methods）和行為（behaviors）可以看作同義詞。理想上一個object的狀態只能透過動作去改變它。&lt;/li&gt;    &lt;li&gt;一個object就是某個class的instance，換句話說可以把object和instance看作是同樣的東西。只是在某些場合大家比較習慣用object這個說法，其他場合則是會用instance。例如，&lt;/li&gt; &lt;/ul&gt;  &lt;blockquote&gt;   &lt;p&gt;List&amp;lt;String&amp;gt; a = new LinkedList&amp;lt;String&amp;gt;();&lt;/p&gt;    &lt;p&gt;List&amp;lt;String&amp;gt; b = new LinkedList&amp;lt;String&amp;gt;();&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;你可以說「a、b兩個ojbects各指到一個LinkedList類別的&lt;font color="#0000ff"&gt;instance&lt;/font&gt;」或是說「a、b兩個ojbects各指到一個 LinkedList類別的&lt;font color="#0000ff"&gt;object&lt;/font&gt;」，但是如果程式變成下面這樣：&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;a = b;&lt;/p&gt;    &lt;p&gt;那麼說成「a、b兩個ojbects都指到一個相同的LinkedList類別的&lt;font color="#0000ff"&gt;instance&lt;/font&gt;」，或是更簡單一點「a、b都指到同一個&lt;font color="#0000ff"&gt;instance&lt;/font&gt;」會比「a、b都指到同一個&lt;font color="#0000ff"&gt;object&lt;/font&gt;」意思要來的清楚一點。&lt;/p&gt; &lt;/blockquote&gt;  &lt;ul&gt;   &lt;li&gt;資料成員（data members）和屬性（attributes）是同義詞，都是用來儲存物件的狀態。如果一個class沒有任何資料成員，這個class所產生的所有objects看起來就會是一模一樣的東西。也就是說，可以把一個沒有狀態的class變成一個static class，不用產生任何instance就可以呼叫該class的operations。&lt;/li&gt;    &lt;li&gt;物件與物件之間的關係可以簡化成兩種：aggregation和association，請參考GoF Design Pattern, pp.22-23。&lt;/li&gt; &lt;/ul&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;看到這邊不知道鄉民們會不會有一個疑問：同樣的東西幹嘛搞出不同的說法啊？這就是「阿斗仔」厲害的地方啦。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：「九x共識」跟「一x各表」算是同義詞嗎？&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-2674922421890289197?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/2674922421890289197/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=2674922421890289197' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/2674922421890289197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/2674922421890289197'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/2object-class-instance.html' title='什麼是物件導向（2）：Object, Class, Instance'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-785718760581881274</id><published>2012-01-22T06:00:00.000+08:00</published><updated>2012-01-22T06:00:00.089+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體設計'/><title type='text'>什麼是物件導向（1）：簡介</title><content type='html'>&lt;p&gt;January 21 19:58~21:38&lt;/p&gt;  &lt;p&gt;談了好幾次軟體設計與軟體架構，Teddy今天突然想到好像一直假設鄉民們都很懂OO（Object-Orientation 物件導向）。不管這個假設是否成立，在兔年尾龍年初的時期就來幫鄉民們複習幾個基本的OO觀念吧。&lt;/p&gt;  &lt;p&gt;鄉民甲：應該是沒料可寫了吧。&lt;/p&gt;  &lt;p&gt;Teddy：這是新年特別節目啦。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;話說又是N年前的事情，當時Teddy還在念五專電子科，應該是專二還是專三的時候，當時C++很流行，由於Teddy當時已經學會了一點C的皮毛想說接著學C++應該也是「順理成章」的事情。沒想到雖然只是多了兩個「++」符號，兩個語言的差異還真大。原來C++只有在「程序導向（Procedure-Orientation 」和C語言差不多，但是對於學習C++所需的物件導向觀念Teddy則是完全不懂。&lt;/p&gt;  &lt;p&gt;在當年那個「&lt;strike&gt;反共抗俄&lt;/strike&gt; 資訊與物資匱乏 」的年代，Teddy可是花了不少冤枉錢買了一堆看完之後還是不知所云的書。請不要說：不是google一下就有答案了？別說google，那個年代WWW都還沒發明勒…XD。&lt;/p&gt;  &lt;p&gt;總之，重點是，後來好像是專四還是專五的時候，有一門忘了是什麼課，剛好有一位剛從國外拿到PhD的老師居然很好心的印了一份講義講了一點OO的觀念。請注意，Teddy五專念的可是電子科，當年能在這麼「硬」的科系學到這麼「軟」的觀念，現在想起來覺得那一學期的學費沒有白交了...XD。&lt;/p&gt;  &lt;p&gt;當初那份講義早就不知道消失到哪裡去了（應該已經重新投胎好幾次了），後來不曉得過了多久Teddy才發現原來那份講義就是&lt;font color="#0000ff"&gt;Object-Oriented Software Engineering: A Use Case Driven Approach&lt;/font&gt;（1992年出版）這本書的第三章。這一章一共有個小節：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;3.1 Introduction &lt;/li&gt;    &lt;li&gt;3.2 Object &lt;/li&gt;    &lt;li&gt;3.3 Class and instance &lt;/li&gt;    &lt;li&gt;3.4 Polymorphism &lt;/li&gt;    &lt;li&gt;3.5 Inheritance &lt;/li&gt;    &lt;li&gt;3.6 Summary &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;這次先整理幾點3.1 Introduction所提到的重點：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Object-orientation is a technique for &lt;font color="#0000ff"&gt;system modeling&lt;/font&gt;. Using OO, we model the system as a number of objects that interact. &lt;/li&gt;    &lt;li&gt;OO提供了兩點很重要的好處：Understanding與Modifications。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;換句話說，OO的目的是一種讓開發人員可以用來model（設計）軟體系統的技術。如何model？透過把系統視為由許多&lt;font color="#0000ff"&gt;彼此互動的物件&lt;/font&gt;所組成。使用OO技術所設計的系統可以提高可了解性與可修改性（這兩點都是non-functional requirements）。&lt;/p&gt;  &lt;p&gt;總之，如果要用一句話來形容，用以說：&lt;font color="#0000ff"&gt;OO是一種用來設計可了解性與可修改性系統的技術&lt;/font&gt;。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：這一篇要測試一下設定張貼日期的功能。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-785718760581881274?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/785718760581881274/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=785718760581881274' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/785718760581881274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/785718760581881274'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/1.html' title='什麼是物件導向（1）：簡介'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-5298325041599881896</id><published>2012-01-21T11:25:00.003+08:00</published><updated>2012-01-21T16:41:57.193+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（9）：Retrospective Meeting</title><content type='html'>&lt;p&gt;January 21 10:41~ 12:18&lt;/p&gt;  &lt;p&gt;在兔年年尾終於來到了Scrum最後一個活動Retrospective Meeting，還記得Scrum雙重回饋機制的那張圖嗎？Retrospective Meeting的目的就是要提供團隊一個反省與檢討「軟體開發流程」的機會，要如何反省與檢討呢？&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/-ru_5T_ehKlU/TxowQ4teyZI/AAAAAAAAAvs/avLqg_Tctlc/s1600-h/scrum-feedback%25255B5%25255D.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="scrum-feedback" border="0" alt="scrum-feedback" src="http://lh3.ggpht.com/-TlcC05r7Rhg/TxowRqIG8ZI/AAAAAAAAAvw/GCJVsQ3x1Ek/scrum-feedback_thumb%25255B3%25255D.jpg?imgmax=800" width="244" height="118" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Teddy的作法是將會議切成兩個階段：&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;感謝&lt;/strong&gt;：第一個階段是請每一個團隊成員輪流表達對於其他團隊成員的謝意，詳細進行方式請參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/05/retrospective-meeting.html" target="_blank"&gt;Retrospective Meeting 之我謝謝你&lt;/a&gt;」。 Teddy個人覺得這個活動的正面力量非常強大，可以讓團隊成員養成一種互相幫忙的風氣，強烈推薦Scrum團隊採用。有一點要補充說明一下，基本上感謝的範圍與對象是在這個sprint中幫助自己的同一個團隊成員（跟你一起開retrospective meeting的人），但是有時候團隊成員會「出軌」感謝其他部門的人，這也是OK。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Good and Improvement&lt;/strong&gt;：第二個階段是要列出這個sprint中關於開發流程上，哪些做法是好的要繼續維持，那些地方是有待改善的，以及討論出下個sprint的改善項目；活動進行方式請參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2009/11/retrospective-meeting.html" target="_blank"&gt;Retrospective Meeting = 許願池&lt;/a&gt;」。 &lt;/li&gt; &lt;/ul&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;最近一次Teddy去參加ezScrum講座的時候有一位朋友問Teddy一個問題：&lt;font color="#0000ff"&gt;「你們團隊實施了三年多Scrum，難道不會遇到retrospective meeting的時候發現沒有事情需要改善的困境嗎？」&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000000"&gt;這個問題問得很好，在軟體開發上可以改善的事情實在太多了，如果遇到不知道要改善什麼的時候很可能是Scrum Master沒有用心觀察團隊開發活動或是團隊成員太忙（通常是瞎忙）以至於腦袋空空想不出有什麼可以改善的。可從下列項目來思考改善的方向：&lt;/font&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;基礎practices達成度&lt;/strong&gt;：團隊目前對於基本agile practices的功力練到了第幾級，是否還有更上一層樓的空間。例如，自動化單元測試的line coverage達到多少百分比了？如果有寫自動化單元測試但是不知道line coverage多少那麼可以先從在持續整合系統加上test coverage工具開始改善起。假設已經有test coverage但是line coverage只達到50%那麼可以把改善目標訂成「將line coverage提升至52%」。如果line coverage以及到達很高的水準，可以考慮提升branch coverage或是其他各式各樣的code coverage。如果自動化單元測試已經做得很好了，那麼團隊有做自動化功能測試嗎？除了測試以外還有很多可以改善的基本practices，例如pair programming實施狀況、有沒有導入持續整合、有沒有做到ten-minute build等等。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;進階practices達成度&lt;/strong&gt;：進階practices顧名思義就是上乘的武功秘笈，看過武俠小說的鄉民們一定都知道上乘武功像是玉女心經、九陰真經、六脈神劍這一等級，練武的時候是很容易走火入魔的，除了練武者需要有一定的武功底子以外，最好能找一個清靜沒人打擾的地方專心修煉。當團隊默契與成員的功力到了一定程度之後，可以視狀況逐步修練這些上乘武功。這一類的招式有shared code、single code base、daily deployment (continuous delivery)、real customer involvement、incremental deployment等等。 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;消除浪費&lt;/strong&gt;：消除以下七種浪費可以當作改善的目標，包含&lt;a href="http://teddy-chen-tw.blogspot.com/2010/10/1partially-done-wrok.html" target="_blank"&gt;Partially Done Work (In-Process Inventory)&lt;/a&gt;、&lt;a href="http://teddy-chen-tw.blogspot.com/2010/10/2extra-features.html" target="_blank"&gt;Extra Features (Over-Production)&lt;/a&gt;、&lt;a href="http://teddy-chen-tw.blogspot.com/2010/10/3relearning.html" target="_blank"&gt;Relearning (Extra Processing)&lt;/a&gt;、&lt;a href="http://teddy-chen-tw.blogspot.com/2010/10/4handoffs.html" target="_blank"&gt;Handoffs (Transportation)&lt;/a&gt;、&lt;a href="http://teddy-chen-tw.blogspot.com/2010/10/5task-switching.html" target="_blank"&gt;Task Switching (Motion)&lt;/a&gt;、&lt;a href="http://teddy-chen-tw.blogspot.com/2010/10/6delays.html" target="_blank"&gt;Delays (Waiting)&lt;/a&gt;、Defects (Defects)。 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;想要了解有哪些值得一試的agile practics可以參考Extreme Programming Explained, 2nd這本書。至於如何消除浪費請參考Implementing Lean Software Development: From Concept to Cash。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p align="left"&gt;Retrospective Meeting是用來討論開發流程的議題，有時候團隊成員會把「產品改善」的意見與「流程改善」混為一談，當這種情況發生的時候Scrum Master要提醒團隊成員不要忘了Retrospective Meeting的目的，把焦點轉回到流程改善上面。&lt;/p&gt;  &lt;p align="center"&gt;***&lt;/p&gt;  &lt;p&gt;友藏內心獨白：這一篇是用Windows Live Writer寫的...Mac上面有沒有其他好用的寫部落格軟體啊？&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-5298325041599881896?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/5298325041599881896/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=5298325041599881896' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/5298325041599881896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/5298325041599881896'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/scrum-9retrospective-meeting.html' title='Scrum 是什麼（9）：Retrospective Meeting'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-TlcC05r7Rhg/TxowRqIG8ZI/AAAAAAAAAvw/GCJVsQ3x1Ek/s72-c/scrum-feedback_thumb%25255B3%25255D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-6895758274180020492</id><published>2012-01-20T11:51:00.000+08:00</published><updated>2012-01-20T11:51:12.890+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Single Code Base</title><content type='html'>&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 20 10:11~11:51&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;昨天傍晚收到出版社編輯的通知信，告訴 Teddy 出版社已經通過編輯小姐所提的&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;出書提案。雖然書本的內容還是需要加以增修，不過 Teddy 預估如果沒什麼意外的話今年內出版應該是沒問題了。想捧場買一本的鄉民們可以把小豬撲滿拿出來開始存錢了...大概一天存個3-5塊新臺幣也就夠了。或是考慮把年終獎金&lt;/span&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;、&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;尾牙抽到的獎金&lt;/span&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;、過年領到的紅包留個幾百塊下來，不要全部都「梭哈」在牌桌上...XD&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;話說 Teddy 昨天還在擔心無料可寫，想來想去還是回頭找「老朋友」，從以前看過的書中擠一些東西出來。今天來談一下 Kent Beck 所寫的 Extreme Programming Explained, 2nd 這本書第 67 頁所提到的 &lt;span style="color: blue;"&gt;Single Code Base&lt;/span&gt; 這個做法。還記得當年第一次看到&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Single Code Base&lt;/span&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;這個做法其實沒什麼特別的感覺，但是剛剛拿出來又看了一次之後，突然聯想到這個&lt;/span&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;做法回答了一個軟體開團隊發經常會遇到的問題：&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;不同的客戶，對於公司所開發的產品有不同的客制化需求&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;對於這個問題基本上有兩個解法：&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;One code base for one customer: 只要有一個新客戶的客制化需求，就把 source code 從原本的開發主幹中複製一份（或是產生一個分支）出來。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;Single code base: 不論有多少個客戶，多少種客制化需求，全部都放在一個單一的開發主幹中。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;第一種作法看起來比較簡單，在剛開始客戶還不多的時候問題也不大，反正就是把原本的 source code 複製一份，然後在加上客制化的功能，最後打包給客戶驗收過後就沒事了。就算事後出包也是交給所謂的「維護合約」以及倒霉的「維護人員」去處理。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;但是當客戶數量變多的時候，第一種作法就很有可能會產生很嚴重的「維護問題」。假設這個產品有 30 個客制化的版本，開發團隊某一天解決了一個在最原始那個版本中的 bug，請問這個 bug fix 要不要套用到其他 30 個&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;客制化版本上？&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;感覺起來好像也許可能應該似乎要套用，但是，這&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;30 個客制化的版本已經各自「演化」一段時日了，&lt;span style="color: blue;"&gt;要確定這個&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;bug fix&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&amp;nbsp;可以安全的套用到這&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span style="color: blue;"&gt;30 個客制化版本而不會產生新的 bugs 會是一件很花時間的工作&lt;/span&gt;。聰明的鄉民們可能會說：「不是有自動化測試案例可以用來驗證新的 bug fix 嗎？」套句賭神電影裡面的對白：「年輕人終究是&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;年輕人&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」，果然是涉世未深。這裡是哪裡？台灣耶，就算是只有單一個軟體版本都少有人在寫&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;自動化測試案例了&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;，誰在跟你寫&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;30 個客制化的版本的自動化&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;測試案例啊。想要知道血淋淋的慘案，請參考「&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;&lt;a href="http://teddy-chen-tw.blogspot.com/2010/05/600-bugs.html" target="_blank"&gt;600 多個 bugs 要怎麼修？&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」。&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;在課本第 68 頁，Kent Beck 叔叔告訴我們：&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;Rather than add more code bases, fix the underlying design problem that is preventing you from running from a single code base.&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;鄉民們可以&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;把不同客戶功能差異的部分移到設定檔中，設計軟體系統使其可以經由讀取設定檔的方式來產生不一樣的行為。接著修改&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;建構系統&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;（build system）讓它&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;可以從 single code base 裡面生出不同客戶所需要的客制化產品（安裝程式）。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;要達到 single code base 會是一件相當有挑戰性的工作，但是如果想要有效率的開發出高品質的軟體，那麼請問有那一件軟體開發的活動不是這樣呢？有一些剛開始看起來好像很簡單或是很省事的做法，其實反而是造成後續軟體持續開發困難的原因。例如，因為「專案&lt;strike&gt;太敢&lt;/strike&gt; 太趕」沒時間而省略不寫自動化測試，因為客制化要求而捨棄 single code base，因為沒人懂而不做持續整合，因為有人不爽而不做 pair programming 等等。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="background-color: #f6f6f6; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;友藏內心獨白：這一篇是在 MacBook Air 上用 Apple &amp;nbsp;的外接藍牙小鍵盤所完成的。Bye bye，Ubuntu...&lt;/span&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-6895758274180020492?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/6895758274180020492/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=6895758274180020492' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6895758274180020492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6895758274180020492'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/single-code-base.html' title='Single Code Base'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-2097271531949119973</id><published>2012-01-19T10:45:00.001+08:00</published><updated>2012-01-19T16:52:29.213+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（8）：Sprint Demo Meeting</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 19 09:40~10:42&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;也不知道是那根筋不對勁沒事訂定什麼「2012 年每天寫一篇部落格文章」的目標，現在想一想真的是頭殼壞去。前幾天赫然發現，農曆新年快到了耶，還是要寫（當初「許願&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;的時候怎麼沒把這點考慮進去啊...Orz）。到底能不能&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;撐過第一個月都還不知道，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;算了，撐一天算一天，反正最近瘦了2-3公斤，還有一點食言而肥的本錢...XD。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;剛剛想了老半天也擠不出什麼新東西出來，那今天就來談一下&amp;nbsp;Sprint Demo Meeting 好了。這個會議有兩種可能的開法：&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;正常版本&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;團隊中有專職的 Product Owner。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;在&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&amp;nbsp;Sprint Demo Meeting 時&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Product Owner&amp;nbsp;、Scrum Master、Developers 都必需要參加。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;其他閒雜人等如果想過來看戲也是可以，但是「理論上」這些圍觀的鄉民們是不能發言的。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;會議可由 Scrum Master 或是協調一位團隊成員主持。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;會議前一天 Scrum Master 要先 email 一份 Sprint demo (review) agenda 給與會人員，範例如下（或參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/scrum-3.html" target="_blank"&gt;Scrum 是什麼（3）：三種補充文件&lt;/a&gt;」）：&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-8EbueAI75Us/Txd5WLz5MCI/AAAAAAAAAvg/zsqKEQHEhSc/s1600/sprint-review-meeting.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/-8EbueAI75Us/Txd5WLz5MCI/AAAAAAAAAvg/zsqKEQHEhSc/s400/sprint-review-meeting.png" width="360" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;會議前一天負責 demo 的人要花點時間準備要 demo 的內容（不要為了 demo &amp;nbsp;花太多時間，最多最好不要超過 1-2 小時），&lt;span class="Apple-style-span" style="color: blue;"&gt;千萬不要沒準備就跑來 demo 然後當場才發現要 demo 的功能都不能動&lt;/span&gt;。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;會議開始時，Scrum Master 說明一下這個 sprint 的目標，然後依據會議議程逐一請相關人等 demo。例如：&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Scrum Master：「大家好，歡迎參加 E-Com 團隊第 5 個 sprint 的 demo。我們已經完成了這個 sprint 的目標 xxxx，現在開始 sprint demo 會議。第一個 story 是 yyy，我們先請 David 示範一下這個功能要如何使用」。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;David：...（開始 demo 這個功能）（在 demo 過程中，如果與會者有問題可以隨時發問）。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;David：（demo 結束）&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Scrum Master：各位關於這個功能還有沒有其他問題？如果沒有的話我們謝謝 David，接下來請 Tim demo 這個功能的測試結果。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Tim：....&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Scrum Master 要控制一下每一個 demo 項目所花的時間，並且要避免過於冗長的討論。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Product Owner 如果對於功能不滿意，或是有修正意見，可以當場反應給 Developers 了解。至於後續要如何修改的細節，則不需要在會議中討論。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;如果經費許可團隊可以準備一些零食給與會者享用，可以把 sprint demo 當成是一個小小的「驗收與慶功場合」...當然如果團隊要是連一個 story 都沒有完成那就另當別論了...XD。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;異常版本&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;/b&gt;&lt;br /&gt;&lt;ul style="font-weight: normal;"&gt;&lt;li style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;團隊中有&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Times New Roman'; font-size: 15px;"&gt;沒有&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;專職的 Product Owner（由其他團隊成員兼任），或是團隊在開發一個新產品，Product Owner 也正在摸索需求（翻成白話文就是 Product Owner 也還搞不太清楚狀況...Orz）&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;&lt;b&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;會參加 sprint demo 會議的人（包含圍觀鄉民）大多是比較偏技術的開發人員。&lt;/span&gt;&lt;/li&gt;&lt;li style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;其他內容與前述正常版本都很像，但是在異常版本中，sprint demo 的項目可能還會包含「施工的 tasks」。也就是說，正常版本的 demo 比較像是「black-box demo」，與會人員只關心每一個做完的 story 要如何使用以及是否真的做完，不去管 Developers 倒底是如何做完這些 stories。而異常版本的 demo 比較像是「black-box &amp;nbsp;+ white-box demo」，除了包含正常版本的 demo 內容以外，團隊也可能會利用機會 demo 技術性的 tasks，例如「database schema design」、「新的 DAO 」、「某某 bug 如何解決」等。&lt;/span&gt;&lt;/li&gt;&lt;/b&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;為什麼會有兩種不同的 sprint demo 進行方式？照道理講應該是只有第一種正常版本，只要 demo 功能如何使用以及讓 Product Owner 「驗收」這些功能這樣就可以了。但是實務上有些團隊所面對的問題（專案）在某些階段技術細節相當程度會決定專案的成敗 ，或是團隊想利用「大家都在」的機會「快速&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;同步一下一些技術性的核心議題（與會者可能大多是技術背景的人）。在這種情況下，在 sprint demo 時如果有需要的話也順便談一點「內幕消息（技術性議題）」應該是可以接受的。&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; font-weight: normal; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; font-weight: normal; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;友藏內心獨白：又在逆練九陰真經了&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;。&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;/div&gt;&lt;ul style="font-family: 'Times New Roman'; font-size: medium;"&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-2097271531949119973?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/2097271531949119973/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=2097271531949119973' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/2097271531949119973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/2097271531949119973'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/scrum-7sprint-demo-meeting.html' title='Scrum 是什麼（8）：Sprint Demo Meeting'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-8EbueAI75Us/Txd5WLz5MCI/AAAAAAAAAvg/zsqKEQHEhSc/s72-c/sprint-review-meeting.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-8354406331086625968</id><published>2012-01-18T11:25:00.000+08:00</published><updated>2012-01-18T11:25:54.923+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Sustainable Pace</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 18 09:58~11:25&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;這幾天作息有點不正常，晚上睡不著，白天爬不起床。有點年紀了，&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;作息不正常這件事對於「生產力」和「身體健康」都有很大的殺傷力&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。昨天晚上也是弄到凌晨2點多才睡著，但是今天下定決心要把「時差」調整回來，早上8點好不容易趕跑周公之後吃完早餐就準備開工了。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;昨天晚上睡得晚，睡前拿起一本買了一年半但卻幾乎沒看的書想說能不能幫助睡眠，沒想到愈看精神越好...Orz。這本書叫做 Kanban: Successful Evolutionary Change for Your Technology Business，Teddy 今天想談一下書中提到的&lt;span class="Apple-style-span" style="color: blue;"&gt; Sustainable Pace&lt;/span&gt;&amp;nbsp;（穩定的步伐，可持續的速度）這個觀念。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Sustainable Pace 是 agile community （敏捷社群）很早就提出來的一個觀念，講單的來講就是說：「&lt;span class="Apple-style-span" style="color: blue;"&gt;每週工作40小時&lt;/span&gt;」。&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;看過 Teddy 部落格的鄉民們應該知道 Teddy 是不相信每天加班可以提高生產力這種作法。Teddy 年輕的時候也是幾乎天天加班，睡在公司也是常有的事。現在回想起來，雖然偶爾靈感來了加一下班可以有「驚人的生產力」，但是很多時候加班其實只是因為東西一直做不完，或是遇到問題卡住了，但是公司或是團隊（有團隊嗎？）也沒有提供一個機制協助 Teddy 解決問題，而 Teddy 也沒有能力可以只依靠自己就可以有效率地解決所有的問題。&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;再加上專案的時程都是業務或是老闆「跟著感覺走」而訂定出來的，身為小小工程師的 Teddy，「事情沒做完怎麼好意思下班」呢？（迷之音：如果老闆叫你去煮沸海水，那不是永遠都不用下班了？！）所以不管有沒有實際的進度，也只能「撐在那邊」，至少「沒有功勞也有苦勞」，老闆看你這麼「拼」，就算是時程到了結不了案也不好意思對 Teddy 過於苛責。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Teddy 很&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;小的時候&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;家裡開了一家小小的塑膠加工工廠，趕出貨的時候除了工廠員工要加班以外，連 Teddy 也被「動員」去幫忙。加班和增加人力對於生產力有沒有幫助？絕對有，因為這是一間「代工工廠」，工人只是做著重複性的工作。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;一般江湖上預估專案開發時程的作法，不外乎：&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;分析需求：看看有多少個 use cases，function points，或是 stories。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;分析人力：看看可以投入多少人到專案中。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;分析風險：...誰那麼認真啊...XD。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;假設有 100 個 stories，團隊有 5 個人，平均一人一個禮拜可以做完一個 story，所以這個專案需要二十週也就是大約五個月可以做完。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;問題來了，「&lt;span class="Apple-style-span" style="color: blue;"&gt;平均一人一個禮拜可以做完一個 story&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;這是怎麼估出來的&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;？這裡講得「一個人」是指怎樣的人？剛畢業的菜鳥，還是已經有5-6年以上工作經驗的工程師，還是寫得一嘴好程式的待退資深員工？這&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「一個人」的技術背景是什麼？對 Java 很熟？很抱歉，這個案子要用 VB.NET...XD。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;如果今天問題換成「下個球季洋基隊打入季後賽的機率有多少」？請問鄉民們會如何去「&lt;span class="Apple-style-span" style="color: blue;"&gt;估算&lt;/span&gt;」這個機率？當然是要看「&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;洋基和大聯盟其他&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;球隊的實力」。也許這個比喻並不是很洽當，因為開發軟體並不是打球，但是軟體畢竟是要靠「&lt;span class="Apple-style-span" style="color: blue;"&gt;人（一群人，也就是團隊）&lt;/span&gt;」所開發出來的，如果預估專案時程的時候所思考的只是「一個個沒有面孔的派遣人力」，那麼用這種方式所組成的團隊其「生產力」與「品質」都是很難預估的。&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman';"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;扯了老半天這和&amp;nbsp;Sustainable Pace 有何關係？鄉民們應該都有打籃球的經驗，打球的時候最重要的就是要選對 team members，持續的訓練，加上有機會就去參加各種比賽以提高團隊的實力。同一批人馬在一起打球，合作久了之後團隊的「戰力」就變得可以預估。開發軟體也是一樣，敏捷方法強調「&lt;span class="Apple-style-span" style="color: blue;"&gt;人（團隊）&lt;/span&gt;」與「&lt;span class="Apple-style-span" style="color: blue;"&gt;溝通，合作&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」的重要性。一個團隊在導入 Scrum 或是 XP 這種敏捷方法之後，大概六個月左右這個團隊的 Pace （腳步，生產力）就可以慢慢地穩定下來。當一個團隊找到自己的 Sustainable Pace 之後，「預估時程」這件事就變得「不是那麼討厭」，而且可以越估越準。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;「培養團隊」是一件費時、費力、又費心的工作，不見得每個公司或是組織的文化都支持這樣的作法。還是那句老話，畢竟「加班」對於公司與員工而言，是一種最不花腦筋（更棒的是又不花錢...因為責任制啊...Orz）又可以「保護&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」雙方的一種工作模式，幹麼花時間去建立團隊的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&amp;nbsp;Sustainable Pace 呢。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;友藏內心獨白：&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;我不當派大星，誰當派大星。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-8354406331086625968?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/8354406331086625968/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=8354406331086625968' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8354406331086625968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8354406331086625968'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/sustainable-pace.html' title='Sustainable Pace'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-1084573586988367144</id><published>2012-01-17T04:38:00.000+08:00</published><updated>2012-01-17T04:38:23.017+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是一組餐具</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 17 03:57~04:38&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;今天無緣無故又失眠了，看來明天又要晚起，翻來覆去睡不著乾脆起來吃點東西順便寫篇文章看看等一下會不會比較好睡。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;前幾天一位非資訊科系的人（簡稱「非資訊人」）問 Teddy 是在怎樣的機緣之下開始實施 Scrum，為了回答這個問題 Teddy 就在想要怎麼跟這位&lt;/span&gt;&lt;/span&gt;「&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;非資訊人」先解釋一下 Scrum，突然之間 Teddy 有一個靈感：&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;Scrum 就像是吃高級日本料理的時候所看到的一組餐具，讓我們把各式各樣的&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;食物&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;可以放到合適的餐具中，然後呈現給顧客&lt;/span&gt; （Teddy 沒有高級日本料理的照片，只能用平價日本料理代替..XD）&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Okk83MijZsg/TxSJXXxxtfI/AAAAAAAAAvY/eIO7o-vRoDw/s1600/DSC04657.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="225" src="http://1.bp.blogspot.com/-Okk83MijZsg/TxSJXXxxtfI/AAAAAAAAAvY/eIO7o-vRoDw/s400/DSC04657.JPG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Teddy 所說得「餐具」，就代表一種「框架（framework）」，而「食物」就是各種「實務作法（practices）」或是「軟體工程方法」經過大廚（團隊）實踐之後的產物。餐具的種類有限，但食物卻可變化無窮。餐具容易獲得，但要做出好食物卻需要一番功夫。&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;回想 Teddy 當年一開始也只不過是看了 &lt;i&gt;Scrum and XP from the Trenches&lt;/i&gt; 這本書就跑去幫人家帶一個 Scrum 團隊，當然後來 Teddy 很認真看了好幾本 Scrum 的書也去上了 Certified ScrumMaster 課程，但總的來講最重要的成功因素還是：&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;以前有過很多開發產品與做專案（失敗）的經驗...Orz。&lt;/li&gt;&lt;li&gt;看了很多，很多軟體開發與設計的書還有論文。&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;翻譯成白話文就是說「有九陽神功護體，學什麼都快」。只要軟工底子好，配合上合適的「餐具」與大廚團隊，要端出一盤盤的好料理也是順其自然的事情。&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;***&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;友藏內心獨白：現在 Teddy 的生理時鐘是在活在那一國的時區啊？&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-1084573586988367144?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/1084573586988367144/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=1084573586988367144' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1084573586988367144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1084573586988367144'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/scrum_17.html' title='Scrum 是一組餐具'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-Okk83MijZsg/TxSJXXxxtfI/AAAAAAAAAvY/eIO7o-vRoDw/s72-c/DSC04657.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-6893063847525234358</id><published>2012-01-16T11:27:00.000+08:00</published><updated>2012-01-16T11:27:24.183+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（7）：Daily Scrum</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 16 10:08~11:24&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Daily Scrum 是從 sprint 開始之後的每個工作天 Scrum 團隊必須舉辦的一個活動，假設鄉民們的 sprint 為期兩週，那麼就會舉辦 9 次 Daily Scrum。依據 Scrum 課本上的講法，Daily Scrum 的進行方式為：&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Daily Scrum 是一種「站立會議（standing up meeting）」，也就是說與會人員必須要站著開會。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Daily Scrum 進行時間以不超過 15 分鐘為原則。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;與會人員包含 Scrum 團隊（開發人員）與 Scrum Master，至於 Product Owner 可自行決定是否參加。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;舉辦時間（幾點舉辦）並沒有規定，假設公司上班時間為 9:00~18:00，有的人會在早上 9:20 舉辦，有的人喜歡在 17:00 下班前舉辦。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;會議開始，由&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;開發人員逐一報告三件事：昨天做了什麼，今天預計要做什麼，有沒有遭遇的什麼困難。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;開發人員報告這三件事的「對象」並非 Scrum Master，而是其他開發人員。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;舉辦的地點在 task board 前面，開發人員報告的過程中，可以順便更新 task board（移動 task 的狀態）。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Daily Scrum 的目的除了可以讓 Scrum&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;團隊成員彼此&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;了解整個團隊的狀態與工作進度（&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;工作進度&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;透明化），最主要的還是可以達到「&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;曝&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;險（曝露風險）&lt;/span&gt;」的目的，以便提早擬定排除風險或是應付&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;風險的對策（不要等 sprint 最後一天，甚至是專案快結束前才突然冒出大問題來）&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;：&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;如果有團隊成員報告說自己有遭遇的問題（call for help），則其他團隊成員可以主動協助。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;如果團隊成員遇到的問題無法在團隊中解決（例如牽涉到其他部門），則 Scrum Master 要出面幫忙協調。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;如果有團隊成員每天都說沒有問題，但是被困在同一個 task 上面已經好幾天都沒辦法做完，此時其他團隊成員或是 Scrum Master 可以主動了解看看該位&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;團隊成員無法完成 task 個原因。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;關於 Daily Scrum 有幾點心得 Teddy 想分享一下：&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Teddy 個人比較喜歡在早上（9:20 或是 9:30）舉辦 Daily Scrum，但是 Teddy 也曾經聽過有的公司採取「彈性上班時間」，所以團隊成員可能在 9:00~10:30 甚至是 11:00 之後才會陸續到齊。&lt;span class="Apple-style-span" style="color: blue;"&gt;Teddy 個人是不建議 Scrum 團隊採取這樣的「彈性上班時間」&lt;/span&gt;，但是如果這是既定無法更改的事實，也許把 Daily Scrum 移到下班前的 17:00 也是一種方法。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;如果有團隊成員表示今天不知道要做什麼的時候，可以先給他一點時間看看有那些 tasks 是可以拿來做的。如果真的都沒有，Scrum Master 可以「建議」幾個可能的 tasks，或是讓他跟別人 pair。但是，如果這種現象持續發生，則表示該名成員可能遭遇的一些問題，例如他的技能可能過於侷限在某個特定領域，此時&amp;nbsp;Scrum Master 要思考如何解決這樣的問題。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;雖然 Scrum 課本告訴大家不要在 Daily Scrum 時討論技術問題（解決方案），如果有需要進一步討論則在 Daily Scrum 之後再把相關人等留下來討論，無關的人就可先行離開。但是，如果鄉民們的團隊人數不多（例如 3-6人），或是幾乎每個人都會與所要討論的主題有關的話，那麼 Teddy 覺的並不一定要那麼嚴格規定都不可以在 Daily Scrum 中討論任何技術問題或是解決方案。不過大原則是，Daily Scrum 不可以開太久，15-25 分鐘 Teddy 覺的還可以接受，如果有一些討論會導致 Daily Scrum 超過 &amp;nbsp;25 分鐘那就應該要另闢戰場。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;有些團隊成員在報告的時候會習慣看著 Scrum Master，為了被免搞到最後&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;團隊成員好像都在跟 Scrum Master 報告，所以有些 Scrum Master 會選擇站在團隊成員的背後。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;友藏內心獨白：最近越睡越晚...XD。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-6893063847525234358?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/6893063847525234358/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=6893063847525234358' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6893063847525234358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/6893063847525234358'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/scrum-7daily-scrum.html' title='Scrum 是什麼（7）：Daily Scrum'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-8663967758838586130</id><published>2012-01-15T12:18:00.000+08:00</published><updated>2012-01-15T12:18:26.516+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='生活'/><title type='text'>防弊還是興利（2）</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 15 11:06-12:18&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;最近突然對「防弊還是興利&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」這件事情有很大的感觸。幾年前 Teddy 還在學校念書的時候，常常在期刊雜誌與研討會的論文集看到很多國外公司（例如 IBM、Microsoft、Google、Sun，以及一些記不得名子的小公司）的員工所發表&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;軟體領域&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;的論文，但是印象中好像幾乎沒有看過台灣民間公司的員工（大學或中研院這種研究單位不算）發表過類似的論文。為什麼？以下是 Teddy 的猜測：&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;洩漏公司機密&lt;/b&gt;：身為公司員工，發表論文是否會有「洩漏公司機密」的疑慮。為了解除這樣的疑慮，公司還要找人先審查論文內容，浪費公司資源。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;對公司有什麼好處&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;：員工發表論文對公司有什麼具體的好處？&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;你很閒喔&lt;/b&gt;：員工居然還有時間可以去寫論文發表，代表這位&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;員工太閒了，多派一些工作給他吧。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;前幾天 Teddy 看到&amp;nbsp;Hadoop 1.0 版正式發表，如果&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;稍微有聽過&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&amp;nbsp;Hadoop 的鄉民，應該會知道&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Hadoop 是根據 Google 工程師所發表的論文中所談到的&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;BigTable、MapReduce 以及&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Google File System&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&amp;nbsp;等概念的實做&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。目前&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Hadoop 由&amp;nbsp;Apache 軟體基金會 (Apache Software Foundation) 所管理，其中&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Yahoo 與 Cloudera 等公司都投入開發人員參與 Hadoop 的開發。&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;奇怪了，Google 沒事幹麼讓自己的員工發表論文「洩漏公司機密」，搞得其他競爭對手都可以學習模仿，開發類似的雲端計算架構？這麼一來&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;雲端市場不是多了很多&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;競爭對手？&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 猜想（公堂之上假設一下，應該不犯法吧...XD），Google 的立場可能是：&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;對自己公司很有信心。因為 Google 公司與員工不斷的在進步，所以把一些「既有的」知識透露一小點分享給社會大眾，不但不會對公司造成負面的影響，反而會對公司的形象加分。為什麼，因為自此之後，每當搞雲端計算的人提到&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;BigTable、MapReduce 以及&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Google File System 這些觀念的時候，幾乎都一定會提到 Google（免費幫公司打廣告啊）。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;雲端計算是一種「生活習慣的改變」，這樣的改變所帶來的市場太大、太大了，Google 一家公司也不可能全部通吃。話說回來，光靠 Google 一家公司的力量要很快地讓大眾達到這樣的改變也是有一定的難度。所以，還不如分一點小甜頭給市場上的其他公司，一起把這個市場做起來，這樣子 Google 反而會是受益最大者。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;有遠見的人會思考如何「&lt;span class="Apple-style-span" style="color: blue;"&gt;把餅做大&lt;/span&gt;」，可惜大多數的人所想得還是如何「&lt;span class="Apple-style-span" style="color: blue;"&gt;把別人的&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;餅搶過來&lt;/span&gt;（這算是一種紅海戰爭嗎？！）&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」。還記得 Teddy 在幾個月前所寫得「&lt;a href="http://teddy-chen-tw.blogspot.com/2011/08/blog-post.html" target="_blank"&gt;防弊還是興利&lt;/a&gt;」，其中引用&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;前任衛生署長楊志良&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;先生關於全民健保部份負擔這個議題所說得一段話：&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px;"&gt;&lt;i&gt;由於不可能針對每個人訂定部份負擔，因此不管如何訂，對某些人總是太低，而某些人則是太高，那麼我們就要問：&lt;span class="Apple-style-span" style="color: red;"&gt;健保的目的是什麼？&lt;/span&gt;如果是減少浪費，那就訂部份負擔愈高越好，甚至100%負擔。&lt;span style="color: blue;"&gt;天下沒有完美的制度，有利就有弊，兩害相權取其輕，兩利相權取其重，去掉弊常也把利&lt;/span&gt;&lt;/i&gt;&lt;span style="color: blue;"&gt;取消&lt;/span&gt;&lt;i&gt;&lt;span style="color: blue;"&gt;掉了。若健保的目的是要達到全民健康照護，那麼部份負擔就只能訂得低，但接受某種程度的浪費&lt;/span&gt;&lt;/i&gt;&lt;span style="color: blue;"&gt;。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 真的很喜歡上面用藍色標注的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;這段話&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;，同樣的觀念其實在很多地方都可以看到。例如，豐田汽車和他的經銷商合作關係，或是在 ted.com 上面的這段演講 &lt;a href="http://www.ted.com/talks/howard_rheingold_on_collaboration.html" target="_blank"&gt;Howard Rheingold: The new power of collaboration&lt;/a&gt;&amp;nbsp;（有中文字幕）所要傳達的觀念。不知道是不是華人社會這種「多一事，不如少一事」的心態已經根深蒂固的默默存在許多人的心中（還是怕被爆料&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;、抹黑？&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;），所以當有些「不同的想法」出現的時候，主事者第一時間想到的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;往往不是&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;「興利」，反倒是如何「防弊」，&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;防到最後就如同&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;楊志良&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;先生所說得：「&lt;span class="Apple-style-span" style="color: red;"&gt;去掉弊常也把利取消掉了&lt;/span&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;2011 年 9 月 Teddy 去李國鼎故居參觀，看了李國鼎先生的生平簡介之後才知道原來他在經濟部長任內曾經因為「東亞紡織公司貸款案」被監察院提出彈劾。站在&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;經濟部長的立場，原本就是要幫助經濟發展，協助企業經營。&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;即使&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;李國鼎先生應該算是公認的「清官」，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;但是他&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;還是在「防弊還是興利&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」的戰爭中輸給了&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;防弊，辭去&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;經濟部長職務&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。時空回到現在的社會環境，想要有勇氣大刀闊斧去&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;興利而又不怕被扣帽子的人恐怕只會越來越少了&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;友藏內心獨白：講這麼多，是你自己太反骨了吧你。&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-8663967758838586130?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/8663967758838586130/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=8663967758838586130' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8663967758838586130'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8663967758838586130'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/2.html' title='防弊還是興利（2）'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-7279849202660365525</id><published>2012-01-14T12:24:00.000+08:00</published><updated>2012-01-14T12:24:49.125+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='持續整合'/><title type='text'>安裝先行</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 14 11:52~12:24&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Test-driven development 或是 test-first development 中文有人翻譯成&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;span class="Apple-style-span" style="color: blue;"&gt;測試先行&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」，大意是說還沒開始寫 production code （就是一般所謂的程式）之前，先把 test code 給寫出來。奇怪了「待測程式（&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;production code&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;）」都還沒個影子，如何寫 test code 去測試它（不存在的東西如何測試&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;？&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;）箇中細節暫且不談，總之&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「測試先行&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」的目的是希望開發人員能夠先從「end users（可能是最終的客戶，或是呼叫你的程式的其他程式或是其他開發人員）」的角度來看看自己等一下所準備撰寫的程式應該長成什麼樣子，之後再實際逐一把這些程式實做完成。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 今天要談的是另一個類似的觀念，姑且稱之為「&lt;span class="Apple-style-span" style="color: blue;"&gt;安裝先行&lt;/span&gt;」。傳統採用 waterfall 開發流程的專案或是產品，安裝與佈署的問題通常都是最後才被考慮的問題。為什麼？因為東西都還沒開發完畢，幹麼去考慮安裝和佈署的問題啊（東西都還不能用啊）。但是如果團隊採用的是 agile methods（&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;敏捷方法&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;），那麼「理論上」每個 iteration 結束時，都應該要有一個可以執行的軟體（running software），所以對於敏捷團隊來說，在專案初期便應該需要考慮軟體安裝與佈署的問題。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;關於這個問題 Teddy 和指導教授曾經發表過一篇持續整合的論文，其中有介紹這樣的觀念（如下圖所示）。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-HjGz8r-8D0w/TxEAacrsvOI/AAAAAAAAAu4/DzCPD3nSiLQ/s1600/CI-PL.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="267" src="http://1.bp.blogspot.com/-HjGz8r-8D0w/TxEAacrsvOI/AAAAAAAAAu4/DzCPD3nSiLQ/s400/CI-PL.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;這兩天 Teddy 把 &lt;i&gt;97 Things Every Programmer Should Know&lt;/i&gt; 這本書翻了一下，發現書中第 40 頁也有提到類似的觀念。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;Deploy Early and Often&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Starting your project with an installation process will give you time to evolve the process as you move through the product development cycle, and the chance to make changes to the application code to make the installation easier.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;有興趣的鄉民們可以參考一下。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;**&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;友藏內心獨白：當遇到防弊與興利的抉擇時，大部分的人還是會選擇比較不會被質疑的&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;防弊&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-7279849202660365525?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/7279849202660365525/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=7279849202660365525' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7279849202660365525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7279849202660365525'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/blog-post_14.html' title='安裝先行'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-HjGz8r-8D0w/TxEAacrsvOI/AAAAAAAAAu4/DzCPD3nSiLQ/s72-c/CI-PL.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-7935208984605118018</id><published>2012-01-13T11:40:00.001+08:00</published><updated>2012-01-13T11:42:22.508+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體設計'/><title type='text'>盤點 Design Patterns</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 13 10:44~11:40&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;前一陣子有朋友問 Teddy 能否去教他們公司的工程師 design patterns。想起 Design Patterns 這本書 &amp;nbsp;Teddy 已經有一陣子沒有去看它了，最近一次仔細重看&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;書中的 Memento 是為了研究 exception handling 裡面關於 state restoration（狀態回復）&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;的問題，那是多久以前的事現在回想起來居然沒有任何印象...Orz。只依稀記得當年在看&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Memento 的時候其實搞不太懂這個 pattern 可以用來幹麼，所以好像從來也沒用過它。一直到 10 幾年後突然發現&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Memento 可以應用在例外處理設計，算是替&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Memento&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;找到一份工作了...XD。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Design Patterns 這本書是 Teddy 在 1997年10月24日在天瓏書局買得，算一算已經是14 年前了事了。當初會買這本書，好像是在 BBS 討論區看到某位前輩提到這本書，後來去&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;天瓏翻了一下覺的寫得真棒就買回家&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。一看之下真的不得了，讀完之後（其實沒有整本全部讀完啦）覺的自己的軟體設計功力大增。書中所講得設計觀念，現在看起來可能覺的是「常識」，可是有好多 patterns 可是 Teddy 自己慢慢在專案中一一自己實做過之後，才體會到這些 patterns 的意義（剛開始自己學習的時候也是一頭霧水）。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;10 幾年前 Teddy 也有做了一些投影片，在自己還是一知半解的情況下，跟公司的同仁分享&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Design Patterns（好東西要跟好朋友分享啊）。當年 Teddy 還是個年輕小伙子，被問到自己也不懂的地方，就說一聲「不會&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」也就沒事了&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。但是現在「年事已高」，如果還被問到不會的地方就有點尷尬了（年紀大有&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;年紀大耍無賴的方式...XD&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;）。所以才想說把書拿出來&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「盤點」一下，看看那些 patterns 是自己很熟的，那些是很少實做而且已經忘得差不多的。&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;Creational patterns&lt;/b&gt;：幾乎稍微大一點的案子都會用到裡面的五種 patterns，尤其是 Singleton，Factory Method 和 Builder。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;Structural patterns&lt;/b&gt;：除了 Decorator、Flyweight 以外，其他的 patterns 用到的機會都滿多的。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;Behavioral patterns&lt;/b&gt;：Command、Observer、State、Strategy、Template Method、Visitor 用到的機會最多，Iterator、Mediator 次之，Chain of Responsibility&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;、Interpreter&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;、Memento 比較少用到（後面這三個有用過嗎？）。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;對於一個剛接觸 design patterns 的新人，Teddy 會建議學習順序為：&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Singleton、&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Factory Method、Adapter、Composite、Command、Observer&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Builder、Abstract Factory、Facade、Proxy、State、Template Method。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Bridge、Strategy、Visitor、Mediator、Iterator、Prototype。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Decorator、Flyweight、Chain of Responsibility、Interpreter、Memento&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;上述建議純粹為 Teddy 個人的偏見，鄉民隨便看看就好，不用太在意。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;寫到這邊突然有一個問題：真的有鄉民把這 &lt;strike&gt;降龍18掌&lt;/strike&gt; 23 個 patterns 一口氣全部都派上用場嗎？有的話請介紹給 Teddy 認識一下，要跟他學習。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br class="Apple-interchange-newline" /&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;友藏內心獨白：手邊的這本書都已經長黃斑了。&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-7935208984605118018?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/7935208984605118018/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=7935208984605118018' title='5 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7935208984605118018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7935208984605118018'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/design-patterns.html' title='盤點 Design Patterns'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-1171935751751494026</id><published>2012-01-12T13:08:00.001+08:00</published><updated>2012-01-12T13:12:53.434+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='生活'/><title type='text'>用軟工改善生活</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 12 11:40~13:08&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;兩個禮拜前跟一位好朋友聊天，Teddy 提到雖然目前處於無業遊民狀態，但是身邊有待 Teddy 去處理的人、事、物還挺多的，搞得 Teddy 比之前工作的時候還忙，而且其中有些事情彼此之間關係還挺複雜的，不太容易做出&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;決定&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;套句軟體架構或是 design patterns 的術語，在 Teddy 目前所遭遇的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;情境&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;（context）&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;之下，存在著太多彼此相互衝突的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;力量（forces）&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」。按照軟體設計的方法，Teddy 應該要想出一個可以&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;解決（&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;resolve&lt;/span&gt;）&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」或是&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;span class="Apple-style-span" style="color: blue;"&gt;平衡&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;（balance）&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」這些 forces 的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;方案&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;（solution）&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」。如果真實世界的事情能夠用軟體設計的方法來處理就好了。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;好朋友告訴 Teddy，拿出一張紙，把自己名字寫在中央，然後依據所要處理的人與自己的關係遠近，把這些人的名字逐一寫在紙上。然後自己在思考一下根據這樣的關係，自己要如何來處理這些人的問題。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;昨天晚上 Teddy 突然回想起之前這位&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;好朋友也曾經告訴過 Teddy，他在家裡對他的在念小學的小朋友也實施 Scrum。什麼？Scrum 也可以用來&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;「管理」&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;小朋友？根據&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;好朋友的說法，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;小朋友很會「耍賴」，常常會要求要看電視、玩電動、吃零食、出去玩等等，但是卻把功課或是其他要幫忙做的家事丟在一旁不管。所以，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;好朋友就借用 Scrum 的 task board 作法，把&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;小朋友每週需要做的事情寫在白板上面。每當&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;小朋友又要開始&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「耍賴」的時候，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;好朋友就會說：『我們來看看白板上面你今天要做的事情是不是已經都做完了』&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。過一陣子之後&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;小朋友要&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「耍賴」之前，會自動去看一下&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;白板上的「今日待辦事項」是否已經完成，以免&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「耍賴」不成反被&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「打槍」（真的有這麼守紀律的小朋友嗎？）&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;一張白紙，一個簡單的 task board，或是更簡單一點的 to-do list，都是一種減少「腦袋負擔」以及增進「溝通」的方法。仔細一想其實這就是 agile methods 所強調的「&lt;span class="Apple-style-span" style="color: blue;"&gt;視覺化溝通&lt;/span&gt;」。不要把待辦事項放在心裡，或是打在電腦裡面，就直接寫在牆上或是白板上面，讓所有與這件事有關的人都可以用眼睛在「案發現場（工作場合）」看到這些&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;辦事項的進度&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;很多事情放在心裡（腦袋&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;裡&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;）沒有加以「視覺化」，每天在那邊反反覆覆想來想去，只會增加自己大腦的負擔，最後搞到自己精神上很累以至於身體上也覺的很累。結果原地打轉，一事無成。所以，Teddy 打算練習一下用看板（Kanban）來管理自己手邊的工作。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-CaXTDhM6_Tk/Tw5oIJ2eOVI/AAAAAAAAAuw/-Vdv13qxwOE/s1600/blog-v0.1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="330" src="http://3.bp.blogspot.com/-CaXTDhM6_Tk/Tw5oIJ2eOVI/AAAAAAAAAuw/-Vdv13qxwOE/s640/blog-v0.1.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;當然要用看板來管理工作進度，要能夠自己拿捏&lt;span class="Apple-style-span" style="color: blue;"&gt;同時間可以處理的工作量（WIP，work in progress）&lt;/span&gt;，否則最後變成一大堆的工作全部處於 Ongoing 狀態，結案的（Done）只有一點點，那也是一樣白搭。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;最後只剩下一個問題：在家裡的牆上貼滿便利貼會不會被罵啊？依 Teddy 看來被罵的機會應該滿高的...Orz。&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-size: 14px;"&gt;友藏內心獨白：人生在世還是至少要認識一、兩位很聰明或是很有見解的好朋友。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-1171935751751494026?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/1171935751751494026/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=1171935751751494026' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1171935751751494026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1171935751751494026'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/blog-post_12.html' title='用軟工改善生活'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-CaXTDhM6_Tk/Tw5oIJ2eOVI/AAAAAAAAAuw/-Vdv13qxwOE/s72-c/blog-v0.1.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-8592700015704825139</id><published>2012-01-11T11:22:00.001+08:00</published><updated>2012-01-11T11:23:39.138+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（6）：Sprint Planning Meeting 眉角</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 11 09:51~11:22&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;對於一個剛開始導入 Scrum 的團隊，sprint planning meeting 最頭大的問題應該是「如何決定每一個 story 的 story point 以及 task 所需的時間」。&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;關於 story points 與 tasks 的估算方法請參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/05/story-point.html" style="color: #de7008;" target="_blank"&gt;如何估算 story point？&lt;/a&gt;」與「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/07/story-point.html" style="color: #de7008;" target="_blank"&gt;Story point 為何沒有單位：相對論篇&lt;/a&gt;」。今天 Teddy 要講的是，假設團隊有 5 個人，現在要估算某個 story 的 story point，結果 5 個人出的牌（假設團隊用 Scrum Planning Poker 的方式用來估算點數）點數分別是：&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;A：13&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;B：2&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;C：20&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;D：?（問號）&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;E：5&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;那麼這個 story 的 story point 要算多少？會出現這種估算結果，通常有幾個原因：&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;團隊成員對於 Product Owner 所解釋的需求內容產生了「&lt;span class="Apple-style-span" style="color: blue;"&gt;一個 story 各自表述&lt;/span&gt;」的現象，所以才會出現 B 認為只需要 2 點而 C 認為需要 20 點這麼大的差距。遇到這樣的情況可以請每個人說明一下他們估算點數的依據，如果時間不夠也可以請差距最大的兩方（B 和 C）說明就好。經過一番說明與討論之後（Product Owner 和團隊成員要互相討論）Scrum Master 請大家再重新估算一次，通常這個時候估算的結果差異會比較小。重複這個過程一直到得到一個大家都認可的點數為止。有人會問如果一直都沒有得到一個大家認可的點數該怎麼辦&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;？重估的過程 Teddy 最多大概只會進行兩次（包含第一次的估算，最多一共估算三次），如果此時還是無法得到共識，Teddy 會自行決定一個「合理」的點數，通常團隊成員也 &lt;strike&gt;不敢&lt;/strike&gt; 不會有太大的意見（因為一直重估太多次大家也是會累的...XD）。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;完全不了解這個 story （或是 task）是要做什麼的。例如，D 出了？&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;（問號）這張牌，表示他對於這個 story&amp;nbsp;（或是 task）完全不了解。此時就要請&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Product Owner&amp;nbsp;針對 D 不了解的地方再次說明。如果估算的是 task 的話，則可以請對於實做該 task 有經驗的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;團隊成員說明一下。之後，回到上一點所說得，再次重估。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;團隊成員不合作。剛開始實施 Scrum 時可能會有那種打死不合作的「刀民」，就是不想了解也不想認真參與估算，總是會在旁邊講一些有的沒的風涼話。如果是這樣的情況，Scrum Master 可以選擇先把該&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;刀民當成隱形人（小時候玩捉迷藏不是有一種人叫做「烏鴉」的嗎？），告訴他先看看別人如何估算，等他了解之後再加入估算的活動（迷之音：如果團隊成員全部都是刀民...Orz）。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;有一件很重要的事情 Scrum 團隊要銘記於心，Scrum 所設計的各種活動其目的是要強調「溝通」，尤其是「&lt;span class="Apple-style-span" style="color: blue;"&gt;面對面的溝通&lt;/span&gt;」。如果只是想從&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Product Owner 所寫出來 &lt;strike&gt;不清不楚&lt;/strike&gt; ... 嗯嗯，那一句短短的 story（As a user, I can...）就可以知道程式要怎麼寫，那是不可能的。所以在&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;sprint planning meeting 的過程中，團隊成員對於&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;story 與 task 有任何&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;不了解的地方，一定要立即發問，主動參與。Teddy 最怕那種在&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;sprint planning meeting 中都不開口的團隊成員，看起來好像都沒問題，但是等真正開工之後，這種人通常問題最多。&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;開 sprint planning meeting 是一件很累人的活動，但對於日後 sprint 的進行是否順利有著決定性的影響。對於剛開始實施 Scrum 的團隊，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;sprint planning meeting 很可能會佔據一整天（6-7 小時）的時間，而且開完會之後對於接下來要做的事情可能還是會有一種「毛毛的感覺」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。這種現象可能會持續一段時間，例如半年以上。等團隊成員默契慢慢培養起來之後，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;sprint planning meeting 就會進行的比較順利&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;span class="Apple-style-span" style="color: blue;"&gt;至少大部分的時間都可以花在「討論真正的問題上面」，而不是花在處理「刁民」與「派大星（拒絕動腦筋的人）」身上。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;最後一個重點，如果快到下班時間而 sprint planning meeting 還沒開完怎麼辦？要明天繼續嗎？No, no, no, 千萬不要。請記得 agile 的核心精神就是 time boxing（編列固定預算的概念），任何活動都是有一定的時間，如果真的發生&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;快到下班時間而 sprint planning meeting 還沒開完，那就「&lt;span class="Apple-style-span" style="color: blue;"&gt;草草結束這次的&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;sprint planning meeting 吧&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。蛤，蝦米，草草結束，這是什麼態度？&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;沒錯，就是&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;草草結束，因為如果把&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;sprint planning meeting 一直延長&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;下去很可能會出現 big up-front design 的症狀。對於新的 Scrum 團隊，很可能團隊成員大多還是抱持著傳統那種「先好好地分析設計一番，然後再開工」的習慣。所以，如果真的無法在預定的時間開完會議，就&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;草草結束，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;反正有問題 sprint 進行的過程中隨時都可以問&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Product Owner。如此一來才可以：&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;strike&gt;強迫&lt;/strike&gt; 循循善誘&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;團隊成員慢慢接受&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;time boxing 的工作模式。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;這次&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;sprint planning meeting&amp;nbsp;花太多時間討論一些可能不是很重要的細節，導致於最後落得&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;草草結束的下場。團隊學得此次經驗之後，下一次的&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;sprint planning meeting 會儘量避免同樣的問題發生。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;友藏內心獨白：難道每天寫一篇對於鄉民來說會看的太累嗎？&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-8592700015704825139?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/8592700015704825139/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=8592700015704825139' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8592700015704825139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8592700015704825139'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/scrum-6sprint-planning-meeting.html' title='Scrum 是什麼（6）：Sprint Planning Meeting 眉角'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-1717355613097946914</id><published>2012-01-10T11:24:00.003+08:00</published><updated>2012-01-10T12:25:43.116+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Pair Programming 沒人性？</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 10 10:32~11:23&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;在上禮拜六 Scrum 講座中 Teddy 提到持續實施 pair programming 可以解決一部分派工（認領 tasks）的問題，此時&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;有位鄉民問了 Teddy一個問題：&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民：可是 pair programming 不符合人性啊！&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Teddy：此話怎講？（&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 內心讀白：&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;難不成&amp;nbsp;pair programming&amp;nbsp;是禽獸...XD）&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民：例如做 pair programming 的時候就不能跟女朋友 MSN。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Teddy：為什麼上班時間要跟&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;女朋友 MSN？你是想要每天加班，然後只能跟&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;女朋友透過 MSN 聊天&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;，還是想要每天可以準時下班然後&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;跟&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;女朋友抱在一起。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民：!@#$!@...&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 的回答算是有點耍無賴，採用&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming 的確是一種&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;span class="Apple-style-span" style="color: blue;"&gt;很累人&lt;/span&gt;」的開發方式，因為在&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming 的模式下，開發人員需要時時保持&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;專注力&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」，並且必須要和搭配開發的對象互動討論，也不能偷個懶休息一下上個&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Facebook 或是和&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;女朋友 MSN&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。所以，很多開發人員對於&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming 都抱持著能免則免，能閃則閃的心態。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 自己當然也不例外，有些工作 Teddy 覺的沒有&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming 會不安心，有些工作則是可以讓開發人員自行決定。討論&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming 的文章網路上應該可以找到一大堆，關於何時應該採用 pair programming 以下 Teddy 講幾點自己的經驗：&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;重要新功能的 coding 工作：&lt;/b&gt;如果系統的架構與設計已經有了大致的想法，此時採用&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming 是一個不錯的時機。但如果連這件工作倒底要如何開始都沒有任何頭緒，此時可以考慮兩人先快速討論一下設計，或是先分頭思考一下各自的解決方案，或是 google 一下可能的解法，然後在「合體&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」繼續開發工作&lt;/span&gt;&amp;nbsp;。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;b&gt;Big Refactoring&lt;/b&gt;：如果要用 refactoring 改善系統架構或是重要設計，此時採用&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming 方式會比較保險，避免不必要的錯誤，或是不斷的&amp;nbsp;refactoring。由於做大範圍的 refactoring 一不小心很可能會發生鬼打牆事件，同樣的模組不斷地改來改去，有另外一個人一起幫忙看著可以可以避免這樣的情況發生。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;帶新人&lt;/b&gt;：有新人加入用&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming&amp;nbsp;&lt;/span&gt;&lt;/span&gt;是最容易讓新人快速上手的一種方法之一。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;知識傳遞&lt;/b&gt;：為了避免系統中每一個模組只有某位特定開發人員知道如何修改，以及為了達到 shared code 的目標，採用&amp;nbsp;pair programming 是一種快速傳遞知識的方法&amp;nbsp;。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;Debug&lt;/b&gt;：假設某個模組有一個 bug，但是對於這個模組最熟的開發人員卻看不出問題出在哪裡。此時可以找團隊中的抓蟲高手（例如 Teddy...XD）或是其他閒閒沒事做的人一起來幫忙看。通常有人一起看會節省很多 debug 的時間。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;寫測試案例&lt;/b&gt;：自己一個人寫（自動化）測試案例很容易會忽略一些很重要，或是看起來不是那麼重要但卻是必要的測試案例（例如例外情況測試）。或者是有些自動化測試案例真的很不好寫，此時採用 pair programming 可以幫忙撰寫出這些測試案例。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;理想上如果所有的工作都能採用&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming 的方式當然很好，但是這樣對於開發人員來講壓力有時會太大。所以實務上每個團隊自己還是需要想出一個折衷方案。例如，對於從來每有做過 pair programming 的團隊，一開始的時候可以約定每個 sprint 每個人至少要以 pair programming 的方式參與 1-2 個 tasks ；或是 10% 的新功能都要以&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;pair programming 的方式來實做，然後每個 sprint 逐步調高 pair programming 的比例到團隊都可以接受的水準（例如， 50%-60% 的重要功能都採用 pair programming）。&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;以 Teddy 自己的經驗，也從來沒有達到 100% 的 pair programming，所以請依據團隊與每個 sprint 工作的特性自行安排與調整。此外，實施 pair programming 的時候，&lt;span class="Apple-style-span" style="color: blue;"&gt;一天最好不要超過五個小時&lt;/span&gt;，&lt;span class="Apple-style-span" style="color: blue;"&gt;一週不要連續超過三天&lt;/span&gt;，否則開發人員會因為太累反而降低 pair programming 的效果。還有， pair 到一定的階段（例如 1-1.5 小時或是完成某個小功能）要休息個 10-15 分鐘左右，可以利用這段時間放空讓腦袋休息一下，轉換一下心情，或是跟&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;女朋友 MSN...XD 。&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;January 10 12:22~12:23&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;補充一點某位鄉民在 Facebook 上面給 Teddy 的留言：&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;鄉民：我之前的 team 是每天 pair 6 小時，一周 5 天，pair 久了你叫工程師自己開發個東西，過沒兩個星期他就回來拜託你幫他排 pair...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;友藏內心獨白：要求員工每天加班導致員工被迫「&lt;span class="Apple-style-span" style="color: blue;"&gt;把生活融入工作&lt;/span&gt;」並不是一種好的做事方法。&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-1717355613097946914?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/1717355613097946914/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=1717355613097946914' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1717355613097946914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/1717355613097946914'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/pair-programming.html' title='Pair Programming 沒人性？'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-5967702494572726450</id><published>2012-01-09T22:14:00.001+08:00</published><updated>2012-01-09T22:26:33.535+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='生活'/><title type='text'>今天好累</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 09 20:40~10:12&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;今天下午和某位鄉民約了見面，沒想到一聊聊了四個小時。由於今天早上 Teddy 才跟另一位朋友聊了兩個小時，所以晚上 Teddy 回家之後吃完晚餐，突然整個人覺的快虛脫了。現在腦袋空空，想了 20 幾分鐘還是擠不出什麼料來，所以今天就來內心獨白一下好了。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Teddy 基本上也算是個宅男，之前的生活除了工作，就是利用回家的空閒時間寫寫部落格或是看看書，假日有時間出外走一走曬曬太陽。少數幾個很好的朋友都好久沒聯絡了，更不用說是認識&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;陌生人（鄉民）&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。回想一下 Teddy 賦閒在家的這一個月：&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;分別和兩位好友吃了午餐，並閒扯了 3 個小時。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;在 Facebook 上認識一位之前聽過 Teddy 演講的鄉民甲，這位&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民甲知道 Teddy 有胃潰瘍的毛病，介紹 Teddy 吃某種「偏方」。吃了兩個禮拜左右 Teddy 的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;胃好像真的有比較好耶（不過也可能是因為不用上班所以沒壓力胃潰瘍因而自然痊癒...XD）。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;某位有在看 Teddy 部落格的鄉民乙知道 Teddy 計畫出書，於是很熱心的把這個訊息告訴他們集團的出版社，讓 Teddy 省去了找出版社的時間（雖然出版社還沒決定是否出版 Teddy 的書 ...Orz）。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;另一位也是之前聽過 Teddy 演講而認識的鄉民丙知道 Teddy 這幾個月有時間可以提供軟體工程顧問服務，找了 Teddy 聊天並說服他老闆讓 Teddy 去教他們一些軟體設計的方法以及提供 Scrum 的諮詢服務（時間未定）。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;上禮拜五下午 Teddy 毛遂自薦跑去一家公司參觀人家的辦公室，邀請 Teddy 的人是之前去上 Certified ScumMaster 課程的同學，在此稱之為鄉民丁。Teddy 和鄉民丁彼此分享了執行 Scrum 的經驗，並且有幸可以觀察到他們實施 daily Scrum 的過程。該公司的辦公室是 Teddy 在台灣看過最「agile」的辦公室，很讚。Teddy 當場還被 &lt;strike&gt;ㄠ&lt;/strike&gt;&amp;nbsp;...嗯嗯...被邀請去使用他們公司的軟體（自己送上門的白老鼠），不過 &amp;nbsp;Teddy 給了幾點意見他們的技術人員表面接受但是內心似乎有點不服氣的樣子，就差沒有關門放狗...XD。 &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;今天下午跟另一位&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民戊聊天，聊天內容就不方便透露，不過真的是非常有趣的一次經驗。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Teddy 從來沒有想過可以跟「陌生人」聊得這麼開心，雖然和&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民甲與&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民乙&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;根本沒見過面，和&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民丙、丁&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;、&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;戊&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;也只是一面至數面之緣，但是卻聊得非常開心，也讓 Teddy 增廣了許多見聞&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。在硬體公司待了三年多的時間，Teddy 都快忘了做軟體的人長得什麼樣子了...Orz。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;最近 Teddy 一直在思考未來要做什麼，最想做的職業是自己開一家公司當「軟體工程顧問&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;，但是口袋不深的 Teddy 如果自己開一家這樣的公司，在台灣應該很快的就會餓死（誰管你開發軟體用什麼方法啊）。這兩天因緣際會之下突然有善心人士介紹 Teddy 一個不錯的工作，只要點頭馬上上班。Teddy 經過一番天人交戰，想一想還是「&lt;span class="Apple-style-span" style="color: blue;"&gt;沒有那個屁股就不要吃那個洩藥&lt;/span&gt;」，只能辜負&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;善心人士的好意了&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。哇哩勒，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;說好的清閒生活呢？&lt;/span&gt;」。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;這幾天一直在思考一個問題：&lt;span class="Apple-style-span" style="color: blue;"&gt;賺錢比較重要，還是興趣比較重要？&lt;/span&gt;廢話，當然是兩個都重要啊，這 Teddy 也知道，但是如果不幸只能選一個呢？奇怪了，軟體的問題隨便分析一下答案就出來了，怎麼人的問題那麼難搞啊。如果能夠買樂透隨便中個幾億就好了，那麼先把這輩子的生活費扣下來之後，Teddy 就可以把錢拿去完成另一個心願：&lt;span class="Apple-style-span" style="color: blue;"&gt;開一家做 open source 軟體的公司，直到錢燒光為止&lt;/span&gt;。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;想太多，套句老人家的話，還是「卡早睡，&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;卡有眠」吧&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br class="Apple-interchange-newline" /&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;友藏內心獨白：人生的 if-then-else 還真不好寫。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-5967702494572726450?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/5967702494572726450/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=5967702494572726450' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/5967702494572726450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/5967702494572726450'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/blog-post_09.html' title='今天好累'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-7451311289651799096</id><published>2012-01-08T11:00:00.003+08:00</published><updated>2012-01-08T11:07:08.946+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 不會幫你解決問題</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 08 09:18~11:00&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;看到本篇的標題「Scrum 不會幫你解決問題&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」鄉民們可以會想：「那我還學個屁啊」。嗯嗯...先不要急著轉台，看完之後再說。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;昨天是舉辦「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Scrum 軟體開發工具與方法—系列講座 (五)」的日子，Teddy 一早 10 點鐘就先到北科大找指導教授聊天，一直聊到下午 2 點講座快開始之前才「趕」到會場（因為舉辦講座的場地與&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;指導教授的研究室在&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;同一棟大樓）。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;昨天 Teddy 分享的題目是「使用Java與C/C++之跨平台軟體開發」，由於 Teddy 第一次分享這個主題，時間拿捏的不是很好（介紹 Teddy 坎坷身世的那一張投影片講太久了...Orz），最後還是有幾張投影片沒有講到。感謝主辦單位給 Teddy 的這機會練習（參加人員內心獨白：那我們不全成了白老鼠...XD）。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;活動結束之後有幾位鄉民跟 Teddy 討論幾個問題，其中有兩位鄉民問 Teddy &amp;nbsp;的兩個問題讓 Teddy 印象最為深刻。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民甲：我有一個系統以前是用 VB 開發的，現在要用 C# 改寫，而且要考慮系統擴充性的問題，有沒有什麼書可以看了之後可以解決我的問題。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 內心獨白：這和今天的主題或是 Scrum 好像沒有什麼關係耶。（這句話當然是放在心裡沒講出來...XD）&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;Teddy：可以請你把你的問題講得具體一點嗎？&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;鄉民甲：目前這個系統只有我一個人負責，我開發軟體有 10 幾年的經驗了，但是以前都沒有使用 OO（物件導向）的經驗，現在要把原本 VB 的程式用 C# 改寫。我設計了很多物件，但是可能是因為 OO 觀念不熟，再&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;加上改寫的過程中還要考慮新的功能還有系統架構的問題，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;所以改寫得很不順利。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;Teddy：你有看過 Teddy 的部落格嗎？（利用機會推銷一下）&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;鄉民甲：沒有。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;Teddy：那建議你回去先看一下 Teddy 的部落格。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;鄉民甲：!@#!$%@!#.....&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;Teddy：聽起來你的問題應該不是一本書可以解決的，比較像是物件導向分析設計與程式開發的問題。如果公司內部沒有具備這樣能力的人可以幫忙，也許你們應該找外面的顧問來協助。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;u&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;Teddy：又或者是你可以考慮到坊間的補習班去上課，這樣比起自學會比較快。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;鄉民甲：!@#%@!#!@S!@#。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;/div&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民乙：在 Scrum 中是誰負責定義需求？&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;Teddy：Product Owner。&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;鄉民乙：這個 Product Owner 是業務，PM（專案經理）還是....&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Teddy：就是&amp;nbsp;Product Owner。&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="-webkit-text-decorations-in-effect: none; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民乙：!@#$!@#=......&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="-webkit-text-decorations-in-effect: none; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy：請問你了解 Scrum&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;運作模式嗎？&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民乙：大概有看過。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民乙：那如果你的客戶很不講理，經常更改需求，Scrum 有什麼方法可以解決的嗎？&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="-webkit-text-decorations-in-effect: none; font-family: 'Times New Roman'; font-size: medium; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="-webkit-text-decorations-in-effect: none; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy：（把 sprint planning meeting 和 sprint demo 以及客戶應該要密切參與專案的觀念快速講過一遍 ）&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民乙：可是客戶就是很不講理啊，假設今天在 sprint planning meeting 剛剛談好也估完的 stories，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;客戶隔天還是要改變那怎麼辦？&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy：請問改變的理由是什麼？ &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;鄉民乙：沒有理由啊，就是他&lt;/span&gt;&lt;span class="Apple-style-span" style="color: blue; font-size: large;"&gt;爽&lt;/span&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;。&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 內心獨白：啊現在是什麼情況... &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;其實此時 Teddy 已經快沒力了，從早上 10 點到下午 4 點，Teddy 連續講了6小時的話，已經有點神智不清了。好里加在，此時有位想要找 Teddy 當「家教」的朋友（在2011年4月 MaoYang 所舉辦的 Scrum 分享活動中所認識的一位很有趣的鄉民）跳出來幫 Teddy 解危：&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;朋友：我幫 Teddy 回答一下，&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 曾經講過一句「至理名言」...&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy：真的嗎？那一句，我趕快拿筆記下來...XD。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;朋友：你自己講過的話還要自己記下來喔...XD。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Teddy：因為我講過的嘉言名錄太多了，多到自己都忘了...XD。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;言歸正傳...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;朋友：就是&lt;span class="Apple-style-span" style="color: blue;"&gt;「Scrum 本身不能幫你解決問題，但是可以幫你把問題暴露出來」&lt;/span&gt;。很多軟體開發所遭遇到的問題，其實專案團隊或是客戶都知道，但苦無沒有一個好的機制或是框架可以讓大家一起開誠布公的正視&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;、&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;溝通、討論&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;、&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;與改善這些問題。至於問題暴露出來以後要如何解決，就要靠團隊的努力（不然這些搞軟體工程方法和 agile practices 的人不是沒飯吃了）。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;/div&gt;&lt;div style="text-align: -webkit-auto;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; text-align: -webkit-auto;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;對對對，Teddy 都忘了曾經講過這句話：&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「Scrum 本身不能幫你解決問題，但是可以幫你把問題暴露出來」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。「沒有銀子彈（No Silver Bullet）」這句話鄉民們應該都知道，軟體開發不可能因為有了 Scrum 的出現所有問題就迎刃而解。就好像戰爭一樣，如果無法一舉殲滅敵人，就只能想辦法各個擊破。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;回到鄉民乙的問題，Teddy 不認識&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民乙的客戶，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;無法得知為何該客戶會因為一個「爽」字就要修改需求（難道&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民乙的客戶叫做史地芬周...XD&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;）。有可能是因為&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;該客戶之前所經手的軟體專案都不順利，所以對於軟體開發團隊抱持著不信任的態度。也有可能是客戶太忙，沒時間，或是沒人教他要如何思考與確定需求。所以導入 Scrum 還是要團隊依據自己的現況因地制宜的判斷與解決問題。&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民乙可以思考先提昇團隊所開發出軟體的品質，讓客戶感受到團隊的產出物（軟體或文件）品質變好，時程也沒有像之前延誤的那麼嚴重，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;也許慢慢地&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;客戶的態度也會跟著改變。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;話說回來，如果隨便把 Scrum 看一下軟體開發的問題就都解決了，那 Teddy 不就不用混了，可以改行賣雞排或是最近流行的滷味。難道要吧 Certified ScrumMaster 的證書貼在&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;滷味攤前面嗎...Orz。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;友藏內心獨白：演講費是不是要分 100 塊給幫 Teddy 回答問題的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;朋友。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-7451311289651799096?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/7451311289651799096/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=7451311289651799096' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7451311289651799096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/7451311289651799096'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/scrum.html' title='Scrum 不會幫你解決問題'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-3248963906215994478</id><published>2012-01-07T18:32:00.000+08:00</published><updated>2012-01-07T18:32:26.147+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體設計'/><title type='text'>亂談軟體設計之答客問：小鄭篇</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 06 21:42~23:05&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 07 18:29~18:32&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 部落格的文章一向都跟&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「剛出爐的麵包」一樣，做好之後熱騰騰的馬上販賣（熱熱吃比較好吃）。Teddy 使用 google blogger 所提供的 web 版陽春編輯器當場寫完之後當場發表，但最近考慮到「&lt;span class="Apple-style-span" style="color: blue;"&gt;美味關係宣言（2012 年每天至少要發表一篇文章）&lt;/span&gt;」，原本這種&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「每天供應現烤麵包」的策略可以需要改變一下，有時間的時候要先準備一點庫存，以免 Teddy 臨時有事，或是出外旅遊無法實現每天寫一篇的諾言。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;明天（禮拜六） Teddy 白天都有事情要忙，晚上回家之後應該也沒力寫部落格了，所以今天（禮拜五）先偷跑一下，「把明天的文章，今天就傳便便（準備好）」，&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;先先好存起來等明天早上再發布。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;今天（一月六日禮拜五）有位名叫&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;小鄭&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」&lt;/span&gt;的&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民&lt;/span&gt;（Teddy 內心獨白：&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;莉莉&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」還好吧...XD&lt;/span&gt;）&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;看了「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/6single-choice-principle.html" target="_blank"&gt;亂談軟體設計（6）：Single Choice Principle&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」之後留言問 Teddy：&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;小鄭問：&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;請教一下，這些原則基本上都是如此相似，基本原則就是要避免重複、發散，完成模組化的效果，為何需要發明出好幾個名詞呢？&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;我想了解的是，這些名詞似乎都可以在把握住模組化精神的前提下，隨著應用場景作出類似結論，實務上困難的往往是執行力與對所花心力的成本考量與取捨，有時甚至不易估算為達到某種彈性所花之心力是否合理。&lt;br /&gt;&lt;br /&gt;舉例來說，為何需要OCP這個名詞？一般都會知道當要引進新功能時，如果還要修改既有代碼，那麼表示既有代碼就還有進一步模組化的空間，但往往是在開發中期（或後期）才因帶入新需求然後發現要提供額外彈性的地方，然後我們透過重構去增加此彈性。令我不解的是，用既有知識與邏輯就可以很好解釋的概念，為何要"新增"名詞呢？&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;b&gt;Spirit Du 代答：&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;會有不同的名詞，是因為相同的想法在不同的context下有相似但不相同的表現，但不能因為相同的想法就用一個名詞代表所有｢相似但不相同｣的表現，不然就不知道是哪一種表現。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;Teddy 答：&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;你說得很對，其實這些設計原則講穿了都是為了達到『模組化』的目的。&lt;br /&gt;&lt;br /&gt;但是你說得「一般都會知道當要引進新功能時，如果還要修改既有代碼，那麼表示既有代碼就還有進一步模組化的空間」這一點 Teddy 並不同意。應該是你已經很有經驗了，所以直覺上會推導出上述的結論。&lt;span class="Apple-style-span" style="color: blue;"&gt;但是對於很多初學設計的人，或是經驗不是那麼豐富的人，他們會認為，「要加新功能就是要改原本的程式啊，不然要怎麼加？」&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;所以，有了這個設計原則（例如 OCP），就好像是 design patterns 一樣，有一個 common languages for communication。作為溝通，教育，反思之用。只要大家都等這樣的原則，設計出來的程式品質也會比較相近。&lt;br /&gt;&lt;br /&gt;不然的話，所有的設計原則最後只有一條「模組化設計」，其他的都可以省略了，但是這樣又太抽象啊。所以才需要根據這個最高指導原則（模組化設計）又衍生出那麼多設計原則。&lt;br /&gt;&lt;br /&gt;其實 Dprint Du 已經幫回答得很好了：『會有不同的名詞，是因為相同的想法在不同的context下有相似但不相同的表現，但不能因為相同的想法就用一個名詞代表所有｢相似但不相同｣的表現，不然就不知道是哪一種表現。』雖然這樣的回答還是有點抽象...XD。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;b&gt;小鄭再問：&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;多謝解釋，我經驗還嫩，只是一直有興趣而已。:-)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;BTW，其實我初看到 design patterns 時也有類似新增"名詞"的感覺 :P&lt;br /&gt;&lt;br /&gt;或許將這些觀念形成語彙並成為開發者的共通語言主要就是為了溝通，但對初學者而言，如果不透過相當份量的實作搭配，只怕真的會變成原則與阻礙，而不是會在實務上應用的手法。&lt;br /&gt;&lt;br /&gt;以新語彙提供概念然後在實作中印證比較好？還是隨著實作經驗引進最基礎的概念（模組化）比較好？或許因人而異，但我比較 prefer 後者的方式。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;b&gt;zwshen 插花：&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;這一切的一切，其實就是一個字：「道」。&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;只要你得道了，到達形而上的境界，就不會侷限於這些「器」了。&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;不過我想我還是需要好好硺磨這些「器」，希望有朝一日能得道啊...XD。&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 想講得是，學設計原理和實做兩者並不衝突，反而是可以相輔相成。這有一點像是論語裡面所說得「學而不思則罔，思而不學則殆」，總之就是「要學也要思，邊學邊思，邊思邊學」。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Teddy 舉個切身的例子，在 「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/5dependency-inversion-principle.html" target="_blank"&gt;亂談軟體設計（5）：Dependency-Inversion Principle&lt;/a&gt;」這篇文章中，Teddy &amp;nbsp;舉了個例子：&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;a href="http://1.bp.blogspot.com/-YLcy3jYQDJQ/TwcAUpNCZ6I/AAAAAAAAAtw/Hg8ZeA6g-bM/s1600/DIP-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="257" src="http://1.bp.blogspot.com/-YLcy3jYQDJQ/TwcAUpNCZ6I/AAAAAAAAAtw/Hg8ZeA6g-bM/s400/DIP-2.jpg" width="400" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;這個例子是從一個叫做 SyncFree 的開放原始碼軟體的設計圖中經過整理之後節錄出來的。Teddy 是這個軟體的第一代原始設計者（算一算又是 10 年前的事了...Orz），但是，上圖的設計（符合 DIP） 原本是長成這樣的：&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;a href="http://3.bp.blogspot.com/-1NpM2mRPZlU/TwcELXdB69I/AAAAAAAAAt4/6COAQCZlmmc/s1600/DIP-3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="346" src="http://3.bp.blogspot.com/-1NpM2mRPZlU/TwcELXdB69I/AAAAAAAAAt4/6COAQCZlmmc/s400/DIP-3.jpg" width="400" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;說實話當年 Teddy 沒有把 DIP 看的很懂，因為實做 IFileManipulate 介面的類別都放在 Mechanism Module （Java package）裡面，所以很自然地 Teddy 就把 IFileManipulate 介面也放到 Mechanism Module 裡面。這樣的結果就變成，high level modules depend on low level modules，違反了 DIP 原則。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Teddy 是何時才發覺到原本的設計違反 DIP？是後來看了 Matin Flower 的「&lt;a href="http://martinfowler.com/bliki/InversionOfControl.html" target="_blank"&gt;Inversion of Control&lt;/a&gt;」然後又想起之前看過的 DIP，又回頭把 DIP 再看一次，才發覺原來這個 IFilemanipulate 擺錯位置了。說真的，&lt;span class="Apple-style-span" style="color: blue;"&gt;如果 Teddy 沒有看過這個（或是說，這些）設計原則，很有可能 Teddy 會一直維持原本的設計&lt;/span&gt;。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="font-size: medium; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br class="Apple-interchange-newline" /&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;最後剩下一個問題，Teddy 原本的設計就算是違反 DIP 好了，那又怎樣？&lt;/span&gt;&lt;strike style="font-size: 15px;"&gt;咬我啊&lt;/strike&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;...嗯嗯...說真的，是不會怎樣，所以 Teddy 一直沒發覺有何不妥。因為原本的設計某種程度是有符合 Open-Closed&amp;nbsp;Principle，只不過是把 IFilemanipulate 擺錯模組有那麼嚴重嗎？&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;假設今天有另外一個團隊，要開發新的實做，例如支援將檔案同步到雲端，於是這個團隊就需要去參考到&amp;nbsp;IFilemanipulate 介面。如果&amp;nbsp;IFilemanipulate 介面放到 Mechanism 模組，那麼&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;模組相依關係就會變成：&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;a href="http://3.bp.blogspot.com/-oZTgnV8rqXA/TwcKjzWJNrI/AAAAAAAAAuY/BItuBsBVMbU/s1600/DIP-4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="338" src="http://3.bp.blogspot.com/-oZTgnV8rqXA/TwcKjzWJNrI/AAAAAAAAAuY/BItuBsBVMbU/s640/DIP-4.jpg" width="640" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;Mechanism Module 2 變成相依於原本的 Mechanism Module，這樣的相依關係感覺就是有點怪怪的（因為某個底層的模組改變，而可能導致上層模組與其他的底層模組也改變了）。如果改成符合 DIP 的話：&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;a href="http://1.bp.blogspot.com/-xctL7W-SKu0/TwcKehg2aHI/AAAAAAAAAuQ/pRN15tJ43qg/s1600/DIP-5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="248" src="http://1.bp.blogspot.com/-xctL7W-SKu0/TwcKehg2aHI/AAAAAAAAAuQ/pRN15tJ43qg/s640/DIP-5.jpg" width="640" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;這種相依性關係就變得比較「乾淨」。&lt;span class="Apple-style-span" style="color: blue;"&gt;當專案裡面有很多模組的時候，模組之間的相依性管理就會變成一個很重要的課題&lt;/span&gt;。如果能夠把模組相依性控管的比較好一點，對於軟體的施工（同一個團隊內的派工或是切割給其他團隊去實做）、持續整合與建構、產生安裝程式與系統佈署等等都有好處。&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium;"&gt;&lt;div style="font-size: medium; text-align: center;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;至於何時要學這些設計原則呢，Teddy 也沒有正確的答案。之前 Teddy 在唸書的時候曾經跟研究所碩士班的學弟介紹過這些原則（3-6 個小時），一般的 programmers 應該只要學過基本的物件導向觀念也都可以理解。既然學這些設計原則花不了太多的時間，Teddy 還是會建議，有機會的話，早點了解也沒什麼不好，因為任何的設計技巧，都是需要時間&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;「發酵（醞釀）」，沒人說要學一次就馬上學會啊，但早點接觸，在做案子的時候，可以激發一下利用機會驗證與釐清這些設計原則&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;友藏內心獨白：總之還是要多看書多寫程式&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-3248963906215994478?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/3248963906215994478/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=3248963906215994478' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/3248963906215994478'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/3248963906215994478'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/blog-post.html' title='亂談軟體設計之答客問：小鄭篇'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-YLcy3jYQDJQ/TwcAUpNCZ6I/AAAAAAAAAtw/Hg8ZeA6g-bM/s72-c/DIP-2.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-8412987341534379236</id><published>2012-01-06T12:29:00.001+08:00</published><updated>2012-01-06T13:39:15.061+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體設計'/><title type='text'>亂談軟體設計（6）：Single Choice Principle</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 06 10:28~12:28&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;今天先把課本換成 Object-Oriented Software Construction, 2nd 來看一下&amp;nbsp;&lt;span class="Apple-style-span" style="color: blue;"&gt;Single Choice Principle&lt;/span&gt;。原本以為這個設計原則比較容易寫，但是為了寫這一篇 Teddy 又把課本的 61-63 頁看了一次，覺的還是有點虛虛的（還好本系列主題是「&lt;span class="Apple-style-span" style="color: blue;"&gt;亂談&lt;/span&gt;」軟體設計...XD）。後來用 google 找了一下，看到兩篇有趣的討論：&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;a href="http://c2.com/cgi/wiki?SingleChoicePrinciple"&gt;http://c2.com/cgi/wiki?SingleChoicePrinciple&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;a href="http://www.geocities.com/tablizer/meyer1.htm#singlechoice"&gt;http://www.geocities.com/tablizer/meyer1.htm#singlechoice&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;這兩篇討論的內容有興趣的鄉民請自行參閱，Teddy 分享一下自己對於此原則的簡單認知。先看一下課本 63 的定義：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Single Choice Principle&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;Whenever a software system must support a set of alternatives, one and only one module in the system should know their exhaustive list.&lt;/i&gt;&lt;/div&gt;&lt;div&gt;（當一個軟體系統必須要支援一組替代方案的時候，系統中應該只有一個模組知道這些替代方案的所有清單。）&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;依照往例，看完定義之後還是不知道這個原則是什麼東東，看例子比較快。還記得之前在「&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/4.html" target="_blank"&gt;亂談軟體設計（4）：Liskov Substitution Principle&lt;/a&gt;」提過的繪圖系統範例嗎？&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;假設鄉民們要設計一個&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;繪圖系統，可以畫圓（Circle）與正方形（Square）等形狀，於是&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民們設計了一個父類別叫做 Shape（形狀），然後讓 Circle 與 Square 都繼承自 Shape。&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-DejJjHQiX9M/TwZnA2saNSI/AAAAAAAAAto/oE8CIuPodaE/s1600/liskov-1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="189" src="http://1.bp.blogspot.com/-DejJjHQiX9M/TwZnA2saNSI/AAAAAAAAAto/oE8CIuPodaE/s200/liskov-1.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;這些畫在螢幕上的圖，最後被存成文字檔案。文字檔內容長成類似下面這樣子：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;define shape {&lt;/div&gt;&lt;div&gt;type=circle&lt;/div&gt;&lt;div&gt;location=25,6&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;define shape {&lt;/div&gt;&lt;div&gt;type=square&lt;/div&gt;&lt;div&gt;location=36,10&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;現在鄉民們要寫程式把這段文字檔的內容讀出來，然後把檔案中所紀錄的圖形畫在畫面上，其中有一段程式可能長成下面這樣：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;List&lt;shape&gt; shapes = new ArrayList&lt;shape&gt;();&lt;/shape&gt;&lt;/shape&gt;&lt;/div&gt;&lt;div&gt;if (type=="circle") then {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;shapes.add(new Circle(...));&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;else if (type=="square") then {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;shapes.add(new Square(...));&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;...&lt;/div&gt;&lt;div&gt;else if (type=="XXX") then &amp;nbsp;{&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp;shapes.add(new XXX(...));&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;為了把所有的圖形物件都讀出來，上面這段程式必須要「詳盡列舉（know their exhaustive list）」出所有 Shape 類別的子類別（a set of alternatives）。看到這邊有鄉民會說，這種 if then else 的寫法，不是 OO（物件導向）的程式。說得很對，Teddy 曾經在某本書（又忘了是那一本）看到一種說法：「&lt;span class="Apple-style-span" style="color: blue;"&gt;物件導向程式設計就是要把程式中的 if-then-else（或是 switch-case）全部拿掉&lt;/span&gt;」。這可能嗎？至少上面這段程式碼是可能的，要如何做？先看一個不花腦經的範例：&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;首先，幫產生每個物件的這段程式（例如&amp;nbsp;new Circle(...)）用一個 Command pattern 包起來，例如：&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; interface IShapeFactory{&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Shape newInstance(argumens...);&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;blockquote class="webkit-indent-blockquote" style="border: none; margin: 0 0 0 40px; padding: 0px;"&gt;&lt;div&gt;&lt;div&gt;class SquareFactory&amp;nbsp;implements IShapeFactory{&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;public Shape newInstance(argumens...) {&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;return new Square(argumens);&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;br /&gt;&lt;blockquote class="webkit-indent-blockquote" style="border: none; margin: 0 0 0 40px; padding: 0px;"&gt;&lt;div&gt;&lt;div&gt;}&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;然後宣告一個&amp;nbsp;HashMap&lt;string,&amp;nbsp;ishapefactory&gt;&amp;nbsp;，HashMap 的 key 存放 Shape type name，value 存放&amp;nbsp;IShapeFactory 的實做（implementation，例如&amp;nbsp;SquareFactory）。&lt;/string,&amp;nbsp;ishapefactory&gt;&lt;/li&gt;&lt;li&gt;接著初始化這個 HashMap。&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;HashMap&lt;string,&amp;nbsp;ishapefactory&gt; factoryMap = new LinkedHashMap&lt;string,&amp;nbsp;ishapefactory&gt;();&lt;/string,&amp;nbsp;ishapefactory&gt;&lt;/string,&amp;nbsp;ishapefactory&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;factoryMap.add("square", new&amp;nbsp;SquareFactory() );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;factoryMap.add("circle", new&amp;nbsp;CircleFactory() );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;...&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;factoryMap.add("XXX", new XXXFactory() );&lt;/span&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;然後就可以用一個迴圈（loop）來取代原本的 if-then-else&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; List&lt;shape&gt; shapes = new ArrayList&lt;shape&gt;();&lt;/shape&gt;&lt;/shape&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for (String shapesFromFile: shape) {&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if &amp;nbsp;factoryMap.containsKey(shape) {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;shapes.add(factoryMap.get(shape).newInstance(...));&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;throw new RuntimeException("Unsupported shape: " + shape);&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/div&gt;&lt;div style="text-align: center;"&gt;***&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;不管是那一種方法，程式中都有一個地方需要去「&lt;span class="Apple-style-span" style="color: blue;"&gt;詳盡列舉（know their exhaustive list）出所有 Shape 類別的子類別（a set of alternatives）&lt;/span&gt;」（範例一的 if-then-else 以及範例二標成藍色的那幾行字）。就算是鄉民們把範例二標成藍色的那幾行字從程式碼中抽離出來放到設定檔中，還是需要在設定檔中列舉出所有 Shape 類別的子類別。&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;結論就是，Single Choice Principle 告訴我們，當有這樣的情況出現的時候，one and only one module in the system should know their exhaustive list，為什麼？因為這個列表可能會隨著時間而改變，例如，假設原本繪圖系統不支援多邊形（Polygon），但是後來因為客戶要求而加入了&amp;nbsp;Polygon 這個繪圖類別。如果程式中有一個以上的地方都必需要列舉出所有 Shape 類別的子類別，那麼當新增了&amp;nbsp;Polygon 類別之後，就要記得去改到每一個需要修改地方，這樣的程式是很容易出現 bugs 的。&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;***&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;又是扯了一堆，其實&amp;nbsp;Single Choice Principle 可以簡單看成是一種對於「&lt;span class="Apple-style-span" style="color: blue;"&gt;避免重複程式碼（duplicated code）&lt;/span&gt;」的特殊要求。因為如果程式可以做到&amp;nbsp;Single Choice Principle，除了可以避免 duplicated code 以外，還可以支援之前介紹過的「&lt;a href="http://teddy-chen-tw.blogspot.com/2011/12/2.html" target="_blank"&gt;Open-Closed Principle&lt;/a&gt;」。為什麼，請鄉民們花一分鐘想一下。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;其實答案很簡單，就在 Teddy 前面舉的那兩個程式範例中。Teddy 之前提過 Open-Closed Principle 的最高境界：&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;藉由&lt;span class="Apple-style-span" style="color: blue;"&gt;增加新的程式碼&lt;/span&gt;來擴充系統的功能，而&lt;span class="Apple-style-span" style="color: blue;"&gt;不是藉由修改原本已經存在的程式&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;碼&lt;/span&gt;來擴充系統的功能&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;(&amp;nbsp;If the OCP is applied well, then further changes of that kind are achieved by adding new code, not by changing old code that already works.)&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;對啊，在繪圖系統的例子中，理想上鄉民們可以藉由新增一個&amp;nbsp;Polygon 類別，然後把這個&amp;nbsp;Polygon&amp;nbsp;類別「外掛」到系統中，不用修改系統的程式就以擴充新的功能。但是，實際上還是要有人去負責處理這些「外掛」，不管這些處理外掛的邏輯是直接寫成 if-then-else，或是用比較物件導向的方法用迴圈取代，或是寫在外部設定檔中（ini 檔或是 xml &amp;nbsp;檔案），如果能做到&amp;nbsp;Single Choice Principle，只有一個人（程式模組）需要知道處理這些所有外掛的邏輯，那麼這樣的設計就算是有支援到&amp;nbsp;Open-Closed Principle。&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;講完收工，吃中飯去。&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;***&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;友藏內心獨白：以前都是寫完睡覺，現在變成&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;寫完&lt;/span&gt;吃中飯&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-8412987341534379236?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/8412987341534379236/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=8412987341534379236' title='9 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8412987341534379236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/8412987341534379236'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/6single-choice-principle.html' title='亂談軟體設計（6）：Single Choice Principle'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-DejJjHQiX9M/TwZnA2saNSI/AAAAAAAAAto/oE8CIuPodaE/s72-c/liskov-1.jpg' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-2914762960674354023</id><published>2012-01-05T12:30:00.000+08:00</published><updated>2012-01-05T12:30:27.111+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（5）：初探 Sprint Planning Meeting</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 05 11:23~12:30&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;今天介紹一下&amp;nbsp;Sprint Planning Meeting，請參考下圖：&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-bucn5xYfF7g/TwUZPaCTiUI/AAAAAAAAAtE/uST26bKdRdU/s1600/scrum-process-v0.3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="441" src="http://3.bp.blogspot.com/-bucn5xYfF7g/TwUZPaCTiUI/AAAAAAAAAtE/uST26bKdRdU/s640/scrum-process-v0.3.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;b&gt;Sprint Planning Meeting&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;開始時間&lt;/b&gt;：每個 sprint 開始的第一天舉辦此會議。Teddy 的經驗是每雙週的週一（Teddy 採用長度為兩週的 sprint）早上 10:00 開始 sprint planning meeting。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;參加人員&lt;/b&gt;：Product Owner、Scrum Master、Developers。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;會議目的&lt;/b&gt;：&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;會議目的是產生一份 sprint backlog（包含每個 story 細分之後的施工項目）讓 Developers 可以開工。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;進行方式（1）&lt;/b&gt;：由&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Product Owner 逐一詳細介紹這個 sprint 要施工的每一個 stories，並且與 Developers 互動，如果 Developers 對於 stories 內容不了解一定要發問。 介紹完之後 Developers 開始估計每一個 story 的 story point（story point 也可能在之前的 product backlog refinement meeting 就已經先估好了，但此時還是可以重估）。此階段通常需要 2-4 小時。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;b&gt;進行方式（2）&lt;/b&gt;：估算好 story point 之後，接著寫出每一個 story 的施工項目（task）。例如鄉民們要開發一個網路銀行的系統，有一個 story 是 As a user, I can view today's transaction records，那麼要完成這個 story 可能的 tasks 就有設計 UI、實做 UI 程式、寫 DAO（data access object，假設資料庫 schema 已經設計好了）、寫自動化功能測試等等。所有的 tasks 都寫好之後要開始估算完成每一個 task 所需的時間（以小時為單位）。&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;此階段通常需要 2-4 小時。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;結尾前&lt;/b&gt;：Stories 與 tasks 都估算好之後，可以準備結束會議了。在散會之前 Teddy 會請 Developers 先認領一下要施工的 tasks。以 Teddy 的經驗，如果是 10:00 開始 sprint planning meeting，通常在 15:30~16:30 左右會議就可以結束了（有時候甚至會提早在 15:00 就結束了），所以當天還有幾個小時可以施工。因此會請 Developers 在離開會議適之前先認領準備要施工的 tasks 並且在該 task 上面簽名。&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;b&gt;結尾後&lt;/b&gt;：Teddy 有使用 ezScrum 這套工具來管理 stories 與 tasks，所以會議結束之後 Teddy（Scrum Master）會把 stories 與 tasks 的資料打到 ezScrum 系統中，大概需要 20-30 分鐘。此外，Teddy 也有使用實體的 task baord，就是在一塊白板上面把 Stories 與 tasks 都貼上去。所以，在把資料打入 ezScrum &amp;nbsp;之後，Teddy 就會把這些實體的 story cards 與 tasks（寫在 3M 小紙條上&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;）貼到白板上面。附帶說明一下，每一張 story card 與 task 一定要用「小磁鐵」固定在白板上，否則過幾天之後很容易跟秋天的楓葉一樣，掉滿地...Orz。&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;關於 story points 與 tasks 的估算方法請參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/05/story-point.html" target="_blank"&gt;如何估算 story point？&lt;/a&gt;」與「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/07/story-point.html" target="_blank"&gt;Story point 為何沒有單位：相對論篇&lt;/a&gt;」。以下是 ezScrum &amp;nbsp;軟體以及實體 task board 的參考畫面。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-XsDxANLuXwU/TwUkWvuKSPI/AAAAAAAAAtQ/7PYvQueoXIE/s1600/ezScrum-TaskBoard.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="321" src="http://4.bp.blogspot.com/-XsDxANLuXwU/TwUkWvuKSPI/AAAAAAAAAtQ/7PYvQueoXIE/s640/ezScrum-TaskBoard.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;ezScrum 畫面，資料來源：&lt;a href="http://scrum.tw/images/ezScrum/TaskBoard.png"&gt;http://scrum.tw/images/ezScrum/TaskBoard.png&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Cks6nS73DQo/TwUlWzwqEGI/AAAAAAAAAtc/OfB2It2snWg/s1600/physical-task-board.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://2.bp.blogspot.com/-Cks6nS73DQo/TwUlWzwqEGI/AAAAAAAAAtc/OfB2It2snWg/s400/physical-task-board.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;實體的 task board，資料來源：&lt;/span&gt;&lt;/span&gt;&lt;a href="http://scrum.tw/"&gt;http://scrum.tw&lt;/a&gt;&amp;nbsp;網站&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;有的人會把 sprint planning meeting 分成「上半場與下半場&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」，也就是 Teddy 上面所說得&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;進行方式（1）與進行方式（2）&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」，然就建議 Product Owner 只需要&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;「上半場&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」在場就可以了，之後估算 tasks 的活動如果&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Product Owner 需要趕場的話就可以離開&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。不過以 Teddy 的經驗，很多對於需求的問題都是&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;在&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;下半場&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;估算 tasks 的時間才會冒出來，所以 Teddy 覺的&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Product Owner 最好全程都在會比較好一點。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;另外，如果團隊剛開始導入 Scrum，極有可能會覺的很難估算 story points 與 tasks，會有好幾個 sprints 的陣痛期每次&amp;nbsp;Sprint Planning Meeting&amp;nbsp;都搞得很痛苦，甚至會覺的時間不夠用無法在一天內完成。（&lt;span class="Apple-style-span" style="color: blue;"&gt;迷之音：此為正常現象，請安心服用&lt;/span&gt;）。Teddy 剛開始採用 Scrum 的時候也有類似的困擾，但是時間一久這個問題就消失了。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Sprint Planning Meeting 在 Scrum 中是一個很重要的活動，因為後續的開發活動都仰賴這個會議所產生的 sprint backlog。在傳統的 waterfall &amp;nbsp;開發方式中，當 Developers 拿到所謂的「分析設計文件」的時候，他們的腦袋中可能對於接下來要如何施工還是一片空白。但在 Scrum 中由於有了Sprint Planning Meeting&amp;nbsp;這個活動，每個 Developers 去認領 tasks 時其實對於要做什麼事情自己心中多多少少已經有了底（當然在實際施工的時候還是有可能有問題產生），所以相較起來後續的施工問題會少很多。所以 Teddy 覺的&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Sprint Planning Meeting&amp;nbsp;真的是一個很偉大的發明...XD。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: 'Times New Roman'; font-size: medium; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;今天先講到這裡，之後再補充 Sprint Planning Meeting 的其他細節。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;友藏內心獨白：有時候選擇太多也是一種困擾。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-2914762960674354023?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/2914762960674354023/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=2914762960674354023' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/2914762960674354023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/2914762960674354023'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/scrum-5-sprint-planning-meeting.html' title='Scrum 是什麼（5）：初探 Sprint Planning Meeting'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-bucn5xYfF7g/TwUZPaCTiUI/AAAAAAAAAtE/uST26bKdRdU/s72-c/scrum-process-v0.3.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-4073128056031050258</id><published>2012-01-04T11:15:00.000+08:00</published><updated>2012-01-04T11:15:41.195+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='軟體設計'/><title type='text'>亂談軟體設計（5）：Dependency-Inversion Principle</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;January 04 09:18~11:15&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;最近為了整理「亂談軟體設計&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」這一系列的文章，回頭把&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Agile Software Development 以及&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Object-Oriented Software Construction, 2nd 又稍微翻了一下。Teddy 第一次看到&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Agile Software Development 書中所提的幾個設計原則大概是在 10-12 年前，第一次接觸的時候對於某些&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;設計原則還是處於似懂非懂的階段，這麼多年下來這些&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;設計原則也陪了 Teddy 經歷過許多軟體開發專案，慢慢地融入 Teddy 的潛意識中&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Design Patterns 雖然好用，當&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民們可以直接說出這邊需要一個「Observer」或是&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「Command」的時候，設計問題看起來立即就獲得解決。但有時候遭遇到的&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;設計問題不是那麼明顯地可以立即套用 patterns，或是套用 patterns 之後可能會有誤用與互相牴觸的時候，亦或是當鄉民們需要幫其他人做 design review 或是 code review 的時候，這些&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;設計原則就可以跳出來幫上忙（打架的時候人多一點總是比較好滴...XD）。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;今天要談的是 The Dependency-Inversion Principle，內容請參考 Agile Software Development 這本第 127-134 頁：&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;DIP：The Dependency-Inversion Principle&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;High-level modules should not depend on low-level modules. Both should depend on abstractions.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;Abstractions should not depend on details. Details should depend on abstractions.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;DIP 的中文有人翻成「依賴倒轉原則&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;、&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;相依性反向原則&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;」&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;、&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;依存關係反轉原則&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;」&lt;/span&gt;&lt;strike&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;、&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;玩具反斗原則&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;」&lt;/span&gt;&lt;/strike&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;，如果一定要說中文，鄉民們就隨便自己挑一個喜歡的翻譯去記吧。這個原則聽起來很奇怪，不過了解之後就會發現怎麼又是在說同樣一件事，什麼事？就是：&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;program to an interface, &amp;nbsp;not an implementation（有種鬼打牆的感覺...XD）&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;這幾年拜房價飛漲之賜，都更建案如雨後春筍般的冒出，隨便在路上逛一逛都可以看到好幾個新屋施工的建案。&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;鄉民們不用是建築師也都知道，要蓋房子，地下室沒蓋好之前不能蓋一樓，&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;一樓沒蓋好之前不能蓋二樓，以此類推。所以說，&lt;span class="Apple-style-span" style="color: blue;"&gt;一個大樓的高樓層（h&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;igh-level modules&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;）相依於低樓層（&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;low-level modules&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;）&lt;/span&gt;，這是一般大家所認知的相依性關係。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;舉個軟體的例子，假設鄉民們要開發一個檔案同步軟體，這個&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;檔案同步軟體可以同步來源端與目的端資料夾中的檔案。為了簡化起見，這個軟體只有兩個模組（如下圖所示），Policy module 決定了同步的策略，例如，SimpleCopy 策略只負責將&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;來源端的資料複製到&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;目的端（單向複製），而 Synchronize 策略則會保證&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;來源端與目的端中的資料在同步之後會完全相同（雙向同步）。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Policy module 中的這兩種策略，都必須依靠 Mechanism Module 中的元件來實際執行檔案操作的動作。例如，使用 Java 的 IO 或是 NIO 物件來&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;操作檔案。因此，我們說上層的&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Policy&amp;nbsp;Module&amp;nbsp;相依於底層的&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;Mechanism Module（high-level modules depend on low-level modules）。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-AKK_OlLX62s/TwO59da9TiI/AAAAAAAAAss/B1whEfaJHQY/s1600/DIP-1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="167" src="http://4.bp.blogspot.com/-AKK_OlLX62s/TwO59da9TiI/AAAAAAAAAss/B1whEfaJHQY/s400/DIP-1.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;這聽起來好像是廢話，因為上層的模組一定會需要用到下層&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;模組提供的服務啊，所以當然是&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;上層模組會相依於下層&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;模組啊，不然程式要怎麼寫？這就是 DIP 這個原則會叫做 DIP 的原因，DIP 告訴我們，這樣的相依關係（上層相依於底層）要「&lt;span class="Apple-style-span" style="color: blue;"&gt;反過來&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;」。但是也不能說直接反過來變成&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;底層&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;相依於&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;上層，而是要變成&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;「&lt;/span&gt;&lt;span class="Apple-style-span" style="color: blue;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;底層與&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;上層都&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;相依於抽象介面（abstractions）&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;」，請參考下圖。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-f3A204jg-bk/TwO98_O97yI/AAAAAAAAAs4/Fq_ObXVMrLI/s1600/DIP-2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="257" src="http://1.bp.blogspot.com/-f3A204jg-bk/TwO98_O97yI/AAAAAAAAAs4/Fq_ObXVMrLI/s400/DIP-2.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;把處理檔案這件事情（這個責任）抽離出來定義成 IFileManipulate 介面（interface），讓上層的 Policy&amp;nbsp;Module&amp;nbsp;要處理檔案的時候只使用&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&amp;nbsp;IFileManipulate 介面所提供的服務，不要跟之前一樣直接去操作 Java 的 IO 或 NIO 物件。底層 Mechanism&amp;nbsp;Module&amp;nbsp;可以提供多個&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;IFileManipulate 介面的實做（implementation），例如可以透過 File、HTTP、FTP 等通訊協定來操作檔案的實做。如此一來整個系統就變得比較有彈性且容易擴充。&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;***&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;看到這邊這種設計不是&amp;nbsp;program to an interface, &amp;nbsp;not an implementation 那還是什麼？在更進一步往下看，這樣的設計也符合&amp;nbsp;&lt;a href="http://teddy-chen-tw.blogspot.com/2011/12/2.html" target="_blank"&gt;Open-Closed Principle&lt;/a&gt;（open for extension, but closed for modification）。&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;如果要擴充不同的檔案同步機制，只要在 Mechanism&amp;nbsp;Module&amp;nbsp;中「外掛」新的&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&amp;nbsp;IFileManipulate 介面的實做就可以了（&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;open for extension&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;），不需要去修改原本已經可以正常運作的程式碼（&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;closed for modification&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;）。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;在靠....近一點看，上述好處要能夠成立，整個設計與實做必須要符合&amp;nbsp;&lt;a href="http://teddy-chen-tw.blogspot.com/2012/01/4.html" target="_blank"&gt;Liskov Substitution Principle&lt;/a&gt;（Subtypes must be substitutable for their base types），以確保底層的實做會遵守上層介面所定義的&lt;span class="Apple-style-span" style="color: blue;"&gt;行為&lt;/span&gt;。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;看這一集等於連續看了三集，CP &amp;nbsp;值還滿高的，如果沒看懂仔細多看幾遍，如果&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;都還看得懂，恭喜老爺賀喜夫人你們已經免費學會了最重要的幾點物件導向設計原則了。&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-size: 14px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px; text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br class="Apple-interchange-newline" /&gt;***&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: xx-small;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;友藏內心獨白：原來這些原則彼此之間也有相依性的關係喔&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;。&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 14px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: xx-small;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1298974142445162186-4073128056031050258?l=teddy-chen-tw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://teddy-chen-tw.blogspot.com/feeds/4073128056031050258/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1298974142445162186&amp;postID=4073128056031050258' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/4073128056031050258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1298974142445162186/posts/default/4073128056031050258'/><link rel='alternate' type='text/html' href='http://teddy-chen-tw.blogspot.com/2012/01/5dependency-inversion-principle.html' title='亂談軟體設計（5）：Dependency-Inversion Principle'/><author><name>Teddy</name><uri>http://www.blogger.com/profile/02066842119056439711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='http://4.bp.blogspot.com/_wUcqQ6-dTE8/TKX5M0qBDEI/AAAAAAAAAZk/XpX71xqpcBA/S220/teddy-3.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-AKK_OlLX62s/TwO59da9TiI/AAAAAAAAAss/B1whEfaJHQY/s72-c/DIP-1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1298974142445162186.post-7768158093389769327</id><published>2012-01-03T10:36:00.001+08:00</published><updated>2012-01-04T09:13:08.546+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Scrum 是什麼（4）：Product Backlog</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;January 03 08:46~10:35&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;前幾集介紹了 Scrum 雙回饋機制與 Scrum 的內涵，包含角色、產出物與活動，這一集依照順序應該要提到當鄉民們要在專案中開始採用 Scrum 時，要如何開始第一個 sprint。不過 Teddy 之前已經先偷跑談過&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif; font-size: 15px;"&gt;這個問題了，請參考「&lt;a href="http://teddy-chen-tw.blogspot.com/2010/03/sprint.html" target="_blank"&gt;萬事起頭難：如何開始第一個 Sprint？&lt;/a&gt;」與&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Trebuchet MS', Trebuchet, Verdana, sans-serif;"&gt;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;「&lt;a href="http://teddy-chen-tw.blogspot.com/2011/06/iteration-0.html" target="_blank"&gt;Iteration 0 要幹麼？&lt;/a&gt;」，所以本集 Teddy 就來談一下 product Backlog。&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="fo
