Culmination
I've been reading about and applying Test Driven Development and Design Patterns over the last few months. Today I saw the culmination of that effort in the design of new module of ASP .NET software that was added to an existing project on Monday.
Early on I had created a generic object for leafing through pages of records in the database. I called the object the RecordCursor, and implemented basic cursor and search functionality (MoveFirst, MoveNext, etc.). Separately, I had designed a generic object for managing records in the database--I called this a RecordManager. It has 3 basic functions (Save, SaveNew, and Delete), and sometimes has others (ListAll).
Of course, there are also the Business Objects themselves.
For any Business Object in the system, there are basically 3 parts--the business object itself, the Manager, and the Browser. This gives me a good separation of the Business Layer from the Data Access Layer.
I wanted to make the UI solely dependent on Interfaces and Abstract classes. When building my DataAccess components, I made sure that they only returned Interfaces from any API function. I further made sure that none of the concrete objects were visible to the UI.
This is where it starts to get cool. The RecordManager classes receive only interfaces to their Save, SaveNew, and Delete functions. The idea I had for the UI was to develop a set of UserControls that implemented the interface of the object they were intended to edit. Thus, if I have an interface IPerson, then I'll have a PersonEditorControl UserControl that implements IPerson. Instead of creating property declarations with internal variables, I'm redirecting the properties to the server controls embedded on the UserControl.
For Example:
Public Property FirstName as String Implements IPerson.FirstName
Get
return Me.txtFirstName.Text
End Get
Set (value as String)
Me.txtFirstName.Text = value
End Set
End Property
'etc...
Thus, the editor becomes an instance of the object it is intended to edit. When I'm done editing, I simply pass the control in its entirety to RecordManager.Save(p as IPerson).
I've been writing code for about 5 years now, and haven't seen anybody doing this in any existing code, nor in any books. It's worked out pretty well for the project I'm working on, so I thought I'd share.