One of the best ways to learn how a system works is by breaking it.
Fun To Fiddle
I've always liked to break things, even though I haven't always
been able to put them back together. When I was eight, I took apart
an 8mm film editor my parents owned and started fiddling about in it.
It was a great way to learn to unplug electrical devices before
touching certain exposed leads. I took apart Pachinko machines and
marveled at how intricate and synchronized a mechanical system could
be, but I also learned not to eat the pretty shiny balls. And I've started building plastic models with my son, which is kind of like breaking things in reverse, or at least you start to think so after several hours with an open glue bottle and little ventilation.
So I often take the same approach with software systems, especially
open source software where you can see all the moving levers and
gears. My current home project involves explorations into what will
eventually be Mailman 3.
Specifically, I've been yanking
Zope Page Templates out of Zope 3,
tying them into a Twisted
framework, and welding some Mailman data structures onto the
contraption. Even though ZPT is designed to be a separate thing from
Zope, it isn't very clear how a third party application would go
about using ZPT with its own application logic.
Since there's almost no internals documentation, and what reference
manuals exist are a bit spread out and incomplete, the
only way to learn the system was to find something that worked
and break it. By observing where it breaks, by deliberately monkey
wrenching key components, you start to get a sense of where its
boundaries are, and where you can put your hooks.
The (Real) Dark Side Of Dynamic Typing
I was reading a
recent blog by Bruce Eckel about the benefits of strong testing
over strong typing. Obviously, being a full-time Python programmer,
I'm a big fan of dynamic typing, and I have definitely been bitten by
the unit testing bug (more on that another time). But there's a dark
side to dynamic typing, which is that it can often be very difficult
to figure out exactly which code is getting executed just by
statically inspecting some random bit of source. With static typing,
you always know the type of the object, at least to some resolution.
But with dynamic typing, the object could be anything. So where do
you start the hunt for the code you're interested in?
The answer is to break it. With ZPT, I was struggling with how and
where macros get evaluated, and I simply could not find the code I
needed to read. But I had a working example in Zope 3, so I found
something that looked a lot like what I had written, and I jammed it
by shoving the pointy fork of a missing end tag into the page template.
Then I ran Zope and watched for the traceback. It actually took
a few pokes to cause it to crash, and I was sure glad that Zope wasn't
hooked up to 110 volts. But eventually, I wedged it and from the
resulting traceback, I found the code I needed to examine in detail.
This was just the clue I needed to get my own, external ZPT
application to work. And CVS makes it pretty easy to put the pieces
back together again afterward.
Python's pdb module and print statements are the indispensable tools of
the professional software monkey wrencher, at least in the Python
world. They may not be terribly high tech, but they can be pretty
effective when exploring. Oh yeah, be sure to open the windows and wear your safety goggles.
The subject line of this post made me think of a conversation I had with Jack Jansen and others at EuroPython about extracting private key data from smartcards by microwaving them :-)
I also agree that pdb and print statements are among the most useful tools in debugging, but am not happy about it. One of the problems Python's unittest module has is that it's far too much work to recreate in an interactive interpreter the state of a failing test. It should be possible to write a test rig that lets you start a pdb session at the point of failure of any test, and there's a good chance I'll end up writing one for PyPy fairly soon...