Reading Ravioli

(This page appears to be commenting on BinarySearchCodeOnly, see CommentingChallengeTwo)

A suggestion: Code consisting of ShortMethods can reveal the algorithm more directly than procedural code usually does, while hiding the implementation. When reading such code, our eyes see different things, and our mind must think different thoughts. --RonJeffries

Frank, I had a similar feeling when reading the two styles, but from the other side of the mirror. I think that the two kinds of code show different things, and hide different things. Let me try to show you what I mean.

When we read:

      while ( upper > lower + 1 ) {
         middle = ( upper + lower ) / 2;
         if  Array[middle] = value then return( middle );
         if Array[middle] < value
            then lower = middle
            else  upper = middle;
      }

we have to invent the comments that Alistair originally asked about. We're figuring out what the abstraction is: what the algorithm is, from the code.

The algorithm is in our head, the implementation is on the page.

When we look at the Smalltalk, the algorithm is explicit, but the implementation is hidden in other methods.

 index
   self doesNotIncludeTarget ifTrue: [^notFoundBlock value].
   self isTargetAtMiddleOfRange ifTrue: [^middleOfRange].
   self adjustRange.
   ^self index

the algorithm is right there. Are we done? If so, get out. Is the target in the middle? No, then adjust the range. So the code written is pretty abstract - it expresses the algorithm. To understand how it works (if we want to), we have to look and see how the code is done, such as:

 isTargetAtMiddleOfRange
   middleOfRange := lowIndex + highIndex // 2.
   ^(array at: middleOfRange) == target

So in Smalltalk it's just the reverse - the algorithm is on the paper, and the code is in our head. (In another method - if we even bother to look.)

When you get good at Smalltalk, you stop bothering to remember the code. You just go with the algorithm as stated, as if the programming language actually understood "is target at the middle of the range". In essence, it does!

I'm grateful to Alistair for making it possible for me to experience both contexts together, and to Frank for bringing me to think about what I experienced. --RonJeffries

Although this page is about how we understand code when we read it, JeanineDeGuzman and KevinBradtke point out below that object programmers learn to trust the abstract algorithm and often don't read beyond unless they have to. Perhaps a little WouldntStartFromHere, but a good point.

Now in fact some of the C and Java versions of BinarySearch have been pretty abstract. "Information hiding" and code that reveals intent were not invented with Smalltalk. However, in my experience, there is a tendency, especially in C, to go right to the implementation without a lot of abstraction cover.


Let's take it one step back, and first look at:

 presortedAscendingIndexOf: anInteger ifAbsent: aBlock 
        ^BinarySearch 
                indexOf: anInteger
                in: self
                ifAbsent: aBlock

As soon as one sees this, we know that a binary search is being performed. If we are all ExtremeProgrammer-s on this project, then we can trust that whoever implemented this method also wrote unit tests (running at 100%), and we don't really need to look any further. --JeanineDeGuzman --KevinBradtke


This page overlaps with many of the arguments found in LongFunctions and ShortMethods. It is one of those PerpetualArguments.

Seems like this page is proof that ShortMethods are the best solution. It seems trivially true that to have both abstraction and implementation in code is better than to just have implementation. That this also leads to many short methods and cleaner code, is an additional bonus.

Some interesting points are argued clearly on this page, but I don't see that ShortMethods paraphrases the conclusion. At most I can see that ShortMethods could certainly complement the points made on this page, but that doesn't mean that LongFunctions contradicts; they're still orthogonal issues.

Well, besides all the samples being short methods... if you explicitly write each step of an algorithmic abstraction in the code... then then implementations of those steps, will each naturally be concerned with exactly one of those steps, will have a clearly defined role, and as a result, is likely to be a very short method, as the examples demonstrate, and as past experiences demonstrate. I also didn't claim their conclusion was short methods, that was my conclusion!


EditText of this page (last edited November 19, 2006) or FindPage with title or text search