From: Joe E. <jo...@em...> - 2006-03-09 12:07:54
|
Rib Rdb wrote: > On 3/8/06, Joe Emenaker <jo...@em...> wrote: > >> Rib Rdb wrote: >> >>> I still think this has problems. How do you handle transient data or >>> data which has multiple getters and setters? >>> >> Well, I think I hinted, at one point, at the idea of, instead of trying >> to autodetect the public getters and setters, maintaining an array or >> vector of the property names to save. For example, if the vector >> contained "Name", "Author", and "Date", then the XML load and save code >> would only try to call getName, setName, getAuthor, setAuthor, etc. But, >> if my suggestions thus far have made you uncomfortable, then *this* idea >> has probably got you squirming. :) >> > > Hmmm. The more I think about it the more I like this idea. It's more > uniform than having setters used for loading, but one method used for > writing. We could add something like "List getXmlPropertyNames()" to > IPatch. But then we still have the super problem. Well, yes and no. If the property names are kept in a vector or something similar, then the vector would be created in the base class and populated with some values via some add() method, like: public Patch() { addPropertyName("Author"); addPropertyName("Comment"); etc. } The default constructor is supposed to be called for all subclasses that don't explicitly specify a super constructor in their own constructor. So, if I subclass Patch in a class called SpecialPatch and write: public SpecialPatch() { addPropertyName("SomeSpecialData"); } then the Author and Comment ones should still get put into the vector. But now it's getting fairly cumbersome. We've got to have matching getters and setters, they have to be public, and their name has to match a String value in the PropertyName vector. So, at this point, I think it would then be easier to just use a special data structure for all data that we want to save (except the sysex. That's always special). How about this. Patch would have some object of Name/Value pairs which would contain all of the data that should be saved. This gets around all of the getters/setters. In fact, a class wouldn't have to change their code much at all. Things like: patchName = getPatchNameFromSysexData(); would become: setValue("PatchName",getPatchNameFromSysexData()); In support of this kind of method, I point out that the JAXP DOM stuff already has something like this in NamedNodeMap. The three problems I see with this are: 1 - The simple implementation I've proposed here only deals with strings. But there's nothing to keep us from making setIntValue(String name, int val), and setBoolVal(..) etc. 2 - There's nothing to purge old deprecated data. If Patch has a field called "Author" and then we decide, later, that we don't want an "Author" field anymore and strip any mention of it out of Patch, the Author data items already existing in XML files will continue to get loaded and saved.... even though they're never used by JSL. It's a weird version of a memory leak, if you will. 3 - Name collision. There's nothing to keep subclasses from stomping on values in the superclass. If you subclassed Patch, you'd need to know that Patch already uses "Author" so that you didn't try to use it yourself for a different purpose. Even worse, if we went in and added a property name to the Patch superclass, it could collide with a property name in one of Patch's subclasses. > But as I said > before, I really don't think new Patch classes are going to be made > often, so we should just pick one. And calling super.write seems more > like the java way to do it. Java doesn't have much magic. > Well, if you don't feel like we're working our way any closer to a better solution, then we can just go with super.write(). The one thing I'd want to change, however, is that I think we should have a read() method as well. Here's why... The current "super.write()" proposal, as I understand it, is to have write() do things like: xml.writeProperty("author", self.author); and then we need a setAuthor(String) method. I'm still wincing over the requirement that "author" in the call to writeProperty match "setAuthor". However, if we had a read() method that did things like: self.author = xml.readProperty("author"); *then* we can put "author" in a constant, so we'd end up with code like this: private static final String AuthorXMLName = "author"; xml.writeProperty(AuthorXMLName, self.author); xml.readProperty(AuthorXMLName); which is what you can see I did in my XMLFileUtils class. It makes it *much* more likely that your IDE will catch any typos. Also, reading is done just like writing. Lastly, the readProperty() method(s) should be really easy to write, since we can have the "xml." part of "xml.readProperty" holding the DOM Node for just that patch... and readProperty could just turn right around return the value returned by "getAttribute()" for that node. - Joe |