【问题标题】:How to amend return value design in OO manner?OO方式如何修改返回值设计?
【发布时间】:2010-04-06 08:41:14
【问题描述】:

我不是 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是一个函数返回的值,其中所有的Exceptions都被吞掉了,在catch块中,上面的值都是显式返回的。通常情况下,异常会被简单地吞下,并带有空的 catch 块。

显然吞下异常是错误的OO设计。我的问题涉及返回值的使用。我认为这也是错误的,但是我认为将异常用于控制流同样是错误的,而且我想不出任何东西可以以正确的 OO 方式替换上述内容。

请问您的意见?

【问题讨论】:

  • @FrontierPsycho:默默吞下异常是不好的,但它与 OO 没有任何关系。实际上异常与OO无关:异常不存在在OOA/OOD级别。例外是(某些)语言特质。苹果/橙子。如果在您的 OO 分析/OO 设计中没有考虑到任何“异常”,那么您的 OOA/OOD 就会被破坏。
  • 谢谢,我没想到异常与 OO 是分开的。不幸的是,应用程序的分析和设计是由其他人在很长时间和许多行代码之前完成的,从头开始更改它是一件痛苦的事情。我只是试图纠正最明显的错误和更容易纠正的事情。

标签: java oop return-value exception


【解决方案1】:

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

OO-vs.-non-OO 设计

基于异常与基于返回值的设计。

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

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

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

祝你好运!

【讨论】:

    【解决方案2】:

    但这是 Java(不是 C++)。因此,如果您使用这样的“代码”,您应该使用 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;
        }
    }
    

    这可以扩展以赋予它更多延续传递风格的味道;通过为 ErrorCode 定义一个回调方法并调用该方法而不是执行 switch() 语句。

    【讨论】:

    • 这看起来很干净,并且让我避免定义自定义异常(尽管它是返回值方法的一个版本)。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      根据 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-else。 这是您的通用“catch”函数可以设置状态的方式。 这当然可以用于常规系统任务,因此任何主要组件都会知道状态是什么,以及应该执行什么操作。

      简化:

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

      【讨论】:

        【解决方案5】:

        通常的共识是异常不应用于控制流。然而,Python 社区似乎有不同的想法。

        但是,我认为您遇到的根本问题是清晰度;在一种方法中捕获异常并将每个条件转换为某个任意数值,这使得代码试图做什么变得非常不清楚。

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

        【讨论】:

        • 说实话,大多数可能的值都表示错误。通常只有一个表示函数按预期执行。我开始倾向于使用异常,尽管这意味着要编写我自己的异常类。
        猜你喜欢
        • 2012-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-05
        • 1970-01-01
        • 1970-01-01
        • 2013-10-22
        • 2012-07-07
        相关资源
        最近更新 更多