How to change the design of the return value in OO?

I'm not new to OO programming, but I ran into a mysterious situation. I was provided with a program for work and expansion, but previous developers did not seem to feel comfortable with OO, it seems they either had background C or an incomprehensible understanding of OO. Now I do not suggest that I be a better developer, I just think that I can detect some common OO errors. The difficult task is how to change them.

In my case, I see a lot of things:

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 is the value returned by the function in which all Exceptions are swallowed, and in the catch blocks, the above values ​​are returned explicitly. Often, Exceptions are simply swallowed with an empty catch block.

Obviously, swalllowing exceptions are a poor development of OO. My question is about using return values. I believe that this is also wrong, but I think that using exceptions for the control flow is equally wrong, and I cannot think of anything to replace the above in the correct OO manner.

Your entry please?

+4
source share
5 answers

But this is Java (not C ++). Therefore, if you work with such “codes,” you must work with Enums. And using Enums (or integers, by the way), you can use the switch () operator to improve this code.

 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; } } 

This can be expanded to give it an even more pleasant Continuation Passing Style fragrance; by defining a callback method for ErrorCode and calling this method instead of executing the switch () statement.

+1
source

These are IMHO two completely different things:

OO-vs.-non-OO Project

and

return-value-based exception design.

You can combine them in any way (although most developers will say that a design without OO is only good for special tasks such as algorithms.

As for your code base: I would recommend a holistic analysis of all the software, and then some careful thought about whether leaving with return codes is a good idea. Will there be a software extension in the future? Or is it just some kind of dead forest lying somewhere to perform one specific task?

I would recommend reading refactoring and legacy code. The people around me say Michael Persian Effectively Working with Legacy Code is a very solid and recommended book. So it can help you.

Good luck

+4
source

Of course, using exceptions for the control flow is not what you need to do. They must be handled separately from the actual program control flow.

The fact that an exception occurred means that there was an exceptional event in your application, and swallowing it or converting it to a return value does not change it (this means that as soon as you turned it into a return value, you used it for the control flow). Normally, return values ​​indicating both success states and exceptional states can be avoided (first step: using enumerations, and then gradually improving the OO design).

+1
source

According to the if-else approach, I will only bring a hint if you want to go further than OO here. You can definitely use a state template .

 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(); } 

You can implement whatever you want in the desired states. That way you throw away if-elses. This way your generic catch function can set states. Of course, this can be used by regular system tasks, so any major component should know what the state is and what action should be taken.

Simplifies:

if you have an exception, set the status to False, then destroy the thread, stop the action, or any object responsible for the failure. You will still have a state, you correctly handled the exception, but still have some states that may be the basis for taking appropriate actions in another thread.

0
source

In general, consensus is that exceptions should not be used for control flow. However, the Python community seems to think differently.

However, I think the main question you have is clarity; catching exceptions in one method and converting each condition to some arbitrary numerical value makes it very unclear what the code is trying to do.

Without seeing the named code that you're talking about, it's hard to suggest how to improve it. If it deals with genuine exceptional conditions, then I would think about letting the calling code be processed and possibly reconstructed, since any exception matches the purpose of the method.

0
source

Source: https://habr.com/ru/post/1306098/


All Articles