2015-05-10 38 views
1

我在填充數據的位置有困難。何處填充數據?內部或外部方法?

以下2個樣的方法來計算報價的總價:

// example in javascript 
function computePrice(quotation) { 
    var totalPrice = 0.00; 
    var items = quotation.getItems(); 

    for (var i = 0; i < items.length; i++) { 
     totalPrice += items[i].getPrice(); 
    } 

    return totalPrice; 
} 

QuotationDao.populateItems(quotation); 
computePrice(quotation); 

寫作的另一種方法是:

function computePrice(quotation) { 
    var totalPrice = 0.00; 

    // Populate items in the quotation from database 
    QuotationDao.populateItems(quotation); 

    var items = quotation.getItems(); 

    for (var i = 0; i < items.length; i++) { 
     totalPrice += items[i].getPrice(); 
    } 

    return totalPrice; 
} 

computePrice(quotation); 

我問我的同事和接受不同的輸入。

  1. 方法#1是正確的,因爲代碼不應該檢索函數中的數據,除非該函數純粹是爲了檢索目的而創建的。

  2. 方法#1是正確的,因爲它允許單元測試。

  3. 方法#2是正確的,因爲在調用該方法之前不需要外部依賴項,該方法具有很高的內聚性。所有的方法都是不完整的,QuotationDao.populateItems(引用)應該像QuotationDao.getComputePriceData(引用)那樣在一個單獨的方法中,並將結果傳遞到computePrice(computePriceData)中;

您對我應該採取哪條路線有任何建議嗎?

回答

1

如果一個應用Law of Demeter,這也被稱爲「最不識的原則」,並Single Responsibility Principle,後來一想寫出這樣的代碼:

Quotation q = dao.fetchQuotation(someCondition); 
totalPrice = q.getTotalPrice(); //Computation inside it 

如果計算是有點複雜和不不涉及只是添加引號內的各種項目的值,然後,可以使用單獨的方法:

Quotation q = dao.fetchQuotation(someCondition); 
totalPrice = PriceHelper.getTotalPrice(q); //Computation inside it 

這兩種方法都同樣可測試(適當嘲笑/將需要存根)

如果你仍然感到困惑,那麼,問自己一個問題 - 「它的做法讓我的代碼,很容易理解」 - 我發現這本書「清潔守則」每當我遇到真正有用的這種窘境

+0

謝謝你的魔杖。但呃..你會在哪裏填充報價單項目?裏面getTotalPrice或fetchQuotation或其他行之間,如: 報價q = DAO.fetchQutation(someCondition); DAO.populateQuotationItems(q); totalPrice = q.getTotalPrice(); – bryan

+0

populateQuotation做什麼? –

+0

嗯,1個報價通常有N個項目,如產品,數量,定價。 populateQuotationItems將填充特定報價的項目。只有在人口可以計算價格工作後。這是因爲沒有人口,報價將有0個項目,因爲他們還沒有從數據庫中檢索。 – bryan

1

你是對您的數據填充方法使用不良方法結構QuotationDao.populateItems(quotation);。爲什麼它不好?

  1. 它突破immutability。對於填充數據或生成數據的簡單方法,接受輸入和返回結果將更有利,因爲它可以被重新調用並且結果將保持一致。

  2. 該方法沒有自我記錄。您不知道數據類型報價是什麼,事先需要執行什麼操作,什麼是填充,什麼是總體參數。

  3. 它不支持靜態類型語言,如java/C#。他們需要將特定的對象類型作爲參數傳遞。

我的建議是有2個不同的獵犬或你說的DAO:

quotationDao.getQuotation = function(){ 
    var quotation = {}; 
    // populate quotation 
    return quotation; 
} 

itemDao.getItems = function(quotation){ 
    var items = {}; 
    // get items 
    return items; 
} 

接下來,你可以按照魔杖製作的有關SRP和Law of Demeter答案。然而他的回答仍然打破了Law of Demeter。它規定:

  • 每個單位應該只有有限的其他單位的知識:只有單位「緊密」與當前單位相關。
  • 每個單位只能跟朋友交談;不要與陌生人交談。
  • 只與您的直接朋友交談。

在您當前的實施中,價格計算的最親密的朋友將只是項目。他們不應該知道報價。因此,而不是使用

Quotation q = dao.fetchQuotation(someCondition); 
totalPrice = q.getTotalPrice(); //Computation inside it 

//or 

Quotation q = dao.fetchQuotation(someCondition); 
totalPrice = PriceHelper.getTotalPrice(q); //Computation inside it 

而是使用:

Quotation q = dao.fetchQuotation(someCondition); 
Items i = itemDao.fetchItem(quotation); 
totalPrice = i.getTotalPrice(); //Computation inside it 

//or 

Quotation q = dao.fetchQuotation(someCondition); 
Items i = itemDao.fetchItem(quotation); 
totalPrice = PriceHelper.getTotalPrice(i); //Computation inside it 
+0

Erm ..我使用的語言是jscript,所以它是一種弱類型。我確實有你建議的兩種方法,但我實現了populateItems方法作爲包裝來將項目與引用相關聯,以便我可以執行quotation.getItems()調用。根據您提供的作爲魔杖製造商擴展的建議,您看起來似乎也暗示應該在getTotalPrice方法之外完成項目的填充。 – bryan

+0

確實。 'getTotalPrice'只與'items'關聯,因此將'quotation'包含/傳遞給'getTotalPrice'是沒有意義的。除非報價參與價格計算,否則只有通過報價。 – Fendy

+0

假設報價參與價格計算,那麼populateItems應該在getTotalPrice之外還是在裏面完成? – bryan