At this point, I think it's fair to call my project a success. So while everything is fresh in my mind, I want to get down things I felt worked very well for me, and things I felt did not, and lessons learned along the way. This is mainly for myself, but if anyone else learns anything, so much the better.
Lessons learned the hard way
MVC:
So trying to adopt MVC was a challenge. It was the first time I'd done it, though I'd read enough I was familiar with the ideas, and I had many mis-starts along the way - some of which got corrected and some didn't. In fact, I could write a whole series of blog posts on lessons learned here - and most of them come from a lot of reading on Java. But if I had to refine it to a single idea, it's "keep your concept clear". I spent a lot of time trying to shoehorn everything into my model classes and I wasn't really clear what belonged in the controller except as something between the model and the front end - which seemed largely unnecessary since I was wiring my model beans directly to my UI components. Should I render in read mode or edit mode? Ask the model what mode it's in. Can the user modify a particular field? Ask the model what the rules are. This led to some painful refactoring, because the simplest answers turned out to be wrong.- Model is state data. Anything that is unrelated to accessing or modifying state does NOT belong in the model.
- Controller is the XPage controller. There is not a 1-to-1 relationship between controllers and models unless every model is associated with one and only one XPage.
- There should generally be a 1-to-1 relationship between controllers and XPages. In my case I have a default fall-back controller (from which the other controllers extend and which provides common methods), so if an XPage needs no specific functionality, a controller isn't needed.
- If you have something that is sort of like a controller, in that it provides UI functionality, but is tied directly to a model, what you have is neither a controller nor a model, so don't try to put that functionality in either. Down the road when you need to use that functionality in a different context, you will almost certainly regret having it tied to one or the other, and it will lead to copy-paste code or some sort of abomination where classes are being invoked for things other than their reason for existing.
Understand the existing objects
What is DominoDocument and how is it different from Document? DominoRichTextItem vs. RichTextItem? I found it confusing and just ignored it. It turns out that DominoDocument is a serializable representation of a Document with the DataAccess, handling of RichText fields, automatically handling the conversion between scalar values and multi-values - basically all the hard parts of serializing Document data. I wasted a fair bit of time on my Model objects when I could probably have just used or extended this one.Understand what you are borrowing
I created a lot of work for myself by copying code from others that just did everything automatically, and I discovered weeks later that it didn't exactly do what I needed it to do automatically. And I had to write a lot of confusing and potentially fragile code to shoehorn my needs into a structure that just wasn't what I needed.Packages
Okay, I confess. My packages are a mess. I think I have too many of them for my relatively flat hierarchy, but at the same time I'm not sure how to manage it any better. I have 2 high-level hierarchies: <domain>.common and <domain>.<project> and from there it's a muddled mess. I have a xxx.yyy.data package where all of my data beans are. Except for User data, because that consists of a User interface, AbstractUser with common User methods, UserBean for referencing user data, and CurrentUser, which extends UserBean with some context-specific stuff. Maybe I should have created xxx.yyy.data.user? But then does that mean I should create sub packages for the rest of my data beans even though they are single classes instead of just one? Or was it a mistake to split off the user stuff - except I rather like having all 4 user classes tied up with a bow.I have a package where all my ActionListeners reside. That makes them very convenient to include in my XML because the hierarchy is always the same. Yet conceptually they are extremely unrelated. Two are for logging user actions, a couple others are for keeping the UI state in sync between the browser and the back-end. Ultimately I realize there is no rule for this - it's a combination of an art and largely irrelevant. But if there were a rule, it would be pick something and then stay consistent.
Comments
Post a Comment