On Sun, 28 Feb 2016 07:44 pm, Chris Angelico wrote: > On Sun, Feb 28, 2016 at 5:34 PM, Steven D'Aprano <st...@pearwood.info> > wrote: [...] >> Drag-and-drop GUI builders have the same advantages over code as Python >> has over languages with distinct compile/execute steps: rapid >> development, prototyping, exploration and discovery. Of course, any >> decent modern builder won't limit you to literally drag-and-drop, but >> will offer functionality like duplicating elements, aligning them, >> magnetic guides, etc. > > Alright, but how do you go about doing, with a drag-and-drop builder, > all those things we're used to with code - composing new named actions > out of primitives, observing the changes to a program through source > control, unit testing (maybe), and code review?
These are all good questions. Let's see if I can give good answers: (1) "composing new named actions" -- I'm not entirely sure what you mean. Do you mean new named *widgets*? A good builder app should give you the ability to Group widgets into a single element, this is functionality which has existed in vector-drawing programs since at least MacDraw in 1984 so it shouldn't be hard. This is composition, a fundamental, powerful and rich design pattern for making new widgets (classes) out of simpler parts. If objects have a name, now you can refer to CompositeMenuDateColourPicker by name. You can copy it, paste it, replicate it 30 times, whatever you like. Possibly the GUI builder will even add it to the "Insert Widget" menu, or put it on the toolbar. Surely the builder app will use a plug-in architecture to control what widgets are available. How easy is it to create new plug-ins from within the builder? This is a "quality of implementation" issue. Presumably a modern GUI builder will have the ability to export to source code, so you can export your CompositeMenuDateColourPicker to a file, then re-use it over and over again in project after project. (2) "source control" -- the world is full of document types that aren't plain text source code, and people have found ways to manage collaborative editing and change management for them. Why don't we ask game developers how they manage changes to the non-code elements in their applications? Textures, icons, player avatars, sound effects, maps, etc. Surely you don't suggest that game developers edit their background images in a hex editor? (3) "unit testing" -- I'm not sure that unit testing is what is needed for the GUI elements of your application. It's more like integration testing, to ensure that the entire application works together as a seamless whole. I'm not sure what the state of the art in GUI application integration testing is like. I suspect crap, judging by the state of the art in GUI applications. But whatever it is, it will surely operate the same regardless of whether you have built the application using code or a graphical builder. (The GUI framework itself may have some analogue to unit testing for the individual widgets, but that's not your responsibility as the user of the framework. It's not up to you to test that menus drop down when clicked, but it is your responsibility to check that the right menus exist and that they do what they are supposed to.) (4) "code review" -- the usual way to review the graphical elements of a GUI app is to call somebody over, sit them down at the running application, and say "What do you think of this?". They will usually answer "that icon needs to be a bit more to the left, and can you make that button blue instead of green?". > The only way I know of > to build a "function" in a DnD builder is to create a composite widget > (eg "horizontal box containing label and entry field"), which is > extremely useful, but limited - it's like saying that the only way to > reuse code is single-inheritance. A poor analogy. Composition is equivalent to multiple inheritance, except without any of the weaknesses of MI. > How would you create a higher-order > operation in a DnD builder? How would you write something that does > some sort of sweep over a set of widgets and does the same thing to > them? In Hypercard, if it was a once-off processing task, I would create a button, edit the button's script: on mouseUp: -- my memory of HC syntax and functions is a bit rusty -- this may not be correct for btnNum in 1 to the number of buttons: if btnNum is the number of me: continue end if set the textsize of button btnNum to 9 set the textstyle of button btnNum to bold,italic if the name of button btnNum starts with "Spam": set the icon of button btnNum to SpamIcon end if end for end mouseUp then I would click on that button and run the script. Then, once I have satisfied myself that it has done what was needed, I'd delete the button. If this was something that needed to run each time the application ran, I would put the script in some other layer of the application, say, in the card layer, in a named handler: on setBtnStyle: for btnNum in 1 to the number of buttons: set the textsize of button btnNum to 9 set the textstyle of button btnNum to bold,italic if the name of button btnNum starts with "Spam": set the icon of button btnNum to SpamIcon end if end for end setBtnStyle then call that handler on some event: on openCard: setBtnStyle end openCard (In Hypercard, the UI model is of a Rolodex or set of cards, once card displayed at a time in a window. Each card can contain widgets and graphics. Displaying a card sends the openCard message to that card, which runs whatever code is in the openCard handler. (Don't be put off by the language of sending messages, that's identical to a method call.) If this sounds kinda Javascript-y, it's because HC is one of the admitted influences of early Javascript. If the business of sending messages sounds kinda like Smalltalk, that's because HC was influenced by it. Apple history buffs will see the influence of Alan Kay and Xerox PARC all over this... Hypercard was not limited to manipulating the state of existing widgets. It could programmatically create new ones. (Apple's Hypercard has a horrible API for that where you literally gave a command to select a tool, then drag from one point to another to create the widget. But later competing products added more sensible commands for this.) If you had a complex layout, you could code that part of the layout, but the point is that you weren't forced to code everything. [...] > This doesn't have to be a dichotomy. I didn't say it did :-) -- Steven -- https://mail.python.org/mailman/listinfo/python-list