2009-10-28 86 views
0

我開始對從提取數據,然後寫回遺留系統數據庫的項目。我已經開始使用領域模型,並試圖在過去的系統中改進這種設計,所以我希望對此有所反饋。OOP設計:字符串,枚舉,接口還是其他?

這個例子是任意的,所以不需要具體的建議有,但讓我們說有一個名爲「WorkflowStep」我正在寫的一類數據庫中的表。表中有一個名爲「CurrentStatus」的列,它定義了工作流程所處的狀態。它存儲爲一個varchar。對於此列,整個表格中有五個不同的字符串,並且不太可能會更改像「打開」,「關閉」,「保持」等值。

類需要跟蹤這個值,但以何種方式?我可以去簡單的方法,只是將其存儲在一個字符串,但是這並不是非常明確,我會想象未來開發商獵取應用邏輯對字符串的不同的值。我可以用枚舉來使事情更加明確,但這可能會導致整個地方出現開關/情況。我讀過,工程師將一個接口,說辦法「IStatus」,然後做出表示的狀態每個可能的狀態具體的類,但在同樣的情況,因爲這一個一些列可以有一百個不同的值,所以100每個州的課程看起來都像是矯枉過正。

我的主要問題:是一種方法事實上的比別人更好,如果沒有,我應該怎麼考慮,以選擇的方法?

注意,該項目仍處於起步階段,我不知道究竟是如何之類的這種「狀態」屬性將被使用。這可能是沒有用的,或者它可能是至關重要的:我還不確定。

回答

2

我不認爲有一個明確的答案,這在任何地方,但它是一個常見的問題,下面的方法一直使我受益匪淺:

  1. 如果你的業務邏輯或任意代碼永遠不會對值做任何事情(比較,根據枚舉的值進行切換等),將其保留爲字符串。
  2. 如果您將對其進行比較,請使用枚舉。如果你有很多這樣的表格,或者這些值可以改變,這是非常適合代碼生成的。
  3. 如果這些值具有與它們相關的其他元數據,請創建包含此元數據的類以及創建相關類的枚舉(在工廠方法中)。再次,代碼生成在這裏非常適合。

對於像CurrentStatus這樣的東西,聽起來像選項2或3是天生的選擇。

  • 要用於該有空格和非字母數字字符(任何Enum.ToString())不能處理狀態的「友好」名稱:如果有下列情形之一的申請方案3將是可取的。
  • 有一些額外的邏輯或屬性與某個狀態「相伴」。例如,如果您有某些邏輯可以在「OnHold」或「Closed」項目上執行特定操作,但不在「Open」項目上執行特定操作,則麥克風擁有該類上的「CanDoAction」屬性是有意義的。
  • 您從中提取的數據庫具有狀態參考表,其中包含與您可能想要在代碼中使用的狀態相關的信息。
+0

正是我需要的,謝謝! – Chris 2009-10-28 15:02:14

2

我個人比較喜歡這種switch語句的

var x = new Dictionary<Status, Action> 
    {Status.Fail,()=>Console.Writeline("Fail")} 
    {Status.Ok,()=>Console.Writeline("Ok")}; 

x[Status.Fail](); 
x[Status.Ok](); 

而且 - 你可能會喜歡吉米this article(如果你將枚舉老式的解決方案棒)。

+0

Ryan在Jimmy的文章中的評論建議Jimmy發現了Strategy Pattern(http://en.wikipedia.org/wiki/Strategy_pattern)。 – 2009-10-28 14:31:14

+0

這個星球上沒有什麼新東西了...... ^^ – 2009-10-28 14:33:53

1

我讀過方法,工程師將一個接口,說「IStatus」,然後使代表的地位每個可能狀態的具體類,

這將是State Pattern

,但在同樣的情況對每個國家一些列,因爲這人能有一百個不同的值,所以100班,似乎有點小題大做。

這似乎是一個單獨的問題。沒有更多細節,沒有什麼可說的。

1

我會建議您調查在領域驅動設計定義的「價值型」的概念。這個WorkflowStep thingy聽起來像是一個優秀的候選人。你不提你的編碼用什麼語言或環境,但在.NET中,如果我結束了使用這個概念,我將創建一個代表這個對象的結構體,並編碼,使得在它的公用接口,通過使用客戶端代碼貫穿整個系統的其他部分,它表現爲,並將用作枚舉。

MyTask.WorkFlowStatus = WorkFlowStep.OnHold; 
// creates and assigns new instance of struct 

在C#

public struct WorkflowStep 
    { 
    public static readonly WorkflowStep Null = new WorkflowStep(); 
    public static readonly WorkflowStep Open = new WorkflowStep(1); 
    public static readonly WorkflowStep Closed = new WorkflowStep(2); 
    public static readonly WorkflowStep OnHold = new WorkflowStep(3); 
    private int val; 
    private bool def; 
    public bool HasValue { get { return def; } } 
    public bool IsNull { get { return !def ; } } 
    private WorkflowStep () { } // disable public instantiation 
    private WorkflowStep (int value) 
    { 
     val = value; 
     def = true ; 
    } 
    } 

您可以鍵入需要跟蹤這是WorkflowStep模型中的其他clases的propertys。這個結構的每個實例的內存中佔用空間非常小,保存該值的int以及保持其可空狀態的布爾值。你可以添加額外的方法和過載到結構來啓用打印格式輸出,ToString過載,無論你想要什麼...

1

這是一個非常普遍的問題,這取決於很多理解問題。通常我認爲這是簡單性,可讀性和可擴展性之間的交集。常量

  1. 枚舉/列表。這是最簡單的途徑,並且如果您在代碼中工作的次數遠遠超過原始數據,那麼它具有良好的可讀性。可擴展性並不好,因爲您需要重構才能保持簡單。
  2. Strings。字符串的優點是您可以一目瞭然地輕鬆理解數據庫數據。但是,他們往往會在程序代碼中添加粗體,而且它們的擴展性也不是很好。
  3. 參考表。這是迄今爲止三者中最具擴展性的。可讀性略有下降,因爲現在只要您想知道發生了什麼,就必須查找參考表中的值。爲此編碼是三者中最複雜的。

最簡單= Enum。大部分可讀=字符串。大部分可擴展=參考表。

哪一個最適合您的問題?

+0

即使使用枚舉,你也可以在數據庫中存儲字符串,所以它與字符串具有相同的優點,沒有缺點。 – 2009-10-28 14:33:19

+0

@Vincent當然:D你也可以使用字符串或整數作爲參考表。這些是這些組合,但根據我的經驗,這些是基本選項。 – Kai 2009-10-28 14:34:49

1

如果您確信該狀態的選項數量不會增加,那麼枚舉就可以工作。我認爲你可以通過一些謹慎的設計避免開關/箱子問題......也許使用戰略模式。

另一方面,如果選項的數量可能增加,那麼創建一個WorkFlowStatus類將是要走的路。這將允許您在不修改代碼的情況下添加更多狀態。我不認爲你必須爲每個人的地位創建一個班級。

1

通常情況下,您最終將引用此類型的項目作爲枚舉。如果你想避免的switch/case地獄,你可以用它映射到每個枚舉的動作 - 在這裏是一個例子:

private Dictionary<WorkflowStep, Action> _actions = 
    new Dictionary<WorkflowStep, Action>(); 

然後用

_actions.Add(WorkflowStep.Open, OpenCommand); 
_actions.Add(WorkflowStep.Closed, ClosedCommand); 

分配了,你就會有簡單的方法,這樣的:

private void OpenCommand() 
{ 
    // Do something 
} 

private void ClosedCommand() 
{ 
    // Do something. 
} 

最後,調用它,你會怎麼做:

if (_actions[step] != null) 
{ 
    _actions[step](); 
} 

請注意,您可以使用字符串做到這一點 - 不使用枚舉,但此方法可以幫助您避免代碼中的魔法字符串。