I like Steve McConnell's idea in Code Complete of layout where he uses
abstract pieces of code without text.
I 100% agree with you that this is important, though I didn't recall it
being in Steve McConnell's books. I thought about this to some depth
before I wrote the article you're replying to. I almost mentioned it
there, but I ended up not addressing it... mostly because I didn't trust
myself to properly explain the idea before going on to explain that I
don't think it applies.
Now here's why I don't think it applies: it all eventually comes down to
something I've talked about in this newsgroup before, generally without
making much of an impression: a gap where abstraction and encapsulation
[for lack of a better word, but not the practical OO kind of
encapsulation] don't quite line up, and the developer wants
encapsulation without the abstraction. Some people just get up on a
soapbox and proclaim that these situations don't exist; I think those
people are fooling themselves.
This is going to get somewhat difficult to explain, so please bear with
me. First some definitions: By encapsulation, I don't mean hiding from
a language perspective. I just mean a general quality of bundling
things together and dealing with them as a group. It's actually closely
related to my discussion of idiomatic reading above: something that's
encapsulated in this sense is easy to label and put out of mind.
Abstraction is something more than that; it requires encapsulation, but
it isn't implied by encapsulation. Abstraction is the quality by which
higher meaning an be assigned to the whole than to the sum of the parts.
It's basically indicated by the ability to give the whole a name that's
more expressive than the code that implements it.
Now abstraction indicates a need to refactor something into a named
method or even class. Mere encapsulation would be very awkward to
refactor, and requires just shoving it out of consciousness as much as
possible so that the main point of a piece of code can be understood,
because the code is still the clearest representation of what's
happening. Refactoring into another method would require that you try
to pick an identifier which does as good a job as possible of expressing
what's in the code, but can never be as good as the code itself. (If you
can pick an identifier that's better than the code, then you should go
for it, and the result will be abstraction rather than just
encapsulation, and you'll have done well to refactor it.)
As an interjection here, this is not all academic. I worked for most of
this past year with a developer who didn't get this, and tried her
hardest to generate identifier names for extracted methods that never
quite lived up to the idea of abstractions. I still have to
occasionally change part of that code and encounter methods named
insanely long things, involving lots of 'and' and 'if' and 'while' in
the identifier, than still never quite accomplish explaining what the
code does well enough that I avoid the need to go read the method
anyway.
Now, here's my contention: I don't think it's any worse to "hide" an if
statement to reduce the impact in a piece of code than to "hide" an if
statement in a call to a refactored method. If no loops or conditions
were ever hidden, then all control flow keywords would occur in main!
Obviously, you'd be in favor of hiding them in extracted methods and
classes, but for some reason de-emphasizing them in included code
doesn't sit right with you.