原文鏈接: Five Practices for Robust Ruby on Rails Applications
轉(zhuǎn)載請注明出處:http://www.tedyin.me/2016/03/06/five-practices-for-robust-ruby-on-rails-applications/
無論什么時候嫉戚,當(dāng)我發(fā)現(xiàn)項目里面存在 bug 或者數(shù)據(jù)不一致,但卻又很難找到是哪里出了問題時肋乍,我總是會感嘆:“他們(the developer)只需要再多敲幾下鍵盤兵怯,這些事情就不會發(fā)生了∧眨”
在Brewhouse的工作中杏愤,我們會應(yīng)用下面5種最佳實踐,讓我們的 Rails 應(yīng)用更加健壯已脓。因為這些方法可以讓代碼在遇到問題時珊楼,可以盡早地、明確地度液、快速地的拋出問題厕宗,告訴我們哪里出錯了。我們可以通過捕捉這些錯誤信息來確保我們所有的數(shù)據(jù)和操作都是正確有效的堕担。
使用 Hash#fetch 方法去處理‘有問題’的 hash 對象
unexpected method 'upcase' for nil…
這樣的錯誤已慢,我們經(jīng)常會遇到。無論什么時候當(dāng)你去遍歷一個hash
對象照宝,如果你希望這個hash
對象中所有的key
都存在蛇受,你最好是使用fetch
方法去代替[]
方法。fetch()
方法在遇到key
不存在的情況時會拋出異常厕鹃,因此你就無法再傳入一個有問題的hash
對象了兢仰,也就不可能出現(xiàn)一些奇怪的 bug 了乍丈。
使用 case ... else raise 去捕獲異常數(shù)據(jù)
最好是在所有的case
條件選擇語句中加入else raise
語句,來處理一些你預(yù)想之外的情況把将。當(dāng)你的方法接收到一些你預(yù)想之外的數(shù)據(jù)時轻专,我想你肯定是想知道這些是什么數(shù)據(jù),而不是說忽略這些數(shù)據(jù)察蹲,而讓代碼繼續(xù)執(zhí)行请垛。因此建議使用case ... else raise
!
使用 ActiveRecord 的 ‘!’ 方法,讓失敗的操作自己說話
對于每個公司來說洽议,數(shù)據(jù)通常都是非常重要的資產(chǎn)宗收。如果在對數(shù)據(jù)進行持久化或者其他錯作時失敗了,但是這些失敗的操作是悄悄發(fā)生的我們并不知道亚兄,那么這會是一件很危險的事情混稽,將會對我們的數(shù)據(jù)造成嚴(yán)重的危害。因此無論什么時候审胚,當(dāng)你不希望某些操作失敗時你卻不知道的話匈勋,建議是用create!
,update!
和destroy!
方法膳叨,在操作失敗的時候他們會拋出異常洽洁,來告訴你操作失敗了。這額外的一個字符!
將會讓你避免去處理麻煩的數(shù)據(jù)不一致等奇奇怪怪的問題菲嘴。
我們一般都會寫測試代碼饿自,但是我們一定要確保測試代碼在setup
時是正確的,而且如果測試在setup
時是錯誤的龄坪,那一定要拋出異常讓我們知道璃俗,因為沒有比使用一個錯誤的setup
跑出正確的測試結(jié)果更讓人蛋疼的事情了,這樣的代碼一旦上線悉默,那后果你懂的...
除了上面說的,在執(zhí)行的多個SQL調(diào)用時苟穆,使用事務(wù)將那些調(diào)用包起來處理抄课,可以避免你的操作導(dǎo)致數(shù)據(jù)處于不一致的狀態(tài),或者是半吊子的狀態(tài)雳旅。
譯者注:確實如此跟磨,曾經(jīng)有一次我在處理數(shù)據(jù)的時候,就是沒有注意這些導(dǎo)致造成了數(shù)據(jù)破壞攒盈,幸虧當(dāng)時的數(shù)據(jù)有備份抵拘,才沒有導(dǎo)致大的問題。
使用 ActiveRecord 的 validate 相關(guān)方法來動態(tài)校驗?zāi)愕臄?shù)據(jù)
使用 ActiveRecord 的 validate 相關(guān)的方法型豁,并且使用帶有!
的方法來做校驗方法僵蛛,將會是一個很好的方式去確保你在持久化數(shù)據(jù)時不會出錯尚蝌。舉個例子:
class Post < ActiveRecord::Model
validates :author, :blog, presence: true
validates :published_by, presence: true, if: :published?
validates :comment_count, numericality: { greater_or_equal_to: 0 }
# ...
end
使用數(shù)據(jù)庫約束來確保你的數(shù)據(jù)的一致性
你的數(shù)據(jù)庫是你最好的朋友,他能夠幫你保存你的數(shù)據(jù)充尉,并且確保你的數(shù)據(jù)不出現(xiàn)重復(fù)和“孤兒記錄”的問題飘言。
一般情況下,你應(yīng)該為你的數(shù)據(jù)庫中的大多數(shù)字段設(shè)置他們默認(rèn)不為空驼侠,也就是null: false
姿鸿。
你是否知道 Rails 中的 has_one
約束,在數(shù)據(jù)的創(chuàng)建時不會起到唯一性約束作用呢倒源?
class Account
has_one :account_settings
end
account = Account.create!
account.create_account_settings!
account.create_account_settings!
account.create_account_settings!
account.account_settings
# => one of the three account settings you've created... -_-
如果想讓你的數(shù)據(jù)不出現(xiàn)重復(fù)苛预,最好的方式是給你的數(shù)據(jù)添加唯一索引。
add_index :account_settings, :account_id, unique: true
這樣做之后笋熬,如果你嘗試去創(chuàng)建重復(fù)的記錄時热某,數(shù)據(jù)庫就會拋出異常,去阻止你創(chuàng)建重復(fù)數(shù)據(jù)突诬。
我們每一個人都不會想存儲一些“孤兒記錄”在數(shù)據(jù)庫中苫拍。但是如何去解決這些“孤兒記錄”呢?使用外鍵是可以很好的幫你解決這個問題旺隙,在這里我推薦大家使用schema_auto_foreign_keys這個 gem 去為你的相關(guān)的表自動添加外鍵約束绒极。
總結(jié)
多寫幾個字母就可以幫我們避免處理數(shù)據(jù)不一致的麻煩問題,也會大大減少我們代碼的 bug 率蔬捷,提高我們的工作效率垄提。記住,使用!
周拐,raise
铡俐,validate
和數(shù)據(jù)庫約束
去強化你的代碼,使你的代碼更加強壯妥粟。你的同事會感謝你审丘,說不定以后當(dāng)你在次翻看你的代碼的時,你會覺得當(dāng)時做的真好勾给,讓你在后來避免了很多不必要的麻煩滩报。