The Art of Unix Programming by Eric Steven Raymond4. 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 SizeThe 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 OrthogonalityAccordingly, 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: [
Book], [
Programming]