[Q] Newbie - Multiple Return Values

Boris Gaertner Boris.Gaertner at gmx.net
Thu May 1 17:31:11 UTC 2003


Ingo Hohmann <ingo at 2b1.de> asked about ways to represent
multiply return values and he got some interesting answers.

I agree with Cees that code like

result := foo doSomething.
(bar := result at: 1) > 0
   ifTrue: [self error: (result at: 3)]
   ifFalse: [^result at: 2]

is a candidate for easy improvements. Yes, it is of course possible to use an Array and it works, but 

  a.. when you use a class - say: MyStructuredMessage - you can use the option "class refs" of the browser to find all methods that reference the class. You can of course also ask for all references to class Array, but in our newest standard image the browser will disappoint you with almost 2.000 methods. It is then your task to find out what all these methods do and which are the ones that you are looking for. 
  b.. when you use methods with specific names, you can search for both the senders and the implementors. This is often very helpful. You can of course search for all senders of method 'at:' but you have to know that this method is defined in the instance protocol of Object (and inherited by Array) and you will get more the 3.500 senders (in out standard image) 
  c.. as Cees pointed out, method names are much more informative than array indices. Users of your code will find it easier to read  'result payload' 'result status' 'result checksum'  than (result at: 1), (result at: 2)  and so on. You should also not underestimate the possibility that you want to change the format of you structured return value for some reason. Consider the following situation: 
    a.. You have a value  Array with: payload with: checksum with: state 
    b.. Somewhere in your code you access the state with (array at: 3), in other places you write  (array last) 
    c.. You did not anticipate it, but for some reason you have to add a fourth data field to your value. To keep the expression (array last) correct, you cannot add the new field after the last one, and to keep the expression (array at: 3) correct, you have to add the new field after the third field which is the last one. You have now all reason to rethink your use of an array.
There is a related problem and I want to explain that too, because it is one of the most costly mistakes that I ever made (in Smalltalk, not in life)

I had a lot of cooperating classes and in the instance protocol of all these classes I had methods with identical names (I wanted to use polymorphism and that was ok). Initially these methods had a small number of parameters, but later I had repeatedly to add additional parameters. Every time I needed a new parameter, I added that new parameter to all these methods and than I updated all senders. Finally I removed all the obsoleted methods. I can only regret my foolishness, but it took me some time to understand that I failed to define a class for all my parameters. (I was even not smart enough to use an array!) Now that I have understood that, the introduction of an additional parameter is very easy. I add an instance variable and access methods to the class that keeps all the parameters and I have to rework only the methods that have to access the additional parameter.

Given this experience, I think now that is is not best practice to ask "Do I really need a class?". It is - in my opinion - much better to ask: "What problems will I incur when I do not define a class?"

By the way, I agree that the use of exception is not always a good solution. Use of exceptions becomes increasingly difficult when you have to handle additional data elements (the equivalent of adding instance variables to a class)

Just my 2 eurocents,
Boris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20030501/e10b9c0f/attachment.htm


More information about the Squeak-dev mailing list