Beyond Java/Rules of the Game

From WikiContent

< Beyond Java(Difference between revisions)
Jump to: navigation, search
(Initial conversion from Docbook)
Current revision (17:12, 17 March 2008) (edit) (undo)
(Initial conversion from Docbook)
 

Current revision

Beyond Java

In 10 years of relatively heavy kayaking, a few scary rapids stand out. The Chatooga River had many such rapids. Bull Sluice on the Chatooga had a waterfall pouring through a hole in the riverbed. It was large enough on one end to admit a kayaker, but not big enough to let him back out. Cork Screw had a violent approach and a keeper hydraulic. Woodall Shoals was a placid-looking drop that masked a near perfect hydraulic that I considered unrunnable in my peak paddling years. On such rapids, the margin of error was frighteningly small. You walked around, hit your intended line, or risked getting hurt or dying. Those were the rules of the game.

Let's assume for a moment that you agree with the premise I laid out at the beginning of the book: conditions are ripe for an alternative applications programming language to emerge, because Java is abandoning its base. I'm not going to pretend to know what's next. Hopefully, I'll lay out some interesting languages and frameworks that have promise. I'll also rule out some languages right off the bat, based on the rules of the game.

If you think about it, you instinctively know that some programming languages will definitely not be the next big one. Lisp is productive, but the average Joe can't understand it. Perl is rich and powerful, but it's subtly inconsistent, and is prone to produce unmaintainable code. With a little vision and experience, you can apply a similar kind of reasoning to understand the types of languages that might follow Java. I suggest that we define success loosely: the language should be recognized widely and adopted broadly among developers who now use Java. This chapter, then, suggests the characteristics that the language should have to have broad commercial success.

Contents

Java Raises the Bar

Each new language is subject to the rules of its time. If you think about new inventions in the world of music, you'll see the same principle in play. Early in the recording industry, a record label would sign an artist to a specified contract, manufacture records, promote them on the radio, and distribute them in stores. You find some of those features today, like many of the roles in the production cycle and the importance of airtime (on radio, and now TV and the Internet). Changes in standards force the industry to retool. Some are relatively minor—changes in record speeds simply forced manufacturers to add capability to record players and recording equipment. Others will almost certainly be more radical. These changes require a critical mass to take hold—CDs achieved a critical mass, but eight-tracks did not. Sometimes, disruptive changes completely redefine the organization and very fiber of an industry. Our kids are redefining the way music is distributed through services like Napster and iTunes. Some artists are distributing their music entirely over the Internet, and they are cutting the publishing industry out of the equation altogether.

New programming languages work in much the same way. Every language leaves behind a legacy. Sometimes, changing languages embrace the legacy. For example, you compiled your C programs into a DLL or an executable. You could take advantage of your C code from C++ by buying a new compiler. You could even use C++ to write procedural code or object-oriented code. C++ changed the way we think, but it did not change much of the machinery. The C programming language was also disruptive in many ways. Java, too, was disruptive, redefining the rules of the game.

Kids like to be able to download songs like "Macarena" instantly, so the old music stores aren't cutting it anymore, and they are closing their doors. Don't even try to open one, unless you plan to bankroll it with your own money. By the same token, we like the convenience of the JVM, the massive open source community, and the focus on the Internet, leaving a higher standard for the next major applications language.

Portability

Remember our technical crown jewels. Java commercially introduced the concept of a virtual machine . It redefined the landscape. You compile Java into intermediate byte code that runs in a virtual machine. We've now gotten a real taste of the advantages of the virtual machine. The next major applications language will almost certainly support a virtual machine. You just can't ignore the benefits:

Security
If you can secure the virtual machine, it's much easier to secure the language.
Portability
The virtual machine provides a common, clean foundation for the language.
Extensibility
If your language turns out to be inadequate, you can always change the byte code. Java extensions like JDO (transparent persistence) and AspectJ use byte code enhancement to extend the Java language effectively.
Interoperability
Lower-level byte code makes it possible for one language to use the same deployment infrastructure, and even run side by side with other languages.

So, the virtual machine is important. I'll go one step stronger. The next commercially successful language should have a version that runs in the JVM. That would help a language overcome many obstacles, both political and technical.

Internet Focus

Java set a new bar for Internet integration , and Java's users took full advantage. Corporations use the Internet internally to discriminate information and control the deployment costs of an application. Businesses use the Internet externally to reach their customers and partners. Enabling applications for the Internet has become the most important problem that a business solves, except maybe database integration. Java enabled a whole new generation of Internet applications, with the servlet programming model, JSP as a compiled template language, and a whole suite of enterprise libraries. The next successful language will have to do the Internet, and do it better than Java.

The Internet has at least two dimensions: interfaces for computers, and interfaces for people. For people, the next language should build more powerful interfaces faster than you can build them in Java. I don't think it's enough to just build simple HTML. You need to be able to build a page that can preserve a common layered look and feel throughout an enterprise, so the next language will need to support some kind of component model. Also, users are just beginning to understand that HTML is not enough. Applications like Google Maps and Google Mail stretch HTML and JavaScript to new levels. That's going to be very important to the next successful language.

In fact, many of the consultants I interviewed for this book believe that HTML is broken in fundamental ways. A broadly successful new language could conceivably present a higher abstraction that makes it easier for the industry to retool, piecemeal. Ruby on Rails and Ajax technologies both seem to be moving in this direction.

Interoperability

Bridging from Java to an emerging language will also be important. Of course, if the new language embraces the JVM, interop at lower levels will not be a problem. Interop on the Internet will undoubtedly play a critical role. I think that leads to three important capabilities: XML , web services, and service-oriented architectures.

XML and structured data

Programming has always meant working with data, yet Java doesn't let you declare nested structured data very well. In Java, you see a proliferation of XML, even where it offers little tangible value. For example, metaprogramming and all kinds of configuration require you to express structured data. The next language should let you declare and express structured data, cleanly and natively.

Still, structured data and a language to describe it are important. If you're dealing with structured data on the Internet, you're probably dealing with XML. The next successful language should let you deal with XML productively, and with good performance. In Java, we've dealt with that problem using parsing schemes, query languages, and binding frameworks. A parser cracks open XML and lets you break it into its constituent parts. A binding framework lets you take an object model and convert it directly to XML, or deal with XML as if it were a native object model. XML query languages like XQuery can reach into a complex XML document to retrieve one named piece of data. It's reasonable to expect an emerging language to support all three XML technologies, and most of them do, to various degrees.

Service-oriented architecture (SOA)

A common structured data format is not enough to bridge two languages. You also need a communications mechanism. One trend in languages like Java is to build loosely coupled services, available on the network, and let them communicate with simple messages, with an XML payload. It's a good strategy for interop, for many reasons:

  • SOA works best with coarse-grained architectures, or calling big chunks of code. Interop between languages is a coarse-grained problem.
  • SOA is hot. Since it's politically popular, support and mindshare will likely remain high.
  • SOA uses Internet standards. That means you can leverage existing infrastructure, like security and existing message protocols.

I'm not sure that web services, as defined by IBM or Microsoft, has staying power. I do believe that a lighter form of web services, called REST, may last. REST stands for Representational State Transfer, and it promotes using services the way Internet sites have used them for years. Like the Internet, REST views the network as a collection of resources rather than a collection of methods (like CORBA or traditional web services.)

A REST-based resource returns a representation of itself, usually in XML form. REST allows and even encourages links. REST-based services are based on well-understood, mature APIs, so unlike the fragile traditional web services stacks, they integrate well with other technologies. They can also rely on existing infrastructure to cache content, build links, or secure communication. It's a powerful paradigm shift.

So, Java provides the first set of rules, shown in Table 5-1. If you want to run this river, you'll need to meet the improved standards set by Java. To do anything less means death.

Table 5-1. Java's legacy requirements

Rule Description
JVM and/or Microsoft Common Language Runtime (CLR) Run in the JVM, or at a bare minimum, run in its own virtual machine.
Internet focus Enable Internet applications.
Internet user interfaces Allow richer Internet user interfaces.
Service layer Provide an SOA-style integration with Java.
Web services Allow some type of web service, whether it's the full web services stack or REST-based web services.
XML Provide a rich, productive XML API.

Enterprise Integration

In some ways, C redefined enterprise integration, by allowing strong database connectivity across an open API (ODBC for Microsoft applications) and providing transaction monitors like Tuxedo and Encina. C was disruptive—it introduced enterprise programming beyond mainframes. Java continued this legacy with frameworks for transactions, rich database integration, messaging, and many other forms of plumbing code called middleware.

I don't think the next major applications language will initially have to have the full enterprise capabilities of C or Java to succeed. Visual Basic certainly achieved tremendous success without these capabilities by leveraging the services provided by other frameworks written in lower-level languages like C. We've already determined that the next language should interoperate with other Java programs, hopefully within the same virtual machine. It should also interoperate through a coarse-grained service layer. That said, some enterprise capabilities will be very important.

Database Integration

Minimally, a new language should access relational databases in a natural, productive way. I don't think any particular application style is important—you can see wildly successful environments with different strategies:

  • Microsoft builds a framework that leverages the power of SQL , row sets, and relational databases. The center of the Microsoft universe, from a data perspective, is the relational database. The strategy can scale very well and is surprisingly productive.
  • Java, instead, seems to be moving toward ORM. The center of Java's data universe is an object-oriented, persistent model. Other Java applications leverage JDBC with helper frameworks quite successfully.
  • Ruby on Rails takes an intermediate approach. Rails wraps a database table with objects that discover the structure of the database dynamically.

All strategies have strengths and weaknesses, and each could serve as an effective foundation for a new language. I do think that emerging languages, and the core frameworks they need, should try to follow these rules:

Embrace the relational database
While a language may integrate with alternatives, the relational database should be a first-class citizen. Too much focus on object-oriented databases proved to be a problem for adoption for some Smalltalk frameworks. Object-oriented databases are an elegant solution that ignores the current political realities.
Don't force structure on the relational database
At some level, a language must make it easy to use existing relational schemas, as they exist. Forcing a surrogate unique identifier rather than a composite primary key also ignores existing realities.
Perform, and scale
High database performance is the single most important indicator of good application performance.

Transactions and Security

Enterprise developers need the ability to define a business transaction. It doesn't matter how fast you can build incorrect applications. If Joe Bob loses $50 in an Internet transaction because Sally Sue crashed the server by tripping on a power cord, the framework is not going to make it in the enterprise.

Security is also important, though you could probably argue over how important it could possibly be with the gaping holes in operating system security today. Java has set a bar that's going to be pretty hard to clear in this area. The next big language will need the ability to integrate with existing enterprise security frameworks, at least the Internet-based schemes and standardized ones like LDAP. Table 5-2 summarizes the enterprise features a new language will need.

Table 5-2. Enterprise requirements for a new language

Rule Description
Database access API Provide a clean, productive API for database access.
Relational databases Focus on relational databases first.
Database performance Database interactions should be very fast.
Transactions Enable application transaction demarcation.
Language security Provide a clean foundation for language security.
Application security Let developers secure their applications.
Security integration Let developers integrate enterprise security, especially for Internet applications.


Like the Java features, having these basic enterprise features does not guarantee success. They just let you play the game.

Generating the Buzz

Many languages have trumped Java technically, but they still failed. Betamax, too, was technically better than VHS. The biggest factor of the equation is social. Without a credible community, there can be no success. To a programmer, a language is an investment in a future, and even an identity. Call it marketing, or buzz, or even hype. If it's hip, or at least interesting, a language stands a fighting chance. If not, there's no chance at all. In some ways, Java helped pave the way for the next language:

  • Communities like TheServerSide and Slashdot provide a forum for new ideas to spread quickly through the Java and non-Java programming communities. It's much easier for smaller projects to create a big buzz.
  • The increased emphasis on open source software, partially driven by Java, makes it easier to wrestle control away from larger companies. Also, those same companies find open source technologies easier and less threatening to adopt.
  • Many Java standards like Web Services (and lightweight HTTP alternatives) make it much easier to interoperate between languages.
  • The JVM will run other languages. A new language on the JVM is a much easier sell than a new language in a new environment.

Still, the challenges of establishing a community are daunting. Microsoft has spent millions of dollars promoting the .NET environment, and the adoption on the server side is still nowhere near Java's adoption, though many of the features and capabilities are similar or superior to Java. Sun, for all of its success with the Java platform, has not been able to capitalize on it in the software realm. Adoption of Sun application servers and management software has been spotty at best. IBM lost the battle of the operating system because it couldn't market a technically superior OS/2.

Programmers are a schizophrenic lot. One moment, we're the ultimate skeptics, ditching the safety of the Microsoft Windows environment for unpredictable Linux systems on our desktops. The next, we're lemmings, adopting hideous architectures like EJB without the slightest bit of proof. You also have many different niches within the programming community. Java's been successful for enterprise developers, but hard-core hackers in the Perl and Python communities frown on Java. And Microsoft developers form cultures all their own, with subcultures in it that favor C++ or Visual Basic.

That means the winning formula will also change. At one point, a dominant personality like Steve Jobs may make the difference, and the next, like with the star-crossed NextStep platform, it's not enough. This is all to say that generating buzz is more art than science, and maybe more luck than art. Still, certain themes and trends ring true.

Open Source

Unless it's a disruptive technology, it's hard to imagine the next major programming language coming from a larger commercial vendor. There's just too much fear and distrust among the major players: Microsoft, IBM, and Sun. Instead, I think a credible alternative is much more likely to emerge from the open source community. The open source model provides a stage for thousands of projects, where they can succeed or fail based on their merits. Projects need to prove effective technologies and marketing amid a cynical, critical audience to succeed. There are several interesting test cases in the open source community now: Perl, PHP, Python, Ruby, and many others. You see far fewer commercial languages with any degree of momentum. The biggest, C#, is effectively a Java clone.

Open source software has something else going for it. Since open source projects usually have no formal support, the community must support the language. This environment tests the community dynamics for a language as well as the technology. Communities take on a personality, like snobbish, edgy, nurturing, or bickering. Larger languages like Java may have subcommunities with personalities all their own. When a language gets sudden attention, the personality of the community will either attract or repel new users. Fine-tuning community dynamics is a difficult proposition, because this personality may be hard to judge from the inside. A new language will need an attractive community to succeed, and the open source community seems like a natural place for that to form.

Economics

While open source frameworks usually lend a certain intellectual honesty to a project, commercial forces will have the deciding vote. A new language needs a supporting ecosystem to thrive, and that means someone has to write a check eventually. Simply put, you can't move away from Java without economic justification. To me, the leading potential economic catalyst is clear—an overwhelming advantage in productivity.

When I stepped away from Java for the first time, I needed an economic mother bird to nudge me out of the nest. Java's just too safe and too comfortable otherwise. Recall that as I write this book, I am calling the shots for a start-up. We're writing a Java application to help engineers configure equipment that measures safety systems in manufacturing plants. I recommended moving the application from Java to Ruby midstream because I found the difference in productivity between the environments too great to ignore. Further, when all was said and done, the new application was easier to maintain with fewer lines of code, it was fast enough, easier to tune, and easier to extend with security. I'd estimate that we're three to five times more productive in Ruby. Certainly, Ruby is not the only language that's more productive than Java, but it's an interesting test case. You'll see more in Chapter 7. Productivity will be the economic catalyst that begins to chip away from the Java base. Productivity will drive the emergence of the next great language.

Approachability

When you look at early adoption for all major successful languages, one of the key issues is approachability. New languages need to grab new users quickly. You should be able to get started quickly, and solve a problem that's important to you immediately. C was approachable because it let hard-core systems programmers solve low-level problems in a high-level language, with much better performance and flexibility than other high-level languages. C++ was approachable because you could write C without modifications, and upgrade to C++ features as you wanted to include them in your programs. Java was approachable because it had a familiar syntax, a friendlier memory model, and a clear, consistent path to Internet solutions. Smalltalk was not approachable, because vendors charged too much—it was too expensive to play.

Though nothing simple has a C++-like syntax, I still think that many languages are approachable because of their friendly, productive syntax with a familiar object model. Python versus Ruby is a good example of differences in approachability. Ruby has one of the most highly productive web environments, and a community and philosophy focused on getting programmers off of the ground quickly and painlessly. You can install components easily, often with two or three words, using a feature called Gems that does the work for you, provided you have an Internet connection. Python, on the other hand, has a simple language and syntax, but the web libraries are nowhere near as approachable. When you start to learn one of them, you don't find the ready tutorials or community reaching out to help you. The Ruby on Rails people understand how to make Rails approachable.

The Killer App

Without some kind of catalyst, it's difficult to imagine how a successful community ever gets started. Applets let Java spread to many desktops quickly. Developers could embed dynamic content into their web pages in a matter of hours.

On the surface, it seems like a language must have a vibrant community to ever get rich enough to succeed on any scale, but the community usually won't come until the language is rich enough. A killer app to a developer is a solution that is so compelling that it transcends language. It alone can rapidly drive community growth. It's not the only way a language can succeed, but it's certainly the most likely way.

The killer app is a popular notion of a catalyst. A killer app solves an important problem in such a forceful way that users are compelled migrate. Think California gold rush. People often point to the Lotus 1-2-3 spreadsheet as the killer app that moved businesspeople to Microsoft Windows. Meanwhile, the killer app for OS/2 never came. For Java, you could easily argue that Netscape made it all possible by putting Java on the desktop of millions of potential developers. Applets, or the idea of deploying applications in a browser, also played a significant role, and it's that concept that morphed into servlets and server-side Java programming. The killer app is a seductive idea, because it encapsulates so many important concepts:

  • The catalyst, with economic justification, often takes the form of a killer app .
  • Once a solution is technically viable, a killer app enables a rapid growth to critical mass. It often solves a chicken and egg problem: you can't build a sufficiently robust language without community, and you can't build a community without a successful language.
  • The killer app often initiates the hype that's required to escape a niche. With the newly found hype, the language can explode from a small, focused niche to a more generally successful language.

Remember, a language alone is rarely enough. Right now, several interesting technologies could possibly grow into potential killer apps. Smalltalk's continuation servers, Ruby's metaprogramming environments, and PHP's many applications like bulletin boards may serve as potential killer apps. We'll look at some potential killer apps in Chapters 7 and 8.

Table 5-3 lists community-centric roles . Each of them will come into play when it's time to determine the next major language.

Table 5-3. Community-centric roles

Rule Description
Open source Have a rich open source community.
Productivity Be much more productive than Java for the simplest commercial applications.
Catalyst Have a tremendously popular application or framework that transcends programming languages.
Familiarity Be easy for Java developers to learn.
Simplicity Make it easy to solve simple problems.

Language Features

It's strange to be more than halfway through the characteristics of the next great programming language without even talking about the major features of that language. When you look at the history of programming languages, it makes more sense. The features of a language are important characteristics for success, but only rarely are they the most important characteristics. Said another way, market share and mindshare matter more than how you interpret whitespace.

Dynamic Typing

Java purists defend strong, static typing with the fervor of English soccer fans. To be sure, static typing does have its advantages:

  • Static typing enforces typing rules at compile time, when they are least expensive to fix.
  • Static interfaces make it easier to enforce a protocol across important boundaries. For example, systems designers may want to force certain types for C interfaces, or certain remote procedure calls.
  • Static typing catches some types of subtle errors at compile time, like the misspelling of a variable name.

Still, as you learned in Chapter 4, there's a related cost, usually in productivity . Java developers often make the comment that you can pay now or pay later. That's strange, because Smalltalk and Ruby programmers rarely make lasting errors related to incorrect typing. Further, disciplined automated unit tests easily catch most type mismatch problems. You've got to unit test your code whether you want to or not, because no compiler can completely guess your intent.

Most Java developers who tout the benefits of strong, static typing fail also to count the cost. When you're learning or playing with a language, the cost is excessive, because you have to declare everything, including a wrapping class, and learn a whole new level of detail. Here's a "Hello, World" example in Ruby:

    puts "Hello, world."

And here's the Java counterpart:

    class HelloWorld {
      public static void main(String[  ] args) {
        System.out.println("Hello World!")
      }
    }

A Java program requires a rigidly typed class with a Main method. The barrier to exploring in Java is simply much higher. Most of the experts that I interviewed for this book recognized that static typing limits productivity for application development dramatically, though some said they were willing to pay the cost for certain types of code, like systems code and middleware. I think it's fair to assume that for applications development, productivity is important enough to warrant dynamic typing for Java's ultimate successor.

Code Blocks and Continuations

The Java open source community now uses anonymous inner classes with greater and greater regularity. When you need lightweight callback-style functionality, in Java the best way is the anonymous inner class. Here's an example of JDBC-style access in Spring, with the anonymous inner class:

    JdbcTemplate template = new JdbcTemplate(dataSource);
    final List names = new LinkedList();

    template.query("SELECT USER.NAME FROM USER", new RowCallbackHandler() {
          public void processRow(ResultSet rs)  throws SQLException {
               names.add(rs.getString(1));
        }
      }
    );

Here's a code block in Ruby:

      dbh.select_all("SELECT name, category FROM animal") do |row|
        names << row[0]
      end

This code example executes the code in bold for each row in the result set, which is passed into the code block's row variable.

For application programming, code blocks show up frequently. Any time you need to iterate through a collection, or a result set, or a file, code blocks come into play. Keeping them simple saves you a tremendous amount of work.

Continuations will also be important. In Chapter 8, you will see how continuations dramatically improve productivity in web-based programming.

Rapid Feedback Loop

Think of a feedback loop as the time between making a change and seeing the impact in running code. New application development principles, like test-first development, work best with a fast feedback loop. Small changes in the feedback loop can make huge differences in overall productivity, because you do it so many times every day. With Java, you need to deal with at least a compile step, and you often add steps for code generation (XDoclet), byte code enhancement (JDO), and deployment (servlets and EJB). For Java, that means you must wait to see a source code change realized in executed code. Developers tend to underestimate the benefits of a small feedback loop, unless they're regularly using a dynamic language and need to go back to a static language.

Smalltalk, Lisp, Perl, Ruby, and Basic all have rapid feedback loops, and they're also incredibly productive languages. C, C++, and Java don't. In fact, Java might not have succeeded if its users had come from a dynamic language supporting a rapid feedback loop.

User Interface Focus

More and more, I'm seeing experts that need to do significant user interface development move away from Java. Given the strong server-side focus of the past six years, that news should not shock any of us. Still, the number of Swing experts who vehemently defend it, without trying a meaningful alternative, confuses me, like two Titanic passengers arguing over which deck is prettier as the ship sinks around them. James Duncan Davidson said it best: "Friends don't let friends Swing." User interface development demands more than Java has to give. For most application developers, the framework should do much more for you.

Dynamic Class Model

The Java successor should be much more dynamic, and reflective. Java's reflection API is particularly hostile because it must deal with primitives , arrays, and classes. Let's look at a Java example of reflection. Here's a simple XML emitter provided by Stuart Dabbs Halloway, courtesy of DevelopMentor:

    public static void doObject(Object obj) throws Exception {
      Class cls = obj.getClass();
      emitXMLHeader(cls);
      Field[  ] fields = cls.getDeclaredFields();
      for (int i=0; i < fields.length; i++) {
        Field field = fields[i];
          field.setAccessible(true);
          Object subObj = field.get(obj);

          if (!Modifier.isStatic(field.getModifiers())) {
            if ((field.getType().isPrimitive()) ||
               ((field.getType().getNamxe() =  = "java.lang.String"))) {
              emitXML(field.getName(), subObj);
            } else {
              doObject(subObj);
            }
          }
        }
        emitXMLFooter(cls);
      }

I've omitted the code to actually emit the XML, but you get the picture. Look carefully at the lines in bold. You had to deal with primitives a little differently, but I'm lucky, because for this particular problem, I can treat all primitives the same. That's usually not the case. I'm really not done, because I also need to deal with arrays, leading to a whole new level of complexity.

Let's take another example. Here's an example that prints method names in Java:

    public static void printMethods(Object obj) throws Exception {
      Class cls = obj.getClass();
      Method[  ] methods = cls.getDeclaredMethods();
      for (int i=0; i < methods.length; i++) {
        Method method = methods[i];
        System.out.println("Method name:" + method.getName());
        Class parmTypes[  ] =  method.getParameterTypes();
        for (int j = 0; j < parmTypes.length; j++) {
          System.out.print("  Parameter " + (j+1) + " type:");
          System.out.println(parmTypes[j]);
        }
      }
    }

It's not as easy as simply grabbing the method names, because Java uses overloading, so you need to know the method name and parameter types to accurately identify a method. I'm going to give a Ruby example next, so if you want to compare apples to apples, just disregard the lines in bold.

Here's how easy reflection can be in Ruby. First, create an object. What class are we dealing with?

    irb(main):001:0> i=4
    => 4
    irb(main):002:0> i.class
    => Fixnum

Return a list of methods supported by a given object:

    irb(main):003:0> i.methods
            

Print a neat list of the methods that Fixnum supports:

    irb(main):003:0> i.methods.each {|m| puts m}
            

So, Ruby is very reflective. We've done the Java example (minus the lines in bold) in a single line of code. You can similarly find the instance variables, super classes, and so on. That's only the beginning of the power at your fingertips, though. You can also change classes, at runtime, on the fly. You can change a method on an object and leave the class untouched. Also, interceptors are child's play. You can use this metaprogramming to do some amazing things. The Ruby on Rails framework, featured in Chapter 7, shows an excellent example of what you can do.

I should point out that the primitives problem goes far beyond reflection. Look at the API for java.util.Array. You've got to treat arrays as their own kind of type. Java 1.5 makes matters worse by introducing generics. You run across similar problems whenever you need to deal with things generically, whether you're comparing, cloning, reflecting, or describing an object. It's a major problem that's encountered equally by people who use and build frameworks that deal with all types of user-defined objects. As we seek to find more ways to use objects transparently, the problem will only get worse.

Sound Foundations

I'm working on pure intuition here, but I do think that Java's successor will probably be object-oriented, and will be theoretically purer than Java. A purely object-oriented language makes things so much easier, especially when you start to consider metaprogramming, simplicity, learning curves, and increasing processing power. With Java's increasing emphasis on transparency, a cleaner approach will simplify many types of frameworks:

  • Transparent persistence frameworks need only deal with objects and collections.
  • XML binding frameworks would have a cleaner API, and a much cleaner implementation.
  • Debugging frameworks like loggers could easily print values of any parameters.

Consistency is important, too. Languages with consistent naming and consistent behavior are far easier to learn. In general, the next language should be much more consistent, and cleaner. The characteristics in Table 5-4 would form a cleaner foundation for another 10 years of successful growth.

Table 5-4. Important language features that will help propel Java's successor

Rule Description
Dynamic typing Support dynamic typing for better productivity.
Rapid feedback loop Minimize the time between making a change and seeing it execute.
User interface focus Provide a productive, rich environment for building user interfaces.
Dynamic class model Improve the ability to discover and change the parts of a class and runtime.
True OOP Provide a conceptually pure implementation of OOP with no primitives and a single root for all objects.
Consistent and neat The language should encourage code that's clean and maintainable.
Continuations The language should enable important higher abstractions like continuations.

A Few Potential Suitors

Now that you've seen what the industry has to offer, let's take a quick review of some programming languages and identify some possible candidates. You'll see a more comprehensive treatment of the contenders in Chapter 9. If you buy what I've been selling so far, you understand that for certain jobs, other languages may be better suited. I encourage you to try one of these languages every month or so.

If you've not been exposed to languages outside of C++, Basic, and Java, I've got to warn you that the experience can be unsettling. You'll be surprised at how much of your knowledge commutes, and how quickly you can grasp the essence that makes a given language so productive. You'll also be surprised at the fury that you can generate around the office just by peeking at alternatives—you may want to leave the nice car in the driveway and take the old Family Truckster to work for a while.

Perl

Perl is a scripting language, with a quirky syntax and a turbulent past. Here's a quick example that prints "Hi, Bruce":

    my $name = "Bruce";
    print "Hi, ", $x, "\n";

What I like

If raw productivity is your goal, perhaps Perl is a possible answer. It's dynamically typed, is highly productive, and has a small community established. It also has a fanatical following.

What I don't like

Perl does have a big downside. To this point, Perl's got a reputation of a write-only language: with its cryptic syntax, you can easily produce code that's very difficult to understand and maintain. Perl's OOP syntax, as with C++, is bolted on and awkward. As something more than a scripting language, Perl's reputation is probably a bit much to overcome.

Python

As dynamic programming languages go, Python has been one of the most successful. It's very close to Ruby in syntax and power, and it supports the language features that you'd want. Here's a brief snippet of Python code that counts to 10:

    for x in xrange(10):
        print x

What I like

It has many of the features you need in an application's language: dynamic typing, a quick feedback loop, and a concise syntax. It's pretty fast, and it has a version that runs in the JVM (albeit slowly).

What I don't like

As much as I'd like it to be, I don't think Python is the ultimate answer. Ruby's inventor, Yukihiro Matsumoto (Matz), didn't use it because it's not object-oriented enough.[1] Python depends too much on whitespace, which most experts agree probably goes a bit too far. Others in the Python community aren't happy with the web development tools.[2] The web tools seem to be based on the Java stack, so there's no radical invention or departure. The community doesn't feel right. At times, it's too academic and too defensive.

The biggest hurdle for Python is its lack of compelling reasons to move away from Java. Python really needs a killer app. In the end, we've already formed our opinions. Python will be a moderately successful dynamic language, on the order of Smalltalk.

Ruby

Ruby is an object-oriented language created in the mid-1990s in Japan. The Ruby community grew steadily, and the language is now emerging beyond Japan. It's gained popularity in the United States only in the last couple of years.

What I like

Ruby has a beautiful syntax. It reads like English, and it miraculously stays out of your way. It's highly dynamic, and the educated core of the Ruby community works hard to produce clean, simple APIs. Ruby has strong web frameworks, and good support for XML and web services. Ruby has a couple of popular emerging frameworks, like Ruby on Rails. The web and XML frameworks are innovative and simple. The portable interpreter is fast, and it has the necessary plug-ins for the Apache web server. The standalone web interpreter, called Webrick, has several high-profile applications running on it. Most importantly, Ruby may have the killer app in Rails, which I'll discuss in detail in Chapter 7. This year will have four new Rails books and a strong publisher in the Pragmatic Bookshelf. Ruby doesn't have any political baggage that would turn away a potential commercial adopter. It's fairly mature.

What I don't like

In Japan, Ruby has good commercial financial backing and support. Outside of Japan, Ruby has an embarrassing lack of commercial backing. Its relatively small community shows in the dearth of niche frameworks. The JVM support is immature (although it is admittedly improving rapidly). Early attempts to produce a version of Ruby running on the JVM had a few false starts. Still, the JRuby framework has seen a resurgence of sorts in early 2005, so it may well produce a credible Java alternative on the JVM. Ruby is on the radar; it just needs a tighter affinity with the JVM and the continued success of Ruby on Rails.

PHP

PHP is a scripting language. With PHP, you effectively start with HTML, and mark it up with tags that can tie your application to a database, or other back-end systems. The tags get interpreted on the server, which returns pure HTML to the client. It's effectively a JSP. Here's a "Hello, World" app in PHP:

    <html>
      <head>
        <title>Hello, world</title>
      </head>
      <body>
        <?php echo '<p>Hello world</p>'; ?>
      </body>
    </html>

What I like

PHP success seems to be ramping up sharply, mostly on the strength of converted Visual Basic programmers. It's very well suited for its "sweet spot," controlling database access from a web page. It's easy to understand and easy to learn. PHP, more than any other language, is taking advantage of the frustration in the Visual Basic community due to changes in .NET.

What I don't like

PHP is theoretically awful. The model tightly couples the user interface and database together, and that's usually a bad idea, because changes in one can ripple through to the other. Since PHP grew rapidly and haphazardly with a heavy Perl influence, method names are often inconsistent, with some opting for underscores between words (stream_get_line) and some opting for concatenation (readline). PHP effectively has a reputation for productivity and rapid innovation at the expense of a consistent language that promotes sound architecture. As a Java programmer, you've probably already seen JSP pages that try to do too much. They're quick to write, but the solution bogs down in a hurry.

C# and Visual Basic

C# is effectively a Java clone. It has many of the same benefits and drawbacks. Visual Basic on the .NET environment seems to be losing momentum, because the older Visual Basic developers don't seem to have the same fervor for VB.NET. Microsoft has other languages as well. In the end, Microsoft will always have a core set of developers. That's effectively a closed ecosystem, though. It's limited by the success of the Windows platform, which is adopted broadly on the client, but decidedly less so on the server side. I'm not predicting success or failure; I just think that Microsoft languages depend on the success or failure of Microsoft platforms as a whole, rather than on the strengths or weaknesses of any given language in it.

Smalltalk

Invented in the early 1970s, Smalltalk is a well-established, hard-luck object-oriented language. Many see Smalltalk as the first object-oriented language, but it never really caught on commercially, despite some attempts as late as 1995 by IBM. It's hugely productive, slightly awkward, and quirky to the extreme. There is a vibrant, but small, Smalltalk community. Most of it is centered on a highly productive, continuation-based application development framework called Seaside, which we'll discuss in Chapter 8.

What I like

Smalltalk has a clean object model, incredible expressive power, and an intelligent design and community. It's got some solid free implementations, and a potential catalyst in Seaside. Glenn Vanderburg is fond of saying that all things will probably return to Smalltalk, but they won't be called Smalltalk anymore. When you see the influence of Smalltalk on languages like Ruby, that idea makes sense.

What I don't like

Smalltalk is not seen as a credible alternative. It just wasn't ever approachable enough. Smalltalk would have been a natural successor to C++ if Java hadn't come around first, but it was always too expensive, or too alien, or too obscure.

No Silver Bullet

You may have noticed that no language has all the characteristics we're seeking. That's not surprising. If one did, we'd be using it by now. Still, you can see that these languages do establish real strength in important areas. In the chapters to come, I'll take a deeper look at Ruby. Since it's not enough just to have a better language, we'll then investigate some potential killer apps.

Notes

  1. Dave Thomas, Programming Ruby (Dallas: Pragmatic Bookshelf, 2005).
  2. http://blog.ianbicking.org/why-web-programming-matters-most.html.
Personal tools