BinarySearchInJava starts out with a very elegant Java translation of a binary search class. The binary search itself is a MethodObject, but interestingly it looks like a ResultObject in some ways. It has a method named index () which returns result of the binary search by way of calculating it.
I do the same sort of thing all the time, but I have mixed feelings about it. Apparently, it bugged PhilGoodwin also. He rewrote the code and changed the name of the method to findIndex ().
Why the trepidation? To me it is a question of how far information hiding goes. You can make a non-trivial method look like a query because logically you get the same thing. But, there is a big difference in performance space.
To me, the index () version is better in spite of the performance revelation issue. I tend to use MethodsWithNounNames where I think that it will clarify things, but I can not discount the fact that it does not reveal performance well. On the other hand, one could argue that caching results would work well these noun named methods.. if you think that index () will be called more than once, only calculate on the first call.
Ahh.. tradeoffs. What do you all think?
I look at names from two places, both aimed at DesignFromTheClientSide. The first place is "what does this return." If a boolean, then the name should read as an assertion "isSmallerThan" or whatever. If a value, then what does the value express?
I would consider a verb command name only if the dominant purpose of the function is not what it returns but how it changes the state of the world. E.g., "setValue", "partitionCollection", implying that something is going to change underneath us, not just the return value. So on this basis, I would not think of "findIndex()", whose primary purpose is to not change the state of the collection, but rather to answer a value of interest. Something like "indexOf" would come to mind.
The second place to look is the client code. I write a few different calls, from within a boolean test, or inside a concatenation of function calls, separately, etc., and see which reads more like an English sentence. So I would write
I'm with Alistair. If it does something, it gets a verb. If it answers an object, it's a noun. If it answers a boolean, it gets a question.
Names of methods should not say anything about the implementation. After all, if you changed the implementation, would you care to rename the method? I think not.
It's nice to see this spelled out so clearly. This is essentially the way I try to do naming as well. Why questions instead of assertions, Ron? Is it because it reads better in Smalltalk?
The name of the private method came from essentially the same kind of thinking. I looked at the client code:
public static int indexOf(int target, int[] anArray) { return new BinarySearch(target, anArray).index(); }and it wasn't clear to me that index() was causing the search to happen, in fact I wasn't sure what it was doing (was it the location currently being searched in?) I also had a hard time finding the actual search algorithm in the code. The findIndex() method name tells me about the algorithm of the code I am reading if I am a maintainer, and it tells me how to actually cause the search to happen if I am a client.
The findIndexOf() static method name was a result of considering:
if( BinarySearch::indexOf(A,t) > 0 ) against: if( BinarySearch::findIndexOf(A,t) > 0 )I didn't consider Alistair's return value test, although I will in the future. I liked the fact that the two methods that actually caused the search to happen were the only ones that had verb names and I liked that the names were so similar. I'm not used to MethodObjects? so I assumed that the call would have to be qualified. On further reflection I've realized that it would not and would therefore be tempted to use searchFor as my verb in order to tie together a family of search algorithms. -- PhilGoodwin
You wrote, it wasn't clear to me that index() was causing the search to happen, which implies you - the client - are cognizant of a search taking place. A worthwhile realization is that "indexInOf(A,t)" might not actually be done with a search at all - it could be table lookup in an array. That realization is part of the ShieldPattern. You would give the function a name that describes what the postcondition is, not saying anything about how the postcondition is satisfied. Then the implementor can change the implementation without worrying about the client. The client wants to know what the index is, that is all.
I am not a client of some container that happens to have an indexOf() method. I am a client of a search algorithm (else I wouldn't be considering a thing called BinarySearch to do the work I want to do). As such I am concerned not only with the result but with when, and in this case, how it is generated. -- PG
Actually, this topic gets me on my secret hobbyhorse - railing against getters and setters called "getGoop" and "setGoop". Those names fail from the DesignFromTheClientSide perspective. Boy, do I feel silly writing area = shape.getWidth() * shape.getHeight(). Much rather write "area = shape.width() * shape.height()". Oops, I let my secret out of the bag. Too late to change the entire C++ and Java cultures, now :-( --AlistairCockburn.
Don't even get me started :)
Well, not all of us are like that. I disliked get/set naming from the beginning. What good is function name overloading if you don't use it?
It is interesting to notice that instances of BinarySearch are ValueObject-s as well. But, that is true of mathematical abstractions in general.