User: Password:
|
|
Subscribe / Log in / New account

A shame

A shame

Posted Apr 8, 2005 2:30 UTC (Fri) by ncm (subscriber, #165)
In reply to: A shame by giraffedata
Parent article: GCJ - past, present, and future

Should I make a list? The language's purpose was not a way to express programs clearly and efficiently, but rather to be a weapon for Sun to use against Microsoft. It's rife with peculiar design decisions that make no sense except in support of proprietary head-knocking. Free Software doesn't need any of that; we already had "write once, run anywhere" that actually works. We don't need to give up anything to get it. The language has no public standard, and its originator has no interest in making one. That makes it unsafe as a development platform for careful people; the future of the language is not controlled by people who use it.

Besides peculiar choices that were more or less purposeful, the language and its libraries were designed in enormous haste by people who really didn't understand quite what they were doing. Therefore, many of the central choices were simply stupid. Examples of that include making member functions virtual by default; compulsory exception specifications; a character type 16 bits wide, not wide enough to represent a whole character, but too wide to avoid endianness problems; syntax that mimics the historical mistakes of C for no plausible reason; no way for user defined types to mimic built-in types. Because no significant program can avoid pervasive casting, it suffers all the inconveniences of a type-safe language without actually providing type-safety. Finally, it is saddled with the academic "garbage-collection" disease, which is one reason why real programs are so slow, despite that benchmarks suggest it should be otherwise. Sophisticated techniques to fix that have been promised to come out any day now for the last ten years. (C# doesn't fix many of its problems, even given years of hindsight.)

The language is a snapshot of how "object oriented" programming was understood (or misunderstood) toward the end of the overhyped '80s. That's hard to excuse considering it came out half a decade later, and it is entirely ridiculous fifteen years on. Object-orientedness has turned out to be useful for some things, and irrelevant for most; while it's handy for a language to support it directly, it's foolish to make every detail of a language depend on the notion.

Design concerns aside, it's notoriously hard to deploy Java programs, because of the JVM incompatibility problem. Each program typically either requires the default platform JVM, if there is one, or ships with its own. A system with six Java programs typically has six JVMs installed.

Fortunately we have a public-standard language that is more powerful and more thoughtfully designed than Java, and you have literally hundreds of end-user Free Software programs written in it on your disk right now. It's unencumbered with submarine patents, fast and efficient, and has lots of fantastically powerful libraries available. It works well enough that you never need to know -- and generally don't know -- that a program was written in it. Can that be said about any Java program?


(Log in to post comments)

A shame

Posted Apr 8, 2005 3:03 UTC (Fri) by giraffedata (subscriber, #1954) [Link]

Thanks for all that. One aspect you didn't really cover is why a language with all those problems is the de facto standard in some proprietary software arenas. Like web services. And these don't seem to be tied to Sun's aspirations.

A shame

Posted Apr 8, 2005 9:42 UTC (Fri) by hmh (subscriber, #3838) [Link]

IMHO it is because the best known competition is a ugly joke for anything of a reasonable size. While it takes a LOT of effort, you can write proper, reasonably resilient code in Java to drive stateful web applications that will scale to the millions of transactions per hour range...

There must be real alternatives out there, but they are not as known as, say, JSP... IMHO anyway.

A shame

Posted Apr 8, 2005 16:12 UTC (Fri) by ncm (subscriber, #165) [Link]

Java was taken up by corporate IT departments because its flaws mesh well with theirs. A Java web application produced by seven or more corporate functionaries, each in his own department, could be done much faster by one or two (say, a coder and a graphic designer) using a better-designed system. However, to allow that would interfere with job security for those functionaries and their managers, and would bridge organizational barriers carefully erected by the latter.

A shame

Posted Apr 8, 2005 9:28 UTC (Fri) by Xman (guest, #10620) [Link]

Just to review the faults you cited:

  • Most OO languages have their methods virtual by default, as it aids in reuse. While there is a performance penalty normally associated with virtual functions in C++, modern JVM's are very good at optimizing this to the point where they often inline virtual function calls. Frankly, I find it annoying how often I have to specify "virtual" in C++. Really, it's a style issue, not a design flaw.
  • compulsory exception specifications. Well, they did better than their predicessors in this regard, but I'd agree this proved in time to still not be a good design. The thinking at the time (and it was by no means restricted to the folks designing Java) was that exception specifications were a good thing, but just hadn't been done right yet.
  • 16-bit characters. They did start out this way, back when everyone thought all Unicode characters could be represented with 16-bit characters (and they weren't the only ones to make this mistake... for example Windows NT and C++'s STL). They now do 32-bit characters and strings are encoded internally in UTF-16. When writing to streams and such you'll find your locale determines the default encoding (so for example things will often get encoded in UTF-8). This is the same scheme used by Unicode libraries for other languages such as the C++ ICU library. It's really hard to run in to endian problems with the internal encoding of strings because that isn't visible. It's really hard to run in to endian problems with integers in Java, because Sun ensures a consistent byte order. They have their bases covered here.
  • not being able to mimic built-in types. This was done deliberately, and frankly has a lot to do with Java's commercial success. Talk to Smalltalk component vendors to get an idea as to why this can be a good thing.
  • They actually did break a lot of C's worst syntax rules and clarified a number of C's ambiguities. That said, they started out originally wanting to be as much like C/C++ as possible while still achieving their design goals, and arguably this was to their advantage.
  • Java has generics now, so you can actually avoid pervasive casting. They avoided putting generics in at first because they weren't 100% sure how to do it right, and they figured doing it even slightly wrong would make generics more of a hinderance than a help (I think they ended up being a little wrong on this, but it was a pretty rational decision as they had no way of knowing how successful Java's initial design would be). Even if you don't use generics and do lots of casting, you get runtime errors if you screw up your types, rather than C's tendancy to ignorantly blunder on.
  • Try profiling Java code sometime and see how much time is spent doing memory management. I've found on average Java programs spend less time managing memory than most C/C++ programs. Ironically, a lot of the performance problems I see in Java programs are caused by trying too hard to avoid allocating memory on the mistaken premise that the performance costs of doing so are as severe as they are in the C/C++ world. There are times when managed memory is a pain, and ever since JDK 1.4 there have been options available to avoid it. There are still cases where Java makes it hard to do what you really should be doing with memory, but they are well past the 90/10 rule.

In summary, I think you lack context when interpreting Java's design. This leads you to see nonsensical design decisions driven by proprietary head-knocking when in fact there are quite rational reasons behind their decisions. Java wasn't designed as a weapon for Sun to use against Microsoft (and looking at the design "faults" you've cited, I'm at a loss to see how they serve to make Java a weapon): that's how it was marketed. The original design was done well before the marketing strategy was even put in place (in fact the marketing strategy changed a few times as I recall), and originally was targetted at networked embedded devices (back before Microsoft had a presence there).

Sure, Java isn't perfect. No language is. Despite this programmers manage to find a lot of them useful, and Java is no exception in this regard.

A shame

Posted Apr 8, 2005 15:10 UTC (Fri) by jonabbey (guest, #2736) [Link]

My favorite thing about Java is just how safe and predictable it is. When I declare a member variable private, I know that nothing outside of that object will be messing with it, no matter what. No worries that some code someplace trying to copy a string will accidentally get a bad pointer and scribble randomly over my stuff.

Java's built-in threading control primitives and its ubiquitously thread-safe libraries are also great, as is RMI, the GC system, and its exceptions system.

There are a lot of things Java isn't good for (see John Carmack's recent comments on Java for some really good details there), but for a large class of programming problems Java is excellent.

Portability can be great as well, my Java server and client code runs just fine on Windows, Mac OS X, FreeBSD, Linux (x86, amd64, powerpc hosted on an AS/400 system), AIX, Solaris, and more, without any ifdef's or recompiles.

Yeah, there's a lot of things that would have been fixed many years ago if Sun were more open with the environment (I've had important bugs outstanding on Sun's Bug Database for 7 and 8 years, now), but you do wind up having to take the bad with the good, and the ubiquity and consistency of the platform is a notable good.

A shame

Posted Apr 8, 2005 16:03 UTC (Fri) by ncm (subscriber, #165) [Link]

In detail and in order,
  • Evidently the consequences of declaring a virtual member are still not very widely understood. A class with virtual members presents two interfaces: one to the user (who calls the members) and another to the deriver (who overrides the virtual members). The first presents an abstraction, while the second manipulates implementation details beneath the abstraction. If your public interface consists of virtual functions, then you aren't really providing much abstraction at all, and your class isn't really earning its keep. Given this, for members to be virtual by default is profoundly silly.

  • Java's exception specifications are markedly worse than in earlier languages. It's true that specs have turned out to be a mistake wherever they appear. (Probably the only form of exception specs that would work is to list exceptions that cannot come from a function. It's not clear how useful that would be, though.) In C++, you can simply leave them off (as everyone does, nowadays) and everything will work. In Java you can't do that; they intrude everywhere, unavoidably. They have actually got worse in Java 1.5 with the addition of generics.

  • As I said, a 16-bit internal character representation is frankly silly. An 8-bit UTF-8 multibyte format is defensible, and a canonical UCS-32 works. Either bank is OK, but the middle of the river is all wet.

  • To take up C syntax and fix only a few of its flaws is worse than silly. It reeks of cargo-cultism. C++ has C syntax to ease upgrading; users can compile a C program with a C++ compiler, and then start cleaning up. Most of the language's other infelicities are traceable to that requirement. Java had no such justification; no C program is a valid Java program.

  • To have to suffer all that the Java type system imposes with no benefit of compile-time error checking is ludicrous. It was known perfectly well how to do (inadequate) generics in the late '80s, as in Eiffel, or Ada. To wait ten years and then paste them on, crippled (because the code generated is the same as if you had done the casts), can only be described as another mistake. C# did only a little better.

  • One of the deep problems with garbage-collected memory is that its costs don't show up in profiling. When a program is an order of magnitude slower than it should be, there's a reason. With GC, it's likely to be bad cache interactions. With GC, there's precious little you can do about it. (Non-portable tricks might help, but then your "run anywhere" leaks away; even the next release of your own JVM might break them.)

  • The faults I listed were incidental stupidities, to illustrate the lack of understanding by the language designers. I didn't list the deliberate design flaws. It's easy to see why it was taken up most enthusiastically by the worst-organized corporate IT departments. People find ways to use all kinds of languages -- even Forth! That doesn't excuse the design, or the designers, of fundamental misunderstandings of their craft, and it doesn't suggest any reason to take up the language for one's own use.

Free Software has largely avoided being saddled with Java overheads, and can only benefit from continuing to avoid them. Let corporate America mire itself helpless.

A shame

Posted Apr 8, 2005 23:05 UTC (Fri) by Xman (guest, #10620) [Link]

I think it's sufficient to say that you see design flaws where language designers see design decisions. You may not like the decisions a language designer makes, but that doesn't make them design flaws. Every design decision has tradeoffs, and you make a choice about which tradeoffs you want to work with. A design flaw is when you make a choice without recognizing its short comings. With the exception of exception specifications and ill defined bits in the Java memory model (both of which were the cases where they tried to do something new with unknown implications, rather than borrow concepts that worked well in other languages), I don't think you'll find James Gosling was surprised or disappointed by how things played out.

You've implied with your statements that you think C++ is a "public-standard language that is more powerful and more thoughtfully designed" than Java. Let's look at how it plays out on these issues. Yes, it defaults to non-virtual functions, but it also defaults to private non-virtual inheritence. While most Java code leaves member functions as virtual, most C++ code uses public inheritence and specifies virtual inheritence whenever it is an issue. I'd argue those are issues of style, but if they aren't then I'd have to say C++'s defaults are far more flawed than Java's. C++'s exceptions create so many problems that the people who *worked on the language* couldn't figure out how one would write an exception safe stack for the longest time. C++'s string class can be made to do UCS-32 (you didn't need that memory did you? ;-), but has no notion of using a variable width encoding of strings, and a lot of implementations still ship with 8 and 16-bit character types. Indeed, C++'s string class is so "broken" that there are any number of competing string implementations out there (include C strings) in wide use while Java's String class seems to work just fine for 99% of Java code. C++ claims to be fully compatible with C, but manages to have several subtle differences which turns out to be far more dangerous than being similar enough to help developers understand what they are looking at. C++ is the home of one of the worst macro systems known to mankind and has a powerful templating system who's syntax is so baroque that a number of semantic ambiguities were uncovered at the last minute, forcing some hacked and overloaded uses of the keywords "typename" and "template" to disambiguate the code. Nevermind that the system is so complex to this day few compilers can fully compile code using the likes of boost::lambda. C++ doesn't come with any support for GC, so you end up with people often jury rigging a solution using reference counting that is inherently flawed, increadibly slow and a potential source of deadlocks if you need thread safety, often slower even when single threaded, still leaves them with a fragmented heap and... (wait for it) bad cache interactions.

Despite pointing out all these issues, I like C++, and use it probably more than any other language. The reality is all languages suck, because most design decisions have unfortunate trade offs. It's unfortunate when this intrinsic property distracts from the advantages each language has to offer.

A shame

Posted Apr 11, 2005 4:02 UTC (Mon) by ncm (subscriber, #165) [Link]

A disappointing feature in a language is a tradeoff only when something was gained in exchange. If you got nothing in exchange, then it's a pure design flaw. Exception specifications are a classic example: C++ has them, but shouldn't. Java has them, too (but markedly worse, despite hindsight!). It's a pure flaw, with no benefit in sight.

One doesn't run across people complaining about how slow programs C++ are, but people frequently complain about Java programs. Java programs, as a rule, really are slow. Garbage collection carries much of the blame. For C++, GC would not be a feature. Rather, it would make encapsulating resource management impossible, as it is in every GC language. The presence of GC doesn't only hint that a language is too weak to encapsulate resource management. GC, by itself, makes that impossible. GC actually sabotages the design of languages, for industrial purposes. It is possible that academia's insistence on GC in new languages is the sole reason that (still!) no language has surfaced that might displace C++ in industrial use.

The whole purpose of exceptions is to make programs simpler and more robust at handling errors. C++ exceptions work superbly: error handling code is reduced to one or a few chokepoints where exceptions are handled, with typically very little code, easy to exercise with minimal testing. Java exceptions, by contrast, fail completely: a Java program that handles exceptions properly is much longer, with error handling scattered throughout. Hard to exercise, it rots. (More commonly, it is just omitted.)

Anybody who can't design an exception-safe stack for C++ has not identified a flaw in the language. Idiocy is a purely personal problem. See http://cantrip.org/stupidity.html.

As I noted before, the macro system in C++ comes unchanged from C, for the strictly practical reason of backward compatibility; most C++ programs use only #include and #if. The template system works fine on mature compilers, of which many are readily available today. (That MS's product remains dodgy tells us way more about MS than about language design.) The problems in template syntax are a product of language evolution: ISO C++ templates are far more powerful than as originally envisioned. Power is worth trading a lot for.

I don't know of any widely-used string type designed after the ISO standard was published. Of course the old ones, and those necessary to interact with C code, hang around. Library apparatus to operate on in-core multibyte strings is no credit to a language. External multibyte text representations (and conversions to and from) are appropriate for interoperability, but it would be foolish to operate directly on strings in that form.

All this is not to claim C++ is especially good; rather, Java is especially bad. If Gosling isn't disappointed with his design, it can only be because he hasn't paid attention. Java has managed to set back the practice of programming by a decade. A whole generation of programmers have had their careers blighted by exposure to it.

A shame

Posted Apr 15, 2005 20:31 UTC (Fri) by renox (subscriber, #23785) [Link]

Frankly I think that your reasons are a bit weak for such "definitive judgements".
While Java has many flaws (the number of bugs in it standard library being the number 1 mistake, Swing..), it is not a bad language just disapointingly average (getting out a language with no generics just to release it faster, no comment).
What I find amusing is that you seem to find C++ okay and Java ugly whereas in my book it is just the opposite: C++ *is* bad: a language which needs years for developpers to learn (and from which they use 30% of the features at most) and for which no compiler can be fully conforming years after the specification was made is bad.
Also in my opinion, the 'bolted on' nature of C++ feels is really ugly (reference and pointers, urgg), whereas Java's shallow use of C syntax to ease migration seems sensible.


Copyright © 2017, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds