《Unix編程藝術》讀書筆記(1)

《Unix編程藝術》讀書筆記(1)


這兩天開始閱讀該書,下面是自己的體會,以及原文的摘錄,雖然有些東西還無法完全喫透。

寫優雅的代碼來提高軟件系統的透明性:(P134)

Elegance is a combination of power and simplicity. Elegant code does much with little. Elegant code is not only correct but visibly, transparently correct. It does not merely communicate an algorithm to a computer, but also conveys insight and assurance to the mind of a human that reads it. By seeking elegance in our code, we build better code. Learning to write transparent code is a first, long step toward learning how to write elegant code — and taking care to make code discoverable helps us learn how to make it transparent. Elegant code is both transparent and discoverable.

調試工具是通往代碼內部的窗口,能夠發現大多數的bug:(P139)

The lesson is this: Don’t let your debugging tools be mere afterthoughts or treat them as throwaways. They are your windows into the code; don’t just knock crude holes in the walls, finish and glaze them. If you plan to keep the code maintained, you’re always going to need to let light into it.

GCC編譯器是一個關於透明性的很好的實例,它能通過命令行清晰的揭示出預處理器,彙編器,連接器等各個組件的具體工作流,中間結果很有用:P(140)

the driver program has monitoring switches that merely (but sufficiently) expose the textual data flows among the components.

要追求代碼的透明,就是不要在具體操作的代碼之上疊放太多的抽象層,保持薄膠合層:P149

If you want transparent code, the most effective route is simply not to layer too much abstraction over what you are manipulating with the code.

批評了過度的面向對象,既要模塊化編程,也要保持着地,而不是站的離基本組件太高(不同的語言應該有所側重??):P150

Unix programmers are the original zealots about modularity, but tend to go about it in a quieter way. Keeping glue layers thin is part of it; more generally, our tradition teaches us to build lower, hugging the ground with algorithms and structures that are designed to be simple and transparent.

透明性和可顯性,與模塊性一樣,是軟件系統的設計特性,而不是代碼的編碼風格,難有特定的硬性規定,需要思考:P150

  • What is the maximum static depth of your procedure-call hierarchy? That is, leaving out recursions, how many levels of call might a human have to model mentally to understand the operation of the code? Hint: If it’s more than four, beware.
  • Does the code have invariant properties that are both strong and visible? Invariant properties help human beings reason about code and detect problem cases.
  • Are the function calls in your APIs individually orthogonal, or do they have too many magic flags and mode bits that have a single call doing multiple tasks? Avoiding mode flags entirely can lead to a cluttered API with too many nigh-identical functions, but the obverse error (lots of easily-forgotten and confusable mode flags) is even more common.
  • Are there a handful of prominent data structures or a single global scoreboard that captures the high-level state of the system? Is this state easy to visualize and inspect, or is it diffused among many individual global variables or objects that are hard to find?
  • Is there a clean, one-to-one mapping between data structures or classes in your program and the entities in the world that they represent?
  • Is it easy to find the portion of the code responsible for any given function? How much attention have you paid to the readability not just of individual functions and modules but of the whole codebase?
  • Does the code proliferate special cases or avoid them? Every special case could interact with every other special case; all those potential collisions are bugs waiting to happen. But even more importantly, special cases make the code harder to understand.
  • How many magic numbers (unexplained constants) does the code have in it? Is it easy to discover the implementation’s limits (such as critical buffer sizes) by inspection?

隱藏細節和無法訪問細節有着重要區別,優秀的程序員應該給程序設定調試標誌和探測開關,看開源代碼,這一點很常見,debug選項,可以透視程序的運行狀態。P151

Programs that cannot reveal what they are doing make troubleshooting far more difficult. Thus, experienced Unix users actually take the presence of debugging and instrumentation switches as a good sign, and their absence as possibly a bad one. Absence suggests an inexperienced or careless developer; presence suggests one with enough wisdom to follow the Rule of Transparency.

將軟件系統劃分爲協作進程,雖全局複雜度降低,但是代價是需要合適的進程間通信協議,接口部分都是bug的聚集地,還需要爲通信各方設計狀態機,真正重要的不是協議語法而是協議邏輯(模型的正確性)。P159

The real challenge is not protocol syntax but protocol logic—designing a protocol that is both sufficiently expressive and deadlock-free. Almost as importantly, the protocol has to be seen to be expressive and deadlock-free; human beings attempting to model the behavior of the communicating programs in their heads and verify its correctness must be able to do so.

這裏翻譯的不好理解,應該理解爲popen只能爲shellout搭建輸入或則輸出管道,但是卻不能構建雙向管道,因爲pipe是單向的。P168

Unix’s popen(3) call can set up either an input pipe or an output pipe for a shellout, but not both for a slave process — this seems intended to encourage simpler programming.

信號IPC的一種常用場景是pidfile,進程A把自身的PID寫入到一個普通的文件中,在以後的某個時候進程B可以據此文件對A進行控制,如kill它。P171

A technique often used with signal IPC is the so-called pidfile. Programs that will need to be signaled will write a small file to a known location (often in /var/run or the invoking user’s home directory) containing their process ID or PID. Other programs can read that file to discover that PID. The pidfile may also function as an implicit lock file in cases where no more than one instance of the daemon should be running simultaneously.

SIGHUP信號通常作爲守護進程重新載入配置文件的信號。P172

Many well-known system daemons accept SIGHUP (originally the signal sent to programs on a serial-line drop, such as was produced by hanging up a modem connection) as a signal to reinitialize (that is, reload their configuration files); examples include Apache and the Linux implementations of bootpd(8), gated(8), inetd(8), mountd(8), named(8), nfsd(8), and ypbind(8).

雖然文本流沒有經典的RPC性能高,但是系統簡單,易於理解,XML-RPC/json-rpc綜合了二者的優點。P179

Even if text streams were less efficient than RPC, the performance loss would be marginal and linear, the kind better addressed by upgrading your hardware than by expending development time or adding architectural complexity. Anything you might lose in performance by using text streams, you gain back in the ability to design systems that are simpler — easier to monitor, to model, and to understand.

線程共享地址空間,暴漏了彼此太多的內部狀態,所以產生了競爭問題。而進程有獨立的地址空間,良好的封裝,通過明確的IPC進行通信。而且,在多線程中的時序依賴也是一個很難的問題。P180

Threads are a fertile source of bugs because they can too easily know too much about each others’ internal states. There is no automatic encapsulation, as there would be between processes with separate address spaces that must do explicit IPC to communicate. Thus, threaded programs suffer from not just ordinary contention problems, but from entire new categories of timing-dependent bugs that are excruciatingly difficult to even reproduce, let alone fix.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章