Back in November I got an email from Jiho Han asking a question about Presenter First:
“In Presenter First, is databinding still feasible? I’m speaking about situations where you might have a 3rd party grid control where it is almost unusable without databinding.”
Happily, we have a new sample illustrating the Adapter extension to Presenter First. The application is a simple book inventory manager with a sophisticated editable table widget (JTable and TableModel data bindings) and MVP-triplet-to-triplet coordination between the editor components.
How Adapters help us encapsulate data-binding-oriented APIs
Data binding (the automated relaying of data between a data model and view) is a common and powerful tool that usually arrives out-of-the-box from our favorite GUI toolkits, like WPF, Java/Swing, etc. For many complex widgets, such data bindings might be the only way to control the user interface.
In Presenter First, we focus on Presenters—domain-level objects that exist between models and views. But a JTable is designed to bind to a TableModel . . . where’s the Presenter in this connection? How do we get in the middle of this model/view duet?
We don’t. JTable and TableModel work well together. Instead, let’s model at the domain level, where a LibraryPresenter sends updated Book data to a LibraryAdapter which manages (indirectly) a JTable and its TableModel and all the fussy API calls that go along with those classes. Despite its “model”-ish name, TableModel is really just our tool to control our JTable view.
Architecturally, the basic MVP triplet looks like this:
Inserting an Adapter between Presenter and View gives:
The Presenter acknowledges the Adapter as an advanced view, capable of dealing in higher-level, domain-specific data types. The Adapter does the heavy lifting of data transformation and widget manipulation.
In the sample code, there is one more piece to the puzzle: the LibraryAdapterModel, which is invoked by the Adapter to store translated data. This class references the actual TableModel implementation, in the guise of ILibraryTableModel. I usually represent Adapter/AdapterModel scenarios like this:
Interestingly, the LibraryAdapter brokers events and data between LibraryAdapterModel and LibraryView in the same way a Presenter brokers activity between a model and view.
Not all Adapter scenarios will necessitate an AdaperModel. The sample app manages several other pieces of interesting information, such as the currently selected library, which are not handled naturally by the TableModel metaphor.
(Jiho also asked why our C# examples don’t publicly utilize the common C# event system, to which I have responded to on Stack Overflow).