You are viewing an old revision of this post, from April 21, 2007 @ 22:09:35. See below for differences between this version and the current revision.
Ever since I read Refactoring to Patterns, I’ve been thinking that I should use Compose Method more. (I should really reread Smalltalk Best Practice Patterns to see what other low-level patterns I’ve missed.) But I’m too timid to perform quite that drastic surgery to the thicket of code that I’m working on.
I just finished Extreme Programming Installed, though, and the authors talk about an interesting way to develop your code so that the methods are nicely composed. It’s called “programming by intention”, and works as follows: whenever you sit down to implement a method, you simply write down a method call explaining what you want the method to do first, another one explaining what you want it to do second, etc., without worrying yet about whether there are, in fact, methods with those names. If there aren’t, you then go and implement those methods. (Again programming by intention, though it should stop after two or three levels.)
I tried this yesterday, and it was great! I wanted to write a method that parsed a series of data structures; I had some ideas about how the low-level details would work, but I decided to just put those out of my mind and program by intention. We were parsing a sequence of data structures for as long as data remained, and the conditions for when data remains were slightly nontrivial in this context, so I started by typing (more or less, details are changed):
  while ( dataRemains() ) {
Each data structure starts with a type field, and a length field, both expressed as a multibyte value that I hadn’t yet had to parse. So:
    int type = nextMultibyteValue();
    int length = nextMultibyteValue();
Next, we start printing out the data. We’d like to output a string representation of the type codes, so:
    printTypeCode( length );
After this, we needed to output the data as a sequence of bytes, with its length given by the number we just read; I already had code to do that, so I just called that code:
    printNextBytes( length );
  }
Once I’d done that, I implemented dataRemains
, nextMultibyteValue
, and printTypeCode
; each of them was easy to implement now that I wasn’t thinking about anything else. (And I knew I wasn’t wasting my time because I’d already shown that, once those were implemented, I’d have exactly the functionality I needed.) And the resulting methods looked great (though Compose Method suggests that I should have gone further and extracted the entire body of the loop into a method, which probably wouldn’t have been a bad idea).
This dovetails very well with test-driven development. One important benefit of TDD is that it focuses your mind on doing one thing at a time: either you’re focused on writing a test to express your next goal, or you’re focused on getting the test to pass, or you’re focused on cleaning up your code. Programming by intention, in turn, helps narrow your focus during the second of those steps: while you’re getting the test to pass, concentrate on what you want your implementation to do on a conceptual level, then drill down and repeat.
Side note: in a recent post on the XP mailing list, Kent Beck talks about how top down / bottom up isn’t a very useful dichotomy for him. Which I agree with to some extent, but programming by intention suggests that a particular form of top down programming is very useful when programming on a small scale. I’ll have to think about the extent to which this is the case at other levels of XP: is top-down the way to go when you’re trying to get an acceptance test to pass, for example? (Probably on the design level, but not on the implementation level, because you’d go far too long without working code.)
Post Revisions:
- October 31, 2011 @ 21:39:30 [Current Revision] by David Carlton
- April 21, 2007 @ 22:09:35 by David Carlton
Changes:
April 21, 2007 @ 22:09:35 | Current Revision | ||
---|---|---|---|
Content | |||
Unchanged: Ever since I read <em>Refactoring to Patterns</em>, I've been thinking that I should use <a href="http:// www.industriallogic.com/xp/ refactoring/composeMethod.html">Compose Method</a> more. (I should really reread <em>Smalltalk Best Practice Patterns</em> to see what other low-level patterns I've missed.) But I'm too timid to perform quite that drastic surgery to the thicket of code that I'm working on. | Unchanged: Ever since I read <em>Refactoring to Patterns</em>, I've been thinking that I should use <a href="http:// www.industriallogic.com/xp/ refactoring/composeMethod.html">Compose Method</a> more. (I should really reread <em>Smalltalk Best Practice Patterns</em> to see what other low-level patterns I've missed.) But I'm too timid to perform quite that drastic surgery to the thicket of code that I'm working on. | ||
Unchanged: I just finished <em>Extreme Programming Installed</em>, though, and the authors talk about an interesting way to develop your code so that the methods are nicely composed. It's called "programming by intention", and works as follows: whenever you sit down to implement a method, you simply write down a method call explaining what you want the method to do first, another one explaining what you want it to do second, etc., without worrying yet about whether there are, in fact, methods with those names. If there aren't, you then go and implement those methods. (Again programming by intention, though it should stop after two or three levels.) | Unchanged: I just finished <em>Extreme Programming Installed</em>, though, and the authors talk about an interesting way to develop your code so that the methods are nicely composed. It's called "programming by intention", and works as follows: whenever you sit down to implement a method, you simply write down a method call explaining what you want the method to do first, another one explaining what you want it to do second, etc., without worrying yet about whether there are, in fact, methods with those names. If there aren't, you then go and implement those methods. (Again programming by intention, though it should stop after two or three levels.) | ||
Unchanged: I tried this yesterday, and it was great! I wanted to write a method that parsed a series of data structures; I had some ideas about how the low-level details would work, but I decided to just put those out of my mind and program by intention. We were parsing a sequence of data structures for as long as data remained, and the conditions for when data remains were slightly nontrivial in this context, so I started by typing (more or less, details are changed): | Unchanged: I tried this yesterday, and it was great! I wanted to write a method that parsed a series of data structures; I had some ideas about how the low-level details would work, but I decided to just put those out of my mind and program by intention. We were parsing a sequence of data structures for as long as data remained, and the conditions for when data remains were slightly nontrivial in this context, so I started by typing (more or less, details are changed): | ||
Deleted: <code> | Added: <code> while ( dataRemains() ) {</code> | ||
Unchanged: Each data structure starts with a type field, and a length field, both expressed as a multibyte value that I hadn't yet had to parse. So: | Unchanged: Each data structure starts with a type field, and a length field, both expressed as a multibyte value that I hadn't yet had to parse. So: | ||
Deleted: <code> | Added: <code> int type = nextMultibyteValue();<br /> | ||
Deleted: | Added: int length = nextMultibyteValue();</code> | ||
Unchanged: Next, we start printing out the data. We'd like to output a string representation of the type codes, so: | Unchanged: Next, we start printing out the data. We'd like to output a string representation of the type codes, so: | ||
Deleted: <code> | Added: <code> printTypeCode( length );</code> | ||
Unchanged: After this, we needed to output the data as a sequence of bytes, with its length given by the number we just read; I already had code to do that, so I just called that code: | Unchanged: After this, we needed to output the data as a sequence of bytes, with its length given by the number we just read; I already had code to do that, so I just called that code: | ||
Deleted: <code> | Added: <code> printNextBytes( length );<br /> | ||
Deleted: Â Â }</code> | |||
Added: }</code> | |||
Unchanged: Once I'd done that, I implemented <code>dataRemains</code>, <code>nextMultibyteValue</code>, and <code>printTypeCode</code>; each of them was easy to implement now that I wasn't thinking about anything else. (And I knew I wasn't wasting my time because I'd already shown that, once those were implemented, I'd have exactly the functionality I needed.) And the resulting methods looked great (though Compose Method suggests that I should have gone further and extracted the entire body of the loop into a method, which probably wouldn't have been a bad idea). | Unchanged: Once I'd done that, I implemented <code>dataRemains</code>, <code>nextMultibyteValue</code>, and <code>printTypeCode</code>; each of them was easy to implement now that I wasn't thinking about anything else. (And I knew I wasn't wasting my time because I'd already shown that, once those were implemented, I'd have exactly the functionality I needed.) And the resulting methods looked great (though Compose Method suggests that I should have gone further and extracted the entire body of the loop into a method, which probably wouldn't have been a bad idea). | ||
Unchanged: This dovetails very well with test-driven development. One important benefit of TDD is that it focuses your mind on doing one thing at a time: either you're focused on writing a test to express your next goal, or you're focused on getting the test to pass, or you're focused on cleaning up your code. Programming by intention, in turn, helps narrow your focus during the second of those steps: while you're getting the test to pass, concentrate on what you want your implementation to do on a conceptual level, then drill down and repeat. | Unchanged: This dovetails very well with test-driven development. One important benefit of TDD is that it focuses your mind on doing one thing at a time: either you're focused on writing a test to express your next goal, or you're focused on getting the test to pass, or you're focused on cleaning up your code. Programming by intention, in turn, helps narrow your focus during the second of those steps: while you're getting the test to pass, concentrate on what you want your implementation to do on a conceptual level, then drill down and repeat. | ||
Unchanged: Side note: in a <a href="http:// groups.yahoo.com/ group/extremeprogramming/ message/108693">recent post</a> on the XP mailing list, Kent Beck talks about how top down / bottom up isn't a very useful dichotomy for him. Which I agree with to some extent, but programming by intention suggests that a particular form of top down programming is very useful when programming on a small scale. I'll have to think about the extent to which this is the case at other levels of XP: is top-down the way to go when you're trying to get an acceptance test to pass, for example? (Probably on the design level, but not on the implementation level, because you'd go far too long without working code.) | Unchanged: Side note: in a <a href="http:// groups.yahoo.com/ group/extremeprogramming/ message/108693">recent post</a> on the XP mailing list, Kent Beck talks about how top down / bottom up isn't a very useful dichotomy for him. Which I agree with to some extent, but programming by intention suggests that a particular form of top down programming is very useful when programming on a small scale. I'll have to think about the extent to which this is the case at other levels of XP: is top-down the way to go when you're trying to get an acceptance test to pass, for example? (Probably on the design level, but not on the implementation level, because you'd go far too long without working code.) |
Note: Spaces may be added to comparison text to allow better line wrapping.