I think everybody hates Java as a desktop thing. I see Java mentioned a lot lately, but all of the mentions within the last year have been of Java as a server language, not as a desktop language. If you go back a year and a half, everybody was talking about Java on the desktop. They aren’t anymore. It’s dead. And once you’re dead on the desktop, my personal opinion is you’re dead. If servers are everything you have, just forget it. Why do you think Sun, HP — everybody — is nervous about Microsoft? It’s not because they make great servers. It’s because they control the desktop. Once you control the desktop, you control the servers.
It’s no longer something that will revolutionize the industry. It could have revolutionized the industry if it was on the desktop, but I don’t see that happening anymore. I hope I’m wrong. Really. I just don’t think I am.
—Linus Torvalds, 1998
A company should build a process that systematically looks at every product, every service, every process, every policy, every market with the question, “If we weren’t doing this already, knowing what we now know, would we start it, would we go into it?” If not, how quickly can we get out?
At first glance, Java looks quite like C, and very much like Microsoft’s C#. Sun’s Java adopted much of the syntax and semantics of C but added object orientation and many other language innovations, including garbage collection, and they made no effort to be 100% backwards compatible like C++ did.
While Java has many important technical advancements, it has achieved only a small fraction of the universal status it should have. Java should have replaced C and C++, languages desperate to be taken out back and shot! However, Java did not, and one of the biggest reasons why software is in shambles today is because Sun repeatedly screwed the pooch with Java.
In mid-2006, after Scott McNealy’s departure as CEO, Sun began making Java free, attempting to solve some of the issues mentioned in this chapter, but Java grew up as proprietary and this has left indelible scars on it. I will discuss why making it free won’t change things at the end of the chapter.
For those not in the software business, it is hard to describe the ire many programmers have felt towards Sun. This frustration is rooted in the special part tools play in the life of a software developer. A programmer is a tinkerer; he tinkers with his own tools as much as he concentrates on the job at hand. Software tools are continuously refashioned. If I need to process columns of data in a text file I receive from the Internet, it is almost as easy to fashion a tool to accomplish the task as it is to do it by hand. (A spreadsheet would be a useful tool, but there are other possible ones. A web server isn’t going to load a spreadsheet to extract and process simple data from a text file.) A suitable tool might not exist, or might not be exactly suitable to the particular task until it is tinkered with and made into the proper tool for the job.
Brilliance is typically the act of an individual, but incredible stupidity can usually be traced to an organization. —Jon Bentley
Sun’s first mistake was that they failed to do what Bell Labs did with C and C++: create freely available compilers and runtimes for people to experiment with and extend. Instead, Sun locked up the Java codebase, letting few see it, and letting even fewer improve it, so that today, there exists only a small community of people, outside of Sun itself, improving Java.
For example, because Sun locked up their code, no one was able to port it to other processors. As I mentioned in the Linux chapter, Debian calls itself “The Universal Operating System” because it contains 18,000 software components that run on 15 different processor architectures:
Intel x86 / IA-32
Renesas’s 32-bit RISC
Debian supports 15 processors, but Sun’s Java web page lists just four.
A wide variety of platforms allow the programmer to decide which processor is the best choice for his product. By contrast, on Sun’s website, you can only download four architectures: x86, PowerPC, AMD64 and Sparc.
The fact that Java doesn’t offer broad support on hardware platforms is a significant consideration. Why invest in a programming language that might not be usable with future hardware? C, and other free languages, provide tremendous hardware flexibility in their widespread adoption.
Flexibility and adaptability of programming tools is especially important for embedded devices because, unlike the PC environment where processors and operating systems have similar functionality, the software must be customized for embedding on low-end hardware, something that Sun did not enable.
For its first five years, when everyone was seriously considering using it, Java ran ten times slower than C because it was interpreted rather than compiled, exactly like Lisp. This would have been fixed a lot faster if Sun had involved and encouraged the existing free compiler development community.
Even in 2008, Java programs on my computer don’t look like they should. For example, when a program asks to display a file chooser dialog box to the user, below are the results for a Java and a native application:
Java had many significant limitations for many years because all progress was held up by Sun.
A “spec” is close to useless. I have never seen a spec that was both big enough to be useful and accurate.
And I have seen lots of total crap work that was based on specs. It’s the single worst way to write software, because it by definition means that the software was written to match theory, not reality. So there’s two MAJOR reasons to avoid specs:
1. They’re dangerously wrong. Reality is different, and anybody who thinks specs matter over reality should get out of kernel programming NOW. When reality and specs clash, the spec has zero meaning. Zilch. Nada. None.
It’s like real science: if you have a theory that doesn’t match experiments, it doesn’t matter how much you like that theory. It’s wrong. You can use it as an approximation, but you MUST keep in mind that it’s an approximation.
2. Specs have an inevitable tendency to try to introduce abstractions levels and wording and documentation policies that make sense for a written spec. Trying to implement actual code off the spec leads to the code looking and working like CRAP.
The classic example of this is the OSI network model protocols. Classic spec-design, which had absolutely zero relevance for the real world. We still talk about the seven layers model, because it’s a convenient model for discussion, but that has absolutely zero to do with any real-life software engineering. In other words, it’s a way to talk about things, not to implement them.
And that’s important. Specs are a basis for talking about things. But they are not a basis for implementing software. So please don’t bother talking about specs. Real standards grow up despite specs, not thanks to them.
Imagine designing a car by a committee on a computer, and then sending the design directly to the assembly line without building a car first and letting anyone test-drive it.
Sun didn’t let anyone read or tinker with their code but they wanted to be seen as a community-oriented effort, so, they created the Java Community Process where human-readable specifications describing Java were produced. Unfortunately, they focused on the specs and not on releasing software for people to try out so that the feedback came years later, or not at all. The biggest feedback that Sun would have received, but did not, was how insanely complicated their Java specs were. As an example, here is what a menu item looks like on the screen:
action, actionPropertyChanged, add, addActionListener, addAncestorListener, addChangeListener, addComponentListener, addContainerListener, addFocusListener, addHierarchyBoundsListener, addHierarchyListener, addImpl, addInputMethodListener, addItemListener, addKeyListener, addMenuDragMouseListener, addMenuKeyListener, addMouseListener, addMouseMotionListener, addMouseWheelListener, addNotify, addPropertyChangeListener, addVetoableChangeListener, applyComponentOrientation, areFocusTraversalKeysSet, bounds, checkHorizontalKey, checkImage, checkVerticalKey, clone, coalesceEvents, computeVisibleRect, configurePropertiesFromAction, contains, countComponents, createActionListener, createActionPropertyChangeListener, createChangeListener, createImage, createItemListener, createToolTip, createVolatileImage, deliverEvent, disable, disableEvents, dispatchEvent, doClick, doLayout, enable, enableEvents, enableInputMethods, equals, finalize, findComponentAt, fireActionPerformed, fireItemStateChanged, fireMenuDragMouseDragged, fireMenuDragMouseEntered, fireMenuDragMouseExited, fireMenuKeyPressed, fireMenuKeyReleased, fireMenuKeyTyped, firePropertyChange, fireStateChanged, fireVetoableChange, getAccelerator, getAccessibleContext, getAction, getActionCommand, getActionForKeyStroke, getActionListeners, getActionMap, getAlignmentX, getAlignmentY, getAncestorListeners, getAutoscrolls, getBackground, getBaseline, getBaselineResizeBehavior, getBorder, getBounds, getChangeListeners, getClass, getClientProperty, getColorModel, getComponent, getComponentAt, getComponentCount, getComponentGraphics, getComponentListeners, getComponentOrientation, getComponentPopupMenu, getComponents, getComponentZOrder, getConditionForKeyStroke, getContainerListeners, getCursor, getDebugGraphicsOptions, getDefaultLocale, getDisabledIcon, getDisabledSelectedIcon, getDisplayedMnemonicIndex, getDropTarget, getFocusCycleRootAncestor, getFocusListeners, getFocusTraversalKeys, getFocusTraversalKeysEnabled, getFocusTraversalPolicy, getFont, getFontMetrics, getForeground, getGraphics, getGraphicsConfiguration, getHeight, getHideActionText, getHierarchyBoundsListeners, getHierarchyListeners, getHorizontalAlignment, getHorizontalTextPosition, getIcon, getIconTextGap, getIgnoreRepaint, getInheritsPopupMenu, getInputContext, getInputMap, getInputMethodListeners, getInputMethodRequests, getInputVerifier, getInsets, getItemListeners, getKeyListeners, getLabel, getLayout, getListeners, getLocale, getLocation, getLocationOnScreen, getMargin, getMaximumSize, getMenuDragMouseListeners, getMenuKeyListeners, getMinimumSize, getMnemonic, getModel, getMouseListeners, getMouseMotionListeners, getMousePosition, getMouseWheelListeners, getMultiClickThreshhold, getName, getNextFocusableComponent, getParent, getPeer, getPopupLocation, getPreferredSize, getPressedIcon, getPropertyChangeListeners, getRegisteredKeyStrokes, getRolloverIcon, getRolloverSelectedIcon, getRootPane, getSelectedIcon, getSelectedObjects, getSize, getSubElements, getText, getToolkit, getToolTipLocation, getToolTipText, getTopLevelAncestor, getTransferHandler, getTreeLock, getUI, getUIClassID, getVerifyInputWhenFocusTarget, getVerticalAlignment, getVerticalTextPosition, getVetoableChangeListeners, getVisibleRect, getWidth, getX, getY, gotFocus, grabFocus, handleEvent, hasFocus, hashCode, hide, imageUpdate,fireMenuDragMouseReleased isBorderPainted, init, insets, inside, invalidate, isAncestorOf, isArmed, isBackgroundSet, isContentAreaFilled, isCursorSet, isDisplayable, isDoubleBuffered, isEnabled, isFocusable, isFocusCycleRoot, isFocusOwner, isFocusPainted, isFocusTraversable, isFocusTraversalPolicyProvider, isFocusTraversalPolicySet, isFontSet, isForegroundSet, isLightweight, isLightweightComponent, isManagingFocus, isMaximumSizeSet, isMinimumSizeSet, isOpaque, isOptimizedDrawingEnabled, isPaintingForPrint, isPaintingTile, isPreferredSizeSet, isRequestFocusEnabled, isRolloverEnabled, isSelected, isShowing, isValid, isValidateRoot, isVisible, keyDown, keyUp, layout, list, locate, location, lostFocus, menuSelectionChanged, minimumSize, mouseDown, mouseDrag, mouseEnter, mouseExit, mouseMove, mouseUp, move, nextFocus, notify, notifyAll, paint, paintAll, paintBorder, paintChildren, paintComponent, paintComponents, paintImmediately, paramString, postEvent, preferredSize, prepareImage, print, printAll, printBorder, printChildren, printComponent, printComponents, processComponentEvent, processComponentKeyEvent, processContainerEvent, processEvent, processFocusEvent, processHierarchyBoundsEvent, processHierarchyEvent, processInputMethodEvent, processKeyBinding, processKeyEvent, processMenuDragMouseEvent, processMenuKeyEvent, processMouseEvent, processMouseMotionEvent, processMouseWheelEvent, putClientProperty, registerKeyboardAction, remove, removeActionListener, removeAll, removeAncestorListener, removeChangeListener, removeComponentListener, removeContainerListener, removeFocusListener, removeHierarchyBoundsListener, removeHierarchyListener, removeInputMethodListener, removeItemListener, removeKeyListener, removeMenuDragMouseListener, removeMenuKeyListener, removeMouseListener, removeMouseMotionListener, removeMouseWheelListener, removeNotify, removePropertyChangeListener, removeVetoableChangeListener, repaint, requestDefaultFocus, requestFocus, requestFocusInWindow, resetKeyboardActions, reshape, resize, revalidate, scrollRectToVisible, setAccelerator, setAction, setActionCommand, setActionMap, setAlignmentX, setAlignmentY, setArmed, setAutoscrolls, setBackground, setBorder, setBorderPainted, setBounds, setComponentOrientation, setComponentPopupMenu, setComponentZOrder, setContentAreaFilled, setCursor, setDebugGraphicsOptions, setDefaultLocale, setDisabledIcon, setDisabledSelectedIcon, setDisplayedMnemonicIndex, setDoubleBuffered, setDropTarget, setEnabled, setFocusable, setFocusCycleRoot, setFocusPainted, setFocusTraversalKeys, setFocusTraversalKeysEnabled, setFocusTraversalPolicy, setFocusTraversalPolicyProvider, setFont, setForeground, setHideActionText, setHorizontalAlignment, setHorizontalTextPosition, setIcon, setIconTextGap, setIgnoreRepaint, setInheritsPopupMenu, setInputMap, setInputVerifier, setLabel, setLayout, setLocale, setLocation, setMargin, setMaximumSize, setMinimumSize, setMnemonic, setModel, setMultiClickThreshhold, setName, setNextFocusableComponent, setOpaque, setPreferredSize, setPressedIcon, setRequestFocusEnabled, setRolloverEnabled, setRolloverIcon, setRolloverSelectedIcon, setSelected, setSelectedIcon, setSize, setText, setToolTipText, setTransferHandler, setUI, setVerifyInputWhenFocusTarget, setVerticalAlignment, setVerticalTextPosition, setVisible, show, size, toString, transferFocus, transferFocusBackward, transferFocusDownCycle, transferFocusUpCycle, unregisterKeyboardAction, update, updateUI, validate, validateTree, wait
The list of functions the Swing Java MenuItem class implements, with bizarro names like “isFocusTraversalPolicyProvider” and “addVetoableChangeListener”. Imagine if you needed to become familiar with 456 things to use your oven.
Such bloated code is hard to understand and even harder to make reliable. And this is just the Swing class library’s opinion of a menu item, one of three popular implementations of Java widgets, and supposedly an efficient one!
Java is plagued by too much complexity as you can see, and releasing specs instead of code is a big cause of this problem. In fact, many of the Java specs aren’t widely used because they do not meet developers’ needs, or they became heavily amended after they finally got into customers’ hands, which was often years after the specs were originally written.2
Java was not growing carefully and organically, as Linux has done, by following the “ship early, ship often” methodology. A lot of people who hate Java do so because of its pervasive extraneous complexity.
When it created Java, Sun didn’t want to release the code because they were worried people would take their code, tweak it slightly to better meet their needs, and create incompatibilities that would hurt the “brand” of Java — confusing a 99% friend with an enemy. This paranoia occurred because Sun made a rookie mistake in not understanding that a language needs to be extensible.
In the C and C++ world, there is even a convention that any non-standard keywords would be prefaced with two underscores, like this: “__inline”. In some cases, a feature started out as a vendor-specific addition, was adopted by others, and eventually became added to the language in an official way. The creators of C and C++ didn’t have the hubris to believe they had built a perfect language.
Even more importantly, the primary way to extend a computer language is by creating new functions and data types, which was also not allowed in any of the domains specified by Sun.
Sun got it backwards — people will only make minimal changes necessary to Java to make it work for them. That is what happened in C and C++. Sun didn’t have faith in its customers and didn’t understand the realities of how large bodies of systems-level code are created.
Because of fear, Sun decided to lock up their code to prevent it from being extended by anyone else. This short-sighted idea, but even worse, the law of unintended consequences came up and bit them in the tush. Because Sun made only the specs but not the code available, many third parties started producing their own Java runtimes so they could control their own destiny. Wikipedia documents 34 different third-party Java runtimes, and their list doesn’t include any of the embedded Java implementations, which are harder to count.
Everyone who wanted to use but improve Java would have to start from scratch. This created much bigger areas of incompatibility because building a Java implementation from scratch requires a lot of work, and they could even unknowingly cut corners.
The biggest problem with so many runtimes, besides the wasted efforts, is that the imperfect specs became the reference rather than the code because there wasn’t an agreed upon codebase containing the official Java design.
Backward compatibility is the greatest cause of complexity, and therefore unreliability, in computers today. As described in the Linux chapter, one of the Linux kernel’s major innovations is that it avoids backward compatibility issues by encouraging all code into one tree. This makes it much easier to make changes to the design.
With an official source tree, Java could become whatever we need it to be, avoiding the mess of different codebases, and serving as a reference when the paper specs are ambiguous. It sounds chaotic, but things quickly converge, and on something with minimal excess complexity, because it can be removed.
While the Java specs were not good because feedback came years later, they became etched in stone because once 30 runtimes have a particular piece of functionality, it becomes very hard to change them all. Even if Sun let you alter their design, it might take years to make any changes. In contrast, if the Linux kernel is missing a feature, you can send some code to Linus and have it in the official codebase immediately.
Another Sun mistake was getting into a war with Microsoft over Java. Microsoft’s tools division was an active participant in Java for its first several years, and PC Magazine wrote in 1997 that: “Microsoft’s Java environment was the fastest and most compatible on our tests.”
When Microsoft improved Java in certain ways that by definition were incompatible, Sun sued them. Microsoft’s changes to Java were minor, the features justifiable, and the incompatibilities almost non-existent.3
A public lawsuit, the exchange of $20 million in damages, and much bitterness ensued.
Eventually, Microsoft quit supporting Java and went off to create C# instead. C# might be considered Java 2.0. While it is very similar to Java, it had five years of refinement and applied Microsoft’s many years of experience as a dominant force in the tools business. C# created unnecessary chaos and confusion in the industry and allowed Microsoft to be 100% incompatible with Java rather than just .01% incompatible. Microsoft would not have created C# if Sun hadn’t sued them.
If Sun had created Java with a GPL license, the landscape of the software industry would look completely different today, and computers would be more reliable and smarter. Java would be more reliable, simpler, richer, and faster, and a community, like C and C++, that Microsoft tools developers would have been a part of.
The success of C was in part due to its widespread support, which made it easier to share code than did its predecessor on the PC — assembly language. It is hard to share code across languages, and the proliferation of new ones has gotten worse since Java was created, when it should have gone in the opposite direction.4
Even within Sun, there is a group of people trying to build another programming language called Fortress, which will be suitable for scientific computing. They too believe Java is not sufficient as it is.5
Scott McNealy, co-founder and CEO of Sun Microsystems from 1984 – 2006, and an impediment to free software — even though his company made most of their money on hardware.
Sun’s first major decision after co-founder Scott McNealy’s departure in mid-2006 was a promise to make much of their software, including Java, free. This announcement was big news and some think it marks the potential for a new day in the life of Java. However, this effort is starting more than a decade after Java’s creation, arguably too late to fix most of the problems.
Even with Sun’s new GPL license, there is a lot of Java code out there that is not free and cannot be made so by Sun. Apple, for example, took Sun’s PC implementation and worked extensively to port it to Macintosh. This code isn’t free, and it doesn’t seem likely that Apple will ever make it such. There is a company making Java run on mainframes, and their enhancements are proprietary as well. Even within the code Sun has recently made free, there are pieces Sun licensed from third parties, and they are having to re-write it because they can’t get permission to change the license.
Even a free Java on its current trajectory will not absorb other communities. C# is considered better than Java, so those programmers are not making a switch. There are millions of web pages written in PHP, and I don’t see them rushing to switch to Sun’s Java either. Sun’s code has been locked up for so long, there are few people in the outside world able to contribute. Why should the community fix a mess that was created only because Sun didn’t work with the community in the first place?
C# and .Net is the dominant platform on Windows, PHP is the dominant language on the Web, and Python and Mono are the most popular GC runtimes on the Linux desktop. So while Java is taught in universities, used for custom applications in enterprises, and has some success on mobile phones, these niches aren’t enough to to ensure its long-term viability. Java has accumulated so much baggage, only some of which I have discussed here, that I think the software community should abandon it. This would also take a big step in lessening the problem of too many programming languages. In earlier drafts of my book, I proposed Sun create a next generation programming language, but I now believe there already are suitable codebases: Mono and Python.
Warning from 2013, this is old text from 2008. I no longer recommend anyone use Mono. However, it was sad to build such a nice runtime and then be afraid to use it even after Microsoft had promised not to sue! Etc.
Today, the most popular GC runtimes on the Linux desktop today are Mono and Python. Both are built by a worldwide community, but each has certain advantages and disadvantages.
One of Mono’s biggest advantages is that it is compiled. While performance is not the most important factor of software quality, any language which wants to become the standard for Linux needs a compiler. Even if only a small fraction of any piece of software is performance-critical, the language doesn’t know what that part is, and so it should run all code fast. Another advantage of Mono is that it comes with a complete end-to-end solution for creating programs: a graphical editor and debugger, code browser with auto-complete, etc. With Python, you must piece together these components yourself, and there isn’t a standard one with critical mass.
Mono’s biggest disadvantage stems from the fact that it is an implementation of .Net which is a standard created by Microsoft. The C# language and the core libraries are not created with much input from the worldwide community and the enhancements are improved only on Microsoft’s schedule. Microsoft has hired some of the best language designers on the planet, like Anders Hejlsberg, but he is not as smart as the combined knowledge of the rest of the languages designers on the planet. This has practical effects: C# added “dynamic language” features in the version 4.0 of the language, while Python has had these for many years.7
Another “disadvantage” of Mono is that there is an enormous amount of FUD (fear, uncertainty and doubt) that surrounds it. Microsoft has historically been hostile towards free software, calling it a “cancer” and sometimes threatening to sue over claimed patent infringements, and while this should create fear all over the free software stack, it appears to be directed mostly at Mono! I believe Linux programmers are being irrational because the .Net specification is publicly available, and Microsoft has repeatedly promised not to sue for implementations of it. Programmers should also realize that Mono extends the reach of .Net to other processors and operating systems, which benefits Microsoft’s customers.
Python’s advantage is that it is created with input from programmers all over the world, and has a larger set of libraries than any other GC language:
A computational fluid dynamic (CFD) visualization of a combustion chamber. The Python community has quietly created a wide variety of libraries for everything from gaming to scientific computing. There are even books to teach it to 8-year olds.
Python’s biggest disadvantage is performance: it is not compiled and doesn’t support multiple threads. These features are a requirement for any serious runtime and so one might wonder whether Python is still at a prototype phase of development. Even fans of Python very loudly complain that while it might be suitable for little scripts and application plugins, it is too slow for writing large applications.
These features are a big amount of work that are not even on Python’s to-do list. And as the language has never been compiled there are even some questions as to whether it can be made fast.8
In addition, Because the Python runtime is slow, the developers are forced to write a lot of support code in C, which further slows its development progress. Is is a shame that Python isn’t fully using a tool which would have made their job easier — their own language. There are efforts such as the PyPy project which has built a Python compiler, in Python, which outputs C. Unfortunately, this piece of elegance is not yet the mainline codebase and is not considered for such.9
And as mentioned earlier, the language doesn’t have a standard graphical programming and debugging environment. So Python today has impediments for both casual programmers looking for an easy way to get into programming, and professionals who care about building high-performance applications.
There are other interesting languages and runtimes out there, but I believe the Linux desktop community should focus on these two. Mono already supports other languages in addition to C#, some that even look like Python.
There are many good programming languages, in fact there are too many, but I also think they a number are good enough. One could further tweak the letter of the English language to make it easier for your eyes to distinguish the letters, and simplify the pronunciation rules, but it isn’t necessary because what we have is good enough. Likewise, it is much more important to build a complete set of libraries for all aspects of computing, a Wikipedia of free code, than to worry that further language innovation is the gating factor towards any future progress in software. Paul Graham and others view programming languages as a continuum of richness and elegance, but that isn’t really true; Lisp is still considered one of the best programming languages, in spite of its age, so we must reach a point of diminishing returns. In general, the way you extend a programming language is with new functions.
All economic activity is by definition “high risk.” And defending yesterday — that is, not innovating — is far more risky than making tomorrow.
When there’s a will to fail, obstacles can be found.
Sometimes the real hurdle to renewal is not a lack of options, but a lack of flexibility in resource allocation. All too often, legacy projects get richly funded year after year while new initiatives go begging. This, more than anything, is why companies regularly forfeit the future — they over invest in “what is” at the expense of “what could be.” New projects are deemed “untested”, “risky”, or a “diversion of resources.” Thus while senior execs may happily fund a billion-dollar acquisition, someone a few levels down who attempts to “borrow” a half-dozen talented individuals for a new project, or carve a few thousand dollars out of a legacy budget, is likely to find the task on par with a dental extraction.
The resource allocation model is typically biased against new ideas, since it demands a level of certainty about volumes, costs, timelines, and profits that simply can’t be satisfied when an ideal is truly novel. While it’s easy to predict the returns on a project that is a linear extension of an existing business, the payback on an unconventional idea will be harder to calculate. Managers running established businesses seldom have to defend the strategic risk they take when they pour good money into a slowly decaying business model, or overfund an activity that is already producing diminishing returns. How do you accelerate the redeployment of resources from legacy programs to future-focused initiatives? —Gary Hamel, The Future of Management
When software, the most important building block of mankind’s intellectual property, uses a standard GC programming language and protects itself with copyleft, mankind will enter a shining age. I think better runtimes are critical to the success of Linux on the desktop.
Unfortunately, fixing this problem is a big task because inertia is such a powerful force. The good news is that the difficulty of porting to a different language is not the same in every case. Porting from one modern language to another is ten times easier than moving from C to C#. Right now, much of our code and infrastructure lives in the dark ages, and this first port is the hardest, but it will provide big benefits.
During my tenure at Microsoft, I witnessed numerous re-writes. Unfortunately, most of them failed. Those that failed had at least one thing in common: they usually were re-writing C code in C, or C++, and because they did not use significantly better tools as part of their plan, they never ended up saving any time in the end. It doesn’t make sense to re-build something from scratch unless you plan to make it a lot better. But if the teams out there move from C or C++ to a much more productive language, they will save time in the end and it is much more likely to succeed — assuming they start. The key is to make a plan and break down the problem.
1 Other widget libraries, like the Gtk#’s MenuItem have hundreds functions as well, but many do not and Java is the worst. The WxWidgets MenuItem class has 50 members, and it uses native widgets on Mac, Windows and Linux. Apple’s NSMenuItem has 55.
2 Two good examples of basically unused class libraries are:
1. JXTA, Java’s peer-to-peer protocol that standardizes many aspects of P2P but is not used because it solves the wrong problems, and,
2. J2ME, Java’s underpowered class library for mobile devices which has primitive widgets, is unable to access a phone’s address book, calendar, camera, GPS, or web browser, and has no ability to make phone calls. J2ME’s goal should be rich enough to build an entire phone user interface in Java, but it only has the ability to make toy applications, and even then, programmers often complain that the differences between the implementations make it a “write once, test everywhere” scenario.
3 One of the things Microsoft changed was to simplify and improve the performance of how a Java developer called in to native operating system functionality. Java has always allowed developers to write non-portable, operating system-specific code when the operating system provided a feature that a developer wanted access to but that Java did not support. By definition this code was not cross-platform, so one would imagine that Microsoft-specific syntax to access Windows-specific features would not have been a big deal. In fact, the way a Java programmer would call the native functionality on Windows had the same syntax between Microsoft’s RNI and Sun’s JNI. It was only the way the native method was declared that was different. Microsoft did make other changes, such as adding a keyword, “delegate”, but if you search the web you can find many people who wished Sun had added that feature and code samples to enable that feature in Java.
4 Sharing code across languages has historically been very difficult. The search engine Lucene is a recent example of something which started in Java but has been forked into versions in PHP and C#.
There are many reasons for it being so difficult to share code between different languages. They have different ways of deploying the code, different naming conventions, and different low-level details. Interoperating layers usually adds significant performance costs because everything from the strings on up the stack have to be marshalled, which usually involves making a copy of the data. If you can’t agree on what a string is, then you will have difficulty sharing code. (Going from C# to C/C++ is fast because a copy of the data doesn’t need to be created — a C Unicode string is a subset of a C# string.)
5 Fortress’s syntax is arbitrarily different from Java in ways not at all related to high performance computing (HPC). A programming language is by definition extensible by creating new functions and classes, and it is also possible to alter the runtime, without changing the language, to optimize it for specialized hardware, etc. The big challenge in HPC is to robustly divide up the work amongst a farm of servers, pass messages and maintain and monitor the system — new software, not new language features.
6 My bible says God scattered the Babylonians because of their “pride.” I can’t know what they thought, but I do believe that learning about ourselves, using technology to save and improve lives, and attempting to understand the true nature of the world, only gives us more appreciation for what He has created. I believe the creator of liberty and science wants us to understand these concepts, as long as we don’t lose track of our relationship with the creator somehow in the process.
7 One other concern about Mono is that it doesn’t use a copyleft license. Excerpt from the FAQ on the Mono website:
“When a developer contributes code to the C# compiler or the Mono runtime engine, we require that the author grants Novell the right to relicense his/her contribution under other licensing terms. This allows Novell to re-distribute the Mono source code to parties that might not want to use the GPL or LGPL versions of the code. Particularly: embedded system vendors would obtain grants to the Mono runtime engine and modify it for their own purposes without having to release those changes back.”
8 In some performance tests, the IronPython implementation on .Net runs slower than the standard Python implementation. So even though IronPython has access to a compiler, it apparently isn’t able to take advantage of it enough to be faster.