(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
- I'd like to add a vote for Ron's "minimum lines but not minimum clarity" as the easiest for me to understand. It's probably partly to do with my never having seriously programmed in Smalltalk, but I was appalled when I first saw all the crowing about how 'sweet' Don and Tom's Smalltalk version is. I still can't make head nor tail of it! It's RavioliCode to Me! Ron's "minimum lines" on the other hand has nothing to get in the way of understanding the algorithm. It's obvious it's recursive, and it's also obvious (to me at least) how similar the algorithm is to the classic method of traversing a binary tree. Let's see who can get some Java here then. --FrankCarver
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.
- We think, OK, the loop is "while the range isn't empty", OK, that's "while the number might still be found".
- We think, OK, he's computing the middle index, he's checking to see if the value is there.
- We think, OK, if it isn't there then he goes to the upper or lower part of the range.
- We invent the abstraction that the original programmer must have had when he wrote 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!
- Ah, ok. I must confess it seems the most obvious conclusion. It's just that I have some long-term qualms about the subject not being as completely analyzed as I would like.
- What qualms, just out of curiosity?
- The old issue about the part of the problem's complexity that is inherent, so that if you minimize it in one part of the solution, then it simply makes a different part of the solution more complex. So my concern is that focusing 100% on ShortMethods might sometimes cause the program as a whole to grow longer/more complex -- and not necessarily linearly; it might cause undue bloat all out of proportion. Sometimes that might even be true but wouldn't matter, but other times it might matter.
- I think software bloat is endemic to the industry these days, and that there is too little concern about it, either in assuming complexity is inherent when it isn't, or in assuming we have conquered it with something like ShortMethods.
- Part of the pressure to offshore software development is directly due to this: if you're going to develop a million line program, that'll be expensive, so offshoring seems reasonable. But to my mind, finding ways to shrink that down to only 10k lines would be an even better (and cheaper) solution. Yet that's not the way people think, these days. "No silver bullet", so give up. But "no silver bullet" does not mean that bloat is generally unavoidable; they are different issues.
- Ironically, the offshored-software no doubt will be a million lines of long methods, at that. Striving for ShortMethods doesn't cause offshoring (in some cases it might even help prevent offshoring); I'm just concerned about where we are neglecting to put our attention.
- I agree with everything you said, but let me add this. I don't think ShortMethods are a goal, I think clearly representing the algorithm in code in it's abstract form is the goal. I think when one does this, that ShortMethods are merely a nice side effect. I think LongFunctions are endemic of not clearly defining the algorithm and of not abstracting much. When one jumps strait to implementation, one ends up with fat bloated million lines of code software. Abstraction is the key to programming, and the key to trimming that million lines of code down to ten thousand. If you strive for ShortMethods as the goal, you'll get a millions lines of code with ShortMethods , if you strive for abstraction as the goal, you'll might only get ten thousand lines of ShortMethods , so the goal is important, the method length is simply a measurement that can be misinterpreted.
- Yes...but I have qualms there, too. I've been collecting references on the subject of abstraction, and so far it seems like everyone means something different. There's a lot of agreement that it is important, but not much effort on defining it in a meaningful way. Mostly it seems like "I know it when I see it". I'm hoping to find something more insightful. Part of the problem is that the spectrum of abstract versus concrete is always dependent on (ill-stated) context, but even so...
- What do you consider abstraction? I consider abstract code to be like pseudo code, it only deals with the problem by description and not implementation, it isn't concerned with pleasing the compiler, just solving the problem in an almost speech like manner while deferring implementation to methods. I think interfaces help in defining abstraction in static languages because they make it explicit that several implementations could be substituted and still work with the algorithm at hand. I tend towards the view that most problems can be solved abstractly and implementation is a trivial detail in most cases. Coding unit test first also re-enforces this idea for me, though I don't do it as much as I should. I believe that programming is all about defining a language suitable to solve the problem at hand. That language is the implementation of methods, but the abstract code is the code written using that mini language to solve problems. Objects serve as mini language containers, and add scope to the problem so that I don't have to mix all the mini langagues together. Every object's interface is then simply a DomainSpecificLanguage to that objects domain. It's the ability to have all these little pieces that can be popped together like lego's that make abstract code, to me anyway.
- Sure, that's all good stuff. I agree. The problem is that what we have a solid grasp of is implementation. That's what computer science is about; whenever we talk about abstraction in CS, we're hand-waving, not being rigorous. Abstraction really is in the domain of cognitive science -- it's about abstract thought. Ideally, anyway; it's not rigorously defined there, either. If it were, we would adapt that to CS usages for abstraction. Meanwhile we have an area that is very much art, and light on the science/engineering.
- So if person A happens to think about a problem in terms of a really good abstraction, they'll write better code than person B, who happens not to have as good of an abstraction on the same topic, even if their programming skills are otherwise equal. To date, everyone just takes for granted that that's how things have to be, but I don't think so; I think this reflects the relative immaturity of the field. To some extent, anyway. Particular abstractions sometimes need to be invented by rare geniuses, and only slowly adopted by other practitioners -- but we don't really understand enough even to really judge which things are more abstract or less abstract than other things. It's all subjective and fuzzy and unclear and ad hoc. Perhaps I'm foolish for hoping it can be improved -- yet I do hope.
- OK, I see what you mean, but I disagree about one thing... I like it this way, I like that it's an art, I like that some people can do it far better than others, I don't want it to be pure engineering, that would make it boring and me just another monkey banging out known patterns. I enjoy the craft of programming because of that sense of accomplishment you get when you know you can do something others can't, just as any craftsman does. It's not because our field is immature, mathematics is a mature field and still has these issues, better ways of thinking will always be able to drastically improve things. What we are missing I guess is a way to measure one solution against another and logically judge which is better, and that I think is due to immaturity of the field and the distain that many seem to have for academia. But you can't measure software when most folks still can't agree on what's important "in" software, too many wanna-be's in the field from the dot com boom that wouldn't know good software if it bit them in the ass. We still have a few more years of shakeout ahead to drop these people.
- True! Well, fear not, even if my dream came true, you wouldn't lose all that. QualityWithoutaName remains.