我正在尝试制定一个计算人员整体成绩的练习计划。测试由三个部分组成,每个部分具有不同的权重。第1部分值5级,第2部分3级,第3部分值2级。
因此,如果一个人得到A B C,他们将获得5A 3B和2C。
现在,为了接收和A / B / C整体需要一定数量的每个等级。例如,为了获得总体A,您需要至少有5A和7个等级必须为B或更高,并且所有等级必须为C或更高。
B,C,D等也都有自己的要求。
最好的编码方式是什么,因为我现在每个年级都使用一个计数器,然后在if / else if语句中查看一个人所得到的每个年级的数量:
if (aGradeCount >= 5)
{
//Add total grade
}
}
}
//To receive a B
if(bGradeCount >= 3 && aGradeCount <5 && cGradeCount >=2)
{
if(bGradeCount + cGradeCount +dGradeCount + aGradeCount>= 7)
{
if(dGradeCount <= 3)
{
//Add new total grade
}
}
}
现在我明白这是一种可怕的做法,但我怎么能更好地编码呢?使用switch语句?如果是这样我该怎么做?
答案 0 :(得分:9)
我怎样才能更好地编码?
编写规范。然后,对于规范中提到的每个概念,编写一个方法。这是规范的一部分;你已经写过:
要获得总体A,您需要至少有5个A和7个等级必须为B或更高,所有等级必须为C或更高。
分解
in order to receive an A overall
at least 5 A's AND
at least 7 of the grades must be B or higher AND
all the grades need to be C or better
好的,现在我们可以开始将其变成一种方法:
static bool QualifiesForA(int aCount, int bCount, int cCount, int dCount)
{
// In order to receive an A overall we require:
// TODO: at least 5 A's AND
// TODO: at least 7 of the grades must be B or higher AND
// TODO: all the grades need to be C or better
// If these conditions are not met then an A is not earned.
return false;
}
好的,我们已将规范转化为代码。错误的代码,但代码。我们继续吧。我们有一条规范。写一个方法:
static bool AtLeastFiveA(int aCount)
{
return aCount >= 5;
}
嘿,这是一个正确的方法。我们正在取得进展。现在使用它:
static bool QualifiesForA(int aCount, int bCount, int cCount, int dCount)
{
// In order to receive an A overall we require:
// at least 5 A's AND
// TODO: at least 7 of the grades must be B or higher AND
// TODO: all the grades need to be C or better
bool atLeast5A = AtLeastFiveA(aCount);
// If these conditions are not met then an A is not earned.
return false;
}
现在我们还有另一个问题。至少7个是B或更高。好的,写一个方法:
static bool AtLeastSevenB(int aCount, int bCount)
{
return aCount + bCount >= 7;
}
另一种正确的方法!使用它!
static bool QualifiesForA(int aCount, int bCount, int cCount, int dCount)
{
// In order to receive an A overall we require:
// at least 5 A's AND
// at least 7 of the grades must be B or higher AND
// TODO: all the grades need to be C or better
bool atLeast5A = AtLeastFiveA(aCount);
bool atLeast7B = AtLeastSevenB(aCount, bCount);
// If these conditions are not met then an A is not earned.
return false;
}
现在我们需要最后一点:
static bool NoD(int dCount)
{
return dCount == 0;
}
把它放在一起。
static bool QualifiesForA(int aCount, int bCount, int cCount, int dCount)
{
// In order to receive an A overall we require:
// at least 5 A's AND
// at least 7 of the grades must be B or higher AND
// all the grades need to be C or better
bool atLeast5A = AtLeastFiveA(aCount);
bool atLeast7B = AtLeastSevenB(aCount, bCount);
bool noD = NoD(dCount);
if (atLeast5A && atLeast7B && noD)
return true;
// If these conditions are not met then an A is not earned.
return false;
}
现在,问自己的问题是:
这段代码是否正确?让它正确处理。这段代码非常详细,但我现在告诉你,完全符合你提供的规范。
一旦代码正确,我们可以更清楚地说明吗?
是;我们可以说:
static bool QualifiesForA(int aCount, int bCount, int cCount, int dCount)
{
// In order to receive an A overall we require:
// at least 5 A's AND
// at least 7 of the grades must be B or higher AND
// all the grades need to be C or better
bool atLeast5A = AtLeastFiveA(aCount);
bool atLeast7B = AtLeastSevenB(aCount, bCount);
bool noD = NoD(dCount);
return atLeast5A && atLeast7B && noD;
}
现在也许你会说,你知道,其中一些方法是不必要的抽象,也许我可以用他们的身体代替它们:
static bool QualifiesForA(int aCount, int bCount, int cCount, int dCount)
{
// In order to receive an A overall we require:
// at least 5 A's AND
// at least 7 of the grades must be B or higher AND
// all the grades need to be C or better
bool atLeast5A = aCount >= 5;
bool atLeast7B = aCount + bCount >= 7;
bool noD = dCount == 0;
return atLeast5A && atLeast7B && noD;
}
重点是:我们从一个非常详细的,清晰正确程序开始,然后我们进行小而简单,清晰正确的转换,使其更简洁。如果您认为自己在简洁性和可读性方面有很好的平衡,请停止。
好的,现在你已经解决了“我们赚了A吗?”的问题。现在你做“我们赚了B吗?”等等。为每个部分编写规范,然后编写明确实现规范的代码。这听起来像是一个重量级的过程,但是当你学习如何编程时,这将带来巨大的回报。您的代码将更好地组织,它将更少的错误,它将更容易阅读和理解和修改。
这种技术的重点是关注每个部分的明显正确性。始终专注于明显的正确性。一个程序是正确的但你不能说它是正确的程序,可能是不正确的!始终专注于正确性首先。使错误的程序更优雅,更快,或更完整的功能意味着您拥有一个优雅,快速,功能丰富的错误场。
总结:
答案 1 :(得分:1)
我不知道这是不是很糟糕的做法。这有点不必要,因为块中没有别的东西,而是另一个if语句。你可以使用更多&amp;&amp;运算符和括号如果你只想使用一个if语句。
if ((bGradeCount >= 3 && aGradeCount <5 && cGradeCount >=2) &&
(bGradeCount + cGradeCount +dGradeCount + aGradeCount>= 7) &&
(dGradeCount <= 3))
{
char b = 'B';
person.TotalGrade = b.ToString();
}
答案 2 :(得分:1)
为了代码清晰,我会这样做:
//Main function
{
///code
if(MethodWhichDescribesLogic(aGradeCOunt,bGradeCount,cGradeCount,dGradeCount){
char b = 'B';
person.TotalGrade = b.ToString();
}
}
然后在其他地方:
bool MethodWhichDescribesLogic(type aGradeCount, type bGradeCount, type cGradeCount, type dGradeCount){
return
(PassingGrade(bGradeCount,aGradeCount,cGradeCount) &&
GoodGradesType(bGradeCount,cGradeCount,dGradeCount,aGradeCount) &&
dGradeCount <= 3);
}
bool PassingGradesCount(type bGradeCount,type aGradeCount,type cGradeCount)
{
return bGradeCount >= 3 && aGradeCount <5 && cGradeCount >=2;
}
bool GoodGradesCount(type cGradeCount,type bGradeCount,type aGradeCount,type dGradeCount)
{
return bGradeCount + cGradeCount +dGradeCount + aGradeCount>= 7;
}
答案 3 :(得分:0)
请记住,每个if-else开关都可以被条件表替换。 因此,如果整体成绩计数为10,那可能是
A B C Overall
5 7 10 A
4 7 10 B
然后你创建它的数组并找到你在数组中的位置。
例如(我承认我对你的例子感到困惑,所以我可能在这里弄错了。):
var grades = new[]{
new { A = 5. B = 7, C = 10, Overall = "A"},
new { A = 4, B = 7, C = 10, Overall = "B"},
...
}
var myGrade = grades.FirstOrDefault(g => myA >= g.A && myB >= g.B && enoughC)
通过适当的格式化,它看起来比大量的if更好。而且你总是在你面前有你的选择表。
答案 4 :(得分:0)
首先,在OverallGrade()
中使用布尔代数来查看不需要考虑哪些案例。例如,如果要检查A等级,您已经看到gradeDistribution.A >= 5
,则在测试等级'B'时不要测试gradeDistribution.A < 5
,因为很明显,如果您正在测试B的情况,您已将gradeDistribution.A < 5
测试为真。
接下来,将等级计算放在另一个方法中,并尽早返回该方法。
最后,为了获得整体成绩,您可以将方法编写为:
private static char OverallGrade(int partA, int partB, int partC)
{
//Now in this method, check one by one which
//overall grade the provided values fall in
//Call another method to get count of individual As, Bs, Cs etc
var gradeDistribution = GetIndividualCount(partA, partB, partC);
//Now, first check for A and return immediately if true
if (gradeDistribution.A >= 5) return 'A';
//Now, check for B and again return if the values satisfy for B
if (gradeDistribution.B >=3
&& gradeDistribution.C <= 2
&& gradeDistribution.D <= 3
&& ...)
return 'B';
//Keep adding for each case and return as soon as you find the grade.
}
现在,可以创建我们上面使用过的变量GradeDistribution
,它可以保存每个等级的数量:
public class GradeDistribution
{
public int A; //Count for Grade A
public int B; //Count for Grade B
public int C; //Count for Grade C
public int D; //Count for Grade D
}
上面的代码是为现实世界中不存在的实体引入类的示例。
接下来,GetIndividualCount()
可写为:
private static GradeDistribution GetIndividualCount(int partA, int partB, int partC)
{
var gradeDistribution = new GradeDistribution();
/*
Calculate and assign values to gradeDistribution.A, gradeDistribution.B...
*/
return gradeDistribution;
}