Pinderkent

Pain and glory from the trenches of the IT world.

Higher-level languages aren't about making experts more productive. They're about allowing average programmers to do the otherwise impossible.

Posted on Saturday, March 28, 2009 at 11:41 PM.

I read an article today about whether higher-level programming languages like Python, Perl and C# are really that much more productive than a comparatively lower-level language like C. This is not a new line of discussion, by any means. But we're getting to the point where we've been using such higher-level languages for over a decade, and thus have had more of an opportunity to observe and analyze how successfully (or not) they've been used.

In my view, that article comes to the general conclusion that many of the popular claims regarding the benefits of high-level languages versus low-level languages don't hold true. It's suggested that languages like C do indeed have aspects that hamper developer productivity, but high-level languages bring their own, albeit different, set of problems. While a C developer may run into problems with pointers, a Perl programmer might lose a similar amount of time optimizing regular expressions.

I think the conclusions of that article are correct to some extent, but I also think that the greater picture may have been missed. The real impact of languages like Python, Ruby, Perl, JavaScript and PHP isn't that they allowed expert programmers to be marginally more productive. Their greatest "benefit" (or arguably their greatest disadvantage) is that they have allowed average and even poor programmers to accomplish things they couldn't have reasonably done in C.

PHP and JavaScript are good examples of this. As anyone who has used them knows, they are very unremarkable languages. Conceptually and syntactically, they're much like C in many ways, but without some of the aspects of C that average developers often find bothersome. They aim to eliminate manual memory management, for instance. They offer slightly nicer string handling. Their execution environments aren't as tied to the native hardware. But otherwise, the core PHP and JavaScript languages generally offer the same basic functionality that C offers.

By eliminating some of the more difficult aspects of C, even if they're not as flexible or as powerful in many ways, they've made programming accessible to people who otherwise would not have been able to handle it. I've had the misfortune of working with people like this. They can understand the concepts of variables, constants, loops, conditionals, functions and even the basics of OO to some extent. But they're totally unable to understand some of the basic, yet essential, concepts of C. Pointers, for some reason, is a common one. But luckily for such average developers, languages like PHP and JavaScript make their lives easier by getting rid of such constructs and functionality.

So we soon enough see these average developers using languages like PHP and JavaScript to develop applications. In many cases, there's little to nothing preventing the same application from having been developed using C, aside from the inability of the average developer or developers to use C. Anyone who has worked in the industry knows why businesses opt to go with such solutions. Sometimes it is cheaper and easier to hire several PHP and JavaScript developers, instead of just one or two expert C developers. Other times it's because inexperienced or unknowledgeable managers just don't know any better, or have bought into hype and marketing. Regardless, the outcome is typically a system that just barely works, assuming it's not outright broken. Whatever costs might have been saved initially end up becoming far more costly in the long run.

Had those JavaScript and PHP developers been forced to use C, it's likely that we wouldn't have seen any sort of a software system be produced at all. They would've still been struggling with significant memory leaks, segfaults, and sometimes even just getting their code to compile. So we can see the actual main benefit of such higher-level languages; they've reduced the complexity of an otherwise difficult skill down to something that is more palatable to non-experts.

Now, we need to ensure that we don't lump high-level languages like Haskell, Erlang, and Common LISP in with other high-level languages like PHP and JavaScript. They are clearly very different. Haskell, Erlang and Common LISP, for instance, use abstraction to empower the developer. They offer advanced features and techniques that expert developers can build upon to great benefit. This is very different from languages like PHP and JavaScript, which clearly took the C model of computing, and stripped out the parts that make C more awkward for the less-skilled programmers.

Even thought they are significantly higher-level languages than C, languages like Erlang, Haskell and Common LISP haven't become as popular because they still require a high level of knowledge and expertise to use for even the most basic of tasks. So they highlight the important difference between a language being "high-level" and a language being "accessible". Functional languages increase expert programmer productivity with more powerful abstractions; PHP and JavaScript increase average programmer productivity via simplification.

The whole debate with respect to whether high-level languages are better than low-level languages will likely rage for many more years. There are some tasks that just can't be done in languages like JavaScript and PHP, so we will surely see C remain around for a long time. But we likely will see languages like PHP and JavaScript remain around for a similar reason. Unfortunately, that reason won't be about allowing good developers to develop more advanced software more quickly, but rather about letting poor developers continue to put out just barely suitable software systems.

Permalink: http://pinderkent.phumblog.com/post/2009/03/higherlevel_languages_arent_about_making_experts_more_productive_theyre_about_allowing_average_programmers_to_do_the_otherwise_impossible
Share:

Getting to know today's practical GUI toolkits.

Posted on Tuesday, March 24, 2009 at 1:23 AM.

For years now, Andy Tai has done a great job of maintaining the The GUI Toolkit, Framework Page. It's a very extensive list of GUI toolkits and frameworks, both open source and commercial, for a wide variety of languages and platforms. In fact, it's almost too complete. Many of the toolkits listed are no longer developed or became obsolete years ago. So my aim here is to narrow down his huge list to the toolkits and frameworks that are practical, from a developer's perspective, and worth using today.

First and foremost, we have Qt. Many consider it to be the premiere C++ GUI toolkit. That's not surprising, of course. It has a long history of being developed as a commercial product, first by Trolltech and then by Nokia after they acquired Trolltech. Nevertheless, it has also been released under a variety of open source licenses throughout its lifetime. Given its maturity and use in a wide variety of software systems, including KDE, Opera and Google Earth, it has become known as a very reliable, portable, high-performance and high-quality toolkit.

Although Qt is written in C++, a variety of bindings have been developed for other languages. Some of the most notable include QtAda for Ada 2005, PyQt for Python, PHP-Qt for PHP, QtRuby for Ruby and qtHaskell for Haskell. In short, it proves to be a great toolkit, almost regardless of what language or platform you're using.

After Qt, we can consider wxWidgets to be the next most practical GUI toolkit. Like Qt, it is written in C++, is available under an open source license, is extremely portable, and can allow for the development of a professional-grade UI. Also like Qt, there are bindings for a number of popular languages, including wxPython for Python, wxRuby for Ruby, wxHaskell for Haskell, wxPerl for Perl, and even wxErlang for Erlang and wxLua for Lua.

One of the main benefits of wxWidgets over other GUI toolkits is its use of native controls. This allows applications developed using it to integrate nearly seamlessly with the host operating system, even while remaining somewhat portable. So while other toolkits offer themes that try as best as possible to emulate the behavior and appearance of the native platform's UI toolkit, this is often done imperfectly. A perceptive user will know they're not using a native application. But with wxWidgets, we typically don't find this happening.

After wxWidgets, GTK+ can be considered the next most usable toolkit. One difference that it has from Qt and wxWidgets is that it is written in pure C, rather than C++. While this makes language bindings easier to develop, it does have some drawbacks. One such drawback is that it makes extensive use of the GObject object system to provide object-oriented-like functionality for C. This typically feels inferior to using an actual OO language.

While it is portable to other platforms, its origin as an X Window System toolkit can still be felt. Applications using the Windows port of GTK+, for instance, typically don't truly feel like a native Windows app. Nevertheless, the Windows ports of applications like GIMP and Inkscape are usable and reliable. For the best experience, however, it's usually recommended to use GTK+ applications within an environment such as GNOME or Xfce, both of which are built upon it.

Like wxWidgets and Qt, GTK+ also has a wide variety of language bindings. Some of the most widely used include gtkmm for C++, PyGTK for Python, Gtk2-Perl for Perl, Ruby-GNOME2, PHP-GTK for PHP, Gtk2Hs for Haskell, Gtk# for the languages supported by Mono and .NET, and LablGTK for OCaml. Unlike Qt and wxWidgets, which are quite usable for large applications written in their native language (C++), it's probably best to use GTK+ from one of its more mature bindings, such as gtkmm, PyGTK or Gtk#, rather than from straight C.

Swing is relatively old and well-known. Originally Java-centric, it is becoming a more viable option as languages like Scala and Clojure, which target the JVM, become more prevalent. Other language implementations targeting the JVM, like Jython for Python and JRuby for Ruby, make it even more usable. Unfortunately, it does have a number of problems. It has never been known for offering high performance, and is somewhat memory-intensive. Applications written using Swing never truly feel like native applications, even when using a platform-specific theme. The API itself is also quite messy, having accumulated much cruft after a decade. And many developers don't want the extra baggage associated with the Java runtime, which makes it less appealing for those not writing an application specifically for the Java platform.

The FOX Toolkit is likely the most practical toolkit after Qt, wxWidgets, GTK+ and Swing. Like Qt and wxWidgets, it's written in C++. But unlike them, it doesn't offer as much of an accompanying framework. So in many respects it's a much more lightweight toolkit. And unlike some other toolkits, it doesn't (yet) include support for themes, so it has its own unique look and feel that is reminiscent of the traditional Windows look and feel. Nevertheless, it is portable and released under an open source license.

Unlike the aforementioned toolkits, the FOX Toolkit doesn't have as wide of a variety of language bindings. FXRuby for Ruby is a mature and usable binding, but others, like the FXPy binding for Python and the EiffelFox binding for Eiffel, have stagnated. So the FOX Toolkit is probably best used from its native C++ or from Ruby.

FLTK is similar to the FOX Toolkit in many ways. It's also written in C++, is portable, and is more lightweight than toolkits like Qt and wxWidgets. Unfortunately, it doesn't have as many bindings for other languages, and the ones that do exist (like the Ruby wrapper and pyFLTK for Python) aren't updated very frequently. So while FLTK is usable, it probably isn't the best option for more complex applications that are expected to have a long lifespan.

There are many other GUI toolkits out there, both commercial and open source. In terms of cost, portability, usability, user-experience and programming language interoperability, the toolkits mentioned above are typically the best options. Qt is perhaps the most flexible option for writing high-quality, portable GUI applications, followed closely by wxWidgets. GTK+ is good for software running on UNIX-like systems, but doesn't offer as seamless as an experience on other platforms. Swing is typically the choice for those targeting the JVM. And toolkits like FOX Toolkit and FLTK provide alternatives for those who don't want the baggage of the larger and more complete frameworks. While no toolkit is perfect for every piece of software, picking Qt, wxWidgets, GTK+, Swing, FOX Toolkit or FLTK should prove to be a safe, viable, practical and capable choice.

Permalink: http://pinderkent.phumblog.com/post/2009/03/getting_to_know_todays_practical_gui_toolkits
Share:

The Java platform needs an overhaul, not just the Java language.

Posted on Sunday, March 22, 2009 at 4:28 PM.

There has been some discussion lately on several blogs about Java and its feasibility as a programming language for practical development these days. The articles I'm talking about are Bruce Eckel's "The Positive Legacy of C++ and Java", "Java as Legacy Language" by Kas Thomas, and "Is it time to retire Java?" by David Arno.

The general theme of all three articles is that the Java language has not kept up with the times. That's not to suggest that it's useless or will disappear any time soon, however. Anyone with experience in industry knows that there is an absolutely huge amount of Java code out there, critical to many business operations. But it is true that Java does not offer the productivity it once did. Relative to languages like C and C++, it did allow for more complex systems to be developed with less effort, and in a shorter period of time. But languages like Python and Ruby have been attacking it from beneath, and now prove to be a better option for many software development projects.

The general feeling after reading those articles is that although the Java programming language isn't as beneficial as it once was, it did provide us with the JVM, and this in turn proves to be a useful platform for languages and implementations like Scala, Clojure, JRuby and Jython.

I'm not so sure that this is the case. The JVM has never really been a spectacular platform. Performance problems have plagued it from the very beginning. Some of the problems are inherent to the Java language itself, namely in limiting what optimizations the compiler, runtime and programmers can perform. Although there have been improvements relating to JIT compilation, for instance, I think a lot of the performance problems of Java have only been mitigated somewhat by hardware consistently getting much faster during the late 1990s and most of this decade.

When the topic of Java performance comes up, some people like to toss around various microbenchmarks showing that some obscure task can be done relatively quickly using code running on a Java virtual machine. Unfortunately, these results don't translate well to the real world, where applications tend to be far more complex. Part of the reason why desktop Java apps never really took off, for instance, was because most of them felt sluggish relative to other applications written in languages like C and C++. Application startup time has also always been a problem with applications running on the JVM. Were it not for server-side applications typically being long-running and typically running on more powerful hardware, it's doubtful that Java would have made the inroads it managed to make there.

Bloat is another issue plaguing the Java platform. The earliest versions of the runtime had installers that were 2 to 5 MB in size. While that seems like almost nothing today, in the mid-1990s that was a hassle to download over a dail-up connection, especially if one was paying by the hour. Although not as much of a problem now due to the prevalence of broadband Internet connections, the Java 1.6.0_12 runtime installer for x64 Linux is still relatively large at over 18 MB.

Even today, with many computers having two or more gigabytes of RAM, we see Java applications using a disproportionate amount of memory. On Linux using Sun's 64-bit 1.6.0_12 runtime, we see the Scala 2.7.3.final REPL using 593 MB of virtual memory, with 153 MB resident, as reported by top. And this is just after starting up the REPL while it's still at its first prompt, without having entered any expressions that may have increased the memory usage. Some applications are even worse. Just after startup, before loading any projects, NetBeans 6.5.1 is already using 1029 MB of virtual memory, with 249 MB resident. We can't blame just the JVM for such problems, but we also can't overlook its involvement.

The Java class library was once one of the key selling points of Java and the Java platform. It provided a lot of common functionality in a manner that could be easily reused by developers, thus increasing their productivity dramatically. But over the past decade, we've seen a variety of libraries for other languages arise that provide the same functionality, but often with much nicer and effective abstractions or APIs. Microsoft's .NET class library is one of the most widely used. Faced with such competition, the Java platform just doesn't look as attractive as it once did.

The Java class library is also starting to really show its age. While many classes and methods have been officially deprecated, they do remain around cluttering up the library. Others, like the AWT, are impractical for use today, but still must remain around due to later technologies, like Swing in the case of AWT, being built directly upon them.

Furthermore, a great deal of the classes don't make good, if any, use of generics, enumerations and the various other language features introduced since Java 5. The benefits of having such language features in Java are negated when many of the core library classes we use don't support them. We're often stuck still using integer constants where enumerations would be much more appropriate, for instance. Unfortunately, there is great reluctance to change the library in ways that would impact compatibility with older Java applications. So it's unlikely we'll ever see these problems fixed up appropriately.

When it comes to running non-Java languages on the JVM, we end up with even more problems. A language like Scala offers features, functionality and concepts that we just don't find within the scope of the Java language. So although it can be used, actually using the Java standard class library from a language like Scala negates many of the benefits of using the newer language in the first place. While such interoperability and reuse is often touted as a benefit of using advanced languages that target the JVM, I fear it's actually a significant downside, as it doesn't promote the effective use of the new language features that really do boost programmer productivity or application quality. They're crippling themselves by trying to reuse existing code that doesn't fit their philosophy.

So while languages and implementations like Scala, Clojure, Jython and JRuby are bringing more impressive languages to the JVM, they can't really do anything about the poor performance or the excessive resource usage of the JVM, nor can they do much about the poor state of the Java class library. But I'm also not suggesting that we have a viable alternative. Even though they recently released Parrot 1.0.0, it's still not a platform suitable for widespread production deployments. The Mono project is making some good progress, although they're typically playing catch-up to Microsoft's implementation, and don't have complete freedom to dictate how their runtime should behave. LLVM is perhaps the most promising alternative, but as the name implies, it is very low-level, not offering functionality we've come to expect from virtual machines (like garbage collection).

If the Java platform is to continue to serve us into the future, I suspect a significant overhaul is necessary. Performance and memory usage improvements to the JVM would be of a huge benefit to many. Better support for acting as the target of non-Java languages would likely be beneficial, as well. And a complete cleanup and reworking of the Java class library is a must. Unfortunately, this would not be a small undertaking, and would require huge amounts of time and effort. So it seems unlikely at this time that we'll see such a rework occur. This is somewhat unfortunate, as now is probably the best time to do it, while languages like Scala and Clojure have really started to mature, but just before they become so widely used that momentum against change develops.

Permalink: http://pinderkent.phumblog.com/post/2009/03/the_java_platform_needs_an_overhaul_not_just_the_java_language
Share:

"Adaptive PHP" techniques help ensure bugs, unmaintainability, and other problems.

Posted on Friday, March 06, 2009 at 2:34 AM.

The recent 6 Signs of Adaptive PHP article gives some examples of different PHP coding techniques. Unfortunately, it only bothers to cover the supposed "benefits" of each, without any consideration of how such techniques can prove to be problematic.

The first technique suggests passing all arguments to a function within a single associative array. The supposed "benefits" all promote laziness, namely in that all parameters become potentially optional, and less or no change is needed to any invocations of the function if parameter changes are made.

Not mentioned in that article were the drawbacks. One obvious problem is the vastly increased verbosity, both when it comes to handling default values, and when it comes to invoking the function. Default parameter values, as offered by languages like C++ and even VB.NET, are syntactically superior to this approach.

Even the very concept itself is flawed, as it's much better in terms of maintainability and clarity to have an explicit list of parameters. For one thing, this technique makes it much less obvious to other programmers how to call the function. Given the general lack of documentation associated with most PHP applications, it's likely that anybody wishing to use the function would have to consult the code of the function itself. It also inhibits the ability of the interpreter to check that the correct number of arguments have been passed to the function.

Furthermore, if one has a function that has so many optional parameters that such a technique is needed, perhaps too much is being done in that single function. It would appear that such a function is a good candidate for heavy refactoring.

The second suggestion recommends checking for functions and classes before making use of them, such as those exposed by a plugin module. This sounds risky. When it comes to plugins, the host application should insist that any plugins conform to a strict API. Working with plugins that may just decide not to export a certain required function, for instance, is a recipe for disaster. If a plugin module doesn't provide the proper interface, it should not be loaded.

The third suggestion is perhaps the only one that's sensible. It suggests using require_once() to prevent multiple inclusions of some external PHP code. Indeed, this typically is a good idea.

The fourth suggestion recommends that associative arrays be used to return multiple values from a function. While this isn't as bad of an idea as the use of an associative array to store parameter values, this seems to indicate that PHP should offer a more lightweight construct such as the tuples found in languages like Python and Standard ML. Sticking with what PHP already offers, perhaps even an object could be returned, rather than an associative array.

The fifth suggestion recommends the use of an __autoload function. The very existence of this function suggests that PHP has some serious shortcomings when it comes to allowing for the sensible separation of code. On one hand, this sort of dynamic loading is the sort of functionality that PHP should offer transparently.

Furthermore, it indicates a laziness on the part of PHP developers who wish to write code making use of classes defined in other source files, but who are unwilling to put forth the small amount of effort needed to explicitly include such files.

In addition, the three notes in the __autoload documentation should make developers hesitant to use such functionality. It appears that it interferes with the semantics of exception handling, it's not available when using PHP in its interactive mode, and has risks associated with the validity of the class names passed to it. Frankly, it sounds like yet another PHP "bandage" meant to patch over problems in the language and programmer laziness, while at the same time introducing far more severe problems.

The final suggestion recommends that the directory of the script be determined by calling dirname(_FILE), especially for the purposes of location other PHP files to include. For the given example, the use of a relative path should be sufficient.

The PHP community has a long history of not fixing the problems with their language and its most common implementation. Far too often we've seen "solutions" like these, which end up being messier and more convoluted than had the problem with PHP itself just been fixed sensibly. It's no wonder that so many PHP Web apps are buggy, full of security holes and essentially unmaintainable; the language itself is inherently broken, the workarounds are just as broken and full of caveats, and together they result in nothing but problems.

Permalink: http://pinderkent.phumblog.com/post/2009/03/adaptive_php_techniques_help_ensure_bugs_unmaintainability_and_other_problems
Share:

Ruby has always been about getting it done quick and dirty.

Posted on Saturday, January 31, 2009 at 11:06 PM.

I read an article today lamenting the lack of good documentation accompanying the recent Ruby 1.9.1 release. While very true, I think it's a result of the general nature of the Ruby community. The general attitude has often been a preference towards the typical "quick and dirty" approach. Performance, maintainability, feature set and documentation have often taken a back seat.

In some cases this is a good attitude to talk. It has made Ruby and Perl useful languages for many system administrators, for instance. They can quickly write one-off scripts with minimal effort. But for software development on a larger scale, those typically aren't good languages to use. There's nothing stopping them from being used, of course. It's just that the end result often isn't of a high quality, and maintainability is often a huge nightmare.

Python is often much better in this regard. The community has generally taken a more careful approach, with greater emphasis on correctness and quality. We see this reflected not only in documentation that actually exists, but documentation that is very informative and clear. So while you many not be able to develop a one-off script as quickly with Python as you could with Ruby or Perl, Python does lend itself towards larger-scale application development.

I have recently worked with several Django-based Web applications, and a number of Ruby on Rails Web apps before that, at one company I'm consulting with. I have to say that the Django Web apps were much cleaner, better documented and had fewer bugs than the Ruby on Rails Web apps. Management always initially liked how quickly the Ruby on Rails development team could get their Web apps up and running in production, but were never pleased with the numerous problems that arose afterwards. Those issues just didn't arise with the users of the Django apps, because the effort was put towards doing it much more correctly the first time, even if it took slightly longer to get the apps into production use.

Unless the general attitude within the Ruby community changes, I think it's unlikely that we will see better documentation. But this will become more of a problem as we have increasingly more Ruby code that needs to be maintained. Good documentation is always essential when performing code maintenance, especially when the underlying programming platform (eg. Ruby) changes so rapidly. So maybe this will help drive demand within the Ruby community for better documentation efforts.

Permalink: http://pinderkent.phumblog.com/post/2009/01/ruby_has_always_been_about_getting_it_done_quick_and_dirty
Share:
Feeds
  • RSS 2.0 Feed
  • Atom 2.0 Feed
Tags
Archives