Sunday, November 30, 2008 

Notes on Software Design, Chapter 1: Partitioning

In a previous post, I discussed Alexander’s theory of Centers from a software design perspective. My (current) theory is that a Center is (in software) a locus of highly cohesive information.

It is worth noting that in order to create highly cohesive units, we must be able to separate things. This may seem odd at first, since cohesion (as a force) is about keeping things together, not apart, but is easily explained.
Without some way to partition knowledge, we would have to keep everything together. In the end, conceptual cohesion will be low, because a multitude of concepts, abstractions, etc., would all mash up into an incoherent mess.

Let’s focus on "executable knowledge", and therefore leave some artifacts (like requirement documents) away for a while. We can easily see that we have many ways to separate executable knowledge, and that those ways apply at different granularity levels.

- Hardware separation (as in distributed computing).
- Process separation (a lightweight form of distributed computing, with co-located processes).
- In-process component separation (e.g. DLLs).
- Interface – Implementation separation (e.g. interface inheritance in OO languages).
- In-component access protection, like public/private class members, or other visibility mechanism like modules in Modula 2.
- Function separation (simply different functions).

Knowledge is not necessarily encoded in code – it can be encoded in data too. We have several ways to partition data as well, and they apply to the entire hierarchy of storage.

- Mass storage separation (that is, using different databases).
- Different tables (or equivalent concept) within the same mass storage.
- Module or class static data (inaccessible outside the module).
- Data member (inaccessible outside the instance).
- Local / stack based variables (inaccessible outside the function).

It is interesting to see how poor data separation can harm code separation. Sharing tables works against hardware separation. Shared memory works against process separation. Global data with extern visibility works against module separation. Get/Set functions work against in-component access protection.
Code and data separation are not orthogonal concepts, and therefore they can interfere with each other.

There is more to say about separation and its relationship with old concepts like coupling (straight from the '70s). More on this another time; right now, I need to set things up for Chapter 2.

In the same post above, I mentioned the idea that centers have fractal nature, that is, they appear at different abstraction and granularity levels. If there are primordial forces in software, it seems reasonable that they follow the same fractal nature: in other words, they should apply at all abstraction levels, perhaps with a different slant.

The first force we have to deal with is Gravity. Gravity works against separation, and as such, is a force we cannot ignore. Gravity, as in physics, has to do with Mass, and another manifestation of Mass is Inertia. Gravity, like in the physical world, is a pervasive force, and therefore, separation always entails a cost. Surrending to gravity, however, won't make your software fly :-). I’ll talk about all this very soon.

On a more personal note, I haven’t said much about running lately. I didn’t give up; I just have nothing big to tell :-). Anyway: there is still a little snow around here, but I was beginning to feel like a couch potato today, so I geared up and went for a 10Km (slow :-) run. At Km 4 it started raining :-)), but not so much to require an about face. At Km 8 the rain stopped, and I ran my last 2 Km slightly faster. It feels so great to be alive :-).

Labels: , ,

Tuesday, November 25, 2008 

A Tale of Two Methods

Once again, I’ve been absent for quite a while. Lot of work to do, many things to ponder, and some fun too (far away from computers :-) all kept me busy. Still, I’m coming back with a few new insights, which I’d like to share over the next few weeks.

Some of you may remember when, in the late ‘90s, I proposed a transformational approach to object oriented design, which I called Systematic Object Oriented Design, or SysOOD. Most of my writings on the subject are now online, some in English, some in Italian.

The reasoning behind the method was quite simple: in many cases, it's rather easy to devise a working solution to any given problem. However, there is large gap between a working solution and an elegant solution. Elegance is an elusive concept, which is often mapped to a large set of nonfunctional attributes like separation of concerns, information hiding, reusability, scalability, and so on. Still, in practice, we can often go through a transformational process and turn our first-cut solution into a carefully crafted design.

Experienced designers apply those transformations on the fly, as part of their conversation with the material. My idea was to make those transformations explicit, to give them a name, a context and a purpose. I drew heavily from the design patterns movement: ideally, I thought, we should be able to generate patterns by transforming a trivial design. To some extent, I succeeded, as documented in some of my works.

I kept exploring. My ultimate goal is to understand “what we really do as we design”, which is quite ambitious. Hence my investigation of Schon, Alexander, the concept of form and force field, etc.

In the last month or so, I've found myself walking a familiar path, one that I already walked during the SysOOD days. Although I tend to design intuitively, borrowing on several years of experience, I started asking myself (again) the familiar question: how did this came to my mind? Is there a systematic process behind this reasoning? Can I make this reasoning explicit?

This time, however, my focus is different. I'm not looking for transformations anymore. I know I could do more on that side, but I also know the limits of a transformational approach. This time I'm against “primordial” forces, and hopefully against a way to describe and reason upon those forces.

It's a difficult endeavor, and the probability of failure is high. But it's also an excellent learning opportunity, and in a sense, an excellent teaching opportunity, as I'm sure I'll learn a few things worth teaching along the way.

I don't expect to discover anything revolutionary. It's about understanding what we do, not what we don't know how to do. But the same understanding, I believe, can help us when we don't know what to do. If anything comes out of it, it will be an explorative approach, a way to frame and understand our own ideas while we design.

What I've collected so far are a few ideas about partitioning and the fractal nature of software (as I hinted to in a previous post), and a few early attempts to visually model the force field. At some point, I'll probably use the Large Display problem to show how some of those concepts can point us toward a better solution.

More on this very soon, I hope :-)

Labels: ,