在2011年9月底的時候,再次於NodeOne網站看到Johan Falk發表了討論Rules模組的文章,Why you don't like Rules (and why you're wrong),感覺十分精彩。去信向作者取得同意後,花了兩三天翻譯了這篇文章,希望能夠幫助更多對Rules模組有興趣的朋友。
以下是翻譯內容
我希望能用這篇文章去釐清說為什麼Rules是Drupal生態系統中很重要的一部份,以及釐清說,你作為一個開發者為什麼應該要知道這點。
在Drupal的社群裡頭,廣泛地去討厭一個模組是相當少見的事情。即使是在評論低水準的、糟糕的和被放棄掉的模組時,開發者也通常會說「我會用X模組來代替」。不過呢,在碰到Rules模組的時候,我有幾次聽到大家說類似「我不喜歡Rules」或者「我想Rules是個爛主意」這樣的話。
只是確認一下我們有共同的認知:Rules是一個用來在Drupal網站上執行「事件-條件-動作」過程的模組。換句話說,當一個選定的事件在你的網站上發生的時候,Rules可以檢查一堆條件並且-如果條件許可-會執行一堆動作。「在使用者登入的時候,如果該使用者並非管理者,就重新導向到首頁去」。「在發表評論的時候,發一封e-amil給網站編輯」。這樣你了解了吧。(如果還是不了解,看一下這些影片吧。)
毫無疑問,事件-條件-動作是一個有用的模式,可以在你的網站上產生很多事情。這是為什麼Drupal有這麼多hook,讓程式設計師可以在Drupal的執行迴圈中,到處加上額外的功能。所以,怎麼會出現這種對Rules的質疑呢?
在我的經驗中,通常都是編碼人員不喜歡Rules。(這個假設受到這個事實的支持:Rules是Drupal 7排名前2%的模組之一)。反對Rules的理由通常落在這幾個範圍或之一:
- 撰寫自己的hooks會更容易。
- 比起Rules外掛,你更能夠控制自己寫的hooks。
- 如果沒有必要的話,最好不要依賴其他的模組。
- Rules過度複雜,因此根本上就是一個不可靠的爛架構。
- Rules太過龐大,因此根本上就是一個不可靠的爛架構。
可能除了第一個理由之外,我認為所有這些理由都是錯誤的。扼要來說,原因是這些:
- 整合Rules是很容易的。
- 整合Rules並不蘊含要依賴Rules。
- 一個事件-條件-動作的架構可以幫助很多模組。
- Rules給我們可供學習的優良作法。
整合Rules既簡單又不痛
你可以在你的模組裡頭新增一個views處理程式而不需要讓它依賴Views,這沒啥令人訝異的。你也可以替你的欄位寫個自動產生的功能而不需要依賴Devel Generate模組。所以啦,一點也不奇怪,你的模組也不必依賴Rules才能把它整合進來。
如果你給了一個hook_rules_action_info,告訴Rules你的動作函數為何,那麼你會讓5-6萬個使用Rules的網站都可以用更彈性的方式來使用你這個函數。那不會比這樣更複雜:「我的動作函數叫作my_callback,有一個使用者物件和字串作為參數"。宣告事件和條件也是依循著類似的、簡單的(而且有完善說明文件的)表單來進行。
我們很快的瀏覽一下你 - 以及那些使用你的模組的人們- 可以從設定Rules出名的事件、條件和動作裡頭所得到的好處:
- 你的動作和條件可以為Drupal的其他部份所用(像是Views Bulk Operations 或是 Page manager)。
- 你的動作和條件可以結合其他的模組,創造出更複雜的效果。
- 你的動作所需要的資料可以在送出前受到變更。不需要跑完整個額外的drupal_alter函數。
- 你可以加入更多的動作到你模組所觸發的事件裡頭。你不需要執行你自己的module_invoke_all函數,強迫其他的模組運行一個特殊的hook。
代價是什麼呢?你還是可以直接的呼叫你自己的函數。Rules並不會依賴你的模組。所以這代價就是大概20行的代碼而已。
沒錯,直接寫一個你要的hook還是比較快,而且這不需要去煩惱Rules的相容性問題。至少短期來說如此。對我而言,這聽來就像是用寫代碼的方式來定義一個內容類型。或者聽起來像是不使用Views而直接寫SQL。或聽來像是「我喜歡寫我自己專屬的代碼,而且我沒興趣去學習與整合其他的架構」。這對我來說不是那麼的Drupal。
Rules的一體成形功能。
如果你介意Rules很龐大而且可能會是個效能殺手的話,我一樣也介意這點。我還沒找到(或進行)效能方面的研究說法,告訴你如果你每載入一頁都執行Rules的話,會發生什麼事情。不過我也很在乎說,如果你每載入一個網頁都要呼叫很多模組話會怎樣。Rules提供了一個很好的包裝,可以納入其他的模組 - 這意思就是說可以在單次執行的時候,跳過所有這些模組。
這裡有個例子。Context模組或許有個比Rules還小的執行過程。不過如果你的網站也有使用Path redirect、Page title以及Custom breadcrumbs模組的話,我不會意外說,這些模組加起來會比Rules有更多效能上的衝擊。而同時Rules可以被用來做到大部分那些模組所能做的事情,如果不是全都能做到的話。現在就是這樣子。真的。(還能夠替你儲存東西咧。)
如果那些模組還有其他的模組都可以透過Rules而有他們自己的事件、條件和動作,我認為這就有可能節省相當多的執行效能。而就算我們真的損失了一點點效能好了,我們仍舊可以得到非常非常多的配置彈性。
另類的作法就是重複的撰寫同樣類型的程式碼,還有類似功能的模組,而這些東西彼此無法互相溝通。這可就不有趣了。
Rules提供了值得學習的好作法
我目前所講的是說,你可以用Rules去做到你的模組已經正在做的事情。不過你也可以從Rules裡頭學到一些新東西。
The Drupal 7 version of Rules has a data management layer that could be very useful in other parts of Drupal. The data management builds on information provided by Entity API, but also extends it with a number of non-entity data types.
Drupal 7版本的Rules擁有一個資料處理層,對於Drupal的其他部份來說會非常有用。這個資料處理層建立在Entity API所提供的資訊上面,不過也可以擴及很多非entity的資料類型。
在Rules裡頭,每個設定都關係到要怎麼把資料彼此配對起來。如果一個事件提供了一個文字字串,它就能夠被用來設定輸入可能的文字字串 - 而不能夠設定日期或時期。所有的設定都預定某種輸入方式,(就我所知) 這讓Rules成為一個在以簡約方式處理資料和設定方面最具前瞻性的模組。
我們還可以從Rules那裡學到一些其他的作法:
- Rules可以被匯出而且與Features整合。
- Rules的匯出程式碼對一般人來說簡單易懂。
- Rules有良好的SimpleTest涵蓋率。
- Rules有清楚的APIs以及良好的開發人員指南。
根據我的經驗,沒有很多模組 - 甚至是排名前100的模組 - 能夠像Rules一樣有那麼優秀的作用。
怎樣做反而是沒道理的?
Rules是一個複雜的架構。在某方面來說,它是很臃腫沒錯。不過事實上,有事件-條件-動作這種風格的模組還挺常見的 - 而如果沒有一個架構能夠管理它們的話,那就太沒道理了。Rules或許不是完美無缺的工具,不過它是一個好工具而且可以被改良。
在Rules不存在的情況底下,開發事件、條件和動作這種事是很白痴的。不花時間去學習重要的架構,這樣是不行的 - 不停的重新發明Rules的某部份功能也一樣不成。知道Rules怎麼運作,然後才選擇不要用它,那倒行。