2010-10-04 47 views
2

我已经阅读了很多重构文献,并且在例子中看到的一个常见主题是大量IF语句的减少。下面是一个非常简单的代码块,首先检查是否提供了电子邮件地址,如果是,则继续验证电子邮件地址。我通常会看到很多这种类型的代码,看起来总是有点混乱,特别是如果有多个变量的话。这个IF语句代码片断如何被重构?

if (string.IsNullOrEmpty(email)) { 

    throw new ApplicationException("Email Address Required"); 
} 

else { 

    if (!ValidationService.EmailAddressIsValid(email)) { 
     throw new ApplicationException("Invalid Email Address"); 
    } 

} 

我的问题是,这个例子是完全可以接受的吗?它有味道吗?如何重构此片段?

回答

7

很难重构这样一个小片段 - 我会跳过关于不重构而不进行测试通常的说法...

当我看到这样的代码,我认为

  • 为什么ValidationService不保存空检查的逻辑吗?如果这不在包含验证逻辑的类中,那么为什么我们要在这里检查必填字段?

  • 我很可能会令空支票存入一个帮手所以代码可能会更喜欢:

    ThrowIfRequiredFieldMissing(email, "Email Address");

  • 除去别的,因为扔无法继续

  • 创建一个帮手投掷:FailIf(!Validation.EmailAdressIsValid(email), "Email Address")。这将引发你的验证异常,并允许在需要时您可以在以后更改例外(虽然我会船到桥头当你来到它)

还有许多其他的可能性,像Func<>本词典,或应用于字段列表的战略模式,以及等等。 但是没有更多的代码,决定做什么(如果有的话)只是猜测

7

抛永远不会返回,所以我会用更好的可读性如下:

if (string.IsNullOrEmpty(email)) { 
    throw new ApplicationException("Email Address Required"); 
} 

if (ValidationService.EmailAddressIsValid(email)) { 
    throw new ApplicationException("Invalid Email Address"); 
} 

// continue here if no error was detected 
+2

-1:不真的*重构*并没有减少if -s的数量 – chiccodoro 2010-10-04 16:50:49

+0

不能不同意更多chiccodoro。虽然它不会减少if-s的数量,但它确实删除了一个,并使其更具可读性,特别是如果它位于您的方法的顶部并充当警卫的话...... – 2010-10-04 17:13:38

+0

@Bryce:好吧,它可能会*稍微*提高可读性(尽管这很主观),但OP的问题是*减少大量的IF语句*。有了这个建议,你仍然有2个if语句直接在代码中。如果你有多个方法进行相同的检查,你在许多地方有验证逻辑,而不是一个。然而,许多重构问题都是关于(恕我直言)。 (顺便说一句:对于迟到的回答,没有注意到你的评论,因为它不是以@chiccodoro开头) – chiccodoro 2010-10-11 13:12:12

0

这很好,但你可以更简化它。

if (string.IsNullOrEmpty(email)) { 
    throw new ApplicationException("Email Address Required"); 
} else if (ValidationService.EmailAddressIsValid(email)) { 
throw new ApplicationException("Invalid Email Address"); 
} 
+2

-1:没有重构,没有减少if语句,甚至没有简单和可读性,如果只是简化代码。 – chiccodoro 2010-10-04 16:55:18

+1

代码重构是改变计算机程序的源代码而不修改其外部功能行为以改进软件的某些非功能性属性的过程。因此我重构了代码。在你倒下某人之前得到你的事实。 – Moncader 2010-10-05 01:35:11

1

你可以做的第一件事是删除行else {及其相应}

这是因为如果电子邮件地址丢失,第一个throw语句将确保当前位于else块中的代码永远不会执行。

0

重构不仅仅是一小段代码样式。

您正在验证用户条目,因此您可能需要定义或重新使用现有的验证框架,而不是在代码中嵌入if语句。你好像差不多了,因为你有ValidationService进行第二次验证。

所以我的建议是:在执行EmailAddressIsValid时加入string.IsNullOrEmpty检查。

当然这只有移动一个if语句,但如果在多个地方使用EmailAddressIsValid它将减少if语句。此外,验证逻辑然后真正整合在一个地方。目前不是。

另一件小事:重命名EmailAddressIsValidIsEmailAddressValid,因为使用“Is”作为返回布尔值的函数的前缀是一个常见的约定。

-2

丑陋的变异,但可行

string msg = string.Empty;  
if (string.IsNullOrEmpty(email)) 
{ 
    msg = "Email Address required"; 
} 
else if (ValidationService.EmailAddressIsValid(email)) 
{ 
    msg = "Invalid Email Address"; 
} 

if (msg != string.Empty()) 
    throw new ApplicationException(msg); 
2

,如果您真的想使你的代码的可读性,你甚至可以做这样的事情:

throwExceptionIfEmailIsEmpty(email); 
throwExceptionIfEmailIsInvalid(email); 
// continue to process the e-mail here... 

随着提取到单独的验证码功能:

private void throwExceptionIfEmailIsEmpty(String email) 
{ 
    if (string.IsNullOrEmpty(email)) 
     throw new ApplicationException("Email Address Required"); 
} 

private void throwExceptionIfEmailIsInvalid(String email) 
{ 
    if (ValidationService.EmailAddressIsValid(email)) 
     throw new ApplicationException("Invalid Email Address"); 
} 

它可能看起来有点过分,但它使得查看真正发生的事情变得更容易!
(鲍勃叔叔的Clean Code启发 - 功能应该做的一件事,他们应该把它做好他们应该只是做(或类似的东西) - 如果有人想知道,。))

+0

只需提一下:你甚至可以更进一步,将两个throw函数包装到另一个函数中,比如'throwExceptionIfEmailIsEmptyOrInvalid(email)'。你的代码变得更容易阅读和自我记录。 – Nailuj 2010-10-04 14:20:23

+1

...或者只是'ValidateEmail(email)'。 (1) – chiccodoro 2010-10-04 16:53:41