2013-01-01 84 views
1

在OOP和所有編程中,我知道一個明確的規則是一個方法只應執行一個特定的任務,如果需要執行另一個任務,則應該創建另一個方法。我的問題是,在我的情況下這似乎毫無意義,因爲它只是使用更多的代碼,而不是一個大的方法。OOP慣例 - 單一函數方法

這裏有2種方式,其中我的代碼可以構造(其中一個遵循標準慣例,而另一個沒有,但可以節省代碼)

情景1(2種方法)

提高統計方法

public void increaseStat(short value, string stat) 
{ 
     switch (stat) 
     { 
      case "stamina": 
       if (staminaCheck.Checked == true) 
       { 
        stamina += value; 
        staminaText.Text = Convert.ToString(stamina); 
       } 
       staminaCheck.Checked = false; 
       break; 

//There are 5 other similar cases for different stats but to save time I removed them 
     } 

和減小stat法

public void decreaseStat(short value, string stat) 
{ 
     switch (stat) 
     { 
      case "stamina": 
       if (staminaCheck.Checked == true) 
       { 
        stamina -= value; 
        staminaText.Text = Convert.ToString(stamina); 
       } 
       staminaCheck.Checked = false; 
       break; 

//There are 5 other similar cases for different stats but to save time I removed them 
     } 

正如你所看到的代碼除了是1而不是 - 的操作完全一樣。因此,而不是複製所有的代碼轉化爲規範起見,另一種方法,我決定做這個

方案2(1種大的方法,從而能夠解決增加和減少)

public void alterStat(short value, string stat, bool operator) 
{ 
     switch (stat) 
     { 
      case "stamina": 
       if (staminaCheck.Checked == true) 
       { 
        if (Operator == true) stamina -= value; 
        else stamina += value 

        staminaText.Text = Convert.ToString(stamina); 
       } 
       staminaCheck.Checked = false; 
       break; 

//There are 5 other similar cases but to save time I removed them 
     } 

這樣我加入了2個額外的通過添加一個簡單的if語句將行分解成每種情況,但是保存了正被複制的代碼的負載。

我只是想讓你知道這是否會被視爲良好的編程習慣。

謝謝你的時間。

+1

'var delta = Operator == true? -1:1;耐力+ =增量*值;' – zerkms

+1

爲什麼停在那裏?充足的理由使用'void adjustStamina(int by)' –

+1

你不能簡單地提供一個負值來減少項目嗎?像DateTime.AddDays(-5)。 –

回答

2

從我的觀點來看,重複代碼少得多的收益顯然遠大於關注點分離的規則,特別是在代碼維護方面。

類似的情況是使用Enum作爲對象的狀態標誌。適當的面向對象的方式是將每個狀態建模爲狀態層次結構中的一個獨立類。後者的缺點是你必須編寫代碼來找出一個對象的狀態,特別是如果你使用Visitor模式(當你使用OOP時)。

你提到的規則對於類的接口特別有用。如果它更清晰(對於您的班級的用戶)具有IncreaseStat()DecreaseStat()的操作,而不是具有通用的ChangeStat(),則沒有人阻止您實施private ChangeStat()方法,該方法由相應的public方法調用以增加和減少統計量。通過這種方式,您可以同時獲得以下優點:在內部執行特定任務的特定操作,而不會出現重複代碼。

2

可以這樣做:

public void Change(string stat, bool decrease) 
{ 
     switch (stat) 
     { 
      case "stamina": 
       if (staminaCheck.Checked == true) 
       { 
        if(decrease) 
         stamina -= value; 
        else 
         stamina += value; 
        staminaText.Text = Convert.ToString(stamina); 
       } 
       staminaCheck.Checked = false; 
       break; 

//There are 5 other similar cases for different stats but to save time I removed them 
     } 
} 

所以創建充電至下降增加傳遞的值的方法。它所做的是基於bool參數。

這將是您在第二種情況下所做的可能「形狀」之一,但採用稍微不同的解決方案。

+1

感謝您提供改進的代碼。 也許我沒有說清楚,但我真的想問這是否可以接受,將兩種執行不同功能的方法合併爲1.這是因爲我被教導說它不好,但在我的情況下節省代碼和時間。 – Ralt

+1

@Ralt:如果您設置方法的名稱並進行適當的評論,這是一個完全可以接受的方法。您再次遵循*單個責任原則*,在這種情況下,對於此方法說明,該方法或增量或減量值。 – Tigran

0

由於C#有lambda表達式,所以這些解決方案都不是理想的。相反,我會嘗試通過作爲一種功能的操作:

public void modStat(string stat, Func<short, short> op) 
{ 
    switch (stat) 
    { 
     case "stamina": 
      if (staminaCheck.Checked == true) 
      { 
       stamina = op(stamina) 

       staminaText.Text = Convert.ToString(stamina); 
      } 
      staminaCheck.Checked = false; 
      break; 

     // more cases 
    } 

這也比以前更一般。理想情況下,我們也可以通過同樣的方式對屬性進行抽象,但這更難(它需要一些被稱爲的鏡頭,而C#對鏡頭沒有太多支持)。

+1

謝謝,我會去研究lambda – Ralt

1

最佳的解決方案是如果你能從兩個世界保持好的東西,因爲你需要他們兩個。問題在於,你將公開的公共接口與內部實現(OOP中的基本概念之一)分離開來。你怎麼做呢?

您仍然可以擁有兩種方法,增加和減少方式,然後將通用代碼重構爲私有方法,每個增加和減少方法都使用適當的標誌調用。

public void increaseStat(short value, string stat){ 
    alterStat(value, stat, true); 
} 

public void decreaseStat(short value, string stat){ 
    alterStat(value, stat, false); 
} 


private void alterStat(short value, string stat, bool operator){ 
    // do the actual work here. 
} 

這是設計課程中一個非常重要的模式。同樣,這個想法是將你公開的類接口分離開來,以及你如何真正實現它。每個人都應該爲其目的服務,兩者都可以一起工作。