Coding style 如果在函数中使用语句,最好的方法是什么
如果我有一个包含大量条件的函数,那么组织它的最佳方法是什么 我担心的是其他人进入代码并理解正在发生的事情。尽管示例很简单,但请想象条件是非常复杂的 例如:Coding style 如果在函数中使用语句,最好的方法是什么,coding-style,conditional-statements,Coding Style,Conditional Statements,如果我有一个包含大量条件的函数,那么组织它的最佳方法是什么 我担心的是其他人进入代码并理解正在发生的事情。尽管示例很简单,但请想象条件是非常复杂的 例如: public void function(string value, string value2) { if (value == null) return; if (value2 == value) DoSomething(); } 或 或 我更喜欢第一种选择——更清晰,更容易阅读和理解 我
public void function(string value, string value2)
{
if (value == null)
return;
if (value2 == value)
DoSomething();
}
或
或
我更喜欢第一种选择——更清晰,更容易阅读和理解
我知道这不是失败,但这个概念仍然适用。我真的不喜欢嵌套的
if
语句。您可以查看防御性编程,以确保实现方法功能的契约
public void function(string value, string value2)
{
if (string.IsNullOrEmpty(value1)) throw new ArgumentNullException("value1", "value 1 was not set");
if (string.IsNullOrEmpty(value2)) throw new ArgumentNullException("value2", "value 2 was not set");
DoSomething();
}
我喜欢第三种选择,但这取决于语言。您假设在第三个语句中,语句的第一部分将失败,而不会执行第二部分。这取决于语言。我知道大多数基于C的语言都可以做到这一点,但由于您没有指定一种,这是一个潜在的问题。可能有一个我不知道的没有短路概念的函数。如果你有一个有很多条件的函数,我会使用一个
switch
语句,而不是ifs。如果可能的话,我还可以将细节分解为几个函数(甚至类)
相关堆栈溢出文章:
- 我
- 我个人认为第一个例子最容易理解 跟着
- 最小化嵌套级别和/或 条件句的数量通常为 提高可读性
- 有些人会反对多重选择 方法的退出点(如 例1),但我认为 当该方法 变得很长。这不是真的 如果你只是 检查输入并快速失败
// leave complex conditional code out, so that we can focus on the larger problem in the function
public void function(string value, string value2)
{
if (MyDescriptiveTestName)
{
DoSomething();
}
}
// encapsulate complex conditional code so that we can focus solely on it.
private bool MyDescriptiveTestName(string value, string value2)
{
if (value != null && value2 == value)
{
return true;
}
return false;
}
组织条件并将其转化为一种方法 例如:
if( a& & n || c && ( ! d || e ) && f > 1 && ! e < xyz ) {
// good! planets are aligned.
buyLotteryTicket();
} else if( ..... oh my ... ) {
}
这样,使用什么样式(1、2或3)并不重要,因为if语句将清楚地描述测试的条件。不需要额外的构造
关键是要使代码更清晰,并且能够自我记录。如果您使用的是OO编程语言,那么您可以使用对象来存储状态(变量),并避免创建包含5-10个参数的方法
这些都是类似的问题:
第二个链接显示了一种更完整、更复杂的方法,可以将可怕的“每个人维护者”噩梦转换为自文档代码
它显示了如何转换此项:
public String myFunc(SomeClass input)
{
Object output = null;
if(input != null)
{
SomeClass2 obj2 = input.getSomeClass2();
if(obj2 != null)
{
SomeClass3 obj3 = obj2.getSomeClass3();
if(obj3 != null && !BAD_OBJECT.equals(obj3.getSomeProperty()))
{
SomeClass4 = obj3.getSomeClass4();
if(obj4 != null)
{
int myVal = obj4.getSomeValue();
if(BAD_VALUE != myVal)
{
String message = this.getMessage(myVal);
if(MIN_VALUE <= message.length() &&
message.length() <= MAX_VALUE)
{
//now actually do stuff!
message = result_of_stuff_actually_done;
}
}
}
}
}
}
return output;
}
我可以推荐Robert C.Martin的书,它为编写可读和可维护的代码提供了一套很好的启发式方法
现在,另一个选项是将条件提取到另一个私有函数中,并命名它,以便它描述您的意图。它与提供的代码不太兼容,因为它是泛型的,但它看起来像:
public void function(string value, string value2)
{
if (valuesAreValidAndEqual(value, value2))
{
DoSomething();
}
}
private void valuesAreValidAndEqual(string value, string value2)
{
return value != null && value2 == value;
}
显然,如果变量名和函数名与您的域相关,则这一点更为有用。一个函数中有这么多语句,这表明该函数应该划分为更小的语句
没有最好的方法来放置if语句,我认为答案是主观的。清晰性通常很难判断。当你在写一段代码时,对你来说很清楚的事情可能对其他人来说是完全迟钝的——或者在足够长的时间之后对你自己来说也是如此 以下是我在构建包含许多条件检查的函数时的个人经验法则:
这三个示例实际上都失败得很快,它们执行相同的null测试,如果value==null,则立即返回如果您必须释放任何资源呢?然后,您需要在每个return语句之前复制此清理代码。我想说第二个和第三个选项要好得多。@SpaceghostAli:是的,你是对的,但这是一个很小的例子,而且大多数情况下并不简单@msvcyc:如果你需要释放资源,那么你真的应该使用try/finally块或using语句(如果适用)。这一点很好。很多嵌套条件可能是一个方法试图做得太多(内聚性低)的症状。在处理失败时,此选项还为您提供了更大的灵活性,这可以通过断言更好地实现。值得注意的是,上面代码的行为与原始问题中的行为不同。扔掉if语句。。。“return value!=null&&value2==value”这是一个很好的调用,当时我甚至没有考虑过它,但我相信我会在重构中捕捉到它
if( arePlanetsAligned() ) {
buyLotteryTicket();
} else if( otherMethodHere() ) {
somethingElse();
}
public String myFunc(SomeClass input)
{
Object output = null;
if(input != null)
{
SomeClass2 obj2 = input.getSomeClass2();
if(obj2 != null)
{
SomeClass3 obj3 = obj2.getSomeClass3();
if(obj3 != null && !BAD_OBJECT.equals(obj3.getSomeProperty()))
{
SomeClass4 = obj3.getSomeClass4();
if(obj4 != null)
{
int myVal = obj4.getSomeValue();
if(BAD_VALUE != myVal)
{
String message = this.getMessage(myVal);
if(MIN_VALUE <= message.length() &&
message.length() <= MAX_VALUE)
{
//now actually do stuff!
message = result_of_stuff_actually_done;
}
}
}
}
}
}
return output;
}
if ( isValidInput() &&
isRuleTwoReady() &&
isRuleTreeDifferentOf( BAD_OBJECT ) &&
isRuleFourDifferentOf( BAD_VALUE ) &&
isMessageLengthInRenge( MIN_VALUE , MAX_VALUE ) ) {
message = resultOfStuffActuallyDone();
}
public void function(string value, string value2)
{
if (valuesAreValidAndEqual(value, value2))
{
DoSomething();
}
}
private void valuesAreValidAndEqual(string value, string value2)
{
return value != null && value2 == value;
}