Application Design Theory | John's Ponderings

Application Design Theory

March 17th, 2007 | jchaager | programming

I’ve been working through some client application architecture issues in a project I’m working on.

Originally, I had decided to make use of an Interface Driven Design. This led me to define a number of interfaces along with their associated implementations. Then I used Spring to wire all these components together. This worked fairly well for my first version, but as I moved forward, issues with this approach started to appear.

Almost immediately, I started seeing some problems with it. It was becoming increasingly difficult to track down bugs in the software. Functionality was starting to get spread across multiple components. We had multiple threads trying to update the internal application model. And testing was becoming extremely difficult because of the number of objects that had to be mocked up to test the application.

Reviewing the code after some time away, a new approach started bubbling around in the back of my mind. I’ve been programming in Cocoa off and on for the last 5 years. Cocoa applications are, by default, single thread. There is a single main thread that executes the main run loop and everything in the system is posted onto the run loop and executed by the main thread. This simplifies the programming paradigm because the entire application is single threaded. This means that there is no need for synchronization between threads, and the order in which things happen is much more deterministic.

So, I decided to re-architect the project to improve the extensibility and debuggability of the code. What I’ve settled on is a system based on the ideas of Cocoa. It has three core components: the Event Queue, the Model, and the Notification Center

The Event Queue is a central dispatcher of events that need to be processed. It will probably use the AWT Event Queue. Events are placed onto the event queue by the UI and by components that need to perform some action at a later time. One of the goals of the re-architecture is to make the application more predictable and simpler. Thus, the Event Queue will be used to insure that all updates to the Model occur when no one is trying to read from it. This will be handled by policy, and possibly by explicitly in the code. If a component is responding to a Notification, it cannot directly modify the model while handling the notification. Instead, it should post an event into the event queue that will cause a method on the component to be called later that will then make the required update to the model. In this way, we insure that all subsequent handlers of a particular notification will see the model exactly that same way that the initial components saw it.

The Model has been changed from an object that has embedded asynchronous notifications into an object that simply contains the state of the application. It is an object relation based model that has classes defined for each of the major elements of the model. Each of these elements can have relationships to other elements as necessary to define the application model. The Model class itself consists of accessors for retrieving the Model objects based on their IDs or other identifying attributes (such as name), or as a collection of objects that match a criteria (such as status). By implementing the model in this fashion, I can persist the model to disk using a standard object-relation mapping tool such as Hibernate without needing to expose the Hibernate interface to the other components of my application.

The notification aspect has been extracted into a Notification Center class. Instead of the 12 existing notifications posted by the Model detailing creation, updates, and deletions of items in the model, there are now 60+ notification types that have a very finer granularity (e.g. UserAcceptedInvitation instead of UserUpdated) and are posted by the components that make up the application. Where previously, a component would set the status of an object and then the Model would asynchronously tell everyone who was listening for changes to that object about it, the new architecture has the component updating the Model, possibly multiple times, then posting a single Notification describing the changes that were made. Additionally, imperative Notifications are being introduced to allow components that wish an action to take place (such as logging in) to be decoupled from the components that actually perform the operation. This means that a UI controller that is handling the login button on the screen no longer needs to have a direct connection to the component that actually executes the login. It simply needs to post the Login Notification and wait for the resulting SuccessfulLogin Notification to be returned.

Taken together, these three components–the Model, Event Queue, and Notification Center–work together to allow the application to be single threaded and to help decouple the components in the application from one another. No longer does a component have to have a reference to another component just to tell it to perform an action. Now it can simply post a notification requesting that the action take place and the target component will receive it and act on it.

This architecture provides many benefits. The single threadedness of it removes the need for complex locking in the model and for dealing with events arriving asynchronously from the operation that caused the event to be posted. The Model becomes much less complex and allows for the easy introduction of persistence libraries to simplify the management of the code. And the Notification Center allows the components to be decoupled from one another making testing significantly easier, and allowing easy replacement of components should some specific customization be needed (e.g. making command line version of the tool).

Related Posts:



One Response to “Application Design Theory”

  1.   Notification Based Design by John’s Ponderings Says:

    [...] As discussed in a previous article, Interface-based design has limitations that I have had to address. In this post, I discuss a specific architecture that applies the theories discussed previously. [...]

Leave a Comment