在调用其他函数时减少if语句

本文关键字:if 语句 调用 其他 函数 | 更新日期: 2023-09-27 18:21:57

我有一个函数,它从不同的对象调用许多其他函数。在调用下一个函数之前,每个函数都必须返回true。正如你所看到的,我使用了太多if语句。如何改进代码并使其更整洁?感谢

bool ISOKToDoSomthing()
{
    boo retVal = false;
    retVal = ObjA.CheckVersion(oldVersion);
    if(retVal)
    {
         retVal = objB.CheckUserRight();
    }
    if(retVal)
    {
          retVal = ObjC.ISDBExist();
    }
    if(retVal)
    {
          retVal = OjbD.ISServerUp(ServerName);
    }
    //tons of similar code as above
    ......... 
    return retVal;
 }

在调用其他函数时减少if语句

return 
    ObjA.CheckVersion(oldVersion) &&
    objB.CheckUserRight() && 
    ObjC.ISDBExist() && 
    OjbD.ISServerUp(ServerName);

我的建议是:如果没有进行更改的明确业务案例,就不要对此代码执行任何操作。

您的代码清晰、明显、可能正确、易于维护和调试你到底为什么要以任何方式改变它?花时间通过修复bug和添加功能来增加价值,而不是不必要地更改工作代码。当你的老板问你"那么你今天做了什么?"答案不应该是"我对正确的、有效的、已经调试好的代码进行了不必要的修饰性更改,从而增加了我们的日程风险"。

现在,如果这里真的有问题,问题可能不是代码难以阅读,而是代码严格地编码了应该是用户可配置的业务流程。在这种情况下,创建一个名为"工作流"的对象,对业务流程进行编码,并创建一个评估任意工作流的引擎。然后根据用户的输入构建一个表示所需工作流的对象实例。

这实际上为用户增加了价值;用户一点也不在乎您是否使用嵌套的"if"语句。

if (!ObjA.CheckVersion(oldVersion)) return false;
if (!ObjB.CheckUserRight()) return false;
if (!ObjC.IsDBExist()) return false;
if (!ObjD.IsServerUp(serverName)) return false;
... your other checks ...
return true;

&&的短路在一些情况下是有用的,但如果你有"大量"的短路,IMO就太多了,不能拘泥于一句话。

不过,两者的结合可能是有用的。更有用的是将这些检查中的一些压缩成更大的块(但比IsOKToDoSomething小)。例如,检查您是否可以同时访问数据库(数据库是否存在,是否可以登录,等等)

说实话,你有这么多对象要检查,这一事实暗示了设计问题——也就是说,你试图一次做太多,或者你有一个"上帝对象",它的小触角遍布系统的各个方面。你可能需要考虑解决这个问题。

return ObjA.CheckVersion(oldVersion) && objB.CheckUserRight() && ObjC.ISDBExist() && OjbD.ISServerUp(ServerName)

&运营商会短路,所以你可以这样链他们:

bool ISOKToDoSomthing()
{
    return
        ObjA.CheckVersion(string oldVersion) &&
        objB.CheckUserRight() &&
        ObjC.ISDBExist() &&
        OjbD.ISServerUp(ServerName) &&
    //tons of similar code as above
    ......... 
 }
bool ISOKToDoSomthing()
{
    return ObjA.CheckVersion(string oldVersion) && 
           ObjB.CheckUserRight() &&
           ObjC.ISDBExist() && 
           OjbD.ISServerUp(ServerName);
}

也许?

 retVal = objB.CheckUserRight() && ObjC.ISDBExist() &&  OjbD.ISServerUp(ServerName);

等等。

附带说明的是,例如,在一条语句中调用方法之前,您可以测试objB是否为null(一旦条件不满足,代码就会中断执行,即不会调用下一个条件),因此您不需要很多if(objB!=null)类型的语句。例如:

retVal = (objB != null && objB.CheckUserRight()) && (ObjC != null && ObjC.ISDBExist()) &&  (OjbD != null && OjbD.ISServerUp(ServerName));

您可以利用C#进行短路评估的事实:

return
    ObjA.CheckVersion(oldVersion) &&
    objB.CheckUserRight() &&
    ObjC.ISDBExist() &&
    OjbD.ISServerUp(ServerName);

编辑以修复CheckVersion参数的语法

如何使用and:

retVal = ObjA.CheckVersion(oldVersion) &&
         objB.CheckUserRight() &&
         ObjC.ISDBExist() &&
         OjbD.ISServerUp(ServerName);
return retval;

为了让代码不那么冗长,可以尝试while循环。假设您的方法是,如果它/ever/变为false,则永远不更改原始值的值,那么它将是while(retval){}并迭代一系列操作。就我个人而言,我认为这很丑陋。考虑使用一个开关,甚至(没错,但它会起作用)一个逐位枚举。

从我的角度来看,当我看到自己写这样的代码时,我在某个地方犯了一个严重的架构错误,我真的应该重新思考发出这个呼吁的原因。也许您应该重新审视一下您的逻辑,而不仅仅是您的代码。坐下来画一些方框,在设计阶段多做一些工作,你可能会发现自己的构建方式非常不同。

edit:或者,是的,像其他人一样,你可以让你的迭代成为一个if语句。同样,这是一个比一长串布尔值更大的问题。

这取决于您想要更改的内容。也许您可以抛出一个异常,而不是从子方法返回bool

bool retVal = true;
try
{
    ObjA.CheckVersion(oldVersion); 
    objB.CheckUserRight(); 
    ObjC.ISDBExist(); 
    OjbD.ISServerUp(ServerName); 
}
catch (SomeException ex)
{
    // Log ex here.
    retVal = false;
}
return retVal;

如果你这样做,IsDBExist可能不是最好的名字(因为在我看来,Is通常翻译为"返回bool"),但你会明白的。