Designing from the Inside Out, a paradigm I've always used but never seen documented, looks to drive out a design by first writing some of the code. This takes the principle of writing ScreechinglyObviousCode
one step further and grants the code itself first class citizenship. In following this technique you write the code the way you would like to see it, then look for the design that supports it.
For example, consider an application which polls devices for raw data which it then converts into higher level information using various algorithms (something I worked on a while ago). UserStories
, or UseCases
, coupled with analysis work means we have established that we will have (at least) two entries into our application:
Poller.poll(Device dev, Information inf)
Poller.dataReceived(Address addr, Collection<DeviceDatum> data)
(consider this, and the following, pseudo code rather than C++/Java - I'm a little muddled between the two languages right now)
That's sort of where the analysis phase leaves us. We have no further idea what the classes and methods will look like at this point and we accept, of course, that we may refactor later. For the next stage, however, we jump straight into code, looking to answer the question "ideally - what would these methods look like". Well, this would be my opinion (note I changed the signature to poll() as I thought about this while I was writing the code):
void poll(Device dev, InformationId infId, PollClient client)
throws DeviceIsDownException, DeviceDoesNotSupportInformationException
if ( ! dev.isUp() ) throw DeviceIsDownException;
if ( ! dev.supportsInfo(infId) ) throw DeviceDoesNotSupportInformationException;
if ( dev.infoCached(infId) )
client.inform( dev.info(infId) );
Collection<DeviceDatumRequests> dataWanted = dev.getDataRequestsForInformation(infId);
if ( dataWanted == NULL )
client.inform( dev.info(infId) );
deviceDriver.Request( dev, dataWanted );
(I won't do the other method - I'm sure you get the idea)
Now I know that there are all sorts of implicit design decisions in the way I've chosen to write this code segment. However, as well as documenting those decisions by writing the code, there is also a reverse consideration taking place looking to investigate what design would need to be in place to allow me to write this code. In other words, my desire to write ScreechinglyObviousCode
drives out the classes and methods which I will need to provide (and note that this isn't just names, it's structure as well). I would probably now investigate some of the methods of Device which have come out of this, and maybe go and code some of that class to see what else gets driven out.
Of course, it could be argued that what I'm doing is some sort of low level UseCases
which needn't be turned into code. But use cases at this level might just as well be expressed as code - and wouldn't it be more in keeping with XP to cut out any middle pseudo-code? I don't see the point of documenting the coding and design decisions made in this code segment in any other way but the code segment.
Does this break XPs CodeUnitTestFirst
? If you aren't going to bother with intermediate documentation then I guess so. However in order to write your UnitTest
s you must at least have decided that your method will:
- Check that a device is Up using an isUp() call and throw a DeviceIsDownException if not
- Check that a device supports the requested information using supportsInfo() and throw a DeviceDoesNotSupportInformationException if not
- and so on
- and that's pretty much what the code documents.
I suppose the XP approach would be to do this within a test case, not the code or anywhere else. The advantage of doing it in the code, though, is that you can give prime consideration to its elegance.
I have always believed that a mark of GoodDesign
was that it produced elegant code. If that is true, why not begin with the elegant code and find the good design that supports it.