A reader proposed me the following question:
You are a newbie Windows programmer, although you have a lot of a general programming experience. You want to develop simple Windows GUI applications that will run on Windows 2000 or XP. What would you do? It seems to me that there is no really simple answer.
That’s a really hard question. GUI development is fundamentally different from server development, and there are a lot of things to consider when you decide to go down this path. As he himself pointed out, there seems to be no easy answer.
As I thought about the issue, it occurred to me that all desktop environments on all operating systems I’ve used share those problems. In fact, development for some environments like Linux is even harder than developing for Windows because those environments have more complex GUI architectures, which are flexible and powerful but also lack standardization.
I believe there are two aspects in this issue: first, the development environment itself, that is, the IDE and/or the language and supporting tools in which the program will be written; and second, the toolkit that will be used to interface with the platform’s native GUI or that will emulate it.
Most of the times, those two aspects need to be considered simultaneously because what you choose to solve one of them will limit the choices you have for solving the other. For example, if you decide to develop for Win32 with Borland’s Delphi, you are limited to Borland’s VCL toolkit. (There’s also CLX but it’s not half as useful and mature as the VCL.) On the other hand, if you choose to develop using Python, will are free to pick among a dozen of competing toolkits, each with their relative merits and drawbacks.
Regardless of languages and environments, however, there are some core criteria that must be considered when choosing a new toolkit for GUI development. Some of them are:
- Speed of development
- Run-time performance
- Visual identity
- Easy of deployment
Speed of development is certainly the most important criterion when choosing a new toolkit. Interesting enough, when you discount the effect of the language used, you realize that, in most mature environments, speed of development is a direct function of the simplicity, power and flexibility of the environment’s supporting libraries. Experienced programmers can acquire a new language with whose paradigm they are already acquainted with in much less time than they will take to truly absorb all the APIs provided by the language and its supporting tools.
Productivity when developing GUI application then becomes a matter of how well the GUI libraries support the underlying platform widgets (simplicity), how well a common API is presented to those widgets (simplicity), how far they let programmers go (power), and how easily they can be integrate and extended (flexibility).
Unfortunately, most toolkits in wide use today fail where simplicity is concerned. Visual Basic succeeded not because it had a visual development environment, but because it made really simple to understand what was going on behind the scenes. Programmers could understand what was happening and devise simple solutions for their problems. The same was true for Borland’s Delphi. The ability to visually create a form and put components on it, linking their events together was secondary to the ability to quickly go beyond that to more advanced programming models. I’ve seen many Delphi applications based on MVC concepts where the GUI was created programmatically and whose programmers were an order of magnitude more productive than those who edited their forms visually.
Many visual environments exist only to hide the complexity of the underlying libraries. Programmers who grow used to this kind of environment will have trouble if they need to extend the environment for more complex tasks. After all, programming GUI applications is not just a matter of laying out components on a form and creating code to respond to user-generated events.
Run-time performance is also an important criterion. One of the causes of Java’s failure to gain the desktop was its abysmal performance in the AWT era. Of course, the virtual machine was not as well developed then and that contributed for the failure as well. Swing today is much better, but its performance is still not good enough, especially when garbage collection kicks in.
Most GUI toolkits avoid performance bottlenecks becoming just thin wrappers around the features provided by the underlying operating system, which is also the common way to meet many of the criteria mentioned above.
The most essential aspect of run-time performance, however, is related to extensibility. The path to extensibility must not harm performance. If a programmers needs to develop a new visual component, that component must perform as well as the components native to the toolkit — provided, of course, that it was correctly written. That’s a big problem for toolkits whose main components are wrappers to the operating system widgets but that require programmers to painstakingly draw the components they create in a generic canvas and process all events they wish to capture, incurring in huge performance penalties
Visual identity, that is, the toolkit’s ability to blend with the operating system under which the application is running, is an interesting issue. As long as applications developed with a given toolkit are able to smoothly integrate into the working flow of the host operating system, acting as users expect them to act, rather large cosmetic differences will be ignored. Users expect consistence. Users will not mind if buttons are larger in one application than in another. But they will mind if each application defines a different keyboard binding.
Easy of deployment is obviously essential because no matter how fast you can develop an application, if you can’t get it to your users you are doomed. But as long as the deployment process is transparent, users will not mind it. Applications can run standalone or require virtual machines and run-time environments, but users will not care until they are forced to take actions other than click the Next button in an installation wizard.
Extensibility is also critical because more than often programmers will need to create additional components not considered for the original libraries. Unless the original library can be easily and seamlessly extended, it won’t provide much value for programmers.
Portability is only important if the users are distributed across heterogeneous platforms. Nonetheless, I included it because I think portable toolkits tend to be simpler and more powerful than native toolkits because they need to cope with different environments and the idiosyncrasies of those environments. As a result they are more well thought and more flexible.
Documentation may be one of the most vital aspects when considering a new toolkit, especially if the libraries provided by the toolkit are big. Without documentation, programmers will be hard pressed to understand the fine points of programming against a given toolkit, mainly because there are no toolkits who provide the same API or behave the same way. Even ports of the same toolkit for different languages hide the toolkit’s complexity in diverse ways so that the mindset for using that toolkit can vary with the language itself.
Once we consider all those criteria, we find that most GUI development toolkits in the market today fail to meet many of them. Especially where speed of development is concerned, most toolkits provide too complex interfaces that force programmers to learn a lot of peripheral details about the toolkit’s workings just to code very trivial applications.
C/C++ toolkits like Qt, Gtk and wxWidgets require programmers to understand a mishmash of functions, objects, macros, and include files before they can even start thinking about the application’s logic. They don’t hide complexity. Programmers need to think about signals and slots rather than application flow — models, views, and controllers. Even when those toolkits are ported to other languages that support more productive constructs — like Python, for example — they tend to preserve the needless complexity, instead of making use of the language’s features to create a better API.
I think one of the few toolkits available in the market today that meets most of the criteria aforementioned is Borland’s VCL, shipped with Delphi and C++ Builder. Except for portability across operating systems, the VCL has all other characteristics described above. Although Borland never attained more than a small share of the development tools market, the VCL was so successful within its niche that it inspired a lot of other toolkits like Microsoft’s Windows Forms for .NET (created by one of the guys who helped to build the VCL) and Sun’s Swing for Java. VCL was successful because it was simple to use and extremely extensible. Programmers could create new components based on existing components or from the scratch in a very easy way. And those components could be completely integrated in the existing development environment. They were identical to the components native to the library. Also, if a programmer found a bug in a given component provided by Borland, it was often just a matter of creating a new component that inherited from the bugged one and overrode the offending method to get the application working again. There are still hundreds of thousands of components available in the Internet for Delphi just because the toolkit was flexible enough. Yet, even though it was simple and powerful, it still took a lot of time to understand all the libraries that made up the VCL, and how they interacted.
To finally answer the question posed by my reader, I have to agree with him. There is no silver bullet. Regardless of the toolkit you choose, there will be a lot to learn in order to become proficient with it. And that knowledge will likely be worthless when the time comes to learn another toolkit.
Some toolkits boast about the fact that you can create complete application without writing a line of code. Therein lies evil. That’s a PowerBuilder mentality. You can indeed create applications that require no lines of code. But they will probably be simple data entry applications that can’t be extended and that break whenever a programmers needs to create a more complex business rule. The only successful application in that regard that I know about is Squeak, and that’ s when it’s used as an educational tool.
That said, I believe there are quite a few toolkits that are worthy learning if you intend to develop professional applications. Most of them have serious problems in one or another of the characteristics discussed above, but they all are interesting and productive enough to be a valuable additional to any programmer’s arsenal of tools.
Borland’s VCL, which can be found for free in Delphi Personal, is worthy a try, although it will likely disappear in a near future. Borland is phasing out pure Win32 development in favor of .NET, and newer Delphi versions sport a new toolkit, VCL for .NET, which is a wrapper around Windows Forms. But it’s a good example of what a good toolkit is, and it’s nice to work with.
Windows Forms is also worthy learning. The .NET redistributable is free, there’s a entry level version of Visual Studio for free, and there are some interesting open source development environments. Windows Forms and the VCL are very similar, but they have some interesting differences that merit a look. And it’s the future for Windows as well — or so it’s said.
Another interesting toolkit is wxPython. It’s a port of wxWidgets, but is slightly modified for a Python feel. There’s even an IDE for it, although was still a bit flaky last time I looked. The most interesting things about wxPython are its portability — it’s available in more platforms than you will likely need to support — and the fact that, being based on wxWidgets, it’s pretty solid.
VisualWorks, one of the leading Smalltalk implementations also features a flexible and powerful GUI toolkit. In fact, Smalltalk and GUI development have common roots, with the same visionary as their pioneer. VisualWorks’ toolkit is a bit complex, but its Smalltalk MVC inheritance makes it very powerful. JPMorgan recently chose (PDF, 1MB) VisualWorks for its Kapital risk management and pricing system. They estimated they cut their costs and development time by three because they choose a Smalltalk-base solution.
Were I to choose a development environment today for Windows or Linux, I’d probably pick wxPython (or any other port of it for the project’s chosen language). wxWidgets is not much more complex than the other toolkits; it has the native look and fell of the platforms it runs on; it’s mature (development on it started in 1992); it’s well supported; and it’s also free. Additionally, it has a lot of things built in, like a configuration manager and support for printing, OpenGL, HTML, networking, and Unicode. There are many supporting tools to choose from, including a GUI builder. Other non-trivial tasks, like database access, would depend on the programming language used. Python, for example, has good database support.
Although those toolkits are dissimilar, they offer a broad range of features that will greatly aid programmers in their tasks. There may be no simple answer, but I believe there are good enough answers for the problem stated.