You may have heard system architects talking about “data-centric design,” or you may have attended an RTI training class and heard one of us use that term. Is data-centricity just a new buzzword to make messaging seem cool again? No indeed!
Message-centric design and data-centric design are similar, but they also differ in important ways. Let’s start with some terminology. There’s a reason why DDS says “sample” where JMS says “message”: those words are intended to suggest a different mental model to you.
When you hear the word “sample,” imagine some data value (perhaps the temperature in a certain place) being published periodically. Those values describe a single logical data object — an “instance” in DDS terms — whose state changes over time. Or think of subsequent frames of a movie: the movie is a single logical object, and you view slices of it one after another. In other words, in a data-centric design, as the system’s state changes, it uses the middleware to publish that state directly.
Therefore, a data distribution middleware — such as RTI Data Distribution Service, which implements the DDS specification — needs to understand what that state is and under what circumstances it should be published. That’s why RTI Data Distribution Service allows you to describe your application’s own data types to the middleware (using XML, IDL, or a programmatic API): your application stores its state using those types, so the middleware needs to understand them in order to publish that state. That’s also why DDS-compliant middleware provides applications with such extensive control over which data should be published where and when, including filters on data contents and update rates, duration- and depth-based time-to-live rules, data reliability and availability contracts, deadline enforcement, and so on. A data-centric system uses its network middleware as a lightweight cache to manage its state, thereby replacing programmatic application logic with declarative descriptions of its delivery obligations and expectations.
In contrast, a messaging middleware provides no facilities for state maintenance or management. Instead, the system maintains that state externally to the middleware, and when it changes, it sends “messages” about those state changes. The recipient(s) of those messages then decide if and how to update their own state. Because only the application-level logic “above” the middleware has access to its state and knows when and how to update it, there’s no need for the middleware to understand the contents of messages. Messaging middleware implementations therefore typically don’t support content-aware message handling and provide more limited control over delivery contracts than do data distribution middleware implementations.
Of course, the lines between these communication paradigms are often blurred, and many complex systems will use both in different places. For example, you may use RTI Data Distribution Service to distribute your data, but use a relational database to maintain and manage that data, and then use a product like RTI Real-Time Connect to make sure changes that occur on one side are automatically propagated to the other. Or you may implement a data-centric system with RTI Data Distribution Service but view that data, in certain subsystems, through a message-centric API with RTI Message Service.
Just as you can write procedural code in C++ or Java by choosing not to use certain object-oriented features of those languages, you can implement a message-centric system using a data distribution middleware by simply choosing to limit the capabilities of that middleware that you leverage. And just as you can write object-oriented code in C if you put your mind to it, you can implement a data-centric system using a messaging middleware. But to get the most value from your middleware, and save yourself the most effort, consider which paradigm will serve you best most often, and pick the right tool for the job.