在升级一些旧代码的同时,我发现这两个 OO 原则似乎相互冲突。
考虑以下伪代码(它是我遇到的简化版本):
int numberOfNewRecords;
int numberOfOldRecords;
int numberOfUndefinedRecords;
void ColourAndCount()
{
foreach(Row row in dataGridView1.Rows)
{
switch(row.Cells["Status"])
{
case: "Old"
row.BackColor = Color.Red;
numberOfOldRecords++;
break;
case: "New"
row.BackColor = Color.Blue;
numberOfNewRecords++;
break;
default:
row.BackColor = Color.White;
numberOfUndefinedRecords++;
break;
}
}
}
这段代码做了两件事:它按状态统计记录的数量,并且还为每一行着色,再次按它们的状态。这很困惑,但是由于这两个操作(到目前为止)总是同时被调用,所以它没有引起任何问题,并且使得像附加状态这样的维护需求很容易添加。
尽管如此,单一职责原则告诉我应该将其拆分为两个单独的方法:
(编辑)小注:我刚刚意识到我可能在这里误用了术语“单一职责原则”,据我所知,它指的是类。 “每个方法一个操作”设计模式的术语是什么?
int numberOfNewRecords;
int numberOfOldRecords;
int numberOfUndefinedRecords;
void Count()
{
foreach(Row row in dataGridView1.Rows)
{
switch(row.Cells["Status"])
{
case: "Old"
numberOfOldRecords++;
break;
case: "New"
numberOfNewRecords++;
break;
default:
numberOfUndefinedRecords++;
break;
}
}
}
void Colour()
{
foreach(Row row in dataGridView1.Rows)
{
switch(row.Cells["Status"])
{
case: "Old"
row.BackColor = Color.Red;
break;
case: "New"
row.BackColor = Color.Blue;
break;
default:
row.BackColor = Color.White;
break;
}
}
}
但这违反了不要重复自己:循环和 switch 语句在两种方法中都是重复的,并且由于此代码最可能的升级路径是添加其他状态,因此它使 future 的升级更加困难而不是更少。
我很难找到最优雅的重构方式,所以我觉得最好问问社区,以防我遗漏了一些明显的东西。你会如何解决这种情况?
(编辑)
我想出了一个可能的解决方案,但在我看来,它就像一个过度设计一个简单问题的例子(它并没有真正解决最初的单一职责问题)。
struct Status
{
public string Name,
public int Count,
public Color Colour,
}
Dictionary<string, Status> StatiiDictionary = new Dictionary<string, int>();
void Initialise()
{
StatiiDictionary.Add(new Status("New", 0, Color.Red));
StatiiDictionary.Add(new Status("Old", 0, Color.Blue));
StatiiDictionary.Add(new Status("Undefined", 0, Color.White));
}
void ColourAndCountAllRows()
{
foreach(Row row in dataGridView1.Rows)
{
CountRow(row, StatiiDictionary);
ColourRow(row, StatiiDictionary);
}
}
void CountRow(Row row, Dictionary<string, Status> StatiiDictionary)
{
StatiiDictionary[row.Cells["Status"]].Count++;
}
void ColourRow(Row row, Dictionary<string, Status> StatiiDictionary)
{
row.BackColour = StatiiDictionary[row.Cells["Status"]].Colour;
}
最佳答案
出于实用的原因,需要不时违反许多编程规则。就您而言,我同意 DRY 和 SRP 似乎在竞争,因此我建议使用两个标准来决定获胜者:
在这种情况下,两次枚举网格行的效率低下对我来说似乎是压倒一切的因素,在这种特殊情况下 DRY 会胜过 。在其他一些情况下,它可能是相反的。
添加注释来解释您做出的决定以及原因是值得的,以便以后查看代码的任何人都清楚。这正是注释应该用于的事情,即 为什么 代码正在做它正在做的事情,而不仅仅是它正在做的事情。
关于c# - 哪个优先 : Don't Repeat Yourself or the Single Responsibility Principle?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23097222/