In a recent post, I mentioned that I was working on a customized grid view. Last week I completed the "binding to user settings" behavior. Then I took a look at the source and was stunned. I had almost 700 lines of code (and comments) and it wasn't well organized. So, I set out to start adding regions to the code to separate different behavior.
The last sentence should have raised some flags. Regions to separate behavior? What happened to the cohesion of my grid view? I seem to have lost sight of the Single Responsibility Principle. What to do? Well, I decided to refactor/redesign my enhanced grid view. It really wasn't that hard to figure out how to split things up. I had distinct enhancements that could easily(?) be extracted. I decided to take an MVC approach, in particular a Supervising Controller. If I were using MVC for my web pages, why not my web controls?
I focused on the row selecting behavior first. I extracted any code related to row selection to a RowSelectorController. Clearly, the code would not compile immediately. I slowly went through all of the extracted code and started building up my RowSelectorView to resolve references to data proprietary to the GridView. I simplified things by tightly binding the RowSelector to the GridView via a property on my view. This allowed my controller direct access to all of the public members of the grid view (including a handful of events). Then I only needed to add a little bit more to my view:
1: public interface IRowSelectorView
2: {
3: event EventHandler ChildControlsCreated;
4: event EventHandler PageSizeChanging;
5: event GridViewRowSelectingEventHandler RowSelecting;
6: event EventHandler AfterPreRender;
7:
8: GridView GridView { get; }
9: bool SelectOnRowClick { get; }
10: ListSelectionMode SelectionMode { get; }
11:
12: void PutInCache( string key, object data );
13: object GetFromCache( string key, object defaultValue );
14: void EnsureChildControl( Control child );
15: }
In the end, there is more code than when I started, but it is much more manageable and testable.
Perhaps the most embarrassing thing about all of this is the total lack of TDD. I've proven to myself that just about any behavior can be designed with testing in mind. Server controls are no exception. At least I can add some tests now that I have introduced my RowSelectorController. Better late than never.