To Couple or Not to Couple; That is the Question

I’ve reached another point of contemplation in my efforts to build the greatest media player ever. This is an architectural matter about application development.

The puzzle in question is the use of loosely coupled application architecture versus event-driven application architecture.

Loosely Coupled Applications

In a loosely coupled application, interfaces define contracts for various components of the application. Dependent code is then given (preferably injected with) a reference to an instance of that interface. The implementation may or may not be a singleton, but it does not matter to the dependent code. It has a handle on an instance of the interface it requires to do its job and can execute accordingly.

Event-Driven Applications

At the other end of the spectrum, an event-based application would have one component broadcasting a message while another component listens for that message. The two components know nothing about each other and neither have any direct interaction. In this case, it is up to a messaging bus to deliver messages from one component to another. The responsibility of the sender ends when it sends the message, but the sender may also be a receiver, listening for a response message of some kind.


The biggest difference in the two schools of thought here is that the event-driven architecture is asynchronous. When a sender broadcasts a message, there’s no guarantee that the response will come anytime soon. This works well for environments like JavaScript where services often cross the client/server boundary in order to fulfill a request, such as in AJAX.

A second advantage of event-driven architecture is the ease with which additional behaviors can be added to an ecosystem. Adding behaviors in response to a message is as simple as adding a new listener for that message; neither the existing receiver(s) nor the sender need to be modified.

Although the asynchronous nature of event-driven applications sounds promising, in actuality, it can create a bit of burdon on the developer. You no longer have any coupling whatsoever (not even loose) between senders and the receivers. This can make it difficult to read and understand code; there are no contextual clues as to who might be listening for a message. This can make it difficult to refactor code if you aren’t able to track down all of the listeners of a particular type of message.

An Example

Since this is in reference to Project: Apollo, I’ll use it as a reference.

The underlying media player in Project: Apollo supports some obvious controls: play, pause, next, and so on. To capture this, I created an interface:

public interface TransportControl {
    void next();
    void pause();
    void play();
    void previous();
    void seek(double percent);
    void stop();

There are several components throughout Project: Apollo that need to be able to control playback. The GUI, for example, has buttons that correspond to these functions. The playlist also invokes these controls to advance the player to the next track.

In a loosely-coupled application, an instance of TransportControl would be injected into the GUI as a collaborator. Then, the GUI could respond to a user click by directly invoking the next() method on the TransportControl. This keeps the code clear and easy to read, but it actually creates another problem. The playlist still needs to be informed when the GUI has invoked a “next” command. Some mechanism must exist to instruct the underlying player what to play next.

In the event-driven architecture, the GUI would simply broadcast a message requesting that the next item be played. In this case, the TransportControl would receive the “next” message and know that it should stop playing the current item. The PlaylistManager would also receive this message and instruct the TransportControl to load a new item. Further, a debug logger can log out the entire process, providing detailed messages about what is happening.

Conclusion and Comments

At this point, I am unsure of the best solution. Clearly there is more than one way to solve this problem and some folks I know would recommend I simply make something work and move on; it can always be refactored later. Good advice for a project on a timeline for budget, but this is a learning experience where I can really explore these types of questions. My instinct tells me the right answer is some manner of balance between the loosely-coupled option and the event-driven option.

So does it make sense to inject the GUI with an instance of the TransportControl? Or does it make more sense for components wishing to control playback to broadcast a message according to their intent? Thoughts?

UPDATE: After reading in more detail on the Wikipedia entries I linked to above, I think the best solution for my example case is a complementary application of both event-based and service-based architectures. Specifically, changes in state throughout the application should be expressed as events, but components that need to invoke certain behavior should do so on a service object or proxy, even if that proxy merely relays an event under the hood.

My Unwavering Support of Apple

Anyone who knows me will attest to my love affair with Apple products. While I wouldn’t go so far as to call myself a fan boy, I will say that I sincerely appreciate a well engineered product; I rarely let price alone influence my buying decisions. Quality matters! After all, I frequently recommend the products I have used and enjoy to friends and family. More often than not, it is Apple’s products that meet my requirements. Does that make me an Apple evangelist? I don’t think so.

I don’t claim that Apple products are problem-proof or that the extra expense of an Apple product implies a problem-free product lifetime. In fact, I make no claims whatsoever as to the hardware quality control Apple institutes. What makes me believe in Apple so strongly is how they act when a problem does arise. And yes, I maintain my faith even after I have had problems with my Apple products. Here’s why.

Today my MacBook Pro had the misfortune of requiring a visit to the Genius Bar at my local Apple retail store. After 18 months of [ab]use, I finally decided to have a long-standing issue looked at by the geniuses in blue.

For as far back as I can remember, I have had miscellaneous intermittent problems with my Mac. When it was new, the display periodically went haywire on my Dell 30″ monitor at the office. It was completely random and extremely frustrating, though I eventually traced the problem to the dual-link DVI adapter and managed to swap* it out with a newer model which had a newer firmware version and that seems to have mostly resolved that issue.

Recently, though, my machine has picked up a habit of going zombie and devouring any works-in-progress left open on my desktop. After the display went to sleep, or sometimes when the machine itself was asleep, it would become unresponsive. The fans inside would speed up to maximum and the machine would get very warm. Possibly some runaway process?

Digging through the Console logs, I saw a lot of this:

kernel	NVDA(OpenGL): Channel timeout!
kernel	NVRM-RC: 0 4e565f504649464f5f494e54525f303a307831303031
kernel	NVRM-RC: 0 4e565f504649464f5f4341434845315f444d415f53544154453a307838303030
kernel	NVRM-RC: 1 363232300a
kernel	NVDA(OpenGL): Channel exception! exception type = 0x6 = Fifo: Parse Error
kernel	00000069
kernel	NVRM-RC: 0 4e565f504649464f5f494e54525f303a307831303031
kernel	NVRM-RC: 0 4e565f504649464f5f4341434845315f444d415f53544154453a307838303030
kernel	NVRM-RC: 1 363232300a

That did not look good. The genius didn’t think highly of it either and quickly concluded that the graphics card, nay the entire logic board in my poor laptop was in need of replacement. Oh dear. The cost of the parts and labor were estimated between $350-700 (essentially, buy a logic board for $700 or option a retroactive Apple Care plan for $350).

This is where the transaction got better. The rep looked through his computer for a moment and I suggested that the problem had been going on for months and that it had taken me this long to compile a reasonable amount of clues. At this point, the technician spoke to his supervisor and offered to waive the entire cost of repair. Apple was going to completely replace the logic board in my laptop 220 days out of warranty absolutely free.

So yes, I will buy any iThingy Apple slaps their logo on. I will consider Apple’s products first and foremost when I am in the market for an iGadget. And I will continue to recommend, nay, endorse the products Apple makes because I know first-hand how highly Apple values the relationship it has with its customers.

Still not convinced? Call the manufacturer of your favorite gadget and see if you can even talk to a human being today. If you can, see if you can convince them to replace your gadget for free, even while under warranty. Good luck.

* When I say “swap”, I mean “purchase a new one, put the old one in the new box and return it.”

Using GWT’s Application Framework Judiciously

I am very excited to see the inclusion of a proper application framework in the upcoming Google Web Toolkit 2.1 release. The addition of this framework is a clear signal that GWT is a serious library for enterprise scale applications.

As a seasoned developer, I am very familiar with the traditional Model-View-Controller approach to building web applications. The MVC approach works great for server-based frameworks like Spring MVC or Struts. However, ever since I started working with GWT way back at version 1.4, I’ve had a hard time mapping MVC into a truly client-side application where the entire GUI is built in GWT.

The MVC approach is tried and true in the desktop software world. But on the web, there are a few extra quirks that make traditional MVC a little tricky. Here are some of the challenges I’ve run into.

History Management and Support

Because it is a web application running in a browser, there is an implied expectation that the forward and back buttons work, regardless of whether your web application is mostly client- or server-side. This presents a unique challenge to MVC because most desktop applications don’t have forward or back buttons.

Bookmark Support

Another important feature to any good web application is the ability to bookmark or share the link you’re currently viewing. It should be possible to bookmark a page or paste the current URL into an email, for example, and restore the state of the application based solely on that URL.

Composite View Structure

When working with traditional MVC frameworks like Spring MVC, the process is pretty straight forward. For any given URL, only a single Controller responds to the request. The Controller prepares a single Model and that Model is handed off to a single View. Common elements of the UI can be rendered with include statements, but the View generally has a very direct relationship with the URL.

Conversely, with a more desktop-like application built in GWT, the UI is frequently built as a Composite. There are several components in play at any given time and there isn’t necessarily a straight forward relationship between the current URL and the current set of components viewable to the user. This makes intra-application messaging and navigation a bit more challenging; you can’t just rely on a DispatcherServlet, for example, to coordinate user interaction.

Enter the GWT Application Framework

Clearly, the new App module in GWT is designed to address many of these concerns. It’s great to see History Management and the notion modular composite structure being supported as first class features.

The application framework in GWT is all new to me, though, and it isn’t really MVC. Instead, it’s more of a Model-View-Activity (or -Presenter) approach. In this case, the Activity takes the place of the Controller and is responsible for only the slice of the UI represented by its View. This MVA approach handles application navigation very well, assuming your application is, like a traditional web application, a series of screens or “activities” through which the user navigates linearly.

So what happens when the UI dictates that two or more of these activities be present at once? Well GWT can handle that as well by using multiple ActivityManagers. The ActivityManager is responsible for coordinating all of the Activities for a designated Display – the area of UI over which control can be delegated to an Activity.

This is all well and good, but Project: Apollo presented me with a unique challenge in this new MVA architecture. What do you do with UI components that are always present? Case in point: Apollo has a control bar that is always present in the UI, similar to the button on the front face of a DVD player.

The control bar allows the user to control playback and displays pertinent playback information such as the elapsed time and name of the current track. The control bar, by nature of its omnipresence, does not participate in the navigational functions of the ActivityManager, nor is there any other Activity that would fill its slot.

I’ve also gleaned through GWT code in trunk that the usual way of handling Activities is through an ActivityMapper; the ActivityMapper is responsible for resolving and creating instances of Activities and their corresponding Views. However, control bar isn’t managed as such. I have a self-imposed rule in development of Project: Apollo that UI components should be UiBinder compatible; I should be able to include the control bar in my UI declaratively through the constructs afforded by UiBinder. By contrast, Activities depend on the current state and history of the application, so their lifecycle would not be appropriate to manage through UiBinder, hence the Display slot concept.

Bring Back the Controller

The Java docs for Activity state:

Implemented by objects that control a piece of user interface, with a life cycle managed by an ActivityManager, in response to PlaceChangeEvent events as the user navigates through the app.

It’s easy to see that my control bar doesn’t strictly qualify as an Activity. In this case, MVA isn’t a good fit; I need a different approach. One option, for simpler components, is to let the UiBinder template be the “view” and the backing Widget code be the “controller”. For more complex components, though, I still want to break out application logic to a separate class and leave UI-centric logic in the View-backing code.

Taking a hint from previous iterations of GWT’s application framework, I am choosing to call my pseudo-controllers “delegates”. The Delegate represents a code structure to which the actual View will delegate user interaction for handling. Delegates contain familiar Activity-esque functions to facilitate lifecycle events where necessary.

public interface Delegate<W extends IsWidget> {
    void shutdown();
    void startup(W widget, EventBus eventBus);

For my control bar, then, I have broken the code into a ControlBarWidget (the View), a ControlBarDelegate (the Delegate), and a ControlBarModel (the Model).

To keep with my requirements that the control bar be UiBinder compatible, I am allowing the View to handle creation of a default implementation of the Delegate. I’m using GWT.create() to instantiate it so the actual implementation can always be easily swapped out later via deferred binding, but for now, the need to swap out implementations is low to non-existent.

The Judicious Part

The lesson I am driving at here is that the new application framework in GWT may be great for some portions of an application, but it probably isn’t appropriate for everything. Parts of the application that do not participate in history or navigation (such as global menus or controls) are not good candidates for Activities.

I think GWT and the new application framework represent a fantastic toolset for building user interfaces and entire applications. You just have to be smart about when and how you use them.

HTML5 Audio: Format Wars

I had originally planned to use HTML5’s new <audio> tag to actually render the audio in Project: Apollo. That went south, however, when I discovered a few critical problems with current implementations that disqualify the <audio> tag from contention.

Different Browsers, Different Formats

Both Mozilla and WebKit have already adopted at least some support for the <audio> tag. Unfortunately, Mozilla has decided to avoid potential licensing issues by omitting support for any audio codec that isn’t freely open source. This means no MP3, MP4 or AAC support, as those are proprietary codecs.

On the other side of the fence, WebKit (driven by Apple) has a substantial interest in seeing both MP3 and MP4 thrive on the web (maybe you’ve heard of iTunes?). Citing “simplicity”, Apple isn’t budging on adding support for the open standards Mozilla supports, such as Ogg Vorbis.

Google Web Toolkit

Unfortunately, there isn’t much support (yet) in Google Web Toolkit for HTML5, but it is coming. This makes it difficult to take advantage of HTML5 right now since my GWT is the main framework at play in Apollo. Specifically, I’m not sure how to go about listening for DOM events that are specific to HTML5, such as the ones fired by the <audio> element. This isn’t a huge hurdle, because I can always bridge to GWT with native JavaScript (ick). But it does add another hurdle to overcome.

The Solution, Sadly, is Flash

I have used Longtail’s JW Player for Flash in the past on other projects. Despite my reluctance to do so*, I have decided to implement JW Player 5 for Flash as the audio rendering engine. JW Player 5 has the best support of formats I called for in my key features, and it is relatively simple to use.

* Okay, I just have some minor gripes with JW. Namely, they documentation is always a sore spot as it’s often conflicting or missing. I also feel like I’m being nickel and dimed to death by their licensing terms.

An Overview of Project: Apollo

To start with, I’d like to lay down my vision statement and some of the major tenets of design for this project (or guiding principles, if you will). These points should help focus direction and guide tough decisions down the right path.

Project: Apollo connects users easily to their media and simplifies management of large, complex collections of media.

Project: Apollo is a learning experience, first and foremost.

The personal and professional gains to be had from seeing out a project of this size and scope are well beyond any short-term plans for entrepreneurialism.

Project: Apollo is designed with future standards in mind.

The goal is to discover what is possible with new tech, not work within the bounds of old tech.

Project: Apollo places the highest possible value on the user experience.

And the experience must be fast. And clean. And simple. And powerful. It is important that new users are just as comfortable as seasoned veterans.

Project: Apollo should be familiar.

Re-inventing the wheel is not a goal or a priority. However, innovation where necessary is perfectly acceptable.

Project: Apollo is about intelligent design.

The user is not stupid. Functionality should work for the user, rather than having the user work for functionality.

Project: Apollo is simple and focused on a single problem.

Stay focused on this problem and solve it well. Apollo is not intended to be a “push-button, do everything” solution nor a buzzword mashup.

Key Features and Functions

  • Browser-based, supporting Firefox 3.5+, Safari 3+, Chrome 5+, Internet Explorer* 8+, and iPad browsers. Native iOS applications are planned.
  • Supports both streaming and downloading of content in a user’s library.
  • Supports playlists with play one, play all, repeat and shuffle modes.
  • Comprehensive library browsers, including: by artist, by album, by genre, by song, by ranking and by year.
  • Support for album artwork and related media.
  • Support for MP3, MP4, AAC, and WAV audio.
* Support insofar as is reasonably possible. I refuse to let Internet Explorer cause me grief or frustration.

The Audacity of Music

For a number of reasons, I find my collection of music to be a generally complicated topic.

It’s Enormous

First of all, I have a ton of it. Gigs of it. Thousands of tracks. I own a 60GB 5th-gen iPod. It’s full. Needless to say, I seem to fancy myself a collector of audio. I refuse to let go of old tracks I would never even admit to owning. Managing such a large library is tough and most would-be music libraries out there I have tried tend to choke on large databases.

It’s Amorphous

My music collection isn’t just large, it’s also fragmented by duplicate tracks, multiple formats, and duplicate tracks in different formats.

It’s On My PC, At Home

Up until recently, I used my MacBook Pro at work and a Gateway desktop at home. All of my music resided on my Gateway with its 1TB internal disk drive. Then I decided to retire the desktop. It’s not old or broken (Intel quad-core 2.4GHz with 6GB RAM and 1TB RAID disk setup). I just grew tired of switching platforms night and day. It’s like getting into your car every morning to drive to work and finding that the seats and mirrors are never where you left them.

My desktop doesn’t travel with me, either. And since I have more music than my iPod can store, much of my music stays locked up at home (yes, I realize that millions of people have dealt with this problem since the dawn of recorded audio).

It’s Not All Physical Audio, or Even Virtual Audio

Not all the music I listen to exists in a physical incarnation. Some of it came from CD’s, some of it I bought on iTunes. Some of it exists only through streaming radio stations such as Pandora.

So What to Do About It?

Unfortunately, I can’t just throw everything onto my MacBook and be off. I don’t have the disk space for it. And I have no interest in carrying a USB drive everywhere I go to store all my music.

I tinkered with a Network Attached Storage device, but many of the same problems remain. Namely, the device is still constrained to my home and to get decent performance out of it would require a total upgrade of my home network to Gigabit.

Helium Music Manager

I did try and thoroughly enjoyed using Helium Music Manager. It’s a fantastic audio database and has some pretty nifty features for audiophiles. However, it is missing one critical, deal-breaker feature for me: it’s Windows-only.

Enter the MKLabs

Since I’m a developer, I think it ought to be possible to build a solution to suit my needs and wants. So that’s what I’m going to do. Part of MethodKnowledgy is to explore and learn about code, so this makes perfect sense. I think I’ll call my little “code shed” of tinkering MKLabs.

I won’t go into all the details of features here and now, but basically I intend to build a web-based audio database application and leverage some of the coolest new platforms and technology out there to make it happen.

I’ll use cloud-based hosting systems like Google AppEngine to host my application and give it a scalable, high performance back end. The AppEngine DataStore also looks like a good candidate for storing massive amounts of data on my music.

I’ll use Amazon S3 to store and backup my music and distribute it through Amazon CloudFront.

I’ll use Google Web Toolkit to build super-fast, engaging user interfaces so my application feels (and works) like a proper desktop application.

And I’ll use new features like HTML5 Audio tags to render the audio, removing the need for special plugins or browsers (albeit I make a rather large assumption about the capabilities of average Joe’s browser).

I’m not trying to reinvent the wheel, though. Products like iTunes, Helium, and Grooveshark have proved what features do and don’t work. Now I just want something that works the way I want it to.

I aim to make regular updates here about the progress of my new music jukebox, codename Apollo. I’ll discuss major successes or failures along the way and try to document things that work well or don’t work well, and how to overcome certain challenges.

Should be fun.

I’ve Done it Again

Yes, again.

For the umpteenth time, I have re-launched my blog. Or a portion of my blog.

Like many people, I too have these illusions of grandeur. My visions tell me I’m going to create some über-popular technical blog that everyone and their sister will read. I start the blog and after a few weeks I lose interest. Then my interest in reinvigorated at some point later on. That’s how it goes; it’s a vicious cycle.

Would there be any point to promising to do more updates or write more about topic ‘X’? Probably not. But I’ll do it anyway. I’m going to make more updates and write more about topic ‘X’. Satisfied? Good.

In all seriousness, though, I really would like to start documenting some of the things I learn as I trowel through code. There’s no reason anybody else should have to make the same mistakes I do, including myself.

It would make sense for me to start documenting things like how I finally managed to get Product Foo working on my atypical setup. Or how I didn’t.

So here goes. I’m looking forward to it. Read on and enjoy.