Showing posts with label programming-languages. Show all posts
Showing posts with label programming-languages. Show all posts

Thursday, 23 May 2013

JavaScript - The Redemption of The Ugly Duckling.



In 1995 when Java was introduced with great fanfare, it brought with it the promise of a browser-embedded rich client with first-class widgets across all relevant platforms. The vision of a server-side Java was talked about but that was for the future; it was the applet that was given us to play.

Depending on who you ask, today the applet is either all-but-dead on the real-world internet or was eviscerated and buried in a tragic explosion when the 90's bubble collapsed on top of it. Server-side, mobile and desktop Java thrive and in a big way, but the dreams of Java as an instrument of a dynamically deliverable lightweight application delivered by and integrated with your browser, that early promise fell dead.

Barely noticed at that coming-out party was Java's awkward little sister, JavaScript (who, later DNA tests proved, proved to be utterly unrelated). It too promised portability across browser and platform, but operating within the context of the current page. It became useful in a utilitarian sort of way and soon came to become indispensable for providing basic features like automating roll-overs and light input validation.

Any attempts to stretch JavaScript, back in those early days, were punishing. The behaviour and even the core libraries of JavaScript implementations varied widely from browser to browser. The MS-v-World DOM Wars were at their height and even if you found something cool which worked across every major browser in your (extremely manual) test suite, it was likely to break with the next browser release.  Even under the best of circumstances, the various browsers themselves did not provide the most accommodating environments.  Debugging was a painstaking process that had to be repeated on a number of browsers and the shifting, incompletely standardized JavaScript engines which browsers were shipping ensured that there were always a lot of bugs.  Things which worked on every other browser but just not this one ate up hours of time that would have been better spent on sleep.

Many web developers grew suspicious of all-too-fragile JavaScript and used it grudgingly only because there very often was no other means of implementing requirements.  It was often treated as a technology of last resort. While there was some work on the server-side, largely pushed by Netscape and a few applications were embedding the open-source Rhino engine, it was pretty marginal and mainstream developers paid it little heed.

Then something happened, or more accurately, a series of things happened which converged in the most delightful way.

The catastrophic failures of the internet bubble had prompted many tech startups to explore faster, more flexible ways of producing applications which lead to a rising interest in server-side scripting languages. PHP had appeared on the scene and new web development was adopting it at a staggering rate. Languages like python, ruby and Lua all gained momentum contributing to a sudden new-found respect for scripting languages in general. And, on the client-side, the JavaScript engines in browsers were quietly improving.

This was the state of affairs when the modern JavaScript framework appeared.  There are others, of course, but I really am referring to the truly innovative, empowering notation which is jQuery. It took a little while for the importance of jQuery to dawn on me, certainly not before FireBug had hit the web and provided the first-ever development environment for JavaScript which was actually sane.  While high-level libraries and 'frameworks' for JavaScript have been around for awhile, providing useful features, jQuery did something more dramatic.  It gave us a fundamentally new, concise notation for performing complex operations, a powerful shorthand for describing the relationship between code and the document in which it resided. In doing so, it showed what a language of tremendous power and elegance JavaScript could be and it extended the power of the developer exponentially.

Interest in JavaScript on the server-side began to rise for the first time.  Through Rhino and Java's JSR-223 Scripting Engine Interface, projects of all kinds began to spring up which supported any compliant scripting language and JavaScript among the most popular.  And along came Node.js.

Node.js  takes advantage of Google's fast V8 JavaScript engine and event processing models learned from Ruby. Both Ruby and JavaScript are Object-Oriented languages that support dynamic typing and dynamically-scoped closures as first-class types. While the event concepts may have come from Ruby, the implementation used a native library (libev, later libav) to facilitate non-blocking I/O via asynchronous execution and the result was a tight scriptable interface with clean semantics and smoking fast performance.

JavaScript is proving to be a potent force on the modern development scene. The rise of HTML5 has given JavaScript more interesting and useful things to do within the browser and it's slowly taking its place as a first-class server-side development language.

Thursday, 16 May 2013

The Rivers of Babylon

The Tao gave birth to machine language. Machine language gave birth to the assembler.
The assembler gave birth to the compiler. Now there are ten thousand languages.
Each language has its purpose, however humble. Each language expresses the Yin and Yang of software. 
Each language has its place within the Tao.
But do not program in COBOL if you can avoid it.



The universe of computer programming languages is in a constant state of evolution. Paradigms once considered vogue are exhausted and shelved, only for new paradigms to be embraced according to the latest schools of thought.

One of the questions I am mostly frequently asked, whether in interviews or in social situations where I am foolish enough to mention what I do for a living, is: what is my favourite language? I have no short answer for that.

For the non-technical inquisitor, I try to offer a metaphor.  What does a carpenter say when asked what his favourite tool is? Does he tell you that he loves his hammer best?  That his skill-saw is suitable to his every task? I certainly hope not. If he does, I'm sure not going to hire him.  I would expect him to tell me that his hammer is best when there are nails to drive, the saw where there are beams to trim.  The typical carpenter owns a large tool chest, both wide and deep, packed with all sorts of contrivance, both familiar and obscure.  It includes the tape measure which is always at hand, the level and the plumb line which are needed every day; it also includes some odd looking contrivances, rarely used but for particular types of work they are exactly the right thing.

It is long proven that any Turing-complete machine can emulate any other Turing-complete machine.  As pretty much all modern programming languages are Turing complete, any given language can perform every possible task that can be performed by any other language.  In practice there are some limitations to the application of this theory, but it is essentially correct. So it is possible for a programmer to tackle anything equipped with nothing more than one programming language, a single tool for every task.

Does this mean that a serious programmer should be content with the first wooden hammer they learn how to swing? Perhaps we could answer that if we take a moment to reflect on why the current proliferation of programming languages exist.

The invention of assembler should need no explanation; directly inputting machine code is monotonous and error-prone.  The interests of both efficiency and sanity were best served by the creation of a symbolic language for addressing the machine. Then we had a human-readable (so it was held) means for instructing our machines. Theoretically, as assembler is Turing-complete (it has to be or we would never have been able to implement any of our higher-level languages upon it), it could be used to implement any computable task but there are several obvious limitations.

Assembler is very much bound to the specific processing unit for which it is designed.  As different processors may perform the same operation in vastly different ways, there is nothing portable about it. As the complexity of requirements began to grow at an exponential rate (as they continue to through this day, thanks again Mr. Moore), it proved to be extremely expensive in terms of man-hours to build the applications then in demand.

The greatest challenge in writing assembler is unfair to refer to as a limitation or a weakness, as it speaks to it's very nature: assembler requires the human programmer to translate the logic of any given problem down to a mechanical level that the machine can follow.

Humans thrive on abstractions.  We pour over maps, devour books, drink in media, all of it abstractions; all of it carefully produced representations of someone else's abstract thought. All efforts at notation made over the many thousands of years of our civilized history have been efforts to record thought into a permanent form to be revisited or reused.  This is as true for the granary records the Sumerians pressed into clay as for the musical notation of European medieval monks.

Mathematicians have been taking advantage of this for quite some time.  Much of the history of mathematics is the history of mathematical notation.  Ken Iverson's essay Notation As A Tool Of Thought demonstrates how our ability to think is enhanced and empowered by the use of notations which are able to encapsulate powerful concepts into unambiguous representations. Ideas which were once unwieldy can be reduced to symbols and become the bricks of a grander edifice. So proceeds much of our scientific and cultural history.

It was quickly seen (anticipated, in fact) that it would be far more convenient to create high-level notations more akin to patterns of human thought rather than to the machines mechanical dialect.  If such a notation is clear, unambiguous and sufficiently complete as to be able to describe a domain problem fully then it should be possible to implement it as a tool to automate that solution.

As patterns of thought are many and diverse, so it is with the the notations devised to express them. In the 1970s, we find RPG, APL, C (and yacc/lex) and Smalltalk all well-established with Scheme and awk gaining attention. The 1980s brought C++, Objective-C and perl each with passionate advocates and adherents before the 90s came along and blew up the scene. Java, JavaScript, PHP, Python, Ruby and Lua have become serious contenders in all kinds of software development and particularly dominate the web. Each of these languages sports features which make them compelling and highly suitable for particular tasks.

This is not to say that each generation throws out the languages and paradigms of the previous decade. The best tools evolve over time, often in useful directions attaining the maturity that invites investment. According to the TIOBE Programming Community Index, C continues to be the single most commonly used language in the development of software showing a slight increase over this time last year (as of May 2013). It is followed closely by Java and a group of C variants further down (objective,++,#) before we find PHP at #6 with around 5.8% of the market.  python, ruby and perl all come in at less than 5% before dropping off into little boutiques of groovy, XSL, R,  J/APL and many others, all of them doing useful work with the best tools available for the task. 

Recommending what languages are best used for new software projects depends very much on the domain.  One can not answer that question without first analyzing the requirements, determining the problem to be solved and selecting a language which is well suited to describing that problem. 

Language adherents often gather themselves into heterogeneous camps eschewing all others, confident that their tools can deliver anything that any other language or tool set can deliver.  What that misses is the education gained from seeing a familiar task undertaken in a completely unfamiliar way.  It stimulates the mind and forces you to consider new possibilities. It will teach you to stretch familiar environments in ways that you had never previously considered.