Never meddle in the affairs of wizards, for you are crunchy and taste good with ketchup.
This discussion was split off from WizardsAreLazy
, after someone rightfully pointed out the confusion between Wizard-as-programmer and Wizard-as-automated-assist-to-generate-code. This page is about the latter.
And so, when Hansel and Gretel were just little children programmers, they
met a kindly old Wizard, who promised them he could help them build
wonderful applications with lots of bells and whistles on each form.
Hand in hand, they followed that Wizard deep into a wide, dark forest. They
followed this way and that, with many confusing turnings and changes, until
they lost all sense of direction. And when they asked where they were, that
Wizard crashed! He disappeared into a sparkle of GPFs and trashed Registry
"We are so totally screwed," Hansel admitted to Gretel, looking at the tall
dark trees in the pathless forest they were in.
"Chill," advised Gretel. "I left a trail of VersionControl
behind us. We can follow each revision, to see what that Wizard was really
doing while he talked to us of magic windows and widgets and stuff!"
"Righteous!" exclaimed Hansel! "That's what pairing's for" advised Gretel.
So, following the trail of source code drops, backwards, they learned what
that Wizard had actually been doing under the surface. And, in time, they
found their way back out of that forest, exhausted from their experience,
but just a little bit wiser.
Acronyms Used: COM ATL FWIW
programming. This is especially the case with VisualBasic
, which removes you from COM altogether. For instance, the Create
Object call can result in more than 12 ComponentObjectModel
calls. I have been called in too many times to find that some clueless person has just pressed some buttons in the VisualBasic
or Visual C++ product and has no idea
whatsoever what is going on and how to even start debugging the problem. Yes, the ComponentObjectModel
wizards save a lot of code and are an essential starting point for ATL based code, but one must understand what is going on underneath!
I agree and would go even further. I find that I prefer to code ATL by hand and don't use any of the wizards. What I do is common enough between projects that it can be broken into a few skeletons and abstract classes. Then again, I even prefer coding Human Interfaces by hand rather than using visual design tools. FWIW, I don't consider myself less productive than other programmers who use Wizards and Designers and I certainly spend a lot less time refactoring Wizard code or trying to get my code back into the Designer. [I should note here for the pedantic that I am not referring to resources, I don't code resource files (things like dialog resources and such) by hand, just the code they use.] -- RobertDiFalco
Good points. I code all my IDL my hand and most of my ATL by hand as well. I find that when you understand things, it's just simpler that way.
These are excellent points and discussion, Sam and Robert. I completely agree - Wizards (or more precisely wizard-generated code) do NOT fit in where efficiency and performance are key. I've seen this many, many times in Smalltalk and Java - in fact, it has come close to *killing* some EJB applications I've worked with. However, this leaves us in a quandary. How do we best balance efficiency with ease of use and training? Do wizards need to be more customizable or smarter about dealing with code optimization? How about letting someone customize *what* code is generated by the wizard with a domain-specific language?
How about designing class libraries and frameworks that are easy to understand, learn and use? For example, Tcl/Tk has never had wizards or a popular user interface builder: it has never needed them because Tcl extensions are usually suitably high-level and the Tk toolkit is so simple yet powerful.
The language provides a lot of this. Tcl makes it very easy to seamlessly extend the base language with domain-specific sub-languages. The same is probably true about SmallTalk
and other languages with a tiny but expressive syntax. It's harder to write simple frameworks in less flexible languages, such as Java or C++, but one can do better than many current libraries (Swing comes to mind!).
I think that good class libraries and frameworks are a necessary but not sufficient condition. I myself never had problems programming directly in Smalltalk's Windowing system. Probably Sam could say the same about Windows and COM. However, both systems quickly evolved wizards and code-generators because even simple
programming is too much for some people.
- Which prompts the question if these people should be programming at all.
I think that we need to think more about how to build wizards and code generators to make it easy to extend and customize THEM. DonRoberts
wrote a neat little patterns paper a few years ago on patterns for domain specific languages. That was the start of something, but we need to explore it more and get it into wider use...
Kyle, good post. I agree. In this day and age of E-commerce sites going up like gangbusters and people being hired after doing a three month web program at some local community college, even simple
programming is too much
for some people. Then there is the myth that ComIsHard
. People don't want to spend the time anymore to learn things thoroughly. MattPietrek
was lamenting the fact that no one knows Intel assembly language anymore, so his or her debugging skills are severely compromised. He advocates learning a small subset. It used to be in the Windows world, that people knew this stuff. The other factor behind wizards and code generators in the case of the ComponentObjectModel
is the sheer amount of code and boilerplate code. Everyone has to write an IUnknown interface implementation. It is better to let ATL do it. No one wants to write IUnknown and IDispatch implementations over and over. Indeed, this is one of the advantages of JavaBeans
components. One just writes the code and follows the conventions and out spits a JavaBean
. By the way, look for MicroSoft
to move in this direction (that's all I can say!!)
But your point is well taken about building wizards that let us customize them and extend them. I would like to see Ralph's paper.
...look for MicroSoft to move in this direction...
Haven't they already with COM+? Back to an earlier point about assembler, I think this may indicate something good. It shows that higher-level languages are starting to work better. Things used to be so flaky you had no choice but to jump into assembler. What astonishes me in Windows development is that I have run into programmers that don't even know about the Windows symbols files (or even what they are) and are happy to debug C++ code without them! It's not that they can read the machine code, it's that they never go deep enough to care what the call stack is below their symbols. Wow! Then again, maybe that's good too. I dunno. -- RobertDiFalco
Well, Robert, they are moving even more in that direction than COM+ but I'd have to kill you if I told you -)). We are working with Microsoft stuff 2-3 years out. Anyhow, it's true that higher-level languages are working better but there is a point to "Just enough Assembler to Get By." In many cases when your application crashes, the real difference between solving the bug and screaming in frustration comes down to how well you can read a little assembly language. Although we'd prefer our crashes to occur in a module with source code and a complete call stack, many crashes just don't happen that way. When you do crash, you're generally left looking at a DisassemblyWindow
in the Microsoft Visual C++ debugger and wondering how you're going to figure out where you are in the program, let alone why they crashed. There is a huge difference between a 3 month Web Certification graduate and a solid software engineer. MattPietrek
like to say:
- Know your project
- Know your language
- Know your technology
- Know your operating system
- Know your CPU (only 8 hours of assembly language study needed for Intel)
because it gets us away from this.
In the Java world, does "know your CPU" mean know your runtime environment?
I've met an architect who said "Don't show me that in the book, I only trust code." I asked him for the SpikeSolution
code he has, and he said "but it doesn't work". (He previously told us to write a custom Java-to-Word component using JNI and COM. He knows our team has no COM/ActiveX experience or training and still insists we can do it in a month. He says JNI is "easy", because he's got a trivial example working. He's helped us by writing a .dll in VB, but he doesn't know whether it's a COM component. ;-) He also claims that software is the flakiest industry in the world. Since I met him, I've learned one reason why that might be true. (I'm seriously tempted to buy him a copy of "ThePragmaticProgrammer
" and highlight the section entitled "Evil Wizards" - but what's the point? He won't read it or think about it.)
Most of his code is written by Borland and Oracle. It worries me when I keep hearing the phrase "such-and-such have a hand-cranked
solution". Translation: "they worked out how to do it properly". Borland and Oracle won't save him - they just want to sell software. Knowing enough about what you're doing is a matter of professional responsibility. I don't see any sign of this person being remotely willing to learn how to do what he's committed himself to deliver.
This is proving to be an interesting life experience.
I think this may win the "Flakiest Architect" award. JNI is NOT easy, as anyone who has ever written more than 10 lines of code will know. However, wouldn't this go in the WizardsAreLazy section?
Indeed it could do. (I think I remember reading WizardsAreLazy
a little differently a few years ago - when it talked about how human "wizards" (aka Gurus) seem to be less productive because they're dealing with things that are less visible or lower-level. From the unenlightened point of view, clueless-code-generator-jockeys would appear to be a lot more productive, until their work falls apart due to lack of care and understanding.) --
Since everyone else seems to be just nodding sagely, I'll speak up in defense of wizards (the tools, not the gurus). Wizards are dangerous, yes, but they are also extremely useful. When you come to a new system, a wizard is usually the fastest way to get underway. Since you have to learn how to use the system somehow, and since one of the fastest ways (possibly the fastest/the only way?) to learn is new systems is from working on live code with a project in mind, using a wizard seems to me to be the most Pragmatic approach. Wizards may be limited tools, but in my experience, they beat sample code and books when used as teaching aids, and when you have working engine code, which needs a UI on an unfamiliar system, they're the fastest way to get going. Most wizards don't write particularly bad code, so there's no significant difference from suddenly having to maintain someone else's code, except that you were in the position to make the decision to accept that maintenance role.
Incidentally, I found the "Evil Wizards" tip in ThePragmaticProgrammer
extremely unconvincing. None of the points it makes are well argued; they're just handed down from on high. Take, for example, their tip; "Don't Use Wizard Code You Don't Understand". They claim that "code that becomes an integral part of [your] application" is in some way different from "the code in supplied libraries", because "no-one should be producing code they don't fully understand". I'd say that they are right: it is different. You always have the source. If you have the time and motivation to understand it, you can. On a new system, you have a choice. You can hit the books, try to learn everything there is about the system, and get nothing done for the first two weeks. Or, you can use the wizard/sample code and accept that you may be exposing yourself to some bugs in exchange for a short-term leap in productivity. Given the benefits of learning from working code, together with the difference in how you look to Management, I'd say that using the wizard is normally the smart move. Once the wizard code becomes the biggest unknown in the behavior of your program, or if it starts behaving strangely, you can set aside time to understand it further. Trying to be aware of the amount you don't understand is better than trying to understand everything. -- AnAspirant
Ok, I'll bite on that. Wizards are OK if you are learning the system but I will still contend that they often have no place in production code. Let's say that you are successful in using a wizard to generate something you don't understand. Let's then say that you then go on to proceed along this path of using wizards for four months and then produce a major part of your system. Then, a year later, the tool vendor comes out with a totally different paradigm for doing what your wizard did. What are your options? If your vendor isn't kind enough to provide a converter, you're out four months of work. BTW, this is a *real* example of what happened to many of our customers when IBM switched from the CCF (Common connector Framework) to the JCA standard - and the wizard-generated code was *not* portable... It still seems to me to be unwisely sacrificing long-term maintenance for short-term gain.
It's not clear from that that any other method would have prepared you better for that. Equally, if they had provided a converter, those who had used the wizard would be laughing. Wizards are an opportunity for those who provide systems to teach the basic design idioms which work on that platform in a concise and effective way. I agree that it's sacrificing long-term maintenance for short-term gain, but that's just like any other trade-off in programming. Sometimes it's the right way to go. Certainly you should try not to couple your code any more tightly to the wizard code than you have to, but in my experience, you understand the wizard code in your app a long time before you understand the rest of the system it's layered on.
As a thought experiment, say you run a wizard and it spits out code. Can you really justify spending the next two days starting again from scratch trying to replicate the functionality you were just given on a plate by someone who actually understood the system? And if you really understand the system better than the author, why not just clean up (I'm sorry, "refactor") the wizard code?
The first is that programmers, like most humans, don't want to be automated out of existence. Fear does play a part in this.
The second is that wizards for code just shouldn't exist. If they're so good at a general solution, the code should be in a framework or object somewhere.
Automated assistants are very helpful when configuring a complex system, such as a web server or OS. They're not as good as a programmer for development, since they: add more code that needs to be maintained, thought about, etc; cannot think abstractly; and cannot capture the art involved with programming the way that a coder can. It's CopyAndPasteProgramming
to use a wizard.
"Can you really justify spending the next two days ... trying to replicate the functionality you were just given ... by someone who actually understood the system?
Yes. What if there's a bug? [You fix it. --AA
] What if you have to refactor it? [You refactor it.
] What if you have to modify it to further suit your needs? [You ...
] Better to take time to understand a system than to just cut and paste and pray.
Furthermore, any API that is sufficiently complex as to need a wizard should be put down, or have a Facade or Bridge pattern between it and you.
Sort of a rant, but... there it is.-- JoeOsborn
With respect to the "What if"s, all I can say is to reiterate that YouHaveTheSource?. It's lovely that you want to have written all the code yourself, but in my experience, it's seldom an option. 99% of coding isn't
art, it's just coding that needs doing. (I've yet to see wizard-generated code which wasn't trivial to understand for anyone who could have written equivalent code from scratch.) I suspect that language/environment experiences make a big difference to your pov on this. C++ has brought out the resigned pragmatist in me. I agree with your second point, but it's irrelevant - you either use the wizard or not, you don't say, "this should be a framework" (I often have to work with systems that should be put down). Basically, I just think that GetItWorkingFirst? is more important than almost everything. A more XP-centric claim would be that to use a wizard is to DoTheSimplestThingThatCouldPossiblyWork. --AnAspirant
Gobs of wizard-generated code go against the OnceAndOnlyOnce
principle. To use wizards is to do the easiest, laziest, or hastiest thing, but it is not the simplest thing. I could make a table by throwing a pile of readily available stuff on the floor and balancing a flat surface on top of it: this might be the easiest, laziest, or hastiest solution. It might even meet my requirements for a table in the short-term. For a simpler solution, consider a board spanning two boxes. The table is still a pile of junk, but it will be a little easier to move or adapt it to a new situation. The first refactoring of the table has gone well!
We should seek not to confuse simple with easy.
I am a newbie who is currently struggling through an infinite mountain of incomprehensible documentation. Here is my 2 cents to add to this discussion:
"wizard seems to me to be the most Pragmatic approach. Wizards may be limited tools, but in my experience, they beat sample code and books when used as teaching aids"
Nothing can beat sample code and books.
Especially well written books with well maintained links to further information.
Wizards are fine.... as long as they come with their source code for anybody who is interested and a chapter or two on how they work....
"You can hit the books, try to learn everything there is about the system, and get nothing done for the first two weeks. Or, you can use the wizard/sample code and accept that you may be exposing yourself to some bugs in exchange for a short-term leap in productivity"
Take the long-term solution.
Understand your code, and document it so that other people can understand it.
What is the use of incomprehensible code?
I think this applies equally to virtual wizards and human wizards. The gurus out their should take better care of us newbies. Just because something is obvious to YOU doesn't mean it is obvious to EVERYBODY. If you think you understand something, but you can't explain it to anybody else, then you don't really understand it,
My problem with wizards is that they tend to create stove pipes. .Net is a good example, where if you use the designer you end up with an unmanageable mess of forms bound to datasets bound to connections bound to stored procedures. This can be deadly for inexperienced programmers. --pjl
I concur that wizards are dangerous, and the reasons have been well-explained for the most part. Here is what I do about it...
First and foremost, I always work towards understanding, so I don't tolerate a lack of understanding of my tools, language, platform, etc. for very long. I read all the manuals, do the tutorials, google for decent examples, and tear it all down until I can build it back up as a solid "house" on a solid "foundation". That usually takes me anywhere from a few hours to a few days.
So, when I must start on a new set of tools, languages, platforms, etc. (typically with every client and project, to some degree), I might use a wizard to generate my first form or wrapper or interface implementation, etc. as part of an application. Then I read, comprehend, and tear apart the resulting wizard code. Sometimes I reimplement it as a proper framework. Sometimes I refactor it in place. Often, I figure out how to do it better and I throw away the wizard code altogether. I have never encountered wizard code that was worth keeping in a production system, and I don't expect ever to do so. I have no intention of ever creating a code-generation wizard.
I have used code generation, and I use StringTemplate?
to do it, but I see it as a failure every time I must resort to such an effort--code generation is a form of CopyAndPasteProgramming
. However, I refactor mercilessly, both the code generation templates and the underlying framework, until the generated code is as simple and light as I can (un)reasonably make it. The last time that I had to do such code generation was in 2002-2004 when my project team "wimped out" and resorted to using a strongly-typed dataset as the object model for about two hundred database tables in a business application. I had already built a real object model with a full unit-test suite, but the other developers did not grok
objects and the PointyHairedBoss
insisted that I help
As an aside, I love using StringTemplate?
for true templating, such as for creating HTML, but that is not the same thing as a code wizard or general code generation.
My brother, who is just learning many of the principles that we are promoting here, nevertheless has always rejected and distrusted wizard code. He has done years of VB and .NET forms and web pages, but he independently adopted the same approach of using the wizard to produce an example and then tearing the code apart.
In my humble opinion, wizards are typically created by business mandate to artificially expand the market for a developer-oriented product (e.g., Visual Studio, WebMethods
) by providing a crutch to people who otherwise would not attempt to be programmers. I have yet to see a case where the resulting wizard code and surrounding "application" were worth keeping and maintaining. I can not justify such use even for so-called prototypes
since they inevitably become production.
Nonetheless, wizards are unfortunately part of our reality.