星期二, 6月 21, 2005

The Art of Unix Programming 4. Modularity

The Art of Unix Programming by Eric Steven Raymond


4. Modularity
早期軟硬體限制,所以比較偏向硬上,直到後來才開始注重結構化和模組化。裡面的一段引言很有意思,也很好笑。

Dennis Ritchie encouraged modularity by telling all and sundry that function calls were really, really cheap in C. Everybody started writing small functions and modularizing. Years later we found out that function calls were still expensive on the PDP-11, and VAX code was often spending 50% of its time in the CALLS instruction. Dennis had lied to us! But it was too late; we were all hooked...
-- Steve Johnson



Encapsulation and Optimal Module Size

The first and most important quality of modular code is encapsulation. Well-encapsulated modules don't expose their internals to each other.


The APIs between modules have a dual role. On the implementation level, they function as choke points between the modules, preventing the internals of each from leaking into its neighbors. On the design level, it is the APIs (not the bits of implementation between them) that really define your architecture.

我想這一段話的意思,大概就跟 ISA 的意思一樣吧。

One good test for whether an API is well designed is this one: if you try to write a description of it in purely human language (with no source-code extracts allowed), does it make sense? It is a very good idea to get into the habit of writing informal descriptions of your APIs before you code them.

不過有意思的是,書上說根據 Hatton 的研究,從經驗上來看,最佳的模組大小是 200~400 logical lines。比想像中小得多。


Compactness and Orthogonality

Accordingly, Unix programmers have learned to think very hard about two other properties when designing APIs, command sets, protocols, and other ways to make computers do tricks: compactness and orthogonality.

Compactness is the property that a design can fit inside a human being's head. A good practical test for compactness is this: Does an experienced user normally need a manual? If not, then the design (or at least the subset of it that covers normal use) is compact.

The purpose of emphasizing compactness as a virtue is not to condition you to treat compactness as an absolute requirement, but to teach you to do what Unix programmers do: value compactness properly, design for it whenever possible, and not throw it away casually.

Orthogonality is one of the most important properties that can help make even complex designs compact. In a purely orthogonal design, operations do not have side effects; each action (whether it's an API call, a macro invocation, or a language operation) changes just one thing without affecting others.

The concept of refactoring, which first emerged as an explicit idea from the ‘Extreme Programming’ school, is closely related to orthogonality. To refactor code is to change its structure and organization without changing its observable behavior. Software engineers have been doing this since the birth of the field, of course, but naming the practice and identifying a stock set of refactoring techniques has helped concentrate peoples' thinking in useful ways. Because these fit so well with the central concerns of the Unix design tradition, Unix developers have quickly coopted the terminology and ideas of refactoring.[43]



Software Is a Many-Layered Thing
做多層級的設計時,主要採用由下而上和由下而上的設計方法,雖然沒有哪一種比較好,但是不同設計方法適何哪一種情況卻是問題。Eric Steven Raymond 的建議是:

A very concrete way to think about this difference is to ask whether the design is organized around its main event loop (which tends to have the high-level application logic close to it) or around a service library of all the operations that the main loop can invoke. A designer working from the top down will start by thinking about the program's main event loop, and plug in specific events later. A designer working from the bottom up will start by thinking about encapsulating specific tasks and glue them together into some kind of coherent order later on.

這裡有一節是討論 glue layer,也正好是我一直搞不懂的,為什麼 python 被稱做 glue language,有些網頁稱 script langueage 為 glue language,但這似乎沒說明什麼,他們到底要黏起什麼?

我沒有足夠的編程經驗,所以並不是很了解他在說什麼。(當然也因為我有限的英文能力)

他的意思大概是說,當程式的設計牽涉到不同的模組,尤其是採用不同的設計方法設計出來的模組時,即使個別的模組有良好設計,但是整體來看卻是缺乏 Compactness and Orthogonality (?) 所以需要 Glue Layers 銜接起來。

One of the lessons Unix programmers have learned over decades is that glue is nasty stuff and that it is vitally important to keep glue layers as thin as possible. Glue should stick things together, but should not be used to hide cracks and unevenness in the layers.

The thin-glue principle can be viewed as a refinement of the Rule of Separation. Policy (the application logic) should be cleanly separated from mechanism (the domain primitives), but if there is a lot of code that is neither policy nor mechanism, chances are that it is accomplishing very little besides adding global complexity to the system.




Coding for Modularity
最後 Eric Steven Raymond 提供了一份列表,讓你檢查一下,你的 modularity 是否設計得不好。


Tag: [], []

2 則留言:

匿名 提到...

1. 我看書都會跳很快,像那種小幽默很少會看到。

2. glue我不太了 但概念應該算有。
在寫perl的時候,不用很多的code就可以連接資料庫,或是讀取網頁,不像oo的要一個物件串一個物件,我像是對於變數和字串的使用很自由吧。

2. 的言論不一定正確,但我使用起來的感覺是這樣。

知北遊 提到...

大概是我對 KUSO 的東西比較敏感吧....哈哈。

至於 glue....

我之前有大概查一下,Python 如何增加程式生產力之類的資料。發現他們的說法或做法,大多不出『code generation tool』(Ref.:Cog,lets you use pieces of Python code as generators in your source files to generate whatever code you need.)或者是『wrappers』(Ref.:Combining Python and C++ by Stephen Figgins)

我想,大體上 glue 的概念就是,不同的東東要合在一起時,因為各個東東各有其 API design,所以整體來看反而缺乏compactness 或者說 coherence。所以既然結合各個東東時必然會發生混亂,那就讓這個 glue layer 最薄....

雖然我不懂 perl,但是 PHP 我懂一點,其實 3P 都是高階語言,不只是字串處理,也能很容易達到各種服務。(其實這應該是 library 的功勞)

但是為什麼 python 特別被強調 glue 的功能?

以 python 來說,他本身就是 OO design,而且是用 C 實作出來的,所以要接合以 C/C++ 寫出來的東西比較容易,所以在相同的概念下,才會有人寫出 Jython 吧。(Jython is an implementation of the high-level, dynamic, object-oriented language Python written in 100% Pure Java, and seamlessly integrated with the Java platform.)

譬如 python 有 py2exe,可以直接把 python script 轉為 C 的 .exe file. 以現在主流是 OO 的角度來看,無怪乎 python 越來越紅了....。