On Sun, 10 Apr 2005 13:57:26 +0200, Diez B. Roggisch wrote: >> Domain-specific abstractions do that *faster* than GUI designers, not >> slower. And better, too, since every iteration tends to be fully >> functional and not just a "let's see what this looks like" prototype. > > Can you show me some working, in-use example for that? I _seriously_ doubt > that the process of rearranging and tuning the layout can be done faster in > the text-world than with a good designer like qt-designer. But I'm all ears > for better solutions.
Regrettably, no. I have them but they are all unsharable, either because the real owner would consider them proprietary, or because they are an unreleased and at the moment unfinished product I can't give the code out for. But I can help some. Part of the problem is the incredible cognitive disconnect between the "layout" system of design and the system I'm advocating. You're looking at your designer and saying something like, "well, if I want to re-order these two options, it's three drags, even less if there's an 'exchange' option, how can anything possibly be any easier?" (At least, that's my guess.) But that is not where the advantage lies. One of the things I can't show you at the moment is actually written as a web application using Javascript and mod_perl. It's a bog-standard GUI app that edits databases, from the surface. SOP for the forms designer approach is to create a form for each thing that will be edited; in this case in HTML, but that's not particularly different and you can get form editors for that, too, if you try. But even now, we have at least 20 different types of things to edit, and the full power of databases is at play here; we have foreign keys that may have an arbitrary number of certain things (customers may have an arbitrary number of phone numbers, for instance; in practice of course you won't have 20, but they may have "home", the may have "home + work", the may have "work + fax", etc.), and a customer's address may actually be in an Address table, rather than directly in their record. Add up all the little pieces and at the moment we've got around 100 different types of things that might need editing, many of which can have arbitrary links to other things. (Some of these 100 things are just "link tables", SQL tables that link an ID in one table to an ID in another for many-to-many relationships and these will not directly be edited, but still there's a lot of "things" in play here.) We could try to create a form for each one, and in fact earlier versions of the system did just that. But that solution sucked, for all of the reasons I typically rant against these solutions; they rapidly got out of sync with the database schema, a bug fix in one was a bug fix in no others (copy and paste code tends to run rampant in this situation, though technically that's just a tendency, not a requirement), and any but the most critical enhancements are out of the question because they only affect a small part of the system. So, instead, with this new system (note I wasn't involved with the old system), I do everything with metadata. (Credit where credit is due, the other programmer was starting to do some of this, though he couldn't quite take it down to the interface and there are some things I had to add later.) Every "thing" (class) has a description of what it's made out of, and what type each of those things are. When I go to edit an instance, the Javascript pulls down that description, and a description of the instance (and all of its associated sub-instances), and instead *generates* a form to edit the object based on what it is made of. Right now, I'm emulating the old two col approach, labels on the left, values on the right, but I'll be changing that later. For now, though, that makes it easy (and like I said, as nice as forms are, having to do that many they bailed out and went with a standard design). And since I'm putting these things in by hand, I can also create custom widget types and use them. (For that, I'm using my XBLinJS library, so you can actually think of the HTML widgets as having capabilities much like Tkinter widgets, in that I can subclass from them and make them do domain-specific things just like Tk.) Integer value types get integer text boxes; these do not allow you to type anything but numbers. Floating point is the same way, but adds the . (although only one). All numeric fields do math within themselves, which is something that should have been standard for a decade now but programmers had to actually do something special in their forms to get it; I get it for the same price as anything else, once I wrote the code. (By that I mean, type "1+4" in and it will resolve itself to "5".) That's one of the reasons I rant about this; there is *so much* functionality like that that ought to be standard because done correctly it's trivial to plunk the right text widget subclass down if you're generating the screen, but form designers make this a lot of extra work. How do I decide the order to create the fields? Classes carry a metadata field called "order" that lists the fields it wants in order, the remainder will by default be tacked on the end. What if I don't want a certain field to display? There's a metadata field that lists the ones we want to display for editing, there's another I can use to just filter a couple out if the first isn't present. What if I want a particular widget to do something special like be a certain width? I've created a metadata "escape hatch" that lets me pass parameters directly to the <input> node; it's "bad style", but sometimes useful. Everything I use is backed by a database which has limited typing abilities, so I have a field called "humantype" that declares the human type of the data, so I can then create intelligent widgets for that, too. One of the things we can do, for instance, is create an "image" widget that specifies a URL for an image, and as validation, shows it there in the browser. We could also make it accept uploads. Then, just by labelling a field as an "htmlImage", we get the image editor, no form redesign, no muss, no fuss. Form designers give you small parts of this; you can create a text node, say it's an int, and get automatic min/max, although... they don't pull it from the database, they don't have any understanding of what's going on, etc. In my design, every is some sort of intelligent field, not a bog-standard text box, and the idea of a "field" includes the ability to validate the value inside of it, depending on what kind it is. (Here, the number fields for instance have a bit of code to check min and max. Other fields make sure they reference something real in the database.) By making smarter widgets, and intelligently assembling them in code instead of plopping down stupid (in the programming sense, not the derogatory sense) text widgets here and checkbox widgets there, I can (and have) created entirely *new* objects, and the editor *just works*. Semi-weakness: Vast, labyrinthine preferences dialogs can be a pain, if your "core app" doesn't itself look like one. Still, you'd be surprised in practice how that tends not to come up, especially if your app can already support that sort of thing, in which case it's just another data source. (All the prefs we have in this app fit right into the same model without any hassle, so this isn't a stopper.) The true and major weakness: You can't hire a guy off the street to draw boxes in his designer, connect a couple of events, and call the form done. (Although in practice it's rarely that easy...) You have to be a programmer that can handle a level of abstraction above the raw fields. But the benefits are... ...ultimately, *exactly* the same benefits you obtain from any other layer of abstraction, and with exactly the same tradeoffs and costs, with exactly the same result that *typically* the abstraction is a good thing but every once in a while, mostly on small jobs, it's a loss. Indeed I see this entire argument as isomorphic to "Why would I want to do OO when my procedural code works just fine?", right down to the different programming style it engenders, the difficulty of crossing the understanding gulf, and the initial difficulties. (Regrettably, this style is unpopular and not immediately supported by frameworks or anything, so initially you end up constructing your own.) It even *feels* the same, with the way I don't want to work on forms-based apps anymore because they feel so static and concrete and immobile, just as non-OO procedural does, and the way it takes so much work to do the same thing, over and over again. If this thread is still going in a couple of days, I'll post a screenshot with some labels on it so I can gesture a little more concretely, and I might post some of the source data files, too, if it seems like it would help. The screenshot won't help much, though, because it is in the *behavior* of the resulting app that the true difference is felt. I wish I could point at a consumer app to download, but I think this has not penetrated the general consciousness yet, because in C or C++ this is a *god awful nightmare*. The function signatures necessary to pull this off would put most C programmers off their feed, and would challenge even C++ programmers (God help you if you tried to template any of this...), and the memory management becomes quite exciting. This is going to follow behind the dynamic languages, which actually make it possible, by a few years, and those are only now beginning to penetrate the mainstream consciousness. I would expect that at least among the good programmers, this will be SOP in about five to ten years, with better framework support, but at the moment all I can say is the benefits in the code I can't show you yet (sorry) are overwhelming, and the obvious problems fully overcomable, once you get into the paradigm. Cue the smalltalk "I did this in the 80's and it's been all downhill since then" replies... -- http://mail.python.org/mailman/listinfo/python-list