Monday, November 1, 2010

Intentional Ignorance

I was recently looking at a quiz that purports to test your Java knowledge. One of the questions required determining which overloaded method was going to be called in a specific code sample. (sorry, I don't have a link to the exam or question. I got the question wrong and this post is my justification for why it is a bad question (aka sour grapes).

Risk of Too Much Knowledge
Imagine I was intimately familiar with the Java Language Specification and knew exactly how method resolution would happen. Further, imagine I have some code that looks like:
  1 public class Test {
  2  
  3   public static void doSomething(Object o) {
  4     System.out.println("Hello"); 
  5   } 
  6  
  7   public static void doSomething(int... x) {
  8     System.out.println("Goodbye"); 
  9   } 
 10  
 11   public static void main(String[] argv) {
 12     doSomething(5); 
 13   } 
 14 }
If you run this code what will be printed?  Do you know? Is it reasonable to assume that every developer on the team will know what this code does just by looking? And that they will be able to understand this without a lot of thought?  i.e. is this readable and good code?

Of course its not good code. If you are overloading a method name, it should be because the same logical action happens for each method. (e.g. they both say "Hello") If this is the case, then you don't care that the method call on line 12 resolves to two different methods - in both cases the same behavior happens. If you have two methods with the same name that do two different things, please, please, please rename one of them.

But what if I was such an expert in this thing, that it was just second nature to me that varargs takes lower priority than non varargs methods? Would I notice the possible confusion in the code? I don't think twice about writing code that looks like x = 5 + 2 * 10 of course this evaluates to 25. Order of operations is just that ingrained in me. Given that this is a concept that exists in math and not just computer science, I don't think this is unreasonable. However, I don't want that attitude to happen in this situation.  By testing for this sort of knowledge I fear that some impressionable developers out there might think that everyone should know this and therefore write code that depends on it. i.e. this test question, as it is written, may be doing a disservice to developers everywhere.

Lesson That Should Be Taught
The important thing that all Java developers should know is that code like the above is legal, and that there is a defined way to determine which method is called. You can look up the specific behavior if you need to know, but just knowing to look it up is half the battle.

However, instead of looking up the correct behavior, or even documenting what is happening, the code should be rewritten (probably by renaming methods if they are logically different) so that it is obvious what is supposed to happen. This is the real lesson that should be taught - don't do this!

So Why Intentional Ignorance?
It would seem that the best scenario is to both know what will happen with the code, but be aware enough not to write code that requires this knowledge.  So am I just being lazy by not wanting to know this?  Maybe, but I'd like to leave you with this passage where Dr. Watson is describing Sherlock Holmes from "A Study in Scarlet" that has always stayed with me.

His ignorance was as remarkable as his knowledge. Of contemporary literature, philosophy and politics he appeared to know next to nothing. Upon my quoting Thomas Carlyle, he inquired in the naivest way who he might be and what he had done. My surprise reached a climax, however, when I found incidentally that he was ignorant of the Copernican Theory and of the composition of the Solar System. That any civilized human being in this nineteenth century should not be aware that the earth travelled round the sun appeared to me to be such an extraordinary fact that I could hardly realize it. 
    "You appear to be astonished," he said, smiling at my expression of surprise. "Now that I do know it I shall do my best to forget it."
    "To forget it!"
    "You see," he explained, I consider that a man's brain originally is like a little empty attic, and you have to stock it with such furniture as you choose. A fool takes in all the lumber of every sort that he comes across, so that the knowledge which might be useful to him gets crowded out, or at best is jumbled up with a lot of other things, so that he has a difficulty in laying his hands upon it. Now the skillful workman is very careful indeed as to what he takes into his brain-attic. He will have nothing but the tools which may help him in doing his work, but of these he has a large assortment, and all in the most perfect order. It is a mistake to think that that little room has elastic walls and can distend to any extent. Depend upon it there comes a time when for every addition of knowledge you forget something that you knew before. It is of the highest importance, therefore, not to have useless facts elbowing out the useful ones."
    "But the Solar System!" I protested.
    "What the deuce is it to me?" he interrupted impatiently: "you say that we go round the sun. If we went round the moon it would not make a pennyworth of difference to me or to my work."

1 comment:

J. M. Haddox-Schatz said...

I basically agree with the main point of this post. It is not realistic or possible to try to memorize every fact about whatever
language, tool, etc. one is using.




This reminds me of conversations I had with my professors at Allegheny College very early in my undergrad career: there is a reason that courses like 'C programming' or 'Java programming' were not taught at this school and still are not taught there. Instead our department (and most reputable CS departments, I imagine) believe it best to offer courses that teach basic principles, theories, etc. of computer science with the expectation that this would equip the students to be able to quickly learn new technologies, languages, etc. as they came along.




If I were hiring an entry level person, it might be in convenient in the short term to bring someone in who had just taken some sort of 'web application' course who had many details memorized about web services development, for example. But in the long term, I'd rather have someone who has demonstrated an ability to learn (even if they had never heard of web services). Technologies are transient; what is important is to know how to efficiently learn and know how to find the answers to what one does not yet know.