MOPED - a Message-Oriented Pattern for Elastic Design

pieterhpieterh wrote on 16 Jun 2011 15:45

sign_leftright2.png

People learning to build distributed systems with 0MQ for the first time (there's a protocol joke in there somewhere) can make some awful mistakes. One cannot just convert design approaches like "let's make a structure of classes" into "let's make a structure of tasks". So, here's a simple design pattern, that I call MOPED, for building distributed systems. Surprisingly, MOPED works, and is fun.

MOPED is perfectly suited for 0MQ. It emerged from my work on the Guide examples, and you can see a near-perfect case in the Majordomo pattern, which I developed over a few days following MOPED, but before I'd written it down, and given it a cute name.

Using MOPED, you should be able to take a rough use case for a distributed application and build a working prototype, in any programming language including C (but perhaps not C++, which lacks the elegant abstractions that C provides1), in under a week.

Step 1: internalize the semantics

You need to learn the semantics of 0MQ messaging patterns. There's no avoiding this. Read the Guide and man pages, write examples, trace them, measure them, throw them away, and repeat until the semantics click. You'll hear a noise. That'll be you going "ah, right…!"

Step 2: get a rough architecture

You want to draw your architecture as a bunch of boxes connected by lines. Use a whiteboard, since you'll do a lot of erasing and redrawing. Work with a few people, since your own view will often be inaccurate. What you want to aim for is the simplest, most symmetrical arrangement that does something useful without trying to cover the whole problem.

Step 3: define the contracts

There are several kinds of contracts you want to define:

  • APIs to external applications (written by your clients or suppliers). Assume the worst and make sure your APIs are as absolutely simple as it is possible to make them.
  • Protocol flows between your pieces. Design these as commands each doing one explicit action, each named clearly, and don't worry about the data they'll carry. The key part is the flow of commands, not their implementation.
  • Any measurable technical requirements in terms of throughput, latency, reliability, etc.

Step 4: write a test case

Yes, even before you have anything else working, write the simplest sane test case, using your (soon to exist) API.

Step 5: write the API

Write the API. At least a skeleton version that lets you build and run your test case, and watch it fail gloriously. You are now in the happy loop of test-driven development. Every single change you make from here on to the architecture and code is now proven by running the test case, watching it not work, making the change, watching it work.

Step 6: document minimal protocols

Write the protocols down, on a wiki or shared document, in such a way that every command is clearly explained without too much detail. Strip off any real functionality, because it'll create inertia that just makes it harder to move stuff around. You can always add weight. Don't spend effort defining formal message structures: pass the minimum around, in the simplest possible fashion.

Step 7: implement an end-to-end skeleton

Your goal is to get the simplest test case working, without any avoidable functionality. Everything you can chop off the list of things to do, you chop. Ignore the groans from your colleagues. You can always add functionality, that's relatively easy. But you have to keep the overall weight to a minimum.

Step 8: add one function at a time

Go through the whole cycle (extend the test case, fix the API, update the protocol, extend the code, as needed) for single testable individual pieces of functionality. It should take you about 10-30 minutes for each cycle, though now and then you'll get stuck chasing some bizarre problem.

Conclusion

MOPED lets you grow, more than build, a working 0MQ architecture from the ground up, with minimal risk of failure. By focussing on the contracts between pieces, rather than the implementation of individual pieces, you avoid the waste of premature optimization. By driving the design process through ultra-short test-based cycles, you can be pretty sure things work before you add more.

MOPED also scales to a larger team. Once you've worked together to define your protocols and APIs, break off and each grab part of the puzzle. You can work in any language that suits.

Comments

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License