jim yeh on 一月 9th, 2009

最近同人看到有一則噗浪提到「一個穩定的程式並非必然,而是偶然」在此噗浪的回應中,發送這則噗浪的噗友表達他對程式穩定性的看法。

先問自己一個問題,一個程式有幾個 Bugs?如果是不可數,那~~它的穩定是相對非絕對,所以穩定不是絕對的,也不是必然的。

同人覺得這位噗友的觀點很有趣,於是加入這則噗浪的討論。我問如果最開始的程式都是穩定的,那麼是什麼原因讓後來的程式變得不穩定?對這個問題,一些噗友提出了他們的看法,其中有一位噗友回應「是我的機器弄好的程式,跑到別人機器就不穩定了」,發送此則噗浪的噗友認為還蠻接近實際的情形。

他提到 Bugs 在自己的機器沒產生,在別人那邊可能會產生,問題可能是因為自己的機器有 Bugs,而不是別人的機器,他說假設機器不會出問題是會有副作用的。

那麼為什麼不在應用系統要運作的目標環境下直接開發程式呢?因為,嚴格來說,開發者不可能有完全一致的環境,因此開發者只能假設環境是不會改變。但實際上,在不同的機器上、甚至在相同的機器上,不同的時間可能也會出現難以預料到的變化,結果使得程式變得不穩定。

這位噗友認為,當我們愈信任一個系統,其實可能是一個災難,因此程式的穩定非絕對而是偶然,它是由一連串的偶然所累積而成的。同人發現這個觀點讓人很難反駁,在我過去程式開發的經驗中,並不乏遇到原來運作正常的程式,在不同時空環境出現問題的現象。正如同這位噗友提到的,作業系統與程式語言它們本身也都是程式,很難確保它們不會出問題。

相信很多人都曾遇到過,程式發生失常通常只因為一個令人難以捉摸的小錯誤,因此似乎真的可以說「穩定的程式是偶然的」。不過,如果穩定的程式真的是偶然的,程式的穩定就只能依賴運氣而不是人為努力,事情真的是這樣嗎?其實這位噗友太過強調環境變化的隨機性,卻忽略了適應環境變化,程式開發必然會經歷複雜演化的過程。穩定的程式是演化而來的,雖然演化的過程是偶然、但其最後結果卻是必然。換句話說,穩定的程式是偶然下的必然

程式的運作通常需要處在多變的環境中,使得開發者很難確知他的程式有多少 Bugs。因此在本質上,程式開發過程是一個偶然,由一連串的隨機事件所構成的。雖然開發者可以使用與將來應用系統所運作環境相同的硬體及作業系統,但實際上終究並非同一台機器。它們可能會因為使用者的差異,而安裝了無法與應用系統相容的軟體或設定了會使系統出現問題的系統組態。就算是兩台機器能夠完全一模一樣,時空環境的變化也可能造成系統運作出現問題的關鍵,即使兩者的差異相當微小。

以上的現象就是程式開發的「蝴蝶效應」,就像天氣很難預測準確的道理一樣。一隻蝴蝶在巴西輕拍翅膀,會使更多蝴蝶跟著一起輕拍翅膀,最後將有數千隻的蝴蝶都跟著那隻蝴蝶一同振翅,其所產生的巨風可以導致一個月後在美國德州發生一場龍捲風。這是「混沌」理論所討論的現象,未來的狀態對初始條件敏感而造成無法預測。在混沌系統中,初始條件十分微小的變化,經過不斷放大,對其未來狀態會造成極其巨大的差別。[1]

除非所有 Bugs 都出現為止,否則程式開發者不會知道他的程式有多少 Bugs。因為他無法預測他的機器和實際運作的機器,有那些差異會造成程式運作出現功能失常。而且問題可能不是因為他的程式錯誤,有時候問題是出在作業系統或程式語言本身的 Bugs;它們都是程式,只要程式都有可能會有 Bugs。

現實真是令人沮喪呀,如果不確定因素使得環境變得如此難料,那要如何期待穩定的程式出現呢?我們不能期待環境不再變化,因為軟體開發的現實就是變化無常,唯一不變的真理就是變。我們也不能不去面對問題,進行規劃及管理,因為隨性地處理問題,只會讓問題變得更加混亂而讓情況失去控制。我們應該讓系統可以 適應環境的變化,發展出兼具穩定與彈性的程式,這樣我們就能在界於混亂與穩定的過渡地帶中,逐步演進出複雜的行為來維持整體系統的動態平衡。

這就是複雜理論複雜適應性系統的觀念,系統透過自我組織來穩定自己,不會因為無法控制混亂而崩解為混沌一片,同時也保有足夠變化的彈性來進化系統行為。就像同人在過去的文章中,曾經提出複雜系統來比喻專案管理的隱喻一樣,複雜適應性系統的演化過程是不斷經歷觀察、假設、調整、再假設的重覆循環過程。

整個專案環境所能供給的資源是有限的(成本限制),而演化競爭者會和我們爭奪這些有限資源(時間限制),所以對一個複雜系統而言,必須達成演化的使命而創造對整體系統的價值最大化(規模限制)。要做到這點,複雜系統必須能依現狀來演化系統,用最經濟的方式創造最大的價值(技術限制),演化則是先對環境的做出假設,然後依據適者生存不適者淘汰的原則來進行演化,過程中會不斷地修正對環境的假設並改變系統行為以求適應環境。

因此,對於程式開發的專案當然也是相同的道理,演化的過程是無法預料的隨機行為,但演化的結果卻是必然的;發展出最適應環境及產生最大價值的穩定系統。假設的目的是為了做到將廣大的可能性限制在一小部分,這是同人在另一篇文章引用 Peter Ho 所提到讓系統停留在混沌邊緣必須做的三件事之一。另外兩件事則是必須保持足夠的穩定,即使有輕微的改變,系統仍不會崩解成混沌一片、以及必須在靜止不動的死寂與過度活動的「混亂政體」間達到平衡。

這也就是同人提出先前穩定的程式,最後卻變得不穩定,到底問題是出在什麼地方?問題並不在我們對環境做出假設,而是無法意識到假設所帶來的風險,以讓開發程式停留在混沌邊緣以達成系統的動態穩定。因此,噗友提到假設會有副作用的問題不在假設,而在於開發者面對環境的反應的變化太慢,以致於造成局面的紊亂而使得問題無法收拾。

然而,如何及早反應環境的變化維持程式的穩定與彈性呢?同人推崇測試、重構與整合三項實務,誠如 Peter Ho 所說的「未經重構,系統將會沒有空間來容納新功能來適應新的變化驅力;未經測試,開發者不會知道系統邊緣在那裡;未經整合,生命火光將逐漸消散。」用紀律來維持系統彈性與穩定,雖然環境的變化是無可預料的,但我們仍將體會到穩定的程式是偶然下的必然!



附註  
  1. 維基百科編者 (2008). 混沌理論. Wikipedia, . Retrieved 03:15, 1月 9, 2009.[]
     

2 Responses to “穩定的程式是偶然?”

  1. GaryChu 說道:

    阿金老師,

    你已經很久沒上線囉,手機似乎也沒開,
    在忙什麼阿?看到都還有寫文章,知道你一切都好,
    有空聯絡一下吧!

  2. [...] 軟體開發是工藝還是工程? 穩定的程式是偶然? 程式碼的結構、迴圈與處理 Time-Boxing 於軟體反覆演進的必要性 [...]

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">