Think “ground” not “figure”

Last week, my friend Furqan and I had an insight: Many software developers build fragile systems, because they tend to focus on technical components rather than the functional interfaces between those technical components. For example, a developer may devote much of his/her time on the code for the billing adapater implementation, without spending adequate time to define/re-factor a robust billing interface.

Off the cuff, I sketched a simple whiteboard diagram: Two small boxes inside of a larger box.

My theory is that most people will gravitate towards seeing the two small boxes; in other words, they focus on the “figure” (in the artistic sense of “figure vs. ground”) However, the proper focus should be on the empty space (the “ground”) between the small boxes and the larger box. As humans, we’ve evolved to focus on concrete visual images which make up the “figure.” As long-term system-builders, we need to fight this “concrete thinking bias” and instead focus our minds-eye on the “ground” instead.

Agile software development requires continuous software refactoring. Functional interface design facilitates refactoring and help build robust systems. Unfortunately, clean functional interface design is often neglected in order to “just get the code working.” Treated as a luxury, it is eagerly sacrified at the altar of expediency.

Imagine my smug self-satisfaction — how fun to criticize others for the fundamental flaw in their conceptual thinking!

Funny how life finds a way to hold up a mirror to your face:

This morning, I reviewed the current high-level architectural diagram for Kinetic. I’m embarassed to admit that it also focuses too heavily on components, and not interfaces. The Parser/Interpreter reads data from an Intermediate Data Model. The Diagram Generator generates a PDF. Very concrete component definitions. Very fuzzy interface definitions. In a nutshell, poor design. It lacks the rigor of deliberate functional thinking.

Please excuse me while I wipe the egg off my face, thanks.

4 Comments »

  1. Zac Said,

    June 7, 2010 @ 7:29 pm

    Interesting point and I think a valid one. The more common problem in my opinion, though, is not a focus on one aspect of a design versus another (i.e. interfaces versus components) but the focus on design period–at least insofar as it being a discrete phase. In fact, what you’re saying is pretty concordant with the formal computer science education I received and the notion of waterfall design where the contracts between components have to be solid, wherease the implementation can be worked out later. I think this approach raises the notion of ‘design’ to too lofty a place in the software lifecycle, though. By that I mean, a focus on interfaces is important, and as you point out, probably one of the most important aspects of design. But I think it should emerge as the system takes shape. Get something working first, have good unit tests, then iterate on the interface and think about how it does or doesn’t make sense for the problems you’re actively trying to solve, not ones you may have one day, if so-and-so just happens to need to do X.

  2. Jim Tran Said,

    June 8, 2010 @ 4:15 am

    Zac, thanks for the incisive points.

    I agree design should be iterative as well, and should emerge alongside the code. As you point out, the appropriate interface definitions may only emerge after several sessions of indiscriminate code-bashing. For many projects, coding and design tasks are necessarily intertwined.

    The behavior I observe too often, however, is this: in the rush to deliver, the interface definitions becomes “frozen” too soon after the “get something working first” milestones are reached. As soon as the code works, it’s tempting for developers to move on, without taking the time to perform the requisite code refactoring needed to clean up the functional interfaces. Within a class, this means cleaning up method signatures, and tuning the public/private visibility of methods. Between sub-systems, the externally-visible API contracts need to be re-visited. This refactoring to clarify the functional interfaces isn’t particularly fun. Really, who enjoys paying off debt?

    The Kinetic architecture diagram evolved alongside several weeks of Ruby coding. I need to now practice what I preach, and spend some time to *really* think about the functional interfaces between the various Kinetic sub-systems. I’ll choose to pay those debts now.

    When it comes to clarifying functional interfaces, as John Wooden said, “If you don’t have time to do it right, when will you have time to do it over?”

  3. Josh Said,

    June 8, 2010 @ 8:30 pm

    I have a lot of //TODO’s in my code, I’m ashamed to say.

  4. Furqan Said,

    June 15, 2010 @ 12:45 am

    Hi Jim,

    Great “first” entry! Happy to have played a small role in your light bulb moment. When engineers focus on the interfaces also it almost forces them to gain an understanding of the bigger picture, to understand the functional or business purpose of the software they are developing. Better collaboration with team members AND improved customer interaction are byproducts of that mindset.

    Look forward to reading additional thoughts on this subject on your blog!

    Best,

    Furqan

Leave a Comment

Powered by WP Hashcash