I’m in Miami today. It’s very nice here, though the locals have informed me that “it’s winter”. Thus far, I have resisted an urge to let them know that they don’t know cold.
On the flight to Miami, I wanted to work on the EBay RCP application that I’ve been tinkering with, but without Internet access to their sandbox, it’s impossible to test anything. I’m a frequent tester. If I go more than about 20 minutes without running something, I start to shake. It’s not pretty, so something needed to be done.
The problem was one that I created. In my haste to get something running, I tied all my code directly into the EBay APIs. Tight coupling makes me itch; it’s refactoring time.
I decided to remove any notion of EBay from the main application plug-in. In it’s place, I built a few generic interfaces and an extension-point. I updated all my view code to make use of the generic interfaces exclusively. The extension point allows other plug-in to contribute an “auction provider”. I moved all the EBay-specific code into a new plug-in that includes an “auction provider” extension. The implementation of the auction provider conforms to the set of generic interfaces defined in the main plug-in. When the main plug-in loads, it looks for “auction provider” extensions and grabs the first one it finds. It instantiates the class defined by the plug-in and uses the result to actually interface with EBay. All very nicely decoupled.
I then built a third plug-in that also extends “auction provider”. This plug-in’s auction provider is totally bogus. It works entirely in-memory from pre-defined data that is hardcoded into its implementation.
The basic idea is that I can use either of my provider plug-ins. If I want to actually access the EBay sandbox, I use the EBay provider. If I’m just testing some user interface stuff and either can’t access the sandbox or don’t want to, I can use the bogus provider. The bogus provider works brilliantly on the plane. Technically speaking, I can actually use both plug-ins, but since my code only cares about the first extension it finds, one of those plug-ins will be ignored. I have nothing in my code that makes predicting which one will win easy, so I just try to avoid the situation.
I also created two separate run configurations: one for each provider. I can run the configuration I want simply by selecting the appropriate entry from the run or debug menu.
Decoupling is good. My next step is to refactor what I’ve been calling the “main plug-in” (I used a better name, really) to separate the definitions of my views from the application. That way, the views will be more easily reusable should I want to include my EBay code in another application.