Disclaimer and License

Opinions expressed here by Tim Tripcony are his own and not representative of his employer.

Creative Commons License
Tip of the Iceberg is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at timtripcony.com.

Unless otherwise explicitly specified, all code samples and downloads are copyright Tim Tripcony and licensed under Apache License 2.0.

Search

What the Quote?

"Nothing in life is free... except for my fist in your face."

Laura Hearron

"I recommended Jelly Bellies, but someone was concerned they might melt under the lights."

Nathan T Freeman

"In the year 7000, August 1st will be on a Wednesday."

Brent Bowers

« will Ajaxian notice XPages? | Main| 2008 - a retrospective »

decomposition and top down design

Category principles
Given the response to Sunday night's post about SEE, I wanted to update you all on the lecture I watched last night.

The third lecture in "Programming Methodology" did not introduce any new language constructs, but focused instead on the value of including useful (not necessarily verbose) comments in code and the process of decomposition. The latter is just a fancy term for breaking larger programmatic tasks into smaller functions, but the professor gave an excellent explanation of why that's preferable to the alternative: for most of us Notes geeks, an example of that alternative would be 900 lines of LotusScript crammed into an Initialize, QuerySave, or Click Sub instead of breaking everything down into 5 - 10 line functions (preferably as members of objects). What was refreshing for me about the lecture was, after a decade of hearing "900-liners" explain that approach as being "just easier", I got to witness a professor demonstrate very effectively to a few hundred of the programmers of tomorrow that, well... no. It's not easier. To paraphrase the instructor, here's why:

If someone tells me they want to meet me at Shane's Rib Shack for lunch, I know how to do that: I get in my car, I drive there, I get out of the car, and I walk into the restaurant. If I want a robot to go get the food for me instead, that's more difficult: at best, the robot will initially understand only a few commands. So I map out the route, and determine exactly what commands to issue:

public class Lackey extends Karel {
// Karel is our robot, so any class that extends him inherits his API

public void run () {
move();
move();
move();
turnLeft();
move();
move();
move();
move();
turnLeft();
turnLeft();
turnLeft(); // I wanted him to turn right, but he only understands how to turn left
move();
...
// he has my food, so now turn him around to bring it to me
turnLeft();
turnLeft();
move();
...

Obnoxious, no? The above commands are considered "primitives": they're already defined, so we can use them without first defining them. This is an example of "bottom up design": I determined the entirety of what needed to be accomplished, and simply wrote it. But we've all known (and, from time to time, been) someone who needs everything explained to them over and over again, no matter how many times we told them. That tends to get a little... frustrating. Wouldn't it be great if our programs didn't require the same process? If we could, for example, teach a robot new tricks? And once we'd defined a trick, just issue the instruction without having to explain it again? Hooray, we can.

private void turnAround() {
turnLeft();
turnLeft();
}

private void turnRight() {
// we don't even need to call turnLeft twice, 'cause now we have a method just for that
turnAround();
turnLeft();
}

private void move(int distance) {
for (int i = 0; i < distance; i++) {
move();
}
}

That last one may be a bit confusing if you're unaccustomed to Java. In LotusScript, we can only define a function once within the same container - a class hierarchy if it's an object member, library hierarchy if it's a "top-level function" - granted, we can override the function body in a descendant class (i.e. Widget has a doStuff method, Sprocket inherits from Widget and its doStuff method does stuff that Widget.doStuff does not), but we can't overload them: the method signature must match... we can't have a function with no parameters in a parent class and then define the same method in a descendant and suddenly add a parameter. So, at best, we could settle for functions with silly names like moveTwice, moveThrice, and so on.

In Java, on the other hand, we can overload methods even within the same class. So in the above example, I know that Karel understands move(), but I can overload that method, adding a distance parameter. Hence, if I tell him to move and tell him how far, he just does what he already knows how to do as many times as I told him to do it. If I omit the distance parameter, he just does it once.

Top down design, then, is writing each function to do only one thing, calling just a few methods... which almost always won't exist yet. Then we simply define each nonexistent method we called using the same process until the whole thing will compile. Decomposition means that we're breaking the tasks out so that each function's "only thing" to do gets decreasingly complex:

public void getMeASandwich() {
// none of these methods exist yet, but they will
goToRestaurant();
orderSandwich();
takeSandwich();
pay();
comeBack();
// Weird... that code almost reads like... English. Hm. Might come in handy someday...
}

The goToRestaurant method will actually be a rather complex task: crossing streets, dodging cars and wildlife, and so on. The good news is that, as long as each portion of that task is similarly decomposed (i.e. broken down into smaller methods that do each sub-task well), by the time you're ready to write the comeBack method, nearly all of it is already written: you're just calling the same functions in ways that allow him to traverse in the opposite direction. That is why it's easier. You're spending less time, less apt to forget some crucial step, and - most importantly of all - you (and those who inherit your code) can actually support the code. So, yeah. Let's do that.

Comments

Gravatar Image1 - Hopefully we will get a LS-Editor, with Quick Fix: in eclipse you can programm top down: just write your code, get an error about a non-existing function and press strg+1 and select to add a method stub.

Oh man, I'm missing the eclipse java editor in Notes Designer: quick fix, code completition, refactoring support, ...

Gravatar Image2 - Excellent introduction to this practice bro!

You can immediately see that all of the product-specific development we do is nothing but this very thing.

For a simplified example, consider that @Command([CreateDocument]) fires in Lotus Notes, is interpreted by the Formula engine, and performs various pre-defined actions. It could be called @Command([getMeASandwich]) for all it cares - as long as it knows what you mean, you're set.

Same thing with any pre-defined API, same thing with XPages (which is designed to accept various markup types and evaluate based on the theme and build kit, same thing if we sat down and wrote our own custom language.

The primitives are excellent lego building blocks to allow you to create some full-functional... stuff. "Stuff", because it's not simply limited to a function, or an application, or a data processing engine, or a suite of applications, or a new custom language alone - but literally anything once you can see past the visuals and look at the elemental code. Remember: there is no spoon!

Brilliant stuff, and hopefully people are listening and learning...


Gravatar Image3 - And I brought my lunch today, but a Big Dad sounds good! Emoticon

Could you program it to get to Shane's from here?

turnleft
go3/4counterclockwise
move
go1/2counterclockwise
move
go1/2counterclockwise
move
turnright
turnleft
turnright

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)