4

I was thinking about patterns which allow me to return both computation result and status:

There are few approaches which I could think about:

  • function returns computation result, status is being returned via out parameter (not all languages support out parameters and this seems wrong, since in general you don't expect parameters to be modified).

  • function returns object/pair consisting both values (downside is that you have to create artificial class just to return function result or use pair which have no semantic meaning - you know which argument is which by it's order).

  • if your status is just success/failure you can return computation value, and in case of error throw an exception (look like the best approach, but works only with success/failure scenario and shouldn't be abused for controlling normal program flow).

  • function returns value, function arguments are delegates to onSuccess/onFailure procedures.

  • there is a (state-full) method class which have status field, and method returning computation results (I prefer having state-less/immutable objects).

Please, give me some hints on pros, cons and situations' preconditions of using aforementioned approaches or show me other patterns which I could use (preferably with hints on preconditions when to use them).


EDIT: Real-world example: I am developing java ee internet application and I have a class resolving request parameters converting them from string to some business logic objects. Resolver is checking in db if object is being created or edited and then return to controller either new object or object fetched from db. Controller is taking action based on object status (new/editing) read from resolver. I know it's bad and I would like to improve code design here.

0lukasz0
  • 3,155
  • 1
  • 24
  • 40
  • In C and C++ at least it's perfectly OK to have out parameters. So I usually return success/failure by return value and modify an out parameter to reflect computation output. This also allows for better resource control in case of dynamically allocated memory. – arne Dec 14 '11 at 08:38
  • There are lots of cons and pro's, but I'm wondering if this question will stay open because it looks to me that is similar to the http://stackoverflow.com/questions/36707/should-a-function-have-only-one-return-statement question. I'm hoping it stays open, I think these kind of questions exactly match what this site was made for. – Maarten Bodewes Dec 30 '11 at 23:37
  • I think that the other question is totally different then this one. It's about having multiple return statement in code, not about returning multiple "results". Also I found this: http://stackoverflow.com/questions/4181018/what-is-the-pros-and-cons-of-using-out-parameter as a pretty good discussion about out parameters, which covers first mentioned approach. – 0lukasz0 Dec 31 '11 at 13:02

2 Answers2

2

function returns computation result, status is being returned via out parameter (not all languages support out parameters and this seems wrong, since in general you don't expect parameters to be modified).

If the language supports multiple output values, then the language clearly was made to support them. It would be a shame not to use them (unless there are strong opinions in that particular community against them - this could be the case for languages that try and do everything)

function returns object/pair consisting both values (downside is that you have to create artificial class just to return function result or use pair which have no semantic meaning - you know which argument is which by it's order).

I don't know about that downside. It seems to me that a record or class called "MyMethodResult" should have enough semantics by itself. You can always use such a class in an exception as well, if you are in an exceptional condition only of course. Creating some kind of array/union/pair would be less acceptable in my opinion: you would inevitably loose information somewhere.

if your status is just success/failure you can return computation value, and in case of error throw an exception (look like the best approach, but works only with success/failure scenario and shouldn't be abused for controlling normal program flow).

No! This is the worst approach. Exceptions should be used for exactly that, exceptional circumstances. If not, they will halt debuggers, put colleagues on the wrong foot, harm performance, fill your logging system and bugger up your unit tests. If you create a method to test something, then the test should return a status, not an exception: to the implementation, returning a negative is not exceptional.

Of course, if you run out of bytes from a file during parsing, sure, throw the exception, but don't throw it if the input is incorrect and your method is called checkFile.

function returns value, function arguments are delegates to onSuccess/onFailure procedures.

I would only use those if you have multiple results to share. It's way more complex than the class/record approach, and more difficult to maintain. I've used this approach to return multiple results while I don't know if the results are ignored or not, or if the user wants to continue. In Java you would use a listener. This kind of operation is probably more accepted for functinal languages.

there is a (state-full) method class which have status field, and method returning computation results (I prefer having state-less/immutable objects).

Yes, I prefer those to. There are producers of results and the results themselves. There is little need to combine the two and create a stateful object.

In the end, you want to go to producer.produceFrom(x): Result in my opinion. This is either option 1 or 2a, if I'm counting correctly. And yes, for 2a, this means writing some extra code.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • thank you for your input in this discussion. I am giving +1, although there are some statements which I not fully agree with you. Firstly, I don't think that out parameters are so good option. They can be really confusing and it's easy to overlook possible side effects of a function which uses an out parameter. I agree that 2a seems like very strong choice, extra code is nothing wrong here, as long as your code stays DRY. Also you made a good point mentioning added complexity in the callback scenario. We both agree that exceptions should only be used with failure scenarios. – 0lukasz0 Dec 31 '11 at 12:57
  • I don't particularly like out parameters either. However, if a programming language has been explicitly written to use output parameters (and they are used in e.g. the standard libraries), then I don't think you should ignore them as a programmer. Programmers should try and fit in with the programming environment, otherwise the code will become a hodgepodge of programming styles. – Maarten Bodewes Jan 01 '12 at 17:02
1

My inclination would be to either use out parameters or else use an "open-field" struct, which simply contains public fields and specifies that its purpose is simply to carry the values of those fields. While some people suggest that everything should be "encapsulated", I would suggest that if a computation naturally yields two double values called the Moe and Larry coefficients, specifying that the function should return "a plain-old-data struct with fields of type double called MoeCoefficient and LarryCoefficient" would serve to completely define the behavior of the struct. Although the struct would have to be declared as a data type outside the method that performs the computation, having its contents exposed as public fields would make clear that none of the semantics associated with those values are contained in the struct--they're all contained in the method that returns it.

Some people would argue that the struct should be immutable, or that it should include validation logic in its constructor, etc. I would suggest the opposite. If the purpose of the structure is to allow a method to return a group of values, it should be the responsibility of that method to ensure that it puts the proper values into the structure. Further, while there's nothing wrong with a structure exposing a constructor as a "convenience member", simply having the code that will return the struct fill in the fields individually may be faster and clearer than calling a constructor, especially if the value to be stored in one field depends upon the value stored to the other.

If a struct simply exposes its fields publicly, then the semantics are very clear: MoeCoefficient contains the last value that was written to MoeCoefficient, and LarryCoefficient contains the last value written to LarryCoefficient. The meaning of those values would be entirely up to whatever code writes them. Hiding the fields behind properties obscures that relationship, and may impede performance as well.

supercat
  • 77,689
  • 9
  • 166
  • 211