The Architect´s Napkin

Software Architecture on the Back of a Napkin
posts - 69 , comments - 229 , trackbacks - 0

My Links

News

Article Categories

Archives

Software cells as asynchronous islands of code

During the first phase of architecting a software you try to break up the "application blob" in OS processes. They are the corner stones of any application. You can view them as large software components: usually they are binary, they are defined by explicit or visual contracts, they are units of deployment and maybe even re-use.

image 

Because identifying the OS processes in your application is so important, I might have emphazised the notion of a software cell being an OS process a bit too much. You might have gotten the impression, software cells in the end are nothing but OS processes. But that´s not what I mean. Really. It´s just that software cells are most often used to depict an OS process.

So let me try a more formal definition of what I think a software cell is:

A software cell is a unit of code - logically or physicall - which operates asynchronously with regard to other units of code.

This clearly is true for an OS process. It runs on its own thread or even its own machine. And so it is also true for an aggregation of processes, e.g. a whole application or a service. They run on one or more threads dedicated to them.

However, I see a process as a physically separate unit of code, whereas a whole application is more like a logical unit of code, since it´s not one "thing" you can put your finger on. Instead it´s distributed across several physical "things" (OS processes, machines etc.). But you can draw a circle around several processes thereby aggregating several units of code into a higher level unit of code and call them an application.

image

But what about smaller units of code, smaller than an OS process? They can be software cells, too. A single OS process software cell can contain/host/consist of several in-process software cells. I call them active components or worker components or async components. (More of components in future postings.)

The software cell hierarchy thus extends from the very large to the pretty small, from cross-process to in-process.

image

Now, although a service is different from an active component which in turn is not the same as an OS process, they all share one characteristic: the run in parallel with other software cells on the same level. That´s what I find important to express across all levels of abstraction.

Why is that important? Because communication between parallel units of code is so different from synchronous units of code. Synchronous sequential processing within a software cell uses the stack and therefore is secure, fast, reliable etc. Asynchronous units of code on the other hand cannot communicate via a stack. They need some other means which always is an indirection of some kind. That makes async communication much slower than sync communication (up 3 orders of magnitude and more). And often it also makes communication less reliable and less secure etc. With async communication the "Fallacies of Distributed Computing" kick in. It´s because of them that I find it so important to be so conscious about where async units of code are in an architecture. That´s why I devote a whole concept with its own visual notation to this. Software cells are supposed to protect your thinking from slipping into one or more of the fallacies.

Software cells run on their own threads. Software cells thus need to communicate with their environment through some medium. This can be an in-proc queue, or some other form of shared memory, or a database, or a TCP connection, or the Windows message pump. You name it.

image

Whenever you see a relationship between two software cells you immediately know it´s a simplyfication. In reality any communication between the software cells is not direct, but mediated. So medium or even infrastructure necessarily sits between them. Like a stack between two synchronous methods, but much slower.

This has some implications. Whenever you draw a software cell you need to ask yourself a couple of questions. Here are some that come to my mind right away:

  • How is the software cell started and stopped?
  • Can the software cell be paused or interrupted?
  • How are processing failures reported to the environment of the software cell?
  • How should data be passed into and out of the software cell?
  • How is shared data protected from inconsistencies through concurrent access by several software cells?
  • How can I be informed of certain states during a process executed by a software cell?
  • How can I know if a software cell is still alive and progressing?
  • How fast, reliable, secure etc. is a software cell and a connection to it?
  • Does it matter to a client of a software cell, where and if the software cell is running?

Some of these questions relate directly to the above fallacies. But there are more that need to be answered. Especially you need to ponder how the communication between a software cell and its environment should take place.

For in-process software cells (active components) you might just use a Queue<T> - with some synchronization code added. For two OS process software cells, though, you´d need to switch to TCP sockets or MSMQ or WCF. Or you use the file system as a medium: one software cell could create and write a file, the other could react on that and read the file.

And there´s one more twist to active components: they are running inside an OS process and so you should decide if they should be hosted inside a special AppDomain. It´s like deciding whether two OS process software cells should run on the same machine or not.

image

As you can see, co-locating or not is an issue you have to decide on, too, at every level of abstraction in your architecture.

Think of software cells as islands with their own population. The people living on an island happly work on some tasks - at their own speed.

image

You can communicate with them, e.g. by sending a message in a bottle or calling them via sattelite or dropping something from a plane. The islands can be located close to each other in the same sea or exist far apart in different oceans. Most importantly they all work pretty autonomously on their own threads.

image

What´s the benefit of all this?

  1. Thinking in terms of async units of code on several levels of abstraction makes you very conscious with regard to the costs and means of distribution.
  2. As long as you model your applications with software cells you keep it flexible with regard to the topology. Software cells can be moved around between processes and machines etc. comparatively easily. This is due to the explicit medium always used to communicate between them. It naturally decouples them.
  3. Since software cells are basically distributable units of code (remember: always indirect communication through some medium), you get a head start in terms of scalability. A software cell can be "multiplied" pretty easily to compensate higher load. Asynchronous processing is main road to scalability, not faster processors. Software cells make scale-out easier.

Print | posted on Sunday, June 22, 2008 3:47 PM |

Feedback

Gravatar

# re: Software cells as asynchronous islands of code

Hi Ralf,

I'm following your writings about software cells for a while now and I like it as a fresh new approach of thinking about structuring a code base. As you state it in one of your posts:

"Software cells - to me - are the structural elements for modeling an application in the large."

What I don't understand fully is why you are (all of a sudden?) putting such a big emphasis on running software cells asynchronously? I think software cells are a nice metaphor even in a single-threaded scenario, lets say within a single component. As an extension to the original concept it is valuable to talk about the importance of asynchronous communication, but not as the "one-and-only", just as an option.

I feel myself restricted not being able to use your concept even if it seems appropriate. Asynchronous communication brings a new dimension of complexity to my solution thats not always necessary. "KISS - Keep it simple and stupid" is the architectural idea I'd follow here as well.

Even if you would hardly ever extend your software cell visualization to become a UML-like modeling language it might be a good idea expressing the actual type of communication between software cells with different border styles. Like biological cells have different plasma membranes. And according to the wikipedia definition a "plasma membrane separates the interior of the cell from its environment and serves as a filter and communications beacon." Fits nicely into the overall metaphor, doesn't it?

Best regards,

Björn
7/11/2008 8:52 AM | Björn Waide
Gravatar

# re: Software cells as asynchronous islands of code

@Björn: Software cells and asynchronicity are not the "one and only" concepts I´ll be talking about in this blog.

But software cells and async "islands of code" to me are the first concern, when I think about software architecture. Nothing more, nothing less.

Why am I emphasizing async programming "all of a sudden"? Because I´ve come to the conclusion that 1. we need to starting thinking about how to exploit multicore processors now!, and 2. that current thinking is along synchronous lines in most software developers heads.

It´s like the difference between "glas half empty" and "glas half full". We need to switch from "try to make most code synchronous" to "try to make most code asynchronous". We need to switch gears and get into the habbit of first seeing the async "islands of code" in our software. And only after that we continue with sync code.

But please bear in mind: I´m talking on the level of large or medium chunks of code. I´m not talking about classes here! I´m talking about components, i.e. binary units of code. But more of that later in this blog.

On KISS: Simplicity by itself does not make sense. Simplicity is a means and always related to something else. Eg. make code simple with regard to such and such functionality. Or make code simple with regard to such and such performance or scalability.

Functional and non-functional requirements are first. And I´m saying: put scalability higher up on the list. And then, once you target certain scalability, make your design simple.

Since scalability needs asynchronicity I´m striving for simple scalable and async code. How that´s gonna look is another question. But with regard to scalability even async code can be simple.

You´re saying: "Asynchronous communication brings a new dimension of complexity to my solution thats not always necessary." Well, that´s true. But I´m not saying you need to make everything async. Just allow the thought that more, much more than you dared to think until now should become asycn.

I admit, however, that might entail a couple of new technologies. Well, why not. They are here already or are in the making. Stay tuned!

-Ralf
7/11/2008 4:17 PM | Ralf
Gravatar

# re: Software cells as asynchronous islands of code

Hi Ralf,

thanks for your answers. Let me explain the point I was trying to make once again:
The metaphor you found with the notion of Software Cells makes a great job on almost every level of detail, from the 10.000 feet perspective (system level) down to class level, even method level. Thats what I understood from your first posts on this topic and I think its true. Combining this general purpose metaphor with the concept of async programming is fine as long as its only an extension of the model. But as you said in your post you understand every Software Cell as a unit of code that runs asynchronously per se. And I don't see why that should be the case except you as the inventor of the metaphor want to (mis)use it to make your point on a totally separate subject. All I wanted to say is: I share your enthusiasm for both topics, but I'd prefer not mixing them when it's not necessary.

About KISS: When thinking about KISS I always think about another nice acronym as well, YAGNI (You ain't gonna need it). Don't implement anything "just in case", instead design your system to be easily modified later, when the feature became an actual requirement. Thats true also for non-functional requirements like scaleability. Regarding server side programming I'd even say you shouldn't really care about it, as this part moved up to the level of application servers. Try to keep your application stateless and you'll get scaleability almost out of the box.
What you described sounds like unmotivated pre-optimization which is one of the deadly sins of programming! ;-)

On the client this is a totally different issue. I'm developing a rich client for almost 3 years now and I can tell you how much trouble we had just because of making things running in the background. I'd be glad to see better tools and framework support in the future. So: Let us now, if you have something to share! :-)
7/14/2008 10:41 AM | Björn Waide
Gravatar

# re: Software cells as asynchronous islands of code

@Björn: Let me put it bluntly: Yes, you´re right, as the inventor of software cells I define them as asynchronous units of code to be used on different levels of abstraction.

But why do you find that so horrible? I´m not (!) saying you should model everything using software cells! I´m just suggesting to switch your view from "sync first" to "async first". Why´s that so difficut? Why does that seem to violate KISS of YAGNI more than "sync first"?

Synchronous programming is just so ingrained in our brains because we program in C# or C++. Had we been raised with Erlang we´d view the world differently. Had we been raised in a world of easy parallelism and multicore processors, we´d think differently.

I´m not (!) saying you should strive for making everything asynchronous. But I´m sure many more programs can benefit from asynchronousity than you might think.

KISS and YAGNI are good - but don´t follow them slavishly! Or the other way round: As I wrote before, what "simplicity" means is dependent on a context. Likewise what YAGNI means depends on your knowledge about the problem/solution domain. It´s not wrong to try to forsee growth in application usage. Refactoring is always necessary - but refactoring is a means to an end and not a goal. So if I can build scalability in without much effort, why shouldn´t I do it?

And be sure, I´m not (!) talking about optimization. I´m talking about ease of thinking.

However, I realize Conway´s Law is hampering the adoption of more autonomy and parallelism. As long as software development organizations are organized in a way that limits parallel accomplishment of tasks, as long as co-location of developers (and thus strong coupling and interruptions) is a must have, well, these organizations will have a hard time to build software consisting of autonomous and parallel and loosely coupled units of code. But I guess I should elaborate on this thought a bit more in a posting of its own.

Cheers!

Ralf

7/15/2008 1:05 AM | Ralf Westphal
Gravatar

# re: Software cells as asynchronous islands of code

I like the article and really impressed by it. Tnx author!
Want to share one more interesting article with you. Have a look here http://techzone.enterra-inc.com/architecture/algorythm-of-defining-plain-polygon-signature-point/
4/28/2009 7:09 AM | Mary
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: