A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.
Alright. I've been banging at this for a day now with no love, and I'm about to start day two.
Let me simple it up for you all.
In our object model we have a Name class. It has properties such as Title, FirstName, OtherNames, LastName etc. Then we have, for instance, a MortgageManager class which extends the Name class and provides properties specific to a mortgage manager. We also have a Borrower class that extends Name and adds borrower specific properties. It's all pretty obvious and standard really.
From a GUI POV, up until now, we've only had mortgage managers. Now we're hitting requirements for other forms for articles like the Borrower etc.
The little red guy on my left shoulder poked me with his fork and said "This is a perfect time to use visual inheritance...". I looked to the little white guy, but he had been out at a long lunch with a client and was napping under his desk George Costanza style. One to the red guy.
Of course, the red guy is in the details and now I'm struggling a little bit. I'm trying the "when it doesn't make sense, add more layers" approach, but some of the requirements are biting me on the backside.
Chiefly, when a user enters a name into the name text box, the system should check for duplicate names and display a list of matches if any are found. At the moment I implement this using a timer triggered when the user leaves the text box.
If matches are found and the user selects one, the system should trot off and retrieve the matching record and populate the form. This works great when it's only dealing with Names.
Now throw in a form subclass for dealing with mortgage managers. I need to have a way to know that the Name form shouldn't handle the repopulation, and that it should be dealt with in the subclass. (By the way, this goes for loading, saving, printing etc).
My first OOP instinct was to add a handfull of abstract methods to the base class (forcing me to mark the base class as abstract), which was all fine and dandy and seemed to work without to much mucking about. This all fell apart in the form designer however.
When you want to layout controls on the subclass form, you'll hit a problem whereby the designer can't create an instance of the base class because it's abstract. It needs to create an instance of the base class to be able to throw the base class controls onto the subclass. Leaving you with an exception in the IDE and no way of laying out your subclass.
Anyway, I'm looking at how I can deal with this through MVC and other patterns. I would really like someone to be able to inherit from the Name base class form and not have to think too much about what they need to do to have it work. That's why I like the abstract methods. If you didn't know you had to implement them, you'd soon find out when the compiler bitched to you.
Did any of that make any sense? Can anyone offer any pointers? I'm still working on it from here, but any help is greatly appreciated. I can't be the only person who's painted themselves into this corner.
What is visual inheritance? I thought you meant virtual, but you seem to really mean visual.
son of parnas
Friday, August 19, 2005
How is it that a MortgageManager IsA Name? I would think the proper relationship would be for a MortgageManager to HaveA name.
In other words, use composition rather than inheritance here.
You need a generalized editor for names, plus some other stuff, yes? How about encapsulating the "NameEditor" into a custom control, and then reuse it everywhere you need such a thing. This way you don't have to deal with the visual inheritance stuff, but you can still easily re-use the NameEditor pieces.
You'll need to add appropriate events and properties in the NameEditor to get the Name in and out, but I think in the end it'll be a lot cleaner.
Yep, I really mean visual. :)
I understand where you're coming from. I suppose the relationship has been incorrectly garnered from the database schema, whereby we have a "Name" table which represents an (bad generic term coming up here) "Entity".
The relationship kind of works more the other way. A "Name" can be a "MortgageManager", or a "Borrower". "Name" is perhaps a bad name for the class, but because a "Name" can be either a person or a company that's what we decided to go with. For the purpose of what I'm trying to convey here, it might be easier to think of the "Name" class as a "Person" class. So a "Person" is a "Mortgage Manager", or as "Person" is a "Borrower". This would imply inheritance instead of composition, yes?
(We did toss around "Contact", but decided that down the track there may be a "Contact" class in the same way that there are "Borrower" and "Broker" classes.)
"Name"s have contact information and addresses. We join the Name table to the ExternalLogin table to provide outside parties with access. So if we want someone who is already in the system as a mortgage manager to be a borrower, we just add a record to the "MortgageManager" table joining it to the "Name" table.
In our particular situation, it's not impossible for a mortgage manager or broker to become a borrower or an investor.
I did toss around the idea of a user control. We do use them in other parts of the interface, but for things that are more closely aligned to GUI controls. For example, I've created a drop-down button that works much like the buttons on the Outlook contact form.
The problem I found with using the user controls is the other programmers tend to just slap their forms together any old way and no two look the same even when they're conveying similar information (ie, mortgage managers and brokers). The idea of using form inheritance in this way was to guarantee some sort of uniformity for contact information related forms (MM, borower, broker, contact, investor, user etc).
I'd like to be able to inherit from the Name form and create a Mortgage Manager form. Drop mortgage manager specific fields on the form, but have the base class take care of moving data into and out of the Name class (including address and contact details), and the mortgage manager form can worry about the MM stuff.
Today I've been messing around with diagramming the flow of events with swimlanes and I think I might be getting close to coming up with a set of objects that interract in a simple enough way, let the existing behaviours continue, and enforce the behaviours on subclassed forms.
"So if we want someone who is already in the system as a mortgage manager to be a borrower, we just add a record to the "MortgageManager" table joining it to the "Name" table."
"So if we want someone who is already in the system as a mortgage manager to be a borrower, we just add a record to the "Borrower" table joining it to the "Name" table."
It's very "inconvenient" that the VS Designer won't display a class inherited from an abstract base class. A while ago I read an interview from one of the VS programmers, who said they have no plans to change this limitation.
So your choice is to make the class abstract/virtual and lose use of the VS Designer, or keep it non-virtual and know that you shouldn't instanciate from it. I mostly do option #2.
When I have to create a visual class that should be abstract, I do the following:
- Add a suffix like "Base" to the visual class's name (e.g. "NameFormBase".
- Put a comment just above the class declaration line stating that this class is abstract should not be directly instanciated.
- For functions that should be abstract, put a comment above the function declaration stating "MUST OVERRIDE" and have the function throw an exception.
This introduces a lot of opportunity for human error, but what else can you do? Write the GUI code yourself?
BTW - I agree with Chris's suggestion that this should be a custom control.
Friday, August 19, 2005
From the custom control point of view, the problem is the name class is not simply a name, as in first, last etc. It has a type (company, individual) and address and contact information in it. It makes for a large user control, and still doesn't enforce a UI standard on other developers.
I think by careful factoring of code into seperate classes, and some nift interfaces, I should be able to achieve the desired effect.
My first thought was the same as Chris's -- encapsulate the name editing in a user control.
If you want to stick with what you have, you might want to take a look at the DesignMode property. This lets you determine from within a Form (or any Component derived class) whether it's running under the IDE or not. Rather than using abstract methods, you could use stub methods that do nothing in DesignMode and Debug.Fail("Must implement!") otherwise. It's a little ugly but gets the job done.
What I'm going to try is setting up the "Name" form and the "Mortgage Manager" form as views, then create a "Name" controller that is abstract and has the methods I need in it marked as abstract, then a dev will inherit from this controller to provide a controller for their subclass. This will force them to override the abstract methods, and wind up with the behaviours I'm looking for.
If I get a chance, I'll whack a sample of what I'm doing up on the web.
This topic is archived. No further replies will be accepted.Other recent topics
Powered by FogBugz