l

2012年9月28日 星期五

尋找Force實驗2:State Pattern篇

Sept. 27 14:51~16:40

image

 

昨天Teddy在《尋找Force:Observer篇》中舉了Observer pattern為例子,說明GoF的pattern寫作格式中,Motivation章節相對於Teddy之前提到的pattern六大元素裡面的force。如果《尋找Force:Observer篇》鄉民們有看懂的話,可能會有一個疑問:

這該不會是碰巧運氣好才在Observer pattern的Motivation找到force的吧?!

昨天寫完《尋找Force:Observer篇》之後Teddy也有同樣的疑惑,那今天就找另外一個有點小複雜但卻十分有用的State pattern來做第二個實驗。今天先從Intent改起(把Intent改成Problem)。

Intent

Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

修改後:How do you allow an object to alter its behavior when its internal state changes? (後面那句可省略)

中文:要如何讓一個物件的行為隨著內部狀態改變而跟著改變?

接下來看一下GoF書中State pattern的Motivation。

Motivation

Consider a class TCPConnection that represents a network connection. A TCPConnection object can be in one of several different states: Established, Listening, Closed. When a TCPConnection object receives requests from other objects, it responds differently depending on its current state. For example, the effect of an Open request depends on whether the connection is in its Closed state or its Established state. The State pattern describes how TCPConnection can exhibit different behavior in each state.

The key idea in this pattern is to introduce an abstract class called TCPState to represent the states of the network connection. The TCPState class declares an interface common to all classes that represent different operational states. Subclasses of TCPState implement state-specific behavior. For example, the classes TCPEstablished and TCPClosed implement behavior particular to the Established and Closed states of TCPConnection.

The class TCPConnection maintains a state object (an instance of a subclass of TCPState) that represents the current state of the TCP connection. The class TCPConnection delegates all state-specific requests to this state object. TCPConnection uses its TCPState subclass instance to perform operations particular to the state of the connection.

Whenever the connection changes state, the TCPConnection object changes the state object it uses. When the connection goes from established to closed, for example, TCPConnection will replace its TCPEstablished instance with a TCPClosed instance.

抱歉,Teddy能力有限,從上面的段落中完全找不到任何一個force…Orz。

請問一下鄉民,State pattern的Motivation章節看起來比較像什麼?

沒錯,比較像是Solution的範例

***

既然在Motivation找不到force,請問鄉民下一個尋找的章節是哪一個?

答對了,就是Applicability

鄉民甲:為什麼?

Teddy:還記得Teddy在《Force是什麼?》有提到一個問題「force和context很像耶,好像可以把force放到context裡面,也可以把context裡面的東西變成force。要如何判斷?」先不要管這個問題的答案,至少這個問題提供給鄉民們一個線索,在Motivation找不到force的話,那就到Context去找吧。GoF的pattern寫作格式中,Applicability相等於Context,所以接下來看一下State pattern的Applicability。

Applicability

Use the State pattern in either of the following cases:

  • An object's behavior depends on its state, and it must change its behavior at run-time depending on that state.
  • Operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State pattern puts each branch of the conditional in a separate class. This lets you treat the object's state as an object in its own right that can vary independently from other objects.

GoF書中記錄的Applicability有兩點,第一點翻成中文的意思是「一個物件的行為和物件本身的狀態有關係;在執行期間,物件的狀態若是改變,則其行為也會跟著改變」。這一點是描述一個事實,比較像是Context。第二點就比較可以找到force,請觀察這一句:

Operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure.

為了讓物件的行為可以隨著狀態改變,一個很簡單的做法就是物件的operation(method或是member function)程式碼裡面有著一個很大的條件判斷式(if-then-else或是switch case)。在不同的物件狀態之下,程式會執行條件判斷式的不同區塊。這還不打緊,問題是相同的條件判斷式結構,會出現在這個物件身上好幾個不同的operation中。這就形成了眾所皆知的duplicated code這個程式碼壞味道了。

扯這麼多,那State pattern的force是什麼?以下是Teddy所推敲的force:

  • 在物件的operation中使用條件判斷式,並依據狀態改變物件行為的這種作法雖然很直覺且簡單,但是會造成物件不同的operation中會出現多處重複的條件判斷式,造成日後維護與擴充的困難度。
  • 由於物件的行為隨著狀態而變,因此若是一個物件的所有行為全部都放在物件自己身上,則容易造成單一物件程式碼太長,同樣增加維護與擴充的困難度。
  • 當物件狀態很多的時候,如果狀態改變的邏輯無法很清楚的被表達出來,則程式可能不容易被理解。

***

State pattern的解決方案Teddy就不在這裡說明(鄉民:不在這裡說明那是要在哪裡說明?挑眉質疑),不然這一篇會寫不完啊。如果知道State pattern的鄉民們,請看一下這三個force,然後思考一下State pattern的solution是否有解決上面這三個force?

螢幕快照 2012-09-26 下午5.25.40

圖片來源:http://upload.wikimedia.org/wikipedia/commons/e/e8/State_Design_Pattern_UML_Class_Diagram.svg

***

做完這個實驗,Teddy才發現一個問題。GoF的《Design Patterns》這本書Teddy也買了超過15年,看了不下N次。這本書寫的真的很棒,但是說真的不是很容易讀懂(有些鄉民讀起來覺得在看天書)。之前Teddy的第一個反應是:「啊,這本書中的C++例子舉的不是很好,所以不容易理解」。但是,就算是讀了其他書籍,像是《大話設計模式》,書中有比較淺顯易懂的C#程式例子,再回頭讀《Design Patterns》,還是會覺得有許多「理解漏洞」無法填補起來。所以,

例子是一個因素,但要深入理解《Design Patterns》,例子非常重要,但並不是決定性的因素。

那到底是什麼問題?從今天的討論中,鄉民們應該可以發現,《Design Patterns》這本書在寫作上其實存在著一些問題。例如,章節定義不清。在昨天的實驗中,Observer pattern的Motivation雖然也有夾雜著example與若干對於solution的說明,但Teddy還是在其中找到了兩個force。在今天的實驗中,Teddy發現State pattern的Motivation只包含了solution的example,並沒有找到任何的force。有一個force跑到了Applicability(Context)章節裡面,經由Teddy把它給拯救出來之後得以和世人見面 XD。另外兩個force是Teddy觀察State pattern的solution與resulting context所歸納出來的。

***

今天又是扯了一大篇。鄉民們可能會想:So what?沒有force又怎麼樣?force跑到Context裡面又怎麼樣?Teddy再幫鄉民們複習一下force的涵義:

  • Force是問題的限制或特性。
  • Force告訴我們為什麼模式所要解決的「問題」是一個真正的問題;為什麼這個問題很難,為什麼這個問題需要一個聰明的,甚至是違反直覺的解決方案。Force也是了解為何會採用此種解決方案(而非其他方案)的關鍵。
  • The often contradictory considerations to be considered when choosing a solution to a problem. Each solution considers certain forces. It optimizes some and may totally ignore others. The relative importance of the forces is determined by the context.

在Teddy的經驗中,很多學習design patterns的程式設計師,在應用design pattern的時候,經常會發生「套錯pattern」的問題。當然這個問題的原因很多,Teddy認為最重要的原因,就是:

  • 沒有弄懂每一個pattern要解決的problem與問題發生的context是什麼。
  • 沒有思考到自己的問題領域中,存在著那些force;在套用某個pattern之後,這些force是否被解決或是平衡了。

這句話再重複一次:

Force告訴我們為什麼模式所要解決的「問題」是一個真正的問題;為什麼這個問題很難,為什麼這個問題需要一個聰明的,甚至是違反直覺的解決方案。Force也是了解為何會採用此種解決方案(而非其他方案)的關鍵

沒有認清force,就很難判斷自己所設計或是挑選的solution是否合適。

***

友藏內心獨白:《設計模式的逆襲》這本書的種子快要發芽了 XD。

2012年9月27日 星期四

尋找Force:Observer篇

Sept. 26 16:20~17:42

image

 

鄉民們還記得Teddy最近經常提到關於pattern的一個重要觀念,那就是pattern的六大元素:

  1. Pattern Name:模式名稱,增加開發者的設計字彙。
  2. Context:描述問題發生的地形地物。
  3. Problem:描述問題本身。
  4. Force:問題的限制或特性。
  5. Solution:解決問題的方法。
  6. Resulting Context:套用解決方案之後的結果。

不知道鄉民們看完之後會不會有一個問題:

奇怪,上面這六大元素怎麼跟GoF的Design Patterns這本書所描述的pattern很不一樣啊?

的確,除了Pattern Name相同,其他的五點都不同。看一下者兩者的對應關係(資料來源:http://www.c2.com/cgi/wiki?CanonicalForm):

六大基本格式 GoF格式
Pattern Name Pattern Name
NA Also Known As
Problem Intent
Context Applicability
Forces Motivation
Solution Participants
Structure
Collaborations Implementation
  Sample Code
Resulting Context Consequences
NA Known Uses
NA Related Patterns

***

今天Teddy要談的還是force的問題。依據Teddy之前上課的經驗,學員們對於force比較不容易掌握。如果有讀過GoF《Design Patterns》這本書的人可能會覺得很奇怪,書中沒有提到force啊?依據上面這個表,force在GoF的書中,相當於Motivation這一個段落。Teddy舉一個最常被使用的Observer pattern為例子,來看一下如何從GoF書中的Motivation段落找出force。

翻開《Design Patterns》第293-294頁。

Motivation

A common side-effect of partitioning a system into a collection of cooperating classes is the need to maintain consistency between related objects. You don't want to achieve consistency by making the classes tightly coupled, because that reduces their reusability.

這裡就找到第一個force:Achieving consistency by making the classes tightly coupled reduces their reusability.

翻成中文就是:為了達到狀態一致性而將物件緊密耦合在一起(你泥中有我,我泥中有你 XD),將會降低(個別)物件的重複使用性

For example, many graphical user interface toolkits separate the presentational aspects of the user interface from the underlying application data [KP88, LVC89, P+88, WGM88]. Classes defining application data and presentations can be reused independently. They can work together, too. Both a spreadsheet object and bar chart object can depict information in the same application data object using different presentations. The spreadsheet and the bar chart don't know about each other, thereby letting you reuse only the one you need. But they behave as though they do. When the user changes the information in the spreadsheet, the bar chart reflects the changes immediately, and vice versa.

上面這一大段是解釋第一個force,所以直接忽略,繼續往下找。

This behavior implies that the spreadsheet and bar chart are dependent on the data object and therefore should be notified of any change in its state. And there's no reason to limit the number of dependent objects to two; there may be any number of different user interfaces to the same data.

這裡就找到第二個force:There is no reason to limit the number of dependent objects; there may be any number of different user interfaces to the same data.

翻成中文就是:無須限制資料相依物件的個數,因為可能有任意數量的物件都有興趣想要知道資料(狀態)

接下來的說明內容其實已經有點像是solution的摘要了,應該也找不到其他force了。

The Observer pattern describes how to establish these relationships. The key objects in this pattern are subject and observer. A subject may have any number of dependent observers. All observers are notified whenever the subject undergoes a change in state. In response, each observer will query the subject to synchronize its state with the subject's state.

This kind of interaction is also known as publish-subscribe. The subject is the publisher of notifications. It sends out these notifications without having to know who its observers are. Any number of observers can subscribe to receive notifications.

***

結論,從Observer pattern的Motivation找到兩個force。

  • 為了達到狀態一致性而將物件緊密耦合在一起(你泥中有我,我泥中有你 XD),將會降低物件的重複使用性。
  • 無須限制資料相依物件的個數,因為可能有任意數量的物件都有興趣想要知道資料(狀態)。

再仔細思考一下,上面這兩個force,分別代表兩個non-functional requirement(或是說對於原本要解決問題的兩點限制) :

  • 重複使用性:由於Subject和Observer彼此之間是所謂的abstract coupling(請參考《亂談軟體設計(1):Cohesion and Coupling》)關係,所以個別都有可能可以在不同的context中被重複使用。
  • 可擴充性:可以有任意數量的Observer。

***

那麼,最後剩下一個問題:Observer pattern的solution是否有滿足上面這兩個force?要回答這個問題之前,再幫鄉民們回顧一下force的涵義:

  • Force是問題的限制或特性
  • Force告訴我們為什麼模式所要解決的「問題」是一個真正的問題;為什麼這個問題很難,為什麼這個問題需要一個聰明的,甚至是違反直覺的解決方案。Force也是了解為何會採用此種解決方案(而非其他方案)的關鍵。
  • The often contradictory considerations to be considered when choosing a solution to a problem. Each solution considers certain forces. It optimizes some and may totally ignore others. The relative importance of the forces is determined by the context.

看到這邊,突然想到,耶,Observer pattern所要解決的問題是什麼?查看上表,Problem在GoF的格式裡面是Intent,所以來看一下Observer的Intent:

Define a one-to-many dependency between objects so that when one objet changes state, all its dependents are notified and updated automatically.

耶,這個句子不是問句耶,怎麼可以稱作是一個問題呢?很簡單,把它改成問句不就好了:

How do you define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically?

Problem有了,接著請鄉民們自己看一下Observer pattern的solution,是否除了解決這個problem以外,也同時滿足了上面這兩個force?

螢幕快照 2012-09-26 下午5.25.40

 

這邊要請鄉民們稍微花點時間思考一下,如果僅有problem還沒有考慮上面這兩個force,你最後得到的solution,很可能就不是現在所看到Observer的這個樣子。所以force的確是「問題的限制或特性」,會影響最後採用何種solution。

***

友藏內心獨白:經過這樣的分析,任督二脈至少也該打 通一脈了吧 XD。

2012年9月26日 星期三

為什麼要培養多才多藝的員工:簡單分析篇

Sept. 25 21:29~22:50

image

 

在昨天《鄉民的問題》這一篇,Teddy談到Scrum團隊要打破傳統「專業分工」的觀念,想辦法做到「多才多藝」(團隊中大部分的事情,儘可能培養一人以上可以處理的能力,這樣團隊成員會有一種可依靠感,而不是所有事情都要單兵作戰的孤獨感。)今天用兩張圖來稍微解釋一下這個概念。

螢幕快照 2012-09-25 下午9.47.07

圖一:專業分工模式。

 

圖一有幾個概念,分別是:

  • 生產力:團隊的整體生產力,越高越好。
  • 專業分工:專業分工越細,通常代表每個人都專精在某一項特別的技能上面。針對所專精的項目,可以有效率地完成被指派的工作。從這個角度來看,專業分工越細,生產力也就越高。
  • 工作調度彈性:團隊調派人力執行某項工作的靈活度。如果工作調度彈性越高,代表被指派新工作之後,團隊中有一人以上可以去執行這項工作,比較不會遇到「有些人一直很忙,而有些人卻閒閒沒事做」的情況。假設現在有很多撰寫資料庫stored procedure的工作,在專業分工的模式下,團隊中可能只有一個人會寫,所以這段時間這個會寫stored procedure的人就忙得要死,而其他人卻可能無事可做。所以專業分工越高,工作調度彈性越低。而工作調度彈性越高則是可以提升生產力。
  • 團隊合作:團隊成員彼此互相合作完成工作的程度。團隊合作越高,做事越有默契與效率,則可提升生產力。在傳統講究專業分工的情況下,通常每個人各自固守自己的一小塊領域,不想也不必去知道團隊中其他人在做些什麼。例如,網頁設計師不需要去管stored procedure怎麼寫,反之亦然。所以專業分工降低團隊合作度。
  • 工作怠倦:同樣性質的工作做久了,人都會有怠倦感,並且可能會覺得沒有學習到新的東西。工作怠倦感越高,人就越不想和其他人合作(因為可能只把工作當成混一口飯吃的例行性反射行為)。而團隊合作度越低,則會增加工作怠倦感(一直都在單打獨鬥,很累)。專業分工越高,相等於同樣性質的工作一直不斷地重複,也會增加工作怠倦感。
  • 離職率:人員異動的比例。工作怠倦感會增加離職率,團隊合作度則會降低離職率(迷之音:某人是來公司交朋友滴 XD)。離職率提高,生產力通常都會大大降低(除非離職的是「牠」)。

這邊先做個小小的註腳:平常大家認為專業分工可以增加生產力,是因為大家只把關注的焦點放在「生產力」和「專業分工」這兩個因素上,而忽略了上圖中也會影響「生產力」的其他因素。也就是說,為了提升「生產力」而僅強調要增加「專業分工」,只做到了所謂的「局部最佳化」。但是從整個生產流程或是所謂的「價值鏈」來看,這種作法其實並沒有真正提高「生產力」。

***

接下來看另外一個圖:

螢幕快照 2012-09-25 下午10.19.24

圖二:多才多藝模式。

 

圖二把「專業分工」換成「多才多藝」,所產生的結果剛好跟圖一相反。如果單獨只看「多才多藝」和「生產力」關係,我們發現「多才多藝」會讓「生產力」降低(因為並不是每次都把工作交給團隊中對該工作最熟悉的人來執行)。但是,「多才多藝」卻會讓工作調度彈性提高,增加團隊合作度,降低工作怠倦與離職率。這些效應都會間接提升生產力,而最後對生產力提升的綜合效果理論上會大於實施「多才多藝」直接對生產力所造成的損失。

***

在談到軟體開發這檔子事,Teddy經常放在口邊的一句話就是:「能量不滅定律」。當團隊領導者或是公司文化,只關注到「局部最佳化」,也就是用「專業 加班 分工」的方式來謀求短期的生產力提升,而忽略工作調度彈性、團隊合作、員工士氣、人員流動率等因素。短期而言,因為不需要耗費精神去管理這些因素,所以團隊的生產力看起來的確是得到提升。但假以時日,就會應驗了「人出來混,總是要還的」(技術債或人情債)這句話。當遭遇到工作調度僵硬、團隊合作、員工士氣低落、人員流動率高,原本「責任制」…不對,是「專業分工」所帶來的生產力提升老早就被打到不成人形了。

***

最後補充說明兩點:

  1. 以上兩張圖只是舉例說明,實際上影響團隊生產力的因素還有很多,包含產品的品質(bug越多,生產力越低)、工作環境等等。
  2. 「多才多藝」不是說每個人都一樣,沒有專業可言。而是團隊成員在某項(或某幾項)技能具備熟稔的專業能力之後,也不要排斥接觸新的技能,把握擴展自己專業領域的機會。

***

友藏內心獨白:講不好聽叫做違反直覺,講好聽一點叫做逆向思考,開拓藍海 XD。

2012年9月25日 星期二

鄉民的問題

Sept. 24 15:08~16:24

image

 

今天早上一起床就收到某位鄉民寄來的一封信:

***

Teddy你好:

(Q1)不好意思,這個問題不知道能不能請教你。
在部落格上面很多軟工方面的文章,
(Q2) 裡面有非常大的成份在開發流程、開發團隊上面,但是實際上,最小的個體還是一個人,
(Q3)所以像是「團體為重、個人為輕」的想法會不會太理想呢?
(Q4) 延伸問題像是:積效/考積/獎金的分配?
當以團體為單位工作,獎勵卻以個人為單位分派時,
很容易就出現問題了啊…
會有這些問題,是因為在工作上常常覺得現有流程不好,
(Q5) 想要改變的時候,發現最大的問題還是在「人」上面………

另一個問題,最新一篇《傻的願意相信(2)》最後提到
「培養多才藝的員工(生產線的工人要能夠具備組裝車輛任何部份的能力)」
這邊有個疑問,當程式設計也變成每個人都一樣的時候,
(Q6)這是不是就沒有專業可言了?
(Q7)延伸問題:當每個人都做一樣的事情的時候,如何培養更深的技術?
舉例來說,每個人都要會DB正規化、stored procedure、Web Server/Client、C++、C#、Flash…etc
(Q8)我不是很容易理解,因為以前的想法都叫「專業分工」,依各自的專業來進行分工,
而專注在自已領域上的人,自然也容易在該領域深入研究。
另一個說法是:要廣或深,如果什麼都學一點的話,就等於什麼都不會的說法

***

以下是Teddy的答覆:

  • Q1:當然可以問啊,而且什麼問題都可以問,但是Teddy保留「不回答」的權利XD。
  • Q2:其實在「搞笑談軟工」裡面,除了「開發流程」以外,Teddy也談了很多關於軟體設計、軟體架構、模式、設計模式、持續整合、軟體測試、例外處理、好書推薦的文章啊。只是這一系列的文章好像都比較沒人欣賞啊…Orz(Teddy內心獨白:還有每週兩篇的大易輸入法遊記哩 挑眉質疑)。
  • Q3:ㄟ,如果你是看完Teddy的部落格而有了「團體為重、個人為輕」的想法,Teddy在此向你鞠躬道歉…Orz。Teddy應該沒有說過類似這樣的話吧?!Teddy要強調的是「個人能力和團隊合作一樣重要(或者說,個人能力和團隊合作之間要取得平衡)」。Teddy曾經說開發團隊成員要有「追求技術卓越」的精神,所以個人重不重要?當然重要。但是(通常這兩個字之後才是重點),何謂「厲害的個人」?是那種自己很厲害但不願意分享也不管別人死活的人,才叫做厲害。還是有能力能夠幫助別人,使得別人原本認為很困難的事情,在他的協助之下,變得比較簡單(這句話有點繞口 XD)。
  • Q4:講到打考績這件事,在台灣應該不容易做到只打「整個團隊的考績」,那怎麼辦?還是有一些折衷的方法,下次請Teddy吃飯再慢慢告訴你 XD。
  • Q5:絕對是人的問題大大大大大大大…於流程的問題啊。開發流程再怎麼搞來搞去,也就是那幾種,最後的問題都是出在「執行流程的那些人身上」。
  • Q6:「培養多才藝的員工(生產線的工人要能夠具備組裝車輛任何部份的能力)」這一點是「理想值」,絕對不代表員工就沒有專業可言。你可以想像,一個Scrum團隊的成員,如果具備所謂的「T型人」(最近學到的一個詞)特質,除了在某一個領域具備專業,對於其他週邊的相關知識也要有所涉獵。Teddy之前舉過一個例子,假設你的團隊中原本有一個資料庫很強人,他的能力用100分來計算。如果在認領工作的時候,有計畫地讓其他不懂資料庫的人和他合作,長久下來,就算其他人達不到100分的程度,但至少也有40、50、60…分。這比「完全不懂(0分)」,全部都要依靠這位資料庫高手,在調配工作的時候彈性就大了很多。另外還有其他的好處,像是日後的維護工作安排、人員請假比較自由、人員流動對專案影響較少等等。
  • Q7:不是每個人都做一樣的事情,而是每個人有自己專精的幾樣(舉例,有些人可能architecture design與multiple-threading programming很強,資料庫設計中等,UI設計只懂概念。而有些人則是HTML/CSS/JavaScrip很熟,資料庫中等,但是軟體架構設計能力很弱)。重點是,團隊中大部分的事情,儘可能培養一人以上可以處理的能力,這樣團隊成員會有一種可以依靠,而不是所有事情都要單兵作戰的孤獨感。
  • Q8:專業分工本身有好處也有缺點,箇中奧妙很難一下子講清楚。我很能理解你對於「專業分工」的疑惑,為什麼以前大家都說要「專業分工」,但是現在Teddy卻說要「多才多藝」。Teddy建議你可以去看一下《決定未來的十種人》這本書。另外,套句Teddy在《Force是什麼?》所引用《POSA5》這本書裡面的一句話:「Force告訴我們為什麼模式所要解決的問題是一個真正的問題;為什麼這個問題很難,為什麼這個問題需要一個聰明的,甚至是違反直覺的解決方案。Force也是了解為何會採用此種解決方案(而非其他方案)的關鍵。」你現在會認為培養「多才多藝」是一種「違反直覺
  • (也就是專業分工)」的解決方案,是因為你對這個問題的force還沒有觀察的非常清楚,所以自然對於solution會有所懷疑。

***

扯了這麼多,結論就是:「這位鄉民病的不輕 XD」,請速 服用 報名「Scrum敏捷方法實作班:第四梯次」。另外,下次如果還有開「模式入門第一堂課:30 分鐘寫出一個模式」也要來報名參加啊 XD(學會pattern方法對於分析問題真的很有用啊)。

***

友藏內心獨白:腦袋中又冒出Quality Without A Name這句話啊。

2012年9月24日 星期一

傻的願意相信(2)

Sept. 23 22:14~Sept. 24 00:28

image

幫鄉民們複習一下,這裡是《傻的願意相信》第一集。「傻的願意相信」這句話是Teddy的指導教授在上課時所經常掛在嘴邊的一句話,藉此勉勵學生要「傻的願意相信」課本上所教授的軟體開法與設計方法。唯有自己先「願意相信」這些方法是可行的作法,儘可能嘗試照著去做,而不要在真正學會之前就先急著去否定這些方法,日後才有深刻的體驗與堅實的立場去評論這些方法。聽起來好像很簡單,但是台灣人都太聰明也缺少耐心,要台灣人不甘寂寞地慢慢練功,傻傻地一步一步按照規矩辦事,說真的還真是不太容易。

上次在 C. C. Agile聚會中,有一位鄉民甲和Teddy聊到Scrum和Kanban的問題。

鄉民甲:我看書上說,Lean Startup應該要採用Kanban會比Scrum還要有彈性。

Teddy:怎麼說?

鄉民甲:例如,假設PO(訂定需求的人)有一個緊急的需求想要讓團隊優先去做,如果是採用Scrum,因為Scrum規定在sprint中不可以更改原先已經選定的story,所以平均來說,這個新的需求最快需要1/2 sprint的時間才可以被團隊給排入下一個開發週期。假設團隊採用兩週的sprint,那就代表這個緊急的需求平均需要等待一週才可以被團隊給實作。

Teddy:然後勒?

鄉民甲:可是如果是採用Kanban的話,就不會有這個限制啊。

Teddy:為什麼?

鄉民甲:因為Kanban沒有規範sprint(iteration),所以新的需求馬上就可以被開發團隊給實作。

Teddy:真的是馬上嗎?

鄉民甲:嗯,應該說,在Kanban中,高優先權的需求,平均等待時間是「一個需求從第一個開發階段被移到下一個階段的時間的一半」。

Teddy:可以舉例說明一下嗎?

鄉民甲:假設有一個四個人(甲、乙、丙、丁)的團隊,它們的Kanban board如下所示。甲跟乙正在做Story A,丙和丁在作Story B。這時候突然有一個很緊急的需求Story E冒出來,由於Not Checked Out的WIP為2,所以先把Story D給移走以便插入Story E。

螢幕快照 2012-09-23 下午10.46.33

Kanban board 變成這樣:

螢幕快照 2012-09-23 下午10.56.46

此時必須要等Story A 或是 Story B被做完之後,移到Review階段,才有可能把Story E拿出來施工。假設現在Story A做完了,甲跟乙把Story E拿出來做,Kanban board如下所示。

螢幕快照 2012-09-23 下午10.58.51

現在團隊發現流程卡在Review階段,所以派丁去處理Story A。

螢幕快照 2012-09-23 下午11.07.56

這樣子等甲跟乙把Story E做完之後,丁可能也把Story A給做完了,這樣子Story E就可以流到Review階段。

Teddy:如你所說的,由於Kanban沒有固定時間的sprint的規範,所以以上面這個例子來看,只要Kanban board上面Not Checked Out之後的階段「有空(WIP未達規範的上限)」,緊急的工作就可以馬上被施工。

Teddy:你實際上應用Kanban的經驗,有沒有發現什麼問題?

鄉民甲:其實我沒有真正用過Kanban耶,我只是看書上這樣寫而已。我目前還是採用Scrum,實際上遇到比較多的問題,反而是派工的問題。

Teddy:派工的問題問題是指?

鄉民甲:以上面這個例子來看,雖然在甲跟乙完成Story A之後,這個很緊急的Story E就可以被拿出來做,但是很有可能會發生甲跟乙其實對完成Story E所需的技能不熟,真正熟的人是丙。但是Story B又非得需要丙不可,所以暫時也不能把丙調來實作Story E。

Teddy:這個問題在Scrum中也經常會發生,但是由於Scrum建議組成cross-functional team,而且如果團隊有採用XP的pair programming與shared code這兩個實務做法的話,這種派工(認領工作)的難題慢慢地會比較少發生。

鄉民甲:Kanban對於團隊組成的方式其實沒有任何規範,不過經過這番討論,如果要達到具備有彈性的認領緊急的工作,團隊還是要借用其他敏捷實務做法,否則實際運作上還是會一直卡卡的。

***

鄉民甲問Teddy:那到底要用Kanban,還是Scrum會比較好?

Teddy在《開發軟體用什麼流程比較好?》有提到,「不管是哪種流程,只要能夠有一個良好的機制,可以把專案與團隊所遭遇的問題給凸顯出來,並且提供一個可以持續改善的機制,這樣這個流程就已經是很不錯的流程了。」講是這樣講,但是實際上團隊如果對於開發流程的掌握還不是很好的時候,Teddy認為還是從學習一個制式的流程開始會比較好。從這個角度來看,Teddy會建議從Scrum開始學習。因為Scrum的「框架」規範相較於Kanban來講要比較清楚(Scrum的限制比較多)。對於一個剛開始接觸敏捷方法的團隊而言,採用稍微限制多一點的流程框架,會比較容易遵循。等熟悉Scrum框架之後(至少需要6-12個月的時間吧),再來討論流程上較大幅度的調整,這樣會比較好。

舉個例子,Teddy剛開始採用Scrum的時候,會把product backlog裡面的story都先估算它們的story point,再藉此畫出release burndown chart。但是經過幾次軟體的release之後,Teddy發現軟體release的時間,經常會因為某些突發狀況而提早或延後,因此過早去規劃release plan的作用不是那麼大。後來Teddy就只關注於接下來1-2個sprint所要準備施工的story,而不再費心去定期重新檢視所有的product backlog item。前一陣子Teddy讀了Henrik Kniberg所寫的《Lean from the Trenches》才發現Teddy後來管理需求的精神,跟書中所提到的在Kanban board上面標示「Next Ten Features」很相似。

但是,Teddy在上Scrum課程時,還是會建議學員們先乖乖地依據Scrum的建議,每個sprint撥點時間讓團隊舉辦product backlog refinement workshop,而不要一下子就跳到比較自由的形式,這樣走火入魔的機率應該會比較低一點 挑眉質疑

***

話說回來,那Teddy怎麼在Scrum中應付「突發的重要需求」?這個問題要分幾點來討論:

  • 這真的是一個「客戶急需的需求嗎?」:很多時候,業務、行銷、主管、老闆、黨國元老、甚至是鄉民,都會以「客戶急需」以及「量很大」這兩點,來要求開發團隊「立即對他所提出的要求有所反應」。而這這種突發的要求,很不幸地經常是未經思考與驗證的「隨口說說」,且經常在政治力之下,打亂團隊的開發步調。在Scrum框架下,當團隊有一定的開發步驟時(例如每兩週產出成品),在平均一週的等待時間內,可以讓提出需求者與PO或是團隊成員稍微冷靜與確認這個突發需求的真正內涵。
  • 原先的需求搞錯了:如果在sprint進行中發現原本某個story的需求搞錯了,那怎麼辦?你可以把這個story丟掉,排入下個sprint繼續開發,也可以直接「就地都更」。
  • 真的很緊急的需求:如果這是一個經過確認真的很緊急的需求,而在這個sprint剩下來的時間中可以完成這個需求,那就把它直接排入這個sprint中。

***

Teddy之前曾說過,導入Scrum到後來所遇到的問題,其實最大的問題是「如何讓團隊分工且合作」,或是「如何流暢的派工(認領工作)」。記得當年Teddy在讀Toyota Production System的書籍時,裡面就有提到一個重點,那就是Toyota Production System的工作流程要能夠成立(即時生產、有彈性的組裝各種不同形式的車輛),除了「自働化」以外,另一點就是「培養多才藝的員工(生產線的工人要能夠具備組裝車輛任何部份的能力)」。如果後者不成立,不管是採用Scrum還是Kanban都會遇到很大的阻礙。

報告完畢。

***

友藏內心獨白:理論上,理論與實務是一樣的。但實際上,這兩者卻不相同。

2012年9月23日 星期日

2011冬遊法國巴黎Day3-C龐畢度文化中心(上)

Sept. 22 12:36~13:18

螢幕快照 2012-09-22 下午12.38.47

龐畢度文化中心在入夜後開燈的照片。

***

 

來到龐畢度,還未入館,就發現有趣的東西。

螢幕快照 2012-09-22 下午12.40.19

 

龐畢度文化中心主建築物旁邊有一個水池,池中有好幾的有趣的裝置藝術品,非常有趣。

螢幕快照 2012-09-22 下午12.40.29

螢幕快照 2012-09-22 下午12.40.52

螢幕快照 2012-09-22 下午12.41.28

龐畢度前方的廣場,提供遊憩和排隊的空間。

螢幕快照 2012-09-22 下午12.42.04

 

剛到龐畢度大概下午兩點左右,還沒開燈。當天有下點小噢,天氣陰陰的。

螢幕快照 2012-09-22 下午12.42.22

 

入館前有一個簡單的安檢,這裡有一件很要的事情要注意,就是不能帶大背包進去。Teddy看到一位背包客被安檢人員拒絕入場,因為她背了一個大背包,而現場似乎也沒有置物櫃可以存放背包,最後這位背包客只好很失望的離開。

螢幕快照 2012-09-22 下午12.42.44

 

入內之後眼睛為之一亮,沒想到從外面看起來灰灰不起眼的建築物,入內之後竟是如此寬敞明亮。

螢幕快照 2012-09-22 下午12.43.28

 

搭上電扶梯往上參觀。電扶梯被包覆在超大的透明管子內,有一種很特別的感覺 微笑

螢幕快照 2012-09-22 下午12.43.58

 

雨水打在玻璃上面。

螢幕快照 2012-09-22 下午12.44.20

 

從這裡可以清楚看到整個水池的外貌。

螢幕快照 2012-09-22 下午12.44.29

 

樓上有一個餐廳,有露天和室內的座位,視野非常的棒。

螢幕快照 2012-09-22 下午12.44.56

 

館內有很多不同的展覽,可以逛上2-3小時沒問題。

螢幕快照 2012-09-22 下午12.45.40

螢幕快照 2012-09-22 下午12.46.22

螢幕快照 2012-09-22 下午12.46.30

 

看到眼花撩亂。

螢幕快照 2012-09-22 下午12.47.03

螢幕快照 2012-09-22 下午1.09.30

螢幕快照 2012-09-22 下午12.47.25

螢幕快照 2012-09-22 下午12.47.10

 

也有展出很多畫作。

螢幕快照 2012-09-22 下午12.46.40

螢幕快照 2012-09-22 下午12.47.40

 

放大版的黑武士的頭盔。

螢幕快照 2012-09-22 下午1.08.39

 

螢幕快照 2012-09-22 下午1.09.51

 

參觀的人雖然很多,但是整個展場非常寬敞,不會覺得壅擠。

螢幕快照 2012-09-22 下午1.10.08

螢幕快照 2012-09-22 下午1.10.17

 

建築模型。

螢幕快照 2012-09-22 下午1.10.26

 

自己猜 XD。

螢幕快照 2012-09-22 下午1.10.43

 

這是一個沙發。

螢幕快照 2012-09-22 下午1.11.15

螢幕快照 2012-09-22 下午1.11.29

***

這裡面可看的東西實在是太多了,下集待續。

***

友藏內心獨白:強烈推薦,讚 很棒

2012年9月22日 星期六

2011冬遊法國巴黎Day3-B文森堡(下)

Sept. 21 23:27~23:59

走過這座橋,來到了堡內某個展覽空間。

螢幕快照 2012-09-21 下午11.33.25

 

應該是介紹文森堡的畫作。

螢幕快照 2012-09-21 下午11.30.00

螢幕快照 2012-09-21 下午11.30.22

螢幕快照 2012-09-21 下午11.30.53

螢幕快照 2012-09-21 下午11.31.11

螢幕快照 2012-09-21 下午11.32.31

 

螢幕快照 2012-09-21 下午11.32.49

螢幕快照 2012-09-21 下午11.33.14

 

沿著樓梯往上走來到另一個展示間。

螢幕快照 2012-09-21 下午11.36.48

螢幕快照 2012-09-21 下午11.39.00

螢幕快照 2012-09-21 下午11.39.20

螢幕快照 2012-09-21 下午11.39.30

螢幕快照 2012-09-21 下午11.39.43

螢幕快照 2012-09-21 下午11.40.13

 

離開展覽室後,到外面拍些照片。

螢幕快照 2012-09-21 下午11.43.34

螢幕快照 2012-09-21 下午11.44.06

螢幕快照 2012-09-21 下午11.45.01

螢幕快照 2012-09-21 下午11.47.35

螢幕快照 2012-09-21 下午11.51.58

 

這是一間教堂。

螢幕快照 2012-09-21 下午11.45.18

螢幕快照 2012-09-21 下午11.52.21

螢幕快照 2012-09-21 下午11.52.33

 

螢幕快照 2012-09-21 下午11.52.50

螢幕快照 2012-09-21 下午11.53.29

 

走出這扇門就離開文森堡了。

螢幕快照 2012-09-21 下午11.54.08

 

文森堡平面圖。

螢幕快照 2012-09-21 下午11.55.04

 

下一站,龐畢度。

***

友藏內心獨白:剛好住在附近,一早來文森堡散散步也不錯啦 XD。