閱讀Erlang官方文檔經(jīng)??梢宰x到下面兩句:

  •   "xxx implemented using this module will have a standard set of interface functions and include  functionality for tracing and error reporting. It will also fit into an OTP supervision tree. Refer to OTP Design Principles for more information."
  •  " xxx comply to the OTP design principles".

    一句是說某模塊包含了一系列標準的接口函數(shù)來實現(xiàn)跟蹤和錯誤報告,這個模塊符合加入監(jiān)控樹的要求,去OTP設(shè)計原則相關(guān)的章節(jié)查詢更多信息.后面一句就簡單了,說xx模塊的實現(xiàn)時符合OTP設(shè)計原則的.但是Erlang文檔組織的問題,文檔中并沒有對OTP設(shè)計原則給出嚴格的定義和解釋.你可能會搜索到下面的鏈接:

http://www.erlang.org/documentation/doc-5.6/pdf/design_principles.pdf

呵呵,這個僅僅是Erlang老版本的文檔而已.本文是我學習OTP設(shè)計原則的一點總結(jié)

 

OTP設(shè)計原則定義

The OTP Design Principles is a set of principles for how to structure Erlang code in terms of processes, modules and directories.

這句來自http://www.erlang.org/doc/design_principles/des_princ.html 給出了OTP設(shè)計原則的大致定義即:OTP設(shè)計原則是如何按照進程,模塊,文件夾的概念來組織代碼的一系列原則.無論用什么技術(shù)實現(xiàn),設(shè)計都是解決代碼如何組織的問題.還記得我們曾經(jīng)提到過設(shè)計的三層視角嗎?(猛擊這里穿越:http://www.cnblogs.com/me-sa/archive/2008/04/15/ooview.html)從概念層確定要做什么,到規(guī)約視角確定各部分之間的關(guān)系,實現(xiàn)視角最終通過代碼實現(xiàn)功能,經(jīng)過這三個視角從宏觀到微觀的設(shè)計過程,代碼結(jié)構(gòu)逐步確定.在Erlang的特定語境下,組織代碼的方式就是:進程,模塊,文件夾;

 

Erlang代碼的物理組織方式 

   模塊和文件夾是代碼的物理組織方式,代碼組織的最小單元是模塊(module),模塊放在不同的文件夾中,下面是一個典型的文件夾布局:

doc  存放程序文檔和配置文件
include  存放頭文件.hrl
priv  類似于Reference文件夾,存放需要引用的第三方類庫
src  源代碼文件夾
ebin 編譯的目標文件夾,存放beam文件

 

Erlang代碼的功能邏輯組織方式

    Erlang的設(shè)計哲學是把獨立的活動通過進程表達;Erlang代碼的功能邏輯組織方式,其實就是在講如何組織進程.

    Erlang/OTP進程組織的方式是監(jiān)控樹(supervision tree),監(jiān)控樹用worker和supervisor的概念把進程分成兩類.worker完成實際的運算工作,supervisor的職責就是監(jiān)控worker的行為,如果worker出錯就通過重啟的方式使worker正常工作.監(jiān)控樹將代碼組織成層級結(jié)構(gòu),我們可以基于這種架構(gòu)泛型建立起一個逐級可控的容錯系統(tǒng).下面是開源項目log4erl的監(jiān)控樹結(jié)構(gòu):

 


   不是所有監(jiān)控樹中的進程都可以成為supervisior和worker,對進程還是有特殊要求的:A.支持調(diào)試sysdebugfacilities B.能夠響應系統(tǒng)消息. 所謂系統(tǒng)消息是在監(jiān)控樹中使用的有特殊意義的消息,比如trace輸出,掛起或恢復進程執(zhí)行.要滿足上面的兩個要求對于開發(fā)者需要做什么呢?我們有兩個選擇:

  • 使用標準behavior實現(xiàn)
  • 使用sys和proc_lib模塊

    在stdlib文檔的behavior章節(jié)可以看到gen_server gen_fsm gen_event supervisior都實現(xiàn)了跟蹤和錯誤報告的功能,并可以處理系統(tǒng)消息.監(jiān)控樹中進程都按照相同的模式編寫,結(jié)構(gòu)上有很多類似.比如supervisor的區(qū)別僅僅在于監(jiān)控哪個進程.很多worker也都是server-client,fsm(有限狀態(tài)機),和event handler的關(guān)系.Behaviours 規(guī)范化了這些通用模式,把一個進程的實現(xiàn)代碼分成兩部分:通用部分和回調(diào)接口.通用部分由Erlang/OTP類庫實現(xiàn),其實我覺得應該稱之為框架更合適一些,回調(diào)接口函數(shù)由我們來完成,并把這些函數(shù)導出.由于回調(diào)函數(shù)往往不會被開發(fā)者直接調(diào)用,開始的時候很容易出現(xiàn)的問題就是忘掉導出回調(diào)函數(shù),特別是初始化函數(shù)init.使用behavior開發(fā)是通過犧牲一點點效率來獲得通用性和一致性.對于復雜性的系統(tǒng)來說,一致性至關(guān)重要,一致性帶來的是更高的可讀性,可維護性.標準的Erlang的behavior有:

gen_server 實現(xiàn)通用client-server關(guān)系  

gen_fsm        實現(xiàn)有限狀態(tài)機

gen_event    實現(xiàn)事件處理功能

supervisor  實現(xiàn)監(jiān)控樹中的supervisor

我們在代碼中顯示添加-behaviour(Behaviour),編譯的時候編譯器會檢查對應behavior的回調(diào)函數(shù),如果缺失或者沒有導出會有警告.

  這些標準的behavior內(nèi)部實現(xiàn)使用的是sys和proc_lib,所以我們可以直接使用這兩個模塊達到同樣的效果,后面我會有專門的文章說這兩個模塊.

 Erlang/OTP中的能完成特定功能集合的組件被稱為application.  監(jiān)控樹是進程的組織方式,application是Erlang功能的組織方式.

 

總結(jié)一下:

  1. Erlang OTP設(shè)計原則關(guān)注的是Erlang代碼的組織方式
  2. Erlang代碼分割存放在不同的模塊,模塊存放在不同的文件夾
  3. Erlang代碼的邏輯組織方式是監(jiān)控樹
  4. 可以成為supervisior和worker需要支持跟蹤,錯誤報告以及響應系統(tǒng)消息
  5. 標準behavior實現(xiàn)了上述要求,也可以通過sys和proc_lib模塊實現(xiàn)
  6.  監(jiān)控樹是進程的組織方式,application是Erlang功能的組織方式

 

  純理論的東西總是顯得空洞,后面的文章中我們會不斷回顧這部分內(nèi)容,將理論和編程實踐做對應.

  周末愉快!