迪米特法則(Law of Demeter)禁舷,又稱(chēng)最少知識(shí)原則,簡(jiǎn)單說(shuō)來(lái)就是 一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的了解毅往。迪米特法則用于降低類(lèi)與類(lèi)之間的耦合牵咙,那么當(dāng)其中某一個(gè)模塊發(fā)生修改時(shí),就會(huì)盡量少地影響其他模塊煞抬,擴(kuò)展會(huì)相對(duì)容易霜大。
一句話(huà)概括下來(lái)构哺,就是“只和朋友打交道革答,朋友的朋友不是朋友”,對(duì)于一個(gè)對(duì)象曙强,其朋友包括以下幾類(lèi):
(1) 當(dāng)前對(duì)象本身(self)残拐;
(2) 以參數(shù)形式傳入到當(dāng)前對(duì)象方法中的對(duì)象;
(3) 當(dāng)前對(duì)象的成員對(duì)象(依rails來(lái)說(shuō)碟嘴,assocation的屬于成員對(duì)象)溪食;
(4) 如果當(dāng)前對(duì)象的成員對(duì)象是一個(gè)集合,那么集合中的元素也都是朋友娜扇;
(5) 當(dāng)前對(duì)象所創(chuàng)建的對(duì)象错沃。
舉一個(gè)例子
發(fā)布批時(shí)會(huì)更新產(chǎn)品信息價(jià)栅组,在價(jià)格網(wǎng)quotation_batch.rb定義方法大致如下:
class QuotationBatch
def publish_prices_no_transaction(options={})
sql, arr = options[:publish_type] == :full ?
['', self.id] : [' and products.id in (?)',[self.id, options[:ids]]]
products_ids = Product.all :conditions => "some",:select => "id"
return 'true' if products_ids.blank?
products_ids.each_slice(1000) do |id_arr|
products = Product.all(:conditions => ['id in (?)', id_arr],
:include => [:all_product_prices])
products.each do |product|
raise ActiveRecord::Rollback unless product.publish_price(options[:user], self)
end
end
'true'
end
end
簡(jiǎn)要說(shuō)明一下: quotation_batch 是保存批的類(lèi);product_price是保存報(bào)價(jià)的類(lèi),字段batch_id保存批號(hào),字段product_id保存產(chǎn)品號(hào),last字段用于聲明是最新報(bào)價(jià)還是歷史報(bào)價(jià)(1為最新報(bào)價(jià),3是歷史報(bào)價(jià));product是產(chǎn)品類(lèi)枢析。代碼大致流程如下:
publish_prices_no_transaction 遍歷product,調(diào)用product的publish_price發(fā)布報(bào)價(jià)玉掸,而product再根據(jù)條件修改product_price狀態(tài)
代碼不太符合迪米特法則,product和quotation_batch之間不應(yīng)該有關(guān)聯(lián)醒叁,初看代碼很是一頭霧水司浪。
首先,真正發(fā)布報(bào)價(jià)的方法不應(yīng)該定義在product中把沼,而應(yīng)該定義在product_price中啊易,因?yàn)橹挥衟roduct_price和product和batch是朋友關(guān)系,那么饮睬,在publish_prices_no_transaction中應(yīng)該遍歷product_price租谈,而不是product
偽代碼如下
class ProductPrice
belongs_to :product
belongs_to :batch
def publish_price
#更新上一版報(bào)價(jià)狀態(tài)
self.prev_price.update_status
#使本次報(bào)價(jià)為最新報(bào)價(jià)
self.make_newst_price
...
end
end
class Product
has_many :product_prices
end
class QuotationBatch
has_many :product_prices
def publish_batch
self.product_prices.each do |product_price|
product_price.publish_price
end
#更新企業(yè)狀態(tài)等其他代碼
end
end
這樣改一下,邏輯就清晰了很多捆愁,看來(lái)在工作中還是要注意下設(shè)計(jì)原則滴~