為什麼你不喜歡Rules模組 (還有為什麼你錯了!)

By tky, 25 九月, 2011

再次於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的理由通常落在這幾個範圍或之一:

  1. 撰寫自己的hooks會更容易。
  2. 比起Rules外掛,你更能夠控制自己寫的hooks。
  3. 如果沒有必要的話,最好不要依賴其他的模組。
  4. Rules過度複雜,因此根本上就是一個不可靠的爛架構。
  5. Rules太過龐大,因此根本上就是一個不可靠的爛架構。

可能除了第一個理由之外,我認為所有這些理由都是錯誤的。扼要來說,原因是這些:

  1. 整合Rules是很容易的。
  2. 整合Rules並不蘊含要依賴Rules。
  3. 一個事件-條件-動作的架構可以幫助很多模組。
  4. 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怎麼運作,然後才選擇不要用它,那倒行。

Area