The Cost of Change
變化的代價
Early on in Beck's book, he challenges one of the oldest assumptions in software engineering. From the mid-1970s, structured methods and then more comprehensive methodologies were sold based on the "facts" shown in Figure 1. I should know; I developed, taught, sold, and installed several of these methodologies during the 1980s.
Figure 1 -- Historical lifecycle change costs.
Figure 2 -- Comtemporary lifecycle change costs.
Beck從他的早期的著作開始,就不斷向那些軟件工程中的一些"古訓"發出挑戰。從19世紀70年代中期的結構化方法,以至后來的那些更復雜的方法,他們都基于如圖1所示的那個"事實",在整個80年代,我必須了解、使用、討論、實施這些方法。 Beck asks us to consider that perhaps the economics of Figure 1, probably valid in the 1970s and 1980s, now look like Figure 2 - that is, the cost of maintenance, or ongoing change, flattens out rather than escalates. Actually, whether Figure 2 shows today's cost profile or not is irrelevant -- we have to make it true! If Figure 1 remains true, then we are doomed because of today's pace of change.
Beck卻給我們提了一個問題,那些在70年代和80年代也許還能起到效果的方法,他們的經費開銷狀況(如圖1)現在已經發生了變化(如圖2),也就是說,維護的成本(也可以等價為不斷發生的變化)降低了,而不是越來越高。實際上,圖2所示的開銷情況在當今是否是事實其實并不重要,重要的是我們必須認識到,如果圖1的現象還在繼續重演的話,我們只有死路一條,因為當今時代變化實在太快了(也就是說維護的成本將是一個天價)。
The vertical axis in Figure 1 usually depicts the cost of finding defects late in the development cycle. However, this assumes that all changes are the results of a mistake -- i.e., a defect. Viewed from this perspective, traditional methods have concentrated on "defect prevention" in early lifecycle stages. But in today's environment, we can't prevent what we don't know about -- changes arise from iteratively gaining knowledge about the application, not from a defective process. So, although our practices need to be geared toward preventing some defects, they must also be geared toward reducing the cost of continuous change. Actually, as Alistair Cockburn points out, the high cost of removing defects shown by Figure 1 provides an economic justification for practices like pair programming.
圖1中的y軸通常用來表示在開發周期的后期發現錯誤后需要花費的改錯成本?墒,這正驗證了一個假設,即后期所有需要做的開動均來自前期的一個錯誤,比方說一個設計缺陷。從這一點來看,傳統方法太依賴于在軟件生命周期的早期"不出錯"。但是在當今瞬息萬變的環境中,我們不能完全預防住那些我們預測不到的東西--即由應用需求不斷增長而帶來的變化,并且這種變化在早期不可能遇見并加以預防。因此,雖然我們要盡可能在早期做出某些應付變化的預防措施,但是更重要的是我們要減少后期改變所帶來的開銷。正如 Alistai Cockburn 所指出的,需要高成本的圖1所示的那種改正缺陷方法,正好從節省開支的角度給了一些實用的方法(如配對編程)一個好的理由。
In this issue of eAD, I want to restrict the discussion to change at the project or application level -- decisions about operating systems, development language, database, middleware, etc., are constraints outside the control of the development team. (For ideas on "architectural" flexibility, see the June and July 1999 issues of ADS.) Let's simplify even further and assume, for now, that the business and operational requirements are known.
在本期eAD雜志中,我打算把討論定位于項目或應用軟件層次上的變化--對類似操作系統、編程語言、數據庫、組件等的討論不在討論之列。(關于軟件結構的靈活性,可以參考ADS雜志1999年6月的那期)另外,讓我們進一步做個簡化,即假定軟件的用戶需求已經確定。
Our design goal is to balance the rapid delivery of functionality while we also create a design that can be easily modified. Even within the goal of rapid delivery, there remains another balance: proceed too hurriedly and bugs creep in; try to anticipate every eventuality and time flies. However, let's again simplify our problem and assume we have reached a reasonable balance of design versus code and test time.
我們的目標是既能快速不斷的發布新功能,同時又要讓軟件的設計易于更改。即使是在快速發布這個目標下,仍然需要在"快速發布但Bug叢生"和"面面俱到但曠日持久"之間進行取舍。因此,讓我再簡化一下我們要討論的問題,我們假定我們已經在設計、編碼和測試這三者之間取得了合理的平衡。
With all these simplifications, we are left with one question: how much anticipatory design work do we do? Current design produces the functionality we have already specified. Anticipatory design builds in extra facilities with the anticipation that future requirements will be faster to implement. Anticipatory design trades current time for future time, under the assumption that a little time now will save more time later. But under what conditions is that assumption true? Might it not be faster to redesign later, when we know exactly what the changes are, rather than guessing now?
在上面這些簡化的基礎上,還留有一個尾巴:我們在設計時對于未知的未來要看多遠?現在的設計已經實現了我們現在想到的一些功能。具有預見性的設計可以使未來的需求更快的獲得實現,也就是說預見性設計方法在以現在的時間換取未來的時間,如果一點點現在的時間可以換來未來節約大量時間,當然是劃算的。但是這種建設怎么才能成為現實呢?也許未來出了問題就整個重新設計一遍也不慢,那又何必現在瞎猜呢?
This is where refactoring enters the equation. Refactoring, according to author Martin Fowler, is "the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure." XP proponents practice continuous, incremental refactoring as a way to incorporate change. If changes are continuous, then we'll never get an up-front design completed. Furthermore, as changes become more unpredictable -- a great likelihood today -- then much anticipatory design likely will be wasted.
這就是我們為什么要提出重構的原因。重構,Martin Fowler說過,是不改變軟件對外表現但是重整內務的一種改進。XP方法的支持者在變化的環境中實踐了連續的、增量式的重構方法。如果變化是不斷演化的的,那就不可能存在什么一步到位的設計方法。說白了,如果變化不可預測--正如當今社會的情況--過多的在設計時考慮以后可能的變化,完全是一種浪費。
Figure 3 -- Balancing design and refactoring, pre-internet.
Figure 4 -- Balancing design and refactoring today.
I think the diagram in Figure 3 depicts the situation prior to the rapid-paced change of the Internet era. Since the rate of change (illustrated by the positioning of the balance point in the figure) was lower, more anticipatory designing versus refactoring may have been reasonable. As Figure 4 shows, however, as the rate of change increases, the viability of anticipatory design loses out to refactoring- - a situation I think defines many systems today.
我認為圖3給出的是互聯網時代到來之前的情況。由于變化的速度慢(圖中由天平的支點比較靠左來表示),早期的預測多一些是合理的。但是在圖4中,由于變化速度變快樂,設計時預測太多是得不償失的,這種情況正是現在許多系統所面臨的。
In the long run, the only way to test whether a design is flexible involves making changes and measuring how easy they are to implement. One of the biggest problems with the traditional up- front-design-then-maintain strategy has been that software systems exhibit tremendous entropy; they degrade over time as maintainers rush fixes, patches, and enhancements into production. The problem is worse today because of the accelerated pace of change, but current refactoring approaches aren't the first to address the problem. Back in the "dark ages" (circa 1986), Dave Higgins wrote Data Structured Software Maintenance, a book that addressed the high cost of maintenance, due in large part to the cumulative effects of changes to systems over time. Although Higgins advocated a particular program-design approach (the Warnier/Orr Approach), one of his primary themes was to stop the degradation of systems over time by systematically redesigning programs during maintenance activities.
在一個長期項目中,檢驗一個設計是否具有很好的靈活性是通過變化需求,同時看看原設計能否很容易的實現新變化的需求。這種傳統的"先設計,再維護"策略的最大問題在于軟件系統存在非常大的熵(極易變化,沒有規律)。一個系統隨著時間的推移,維護、改錯、打補丁、增強功能等工作會使系統的熵越來越大,F在由于外部環境變化加快,情況正越來越糟。不過,現在的重構技術也不是第一個試圖解決這個問題的方法。早在所謂的"黑暗時期"(circa 1986),Dave Higgins 就寫過一本名為"Data Structured Software Maintenance"的書,該書指出了由于隨著時間的推移變化的累計影響不斷增大,維護所需要的開銷也將越來說龐大,Higgins 提出了一種新的設計方法(the Warnier/Orr Approach)用于阻止系統的熵增大所帶來的負面影響,該方法的思想是在維護過程中有系統的對程序進行重新設計。
Higgins's approach to program maintenance was first to develop a pattern (although the term pattern was not used then) for how the program "should be" designed, then to create a map from the "good" pattern to the "spaghetti" code. Programmers would then use the map to help understand the program and, further, to revise the program over time to look more like the pattern. Using Higgins's approach, program maintenance counteracted the natural tendency of applications to degrade over time. "The objective was not to rewrite the entire application," said Higgins in a recent conversation, "but to rewrite those portions for which enhancements had been requested."
Higgins 的方法首先為程序改如何設計設定一種模式(雖然那時還沒有模式這個提法),然后在細致的代碼設計與"好"的模式之間建立一種映射,程序員即根據這種映射關系來理解系統并修改程序,使修改的結果更接近于那個模式。使用 Higgins 這個方法可以通過維護抵消系統誰時間而熵增大的趨勢。Higgins 說:"該方法的目標并不是重寫整個系統,而只是重寫那些根據需要必須增強的部分。"
Although this older-style "refactoring" was not widely practiced, the ideas are the same as they are today -- the need today is just greater. Two things enable, or drive, increased levels of refactoring: one is better languages and tools, and the other is rapid change.
雖然這種原始的"重構"技術并沒有被廣泛的實踐檢驗,其思想與現在的重構還是相通的,只不過現在的需求變化更快、更大。不過有兩個東西驅動、提高了現代的重構技術:一是更好的程序設計語言和開發工具;二是更快的變化需求。
Another approach to high change arose in the early days of RAD: the idea of throwaway code. The idea was that things were changing so rapidly that we could just code applications very quickly, then throw them away and start over when the time for change arose. This turned out to be a poor long-term strategy.
在早期的 RAD(快速原型開發)方法中還有另一種應付變化的辦法:代碼拋棄思想。這個思想認為環境和需求變化太快,因此我們唯一的辦法只能是快速編寫新代碼,并且也快速的拋棄老代碼。我們認為這不是長久之計。
文章來源于領測軟件測試網 http://www.kjueaiud.com/