最近這段時間一直在讀大家寫的代碼,發現有時候不好的代碼有些是因為不了解程序運行的本質,有些代碼是因為沒有用心
這次我就分享一些代碼中的簡單的錯誤
-
數據庫查詢多次,改變寫法可以減少數據庫查詢次數,降低數據庫壓力
if Employee.find_by_id(12345) and Employee.find_by_id(12345).username=='bad.code'
如上這段代碼,很明顯會查詢兩次數據庫,但是完全是沒有必要的
發生錯誤的原因我猜有兩種可能
1.不了解rails查詢的本質,不知道上面會查詢兩次(這種可能比較小)
2.沒有用心去想程序應該怎么寫更好,實現功能就好users = User.all(:conditions=>['status=:status',{:status=>1}]) users.each do |user| company = Company.find_by_id(user.company_id) .....其他操作 end
如上這段代碼,company查詢了多次,其實我們可以在each外面先一次查詢出來,這樣就不需要多次查詢數據庫了,形成如下代碼
users = User.all(:conditions=>['status=:status',{:status=>1}])
companies = Company.all(:conditions=>['id in (?)',users.map(&:company_id)])
users.each do |user|
company = companies.find{|com|com.id==user.company_id}
.....其他操作
end
上面的代碼和數據庫的交互就比較友好了,不過仔細觀察如上代碼,其實User和Company是存在關聯關系(relation)的,一般我們已經定義好了他們之間的關系,所以我們的代碼其實應該是這樣的
users = User.all(:conditions=>['status=:status',{:status=>1}],:include=>[:company])
users.each do |user|
company = user.company
.....其他操作
end
- 代碼嵌套層數比較多
if user.present?
if company.present?
return "#{company.name}-#{user.name}"
else
return '公司不存在'
end
else
return '用戶不存在'
end
如上代碼,符合人的正常思維邏輯并沒有問題,但是是不是有點長呢? 其實我們可以反過來先判斷不存在的情況,代碼可以簡化為
return '用戶不存在' if user.blank?
return '公司不存在' if company.blank?
"#{company.name}-#{user.name}"
代碼是不是簡潔多了呢?我個人把這種情況叫做“盡早返回原則”,就是如果滿足某一個條件就可以忽略其他條件的話,那么我們可以先判斷這個條件以簡化代碼。