作者:探碼科技, 原文鏈接: http://nbbskj.com/tmf/145
原文轉載自:?https://ruby-china.org/topics/31249
Ruby on Rails 能夠現象般地崛起并取得如此卓越的成就,很大程度上應歸功于其對新技術的運用及切入的時機。但技術優勢一般會隨著時間推移而逐漸削弱,而好的時機也并不總會長久相伴。Rails 為何能始終保持與時俱進,并不斷擴大其影響力和社區呢?這里有必要給大眾一個合理的解釋。我認為最主要的原因就是其一直堅守的那些飽受爭議的信條。
這些信條在過去的十年中也在不斷地演進,但最重要的依舊還是那些最基礎的信條。我不會自詡是這些信條的原創者。畢竟,Rails 取得的最大的成就就是:圍繞諸多離經叛道的思想(主要是關于程序設計和程序員本質),融合并培養了一個如此強大的社群。
閑話到此,以下就是 Rails 中最重要的9個信條,請用心領悟:
沒有 Ruby 就不會有 Rails,因此,第一信條必然是來自于創造 Ruby 的核心理念。
Ruby 最初的理念確實將“程序員的開心”放在最首要的位置,也就是將它放在許多曾經驅動程序設計語言和生態圈前進的真理之前。
當 Python 推崇“完成一件事情,有且最好只有一種方式”,Ruby 卻沉醉于表達方式的豐富多彩和優雅精妙。當Java因其保護程序員自身的特性而備受推崇,Ruby 卻在歡迎工具里就附上了自盡的繩子。當 Smalltalk 專注于消息傳遞的純粹性,Ruby 卻近乎貪婪地增加關鍵字和構造器。
Ruby 如此與眾不同是因為它非常尊重事物的多樣性。而這些多樣性中的絕大部分恰是為了滿足程序員開心而服務的。這種追求不僅引起了 Ruby 與其他編程語言環境的爭論,也開啟了主流文化對“究竟什么是程序員,以及他們應該如何工作的”的認知。
Ruby 不僅了解程序員的編程感受,而且還會盡量滿足甚至改善他們的編程感受。無論這些感受是不當的、異想天開的或是令人愉悅的。Matz 跨越了復雜度如此驚人的實現門檻,才讓機器最終面帶微笑以取悅它的人類伙伴。Ruby 充滿了視覺假象,那些表面上看上去如此簡潔、清晰和優美的代碼,其背后的實現卻如雜技般錯綜復雜。當然這些選擇并不是沒有代價的(不信的話,可以問問 JRuby 那些嘗試對 Ruby 做逆向工程的人),這也恰恰是這些選擇如此值得稱贊的原因。
正是這種從另一個角度致敬程序設計和程序員的方式,使我深深的愛上了 Ruby。這不僅僅因為它的簡單易用和充滿美學的設計,也不是任何一項單一的技術成就,而是一種愿景,一種反文化。Ruby 就是程序設計領域中與現有專業程序設計模式相左,而又符合人類思維習慣的缺失部分。
我曾經說過,發現 Ruby 就像是找到了完全適合我大腦思維習慣的魔術手套。比我曾經夢想過的任何手套都要來得合用。它甚至成為了我從“寫程序只是因為我需要程序”到“寫程序是因為我愛上了這種思維的運用和表達方式”的轉折點。就像是找到了“流動之泉”(流動指的是著作?Flow:The Psychology of Optimal Experince?中描述的一種意識狀態,處在這種狀態中的人通常非常愉悅,富有創造力,并且完全沉醉其中),并能隨意進入其中。熟悉 Csikszentmihalyi(上述著作的作者)著作的人都應該知道,這種影響力簡直是有過之而無不及。
毫不夸張的說,Ruby 改變了我,并為我設定了人生努力的方向。這種啟示是如此深刻,以致于讓我對布道這個 Matz 的作品充滿了使命感,也就是去傳播這個意義深遠的作品和它的優點。
讀到這里,我可以想象你們中絕大部份的人都會難以置信地搖搖頭。我不怪你們。當我對程序設計的認識還處在“程序設計只不過是個工具”的階段時,如果有人跟我描述上述經歷,我也會搖頭的。并且,我還可能嘲笑這種過分夸張近似于宗教語言般的描述。但這確實是我的真實想法,也是我的肺腑之言,即便這也許會讓某些人或絕大部分人感到不適。
無論如何,這對Rails來說究竟意味著什么,以及這個理念是如何指引 Rails 持續演進的呢?要回答這個問題,我想先來看看另一條早期經常被用來描述Ruby的原則是非常具有啟發性的:最小驚奇原則。即 Ruby 應該如你預期般運行。通過以下與 Python 對比的例子可以非常容易地理解這個原則:
$ irb
irb(main):001:0> exit
$ irb
irb(main):001:0> quit
$ python
>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit
Ruby 可以同時接受?exit
?和?quit
?來退出終端交互界面,以此來滿足程序員那顯而易見的需求。而 Python 則會迂腐的指導程序員如何正確完成操作,即便它已經明確地知道程序員想要干什么(因為它給出了錯誤信息嘛)。這就是一個非常清晰而又短小的解釋最小驚奇原則的例子。
最小驚奇原則最終在 Ruby 社區失寵的原因是:這條原則本身是非常主觀的。最小驚奇原則,驚奇誰呢?顯然是 Matz,以及那些和 Matz 具有相似思維方式的人。但是,隨著Ruby社區的逐漸壯大,和Matz思維方式相左的人數比例也越來越多,這也成為了郵件列表里那些毫無意義的爭論之源。因此,這條原則最終淡出了人們的視線,以避免“甲男是否對乙物是否驚奇”的爭論無處不在。
但這跟 Rails 又有什么關系呢?其實,Rails 最初就是基于一個與最小驚奇(Matz)原則相似的原則設計的。這個原則就是DHH的?璀璨微笑原則?,簡單來說就是:接口設計的最大考量是如何讓我盡可能地開懷大笑。當我把這條原則寫出來的時候,連我自己都覺得這聽起來有些滑稽和自戀。
然而,正是由于這種最初的深度自戀才造就了 Ruby 或 Rails 這樣的作品,并且這兩個項目都是從單個作者的思想中迸發出來的。當然,這樣說有將我自己的創作動機強加到 Matz 身上之嫌,因此我將聲明縮小到我所知道的范圍:我創作 Rails 純粹是為了我自己。第一條也是最首要的原則就是為了能讓我微笑。盡管 Rails 有各種各樣的功能,但這些功能的最終目的都是為了能讓我更好的享受人生,是為了幫助我改善為網絡信息系統需求所爭論不休的日常生活。
就像 Matz 一樣,有時我也會做出一些愚蠢的決定來實現我自己的理念。其中的一個例子就是 Inflector,一個恰可以完成類到表映射的類(包含規則和不規則的情況),譬如 Person 類對應到 People 表、Analysis 對應到 Analyses,Comment 對應到 Comments。這種行為現在已成了 Rails 中毋庸置疑的一部分,但當我們還在宣揚該原則及其重要性的早期,爭議的怒火曾經肆意蔓延。
另外一個例子是“為了減少了些許實現的工作量,卻幾乎觸發了大量程序員的恐慌”,如:Array#second
?到?#fifth
(以及額外增加?#forty_two
)。這些訪問器別名曾嚴重冒犯了一位非常直言不諱的支持者,他認為這些過度設計(以及額外的那個?#forty_two
?都快接近文明的終點了。這是一個關于42的梗,請自行搜索答案,?)完全可以改寫成?Array#[1]
、Array#[2]
(和?Array[41]
)。
但是,時至今日上述兩個決定依然能令我開懷。我非常享受可以在測試用例或終端里輸入?people.third
。這并不符合邏輯,也不高效,甚至有些病態。 但卻能使我持續開懷,并由此充滿信念并豐富我的人生,繼而證明在服務了 Rails 12年之后依然參與其中是完全正確的選擇。
和性能優化不一樣,開心優化很難衡量。這使得開心優化幾乎成了不科學的無謂之舉。即使有些人并未完全放棄,但也覺得這是無關緊要的事情。因為程序員一直被教導要執著并攻克于可被衡量的事物,也就是那些可以明確指出A要比B好的事物。
盡管對開心的追求很難在微觀角度加以衡量,但從宏觀角度來看卻很清晰。Ruby on Rails 社區中的很多人明顯是因為這樣追求的才聚集于此的。他們因擁有更好的,更能帶來滿足感的職業生涯而驕傲。而這條原則正好處于這些情感的匯集之地,可想而知它的成功是必然的。
因此,我們可以得出以下結論:盡可能讓程序員開心可能是造就 Ruby on Rails 最關鍵的因素,它應該陪伴 Rails 一直走下去。
一條 Rails 早期廣為流傳的箴言是這樣的:你并不是唯一美麗的雪花。如果能放棄那些毫無意義的個人喜好,你就可以跳出諸多無謂選擇的牢籠,在那些真正重要的領域快速前進。
有誰會在乎你的數據庫主鍵采用什么格式嗎?選擇 id,postId,posts_id 或 pid 真的那么重要嗎?這真的值得反復討論才做出決定嗎?當然不。
Rails 的部分使命就是,幫助那些創建網絡信息系統的開發者在日益龐大并一再出現的決策叢林中劈荊斬棘。其實這些成千上萬的的決策只需要做一次就夠了,如果有人能幫你做,那就再好不過了。
約定優于配置,不僅可以讓我們避免許多無謂的思考,而且為更深層的抽象提供了肥沃的土壤。如果我們可以遵循 Person 類到 people 表的映射約定,那么我們也能用相同的約定來為 has_many :people 定義的關聯找到 Person 類。優良約定的威力就在于:每個廣泛使用它們的領域都會受益頗豐。
不僅專家可以借此提升生產力,新手們的入門門檻也可以大大降低。Rails 中包含了如此之多的約定,以至于新手們即使都沒有察覺到它們的存在就可以從中獲益。就算不了解每件事情的底細,也可能創建出偉大的應用。
如果你的框架僅僅是一本厚厚的教科書,而你的新應用只不過是一張白紙,你是不可能成功的。僅僅是找出從哪里以及如何開始就會花費你大量的精力。估計項目開始的大半時間基本上就耗在尋找哪個才是正確的入口上了。
即使你已經了解了所有組件是如何一起工作的,這種情況也不會有所好轉。但是,如果每次變動都有一個明確清晰的應對話,我們就可以快速地略過應用中的大部分工作。因為這些內容和其它應用中曾出現過的內容是相同或類似。所謂各得其所,物盡其用就是這個樣子。從這種意義上來講,約束甚至讓那些最有能力的人獲得了解放。
當然和其它事物一樣,約定的力量也并不是沒有風險的。Rails 如此簡潔就可以完成如此多的事情,這很容易就讓人覺得應用中的每個部分都可以由預定的模版來完成。但是大部分值得創建的應用總會包含一些本身特有的元素,盡管它們可能只占 %5 或 1%,但總會有的。
因此,最難的部分是知道何時我們應該打破約定。那么什么時候值得偏離正軌呢?我認為,大多數想成為唯一美麗雪花的沖動都是不明智的,并且大大低估了脫離 Rails 的成本。但是僅打破該打破的那一小部分應該是沒有問題的,當然你的仔細斟酌每個細節。
當你不知道餐廳里的哪些菜好吃時,如何點餐呢?如果可以讓主廚幫你點的話,那么即使之前你并不知道哪些菜好吃,也可以吃上一頓美味大餐。這就是主廚推薦。一種無需成為美食專家或通過亂點一氣來碰運氣就可以享受一頓美餐的方法。
對于程序設計來說,這條實踐帶來的好處就是讓別人幫你搭建技術棧。這與我們從約定優于配置得出的觀點類似,只是層次更高。約定優于配置著重于為何我們應該使用單一的的框架,而主廚推薦考量的是多個框架如何協同工作。
這和保守的程序設計傳統大相庭徑。傳統做法是提供可用的工具讓程序員自行挑選,并賦予程序員自行決定的權利(其實這是一種負擔)。
你肯定聽說過并贊同這句話:工欲善其事,必先利其器。聽起來就像是一種毋庸置疑的常識,但前提是你的有自信分辨出哪種工具才是最好的。其實,這遠比想象中的要難得多。
這和之前在餐廳吃飯時遇到的問題類似,選擇每個單一的庫或框架并不是獨立的工作,就像為一個包含八道菜的套餐挑選每道菜一樣。兩者的目標都需要基于整個晚宴或系統統籌考慮。
因此,在 Rails 中我們決定舍棄小利:程序員在工具箱里挑選每件工具的權利,來換取更大的利益:一整套更好的工具箱。這個決定回報頗豐:
人多勢眾:當大家都用默認的方式使用 Rails 時,我們就擁有了共同的體驗。教授和幫助他人就會變得容易的多,同時討論也有了共同的基礎。就好比我們都在昨晚7點看了相同的節目,第二天我們的討論就有了共同話題。這種共同的體驗進而促成了更有凝聚力的社區。
日益完善的基礎工具箱:Rails 作為一個全??蚣馨嗽S多活動組件,它們之間如何協同工作與它們單獨運行具有相同的重要性。軟件工程的痛點大部分不是來自于組件內部,而是組件之前的相互協作。當我們都在一起努力工作修復這些大家都會碰到的痛點(因相同的的配置和使用方式而獲得一致的錯誤)時,這些痛點就會越來越少。
按需替換:盡管 Rails 是一個主廚推薦的技術棧,你仍然有機會替換掉其中的某些框架或類庫。只是不建議你這么做。當你需要為某些特定的場景開發出一套清晰的個性化工具箱時,再來考慮這些決定吧。
即使那些最博學多才且經驗豐富的 Rails 程序員也不可能抵觸菜單上的每道菜(如果是的話,那他們就不會選擇繼續使用 Rails 了)。因此,他們會謹慎的挑選替代者,并和其他人一齊享受剩下的部分。
大家都對挑選并遵循單個核心理念來構建自己的基礎架構具有強烈的訴求。這個訴求如此純粹,以至于程序員都會自然而然地被它所吸引。
Rails 不遵循上述理念。它不是單件完美剪裁的衣服,它是一床棉被,是諸多不同理念和模式的組合體。如果將它們分開來一一對比的話,其中許多通??磥磉€是相互抵觸的。當然,我們也不會這么去做。這又不是僅有一個贏家的超級理念錦標賽。
來看看 Rails MVC 模式中用來創建 View 的模板。默認情況下,所有從模板里抽取出來的 Helper 不過是一堆方法,甚至擁有同一個命名空間。是不是感到有點震驚和恐懼,這不就是 PHP 嘛!
但我認為,PHP 處理這些方法的方式是正確的,因為它們之間很少相互調用,就像那些從 View 模板中抽取出來的方法一樣。以此為目的,使用單個命名空間來包含這些方法不僅是理性的選擇,而且是一個很棒的選擇。
我們偶爾也會想用更加面向對象的方式來創建 View。MVP 模式中的 Presenter 就是這樣一劑解決方法之間相互依賴的良藥。Presenter 中封裝了一系列相互獨立的方法和這些方法要處理的數據。但事實證明這種情況并不常見。
相較而言,我們將 MVC 中的 Model 看做面向對象思想的精髓所在。領域建模的樂趣就在于為對象挑選合適的名稱、提高一致性和降低耦合程度。這是和 View 層完全不同的場景,因此需要另辟蹊徑。
即便如此,我們也不會遵循單一理念的信條。Rails concern (定制過的 Ruby mixin) 經常用來擴展 Model。它可以和 Active Record 模式完美結合,讓那些混入的方法可以直接存取它們要處理的數據。
就算是 Active Record 模式最基本的理念也會冒犯某些純粹主義者。因為,我們將與數據庫相關的操作和業務邏輯直接混合在了一起。毫無邊界的融合!沒錯,因為這是已經證明的切實可行的方法,可用于構建需要經常訪問數據庫,以存取領域模型狀態的網絡應用。
Rails 擁有如此理想的靈活性,使得它可以處理各式各樣的問題。而大多數單一模式僅在問題的某一領域運轉良好,當超出其范圍時就顯得力所不及了。但是,通過將多個模式疊加應用,我們就可以做到全面地覆蓋。最終框架的健壯性和能力將遠超任何單一模式所能達到的高度。
目前,理論上來說維持眾多編程模式多元共存關系的代價是高昂的。想要用好 Rails,僅了解面向對象編程是不夠的,最好還能有面向過程編程和函數式編程的經驗。
上述原則也同樣適用于 Rails 中的其他子語言。 我們不會為你提供過多保護,以便讓你不必學習那些必須掌握的知識。比如,在 View 中使用 JavaScript 或偶爾用 SQL 來構建復雜查詢。至少這類保護不會以盡可能完善為目標。
降低學習曲線的方式就是讓大家容易上手,在了解框架的每個細節之前,就可以做出一些有真正價值的東西。這也是為什么我們會有一個快速搭建 Hello World 方法的原因。萬事俱備就等你來嘗試了。
Rails 的思路是,通過讓從業者盡早地創建真正有價值的東西,來鼓勵他們快速成長。讓他們覺得學習 Rails 是一種愉悅的過程,而不是一種障礙。
寫代碼并不僅僅是為了讓計算機或其他程序員易于理解,而且還要享受那種沐浴在優美代碼中的愉悅感。從美學角度來說,令人愉悅的代碼本身就很有價值,應該值得我們花精力去追求。這并不意味著優美的代碼應該勝過其他考量,但至少應該在優先考量中占有一席之地。
那么什么才算優美的代碼呢?在 Ruby 中,通常指的是 Ruby 固有語法和自定義 DSL 力量的交集。這是一條模糊的定義,但非常值得一試。
下面是一個取自 Active Record 的簡單例子:
class Project < ApplicationRecord
belongs_to :account
has_many :participants, class_name: 'Person'
validates_presence_of :name
end
它看起來和DSL非常相似,其實不過是一個類定義,加上三個帶 symbol 參數和選項的類方法調用。這里并沒有什么魔幻的東西,不過確實優美而又簡潔。簡單幾行聲明就帶來了如此強大的洪荒之力。
這種優美部分應該歸功于之前提到過的那些原則,如約定優于配置。 當調用?belongs_to :account
?時,我們假定 projects 表中存在一個名字為 account_id 的外鍵。當必須為 partcipants 關聯指定 class_name 為 Person 時,我們只需定義 Person 類即可,并可以由此推斷出外鍵和其它相關設定。
下面是另一個取自數據庫遷移系統的例子:
class CreateAccounts < ActiveRecord::Migration
def change
create_table :accounts do |t|
t.integer :queenbee_id
t.timestamps
end
end
end
這個例子體現了框架威力的精髓。這里程序員遵循某種約定定義了一個類,這個類繼承自?ActiveRecord::Migration
?并實現了一個 change 方法。剩下的事情就可以交給框架去處理了,并且框架知道該調用這個change方法來處理。
這樣程序員只需要寫很少的代碼就可以很好地完成工作了。上述代碼不僅支持通過調用?rails db:migrate
?為數據庫添加一張新表,同時也支持通過調用另外一個命令從數據庫中刪除這張表。這和工程師自己實現這些功能,并將它們整合為工作流的方式完全不同。
優美的代碼有時看起來也會顯得晦澀難懂。但優美的代碼不應該是為了盡可能地短小精干,而應該更加關注閱讀的流暢性。
以下兩條語句是等價的:
if people.include? person
...
if person.in? people
但它們在語境和側重點上存在細微的差異。第一條語句側重點在集合,因為它是主語。第二條語句中,主語明顯是 person。這兩條語句在長度上并沒有太大的差別,但是我認為第二條要優美的多,特別是當它用在判斷條件是關于 person 的時候,這會讓我感到由衷的開心。
Ruby 本身就包含了許多開發利器。不是碰巧,而是設計如此。其中最著名的應屬 Monkey Patching: 一種可以修改現有類和方法的能力。
這個能力經常被嘲諷為:太簡單了,即便是最普通的程序員也可以輕松掌握。以至于那些來自限制性較為嚴格語言陣營的人曾經?;孟耄禾^信任程序員可以駕馭這項能力最終會毀了 Ruby 這門語言。
因為,如果什么都可以修改的話,那還有什么可以阻止你重寫 String 的 capitalize 方法,讓?“something bold”.capitalize
?返回?“Something Bold”
,而不是?“Something bold”
?呢?這在你自己本地的應用中可能沒有什么問題,但所有那些依賴于原始實現的輔助代碼可能就要遭殃了。
那么有什么解決方案嗎?答案是:沒有。在 Ruby 中,只要有好的理由沒有什么可以阻止你用利器來掃除障礙。我們會通過約定、勸說和教育來推行好的理念,而不是通過禁止使用廚房中的利器,并堅持讓每個人使用勺子來切西紅柿。
由于 Monkey Patching 的負面效應創造了諸如?2.days.ago
(返回兩天前的日期)般的壯舉。你可能會覺得這是一樁虧本的買賣。也就是說寧可沒有?2.days.ago
,你也不想修改語言的原始實現。如果這就是你的觀點,那么也許 Ruby 并不適合你。
也許你從那些出于安全考慮而放棄自由的人口中聽說過:正是可以修改內核類和方法的能力毀了 Ruby 這門語言。然而事實剛好相反,Ruby 的蓬勃發展正是由于它為程序員提供了全新的不同看法:完全可以相信程序員可以駕馭利器。
當然僅相信是不夠的,還應該教授他們使用這些利器的方法。如此一來還有利于提升整個行業水平,當然前提是大多數程序員都想成為更好的程序員,并有能力在使用利器的同時避免割傷自己的手指。這真是一個夢寐以求的想法,也是一個有悖于許多程序員對其它程序員初衷(不相信其它程序員)的想法。
當討論開發利器的重要性時,對象總是其它程序員。我從未聽過有程序員說:”我不確信自己可以駕馭這種能力,請讓我遠離它!“ 經常聽到的卻是 “我覺得其他程序員可能在濫用利器”。但這種專制的想法從未出現在我的腦海中。
正是這些開發利器將我們吸引到了 Rails 周圍。Rails 提供的利器盡管沒有 Ruby 提供的那么鋒利,但其中有些還是頗具威力的。我們不會因為在工具箱里放置了這些利器而感到抱歉。事實上,我們對工程師們敢于嘗試的渴望持有足夠的信念,并為之自豪。
Rails 的許多功能一直因 “太過隨意” 而飽受爭議。當下最流行的一個例子是:Concern。其實它就是在 Ruby 本身內建的 Module 功能上添加了一層薄薄的語法糖,允許使用單個類來封裝多個相關又可以獨立理解的業務(也就是 Concern 這個名字的由來)。
Concern 功能備受指責的原因是,通過它程序員可以很容易將一些不相關的東西塞到對象中。說的沒錯,Concern 確實可以這樣使用。
一種謬論認為,如果不提供類似于 Concern 的功能(即使是最溫和的用法也會導致設計思想的部分分離),就可以讓程序員處在通往幸福的康莊大道上。但是,如果你連讓對象保持整潔都做不到的話,談何可以寫出優雅的代碼呢?
尚未學會如何使用利器的程序員就不可能做出甜美的糕點。注意這里的用詞:尚未。我相信每個人自己都會有一條成為 Ruby 和 Rails 稱職程序員的道路,即使這條道路并不完全順利。我說的稱職是指:有足夠的知識知道,何時以及如何根據不同的場景使用不同的工具,有時甚至危險的工具。
這不是在推脫幫助他們達成稱職程序員的責任。語言和框架應該是有耐心的導師,愿意幫助和指導每個人成為專家。唯一可靠的道路就是不斷犯錯:錯誤地使用工具,些許血淚教訓。沒有捷徑。
Ruby on Rails 是大廚以及那些想要成為大廚的人的廚房。也許剛開始你只是洗洗碗,但可以逐漸成長,最終可以運營整個廚房。在這個過程中,別相信任何人告訴你的:你無法駕馭業內最好的工具。
Rails 可用于許多場景,但最初目的是創建一個整合系統:Majestic Monolith!即一個可以解決所有問題的完整系統。這就意味著 Rails 需要考慮從前端需要即時更新的 JavasScript 到生產環境下數據庫如何進行版本遷移的所有細節。
如上所述,這確實是一個非常寬廣的領域,但尚在我力所能及的范圍之內。Rails 會專門尋找全棧工程師來創建這個整合系統。當然,目的不是將那些專注于某個領域的專家排除在外,而是因為整個全棧的團隊可以更好的創建具有長遠意義的事物。
正是專注于提高個體程序員的開發能力,讓我們想要創建這樣一個整合系統。在整合系統里,我們可以拿掉很多不必要的抽象,減少各層之間的重復(就像服務端和客戶端共享的模版),最重要的是可以避免讓應用成為分布式系統(在確實有必要之前)。
許多系統開發的復雜性來自于引入組件之間的新邊界,這些邊界限定了組件之間相互調用的方式。對象之間的本地調用要比遠程微服務之間的調用簡單得多。那些冒險啟用分布式系統的人會發現,這是一個充滿失敗調用、網絡延時和依賴更新周期的全新地獄。
有時候這種分布僅僅是簡單的需求。比如你為 web 應用創建了一個 API 接口,以供其他人通過 HTTP 調用,那你就乖乖等著收拾爛攤子吧(盡管處理請求要比發送請求要容易的多。因為在發送請求時,別人的錯誤也會導致你自己的錯誤)。但對你自己來說,這至少不是一次愉快的開發經歷。
更糟的情況是,系統可能過早地被拆分成了服務,甚至是更差的微服務。這通常來自于一個錯誤的認知:如果你想要個現代網絡應用的話,只需要簡單地多次的構建系統,一次在服務端,一次在基于 JavaScript MVC 的客戶端,以及每個移動端的本地應用等。這不是基本規律,也完全沒有必要。
其實完全可以在多個 app 間共享整個應用的大部分內容。相同的 Controller 和 View 可以用于桌面 web 應用,也可以內嵌到手機 app 的本地應用中。也就是盡可能將開發集中在同一個整合系統中。
而且這樣做完全不必犧牲速度、用戶體驗或其他任何誤導你過早拆分系統的因素。
這就是我們一直追尋的大一統:可自行調配、適用于多平臺應用開發、易于理解和使用的單個整合系統。
當一個系統存在已經超過10年,如 Rails,一般都會自然僵化。每一處修改都有各種可能給他人帶來災難,因為他們可能依賴于過去的實現。而且,對這些人來說,他們的要求完全是合理的。
但如果我們太過遷就保守派的意見,我們將永遠看不到事情的另一面。因此,我們必須偶爾打破陳規,以改變事情演進發展的方式。正是這種演進方式才讓 Rails 得以存活,并可能在未來(數)十年繼續蓬勃發展。
永遠都是說起來容易做起來難,特別是當你自己的應用因 Rails 的重大版本升級(不向下兼容)而崩潰時。然而正是這些時刻,才讓我們謹記?演進優于穩定?的價值所在,并為我們帶來修復崩潰應用的力量,從而繼續保持與時俱進。
這并不代表我們就可以不管三七二十一地給別人帶來不必要的或過份的傷害。Rails 2.x 到 3 的重大升級就是這樣一個艱難的決定,它所帶來的噩夢還依然徘徊在那些親身經歷過的人的心頭,經久不散。它讓許多人在 2.x 版本停留了很長一段時間,有些人甚至對此深惡痛絕到失去了理智。但,從大局來看這個決定還是值得肯定的。
這些就是我們一直要做的艱難抉擇。Rails 是否會因為今天的改變而在未來五年內變的更好?Rails 是否會因為接納其他解決方案,如異步任務隊列或 WebSocket,而變的更好?如果答案是肯定的,那就啥都別說了,讓我們卷起袖子干活吧。
其實這項工作并不僅限于 Rails 本身,而應該在廣大 Ruby 社區推行。Rails 應該站在幫助 Ruby 進步的前沿,推動廣大社區成員盡快使用最新版本。
就目前情況來看,我們做的還不錯。從我開始實踐這個信條開始,我們已經經歷 Ruby 1.6、1.7、1.8、1.9、2.0、2.1、2.1、2.2,直到目前最新的2.3。一路走來伴隨著許多重大的變遷,但 Rails 始終是 Ruby 的堅強后盾,它幫助每個人盡快地適應新版本的變遷。這是 Rails 作為Ruby 主要推廣者的部分權力和義務。
同樣,這一點也適用于工具鏈上的其它輔助工具。Bundler 曾經是一個充滿爭議的理念,但是經過 Rails 的不懈努力的推廣,它已經成了可以和 Rails 相提并論的基石,并成為人們理所當然的選擇。像 Asset Pipeline 和 Spring 這樣的連續處理指令組件其實也一樣。這三個組件全都經歷過或正在經歷演進的痛苦,但是這些工具的長遠意義促使我們一直推動他們前進。
最終,進步還是要取決于人以及他們想要做出改變的意愿。這就是為什么在 Rails Core 或 Rails Commiters 類似的小組中沒有終身職位一說。這兩個小組的成員都是那些為推動框架進步而積極工作的人。有些人可能只會堅持幾年,不管怎樣我們會永遠感謝他們做出的貢獻,但另外一些人可能會為之持續數十年。
因此,我們會一直歡迎和鼓勵新的成員加入社區,這對我們來說至關重要。我們需要新的血液和理念來激蕩出更好的進步。
Rails 因包含諸多富有爭議的理念而聞名。如果我們要求每個人無時無刻遵循所有的信條,那么 Rails 將會很快淪為孤芳自賞的小群體。所以我們絕不會這樣做。
我們需要不同的意見。我們需要不同的語法。我們需要多樣的思想和成員。在這個思想的大熔爐中,我們可以提煉出最好的精華部分給大家分享。在此過程中,許多人以代碼或深思熟慮的論點貢獻了他們的意見。
這篇信條其實描述的是一種理想狀態,日常生活中的實際情況要微妙(也更有趣)的多。Rails 可以在同一個帳篷里容納下如此龐大的一個社區,究其原因是 Rails 很少或者根本沒有試劍石(非一即二的考驗)。
RSpec(一個我經常表達不滿的測試DSL框架)的持續成功就是一個完美的佐證。盡管我可以為此吐槽到口干舌燥:為什么我覺得這不是正確的測試方式。但依然不能妨礙它大獲成功。這點才是最為至關重要的。
Rails API 的出現同樣如此。盡管我個人是關注和傾力的重點是帶有 View 的整合系統,但對那些想要做前后端分離的人來說,毫無疑問這是 Rails 可以改進的地方。因此,我們應該欣然接受 Rails API 成為 Rails 的第二使命,而且我相信它配得上如此重要的地位。
當然,擁有同一個帳篷并不意味著需要迎合所有人的所有需求。它僅僅意味著歡迎所有人加入這個大家庭,并帶來他們自己的想法。我們不必犧牲我們的靈魂和價值觀來讓他們加入我們,我們只是知道如何將不同的想法混合在一起,來產生新的美妙思想。
當然這樣一個帳篷不是唾手可得的,還需要很多工作來讓它受到大家的歡迎,特別是你的目標不僅僅是吸引那些已經在社區里的人。因此,降低入門門檻總是我們需要慎重考慮的工作首選。
你永遠不會知道:修正文檔中拼寫錯誤的人是否最終可能會創作出下一項偉大功能。但是,你有機會向每個做出微不足道貢獻的人表示感激,從而激勵他們繼續努力工作。
?