Times used to be when people who were really conscientious wrote Squeaky Clean Code. Others, watching them, thought they were wasting their time. I got a shock one day when I realized that Squeaky Clean Code isn't good enough.
I was standing behind two people who were working their way through a bug list sent up by the testing group. Instead of helping them work, I started watching their movements (this was Smalltalk, 1995, many browser windows on the screen). They would look through the method where the error had been caught, and guess at which called method contained the error. They called up the browser for a class, scanned the method list and opened a method. They looked at the method to see whether it was the place they were going to type in their fix. When it turned out not to be, they looked for what other method could be the one? They averaged 15-45 seconds per method as they went down through the code and across the methods in the browser list. At each point, they were looking for, is this the place I type my fix, or where does it point to next?
It occurred to me that where they went down a dead end was because the method's contents did not match its name. These people were basically looking for a sign in the browser that would say, "Type in here, buddy!"
That's when I recognized that they needed ScreechinglyObviousCode.
At the time, it was considered an OK thing to do to have an event method, doubleClicked or similar, and inside that method to do whatever needed to be done. That would be allowed under Squeaky Clean Code. However, in ScreechinglyObviousCode, it wouldn't, because the method doubleClicked only says that something was double clicked, and not what would happen. So let's say that it should refresh the pane or something. There should therefore be a method called refreshPane, and doubleClick would only contain the one line: self refreshPane.
The people fixing the bug knew there was a problem refreshing the pane, but had to dig to learn that refreshing the pane was being done inside doubleClick. It would have saved them much effort if the method refreshPane was clearly marked in the method list in the browser, so they could go straight there. I learned, from that afternoon, not to put behavior into an event-handling method, but for such a method to call out a behavior-containing method with the appropriate name. The reading of the code is then, simply: "When a doubleClicked event occurs, refresh the pane" rather than "When a doubleClicked event occurs, do all this stuff, which, by the way, if you read carefully, you will notice refreshes the pane."
At that point I started looking for ScreechinglyObviousCode (hint: be sure to use "IntentionRevealingNames"). XP, of course, encourages this. Personally, I think the StatePattern violates ScreechinglyObviousCode and makes for pretty obscure code, but I don't have the energy to revise it and publish... maybe someone else will take up the challenge. -- AlistairCockburn
This specific example (separating the action from the event that invokes it) has been one of my pet peeves for years. I personally like the Java approach of building classes that implement the Action interface, and then handling separately the means by which the Action is invoked. That way, a given Action can be started by a button, a menu item, pressing RET in a text field, a command line argument, a message from another subsystem altogether, etc.; ANY or ALL of those means, and you can even support changing or customizing the linkage/mapping in real time...
I don't approach it as ScreechinglyObviousCode so much as minimizing coupling by putting "pivot points" in the code, so that code that handles one aspect of the functionality doesn't directly invoke code that handles another aspect. I think of code that doesn't do this as "point-to-point" or "hardwired" code, with direct connections, which might seem to be simplest, but end up being very inflexible. In this sense, it ISN'T "screechingly obvious", at least not to the developer adding functionality in the first place.
Perhaps a key point is trying to keep in mind the sometimes very different points of view between someone implementing functionality in the first place, and someone modifying functionality later. What is "screechingly obvious" to one becomes obscure to the other, and vice versa. As one of my college instructors often said, "Code is usually written once, but read many times..."
Isn't that just OnceAndOnlyOnce? At first you directly couple things because you DoTheSimplestThingThatCouldPossiblyWork, and then when you want to have multiple ways of triggering the behaviour you ExtractMethod and call it from each triggering event...
Yes, if you're doing XP. I don't, and so I am "free" to ignore advice like DoTheSimplestThingThatCouldPossiblyWork and YouArentGoingToNeedIt, and go ahead and build in flexibility up front... (GASP!) Poor me, I miss out on another opportunity to Refactor! (grin)
The author above seems to be proposing LotsOfShortMethods or functions in order to use the function/method names as textual indexes to help find stuff. I am not sure I agree. Its harder to visually search 500 methods/functions than 100.
method event_doubleClick(e) { self refreshPane }Versus
method event_doubleClick(e) { refreshPane() } ... method refreshPane() { self refreshPane }The second just creates code and name-space bloat. If "refreshPane" is already an API method, why put a wrapper around it just to have something to search? One should use a code indexer to search for the refresh API name, not create methods just to have it in the name list.
Related: SeparateDomainFromPresentation
Alistair, I've noticed the same thing. A lot of contextual information needs to be saved or mentally reconstructed when you use StatePattern in anger. But, if you set up states using a code generator, or something like that, things can be screechingly obvious. Another case where I notice the screech as a whisper is in event driven systems. NamingNotifications hides intention. -- MichaelFeathers
On a cynical note, writing ScreechinglyObviousCode to solve a problem may lead people to believe that the problem was easy in the first place, and that you have not proved yourself as a RealProgrammer. The same thing applies to quietly releasing working apps as opposed to doing a heroic integration phase. -- AndyMorris
There must be an AntiPattern in there somewhere; I've experienced both instances of that myself.
PleaseShowMeAlargeWellFactoredProgram!!! (See that page for comments)
I was looking for this (rule? guideline?) today, so I could reference it in some training I am doing. It took me forever. Could we make a synonym named something like "FunctionNamesShouldSayWhatTheyDoNotWhatTriggeredThem?" and yes, that is obscenely long, but you get the idea.
See IdentifiersRevealIntent and the related/redundant pages it links to. Also look at BackLinks for those various pages. Also CodeSmell and VagueIdentifier
Please allow me to steer you to a page where I have argued that ScreechinglyObviousCode can be used as a driver for low level design. I've documented this approach in DesignFromTheInsideOut. -- RichardDevelyn