如何以OO方式修改返回值设计?

时间:2010-04-06 08:41:14

标签: java oop return-value exception

我对OO编程并不感兴趣,但我遇到了一个令人费解的情况。我已经获得了一个工作和扩展的程序,但是之前的开发人员似乎对OO不太满意,似乎他们要么具有C背景,要么对OO的理解不清楚。现在,我不建议我是一个更好的开发人员,我只是认为我可以发现一些常见的OO错误。困难的任务是如何修改它们。

就我而言,我看到了很多:

        if (ret == 1) {
            out.print("yadda yadda");
        } else if (ret == 2) {
            out.print("yadda yadda");
        } else if (ret == 3) {
            out.print("yadda yadda");
        } else if (ret == 0) {
            out.print("yadda yadda");
        } else if (ret == 5) {
            out.print("yadda yadda");
        } else if (ret == 6) {
            out.print("yadda yadda");
        } else if (ret == 7) {
            out.print("yadda yadda");
        }

ret是函数返回的值,其中吞并了所有异常,并且在catch块中,显式返回上述值。通常情况下,只会吞下Exceptions,并使用空的catch块。

很明显,漏风异常是错误的OO设计。我的问题涉及使用返回值。我认为这也是错误的,但是我认为使用Exceptions控制流程同样是错误的,我无法想出以正确的OO方式替换上述内容。

请你输入?

5 个答案:

答案 0 :(得分:4)

这些是恕我直言两件完全不同的事情:

OO与非OO设计

基于异常的与基于回报价值的设计。

您可以以任何方式组合它们(尽管大多数开发人员会说非OO设计仅适用于算法等特殊任务。

关于你的代码库:我建议对整个软件进行整体分析,然后仔细考虑是否取消返回代码是一个好主意。这个软件将来会扩展吗?或者只是某些死木躺在某处执行某项特定任务?

我建议阅读“重构”和“遗留代码”。我周围的人说Michael Feathers的“有效地使用遗产代码”是一本非常可靠且推荐的书。所以这可以帮到你很多。

祝你好运!

答案 1 :(得分:1)

当然,使用控制流的异常不是正确的做法。它们需要与实际程序控制流分开处理。

发生异常的事实意味着您的应用程序中存在异常事件并吞下它或将其转换为返回值并不会改变它(意味着只要您将其转换为返回值,您就会用它作为控制流程)。通常可以避免表示成功状态和异常状态的返回值(第一步:使用枚举,然后逐步改进OO设计)。

答案 2 :(得分:1)

但这是Java(不是C ++)。因此,如果您使用“代码”,那么您应该使用Enums。使用Enums(或整数,顺便说一句),您可以使用switch()语句来改进代码。

public abstract class Example {

    protected abstract ErrorCode test();

    public void run() {
       ErrorCode code=test();
       switch(code) {
           case OK: 
               System.out.println("All ok"); 
           break;
           case OOPS: 
               System.out.println("Oops, an error occurred.");
           break;
           case OTHER_ERROR: 
               System.out.println("A different error occurred");
           break;
           case UNKNOWN_ERROR: 
               System.out.println("Yet another, unknown error occurred.");
           break;
       }
    }

    public static enum ErrorCode {
        OK, OOPS, OTHER_ERROR, UNKNOWN_ERROR;
    }
}

这可以扩展到更多的Continuation Passing Style风格;通过为ErrorCode定义一个回调方法并调用该方法而不是执行switch()语句。

答案 3 :(得分:0)

根据if-else方法,如果你想在这里更多OO,我会带一个提示。 你绝对可以使用state pattern

Class State{
   public:
       virtual void showInfo()=0;

}

class Iddle:public State{
    public:
       void showInfo(){
        std.cout<<"I've just initialized"<<std.endl;
        };

}

class Wrong:public State{

   public:
       void showInfo(){
        std.cout<<"Something goes wrong"<<std.endl;
        };

}
main()
{
boost::scoped_ptr<State> mystate = new Iddle();

mystate->showInfo();

.....
mystate.reset(new Wrong());
....
mystate->showInfo();

}

您可以在所需的状态下实现任何所需的内容。 这样你就会扔掉if-elses。 这是您的通用“catch”函数可以设置状态的方式。 这当然可以用于常规系统任务,因此任何主要组件都会知道状态是什么,以及应该采取什么行动。

简化:

如果您有异常,请将状态设置为Wrong,然后终止该线程,停止操作或任何导致失败的对象。 你仍然拥有状态,你以适当的方式处理异常,但仍然有一些状态,这可能是在另一个线程中采取适当行动的基础。

答案 4 :(得分:0)

一般认为,不应将异常用于控制流程。但是,Python社区似乎有不同的想法。

然而,我认为你所拥有的根本问题是清晰;在一个方法中捕获异常并将每个条件转换为某个任意数值会使得很难清楚代码尝试做什么。

如果没有看到您提到的被调用代码,就很难建议如何改进它。如果它处理真正的异常条件,那么我会考虑允许那些由调用代码处理并可能重新抛出,因为任何异常都符合方法的目的。