Beyond Java/Owls and Ostriches

From WikiContent

< Beyond Java
Revision as of 17:12, 17 March 2008 by Docbook2Wiki (Talk)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search
Beyond Java

Some kayakers that I know have a death wish. They bomb down Class V runs with reckless abandon. It seems like a matter of time before they run that waterfall that has trapped deadwood underneath it. Such an obstacle would trap the boat, and the force of the river would pin the boater underwater. They're like ostriches, ignoring the danger with their head in the sand.

There's another kind of boater, though. When I first started kayaking, I scouted everything. I would stop at the most casual Class II+ (beginner) ripple to look it over and set up safety ropes for 45 minutes before making the run. Often, I'd run out of time on a river, and be forced to bomb down a bottom section to complete it before nightfall. Now, I rarely get out of my boat to scout most minor rapids. In certain places, it's just not practical. Instead, I use chase boating techniques, invented in the narrow, steep rivers of the Southeast, to improve my chances. I don't boat this way because I like danger. In fact, I've honed my instincts to understand where danger is most likely to be. I boat this way because it lets me focus my scouting time where I need it most. These boaters are the owls.

It comes down to this. I'll often ignore risks involving minor consequences or low frequencies because dealing with the risk is not wise. Managing the risks properly may take too much effort, money, or time, opening me up to additional risk, which brings me back to owls and ostriches . Normally, there's a huge difference between the two, but occasionally, owls will get overconfident or make minor errors in risk assessment, and convince themselves to run something dangerous without scouting. That's happened to me. I've run the same creek hundreds of times, and something changes like higher river levels or the creek bed after a flood. There's a fine line between owls and ostriches. Sometimes, it's even tough to tell the difference between the two. As a kayaker, even if I've decided to ignore certain kinds of risks on certain rivers and conditions, I've sometimes got to step back and reassess the risk. That's the subject of this book.

Contents

Ignorance as a Virtue

In many ways, kayaking is like programming. I've learned an incredible trick. I can be surprisingly productive by simply ignoring most problems. With a little luck, the problems often just go away. Such an attitude can work for you or against you. Many post office clerks and minimum-wage fast food employees have learned that the same technique actually works for their problems, also known as customers. These are ostriches. If you look closely, you can find some selective, wise application of ignorance—the owl's trademark. I actually find that most "problems" in programming are merely potential problems. If you've read any of my books, you know that I preach against the dangers of premature optimization, and echo the popular agile principle of YAGNI : "You ain't gonna need it." I usually ignore bloated frameworks that promise to save me time, trusting my instincts to simpler solutions.

More to the point, I've found that Java does everything that I need, so I haven't looked beyond these borders for a very long time. Ignorance is bliss. I know some languages are more dynamic, and possibly more productive in spurts, but in the end, it seems like Java will always win. It's got tens of thousands of frameworks to do anything from running systems for nuclear reactors to programming an embedded controller on a power toenail clipper. Many of the best frameworks are even free. I can always find a Java developer to do what I need. I know that people have made it work to solve massive problems. And I know that my customers will feel safe and secure. In short, the community and breadth of Java have always trumped anything that the alternatives have to offer. So I quit looking. And I'm glad that I did, because it allowed me to focus on building a consulting business and satisfying my customers instead of doing exhausting research for every new problem.

When a dominant language or technology is in its prime, there's a blissful ignorance stage, when ignoring alternatives works in your favor. Figure 1-1 shows what I mean. When a new language arrives with the power and dominance of a Java or C++, you can afford to ignore alternatives for a while. But if you don't accurately identify the end of the cycle, you can get steamrolled. Suddenly, your competition has the jump on you, with much better productivity leading to better quality, improved productivity, and more customers. When you enter the transition time, you'd better start paying attention.

I admit unashamedly that I liked having my head in the sand. It was easy, and productive, and politically safe. I bet that many of you Java developers act like me. You may have your own reasons. Living in this shelter is certainly easier—doing nothing trumps extra work. You might feel safer—no one ever got fired for choosing IBM. (OK, so maybe Component Broker on

Figure 1-1. For a period of time, ignorance is productive, but the ending of that period can be unpredictable

For a period of time, ignorance is productive, but the ending of that period can be unpredictable

OS/2 was not such a good idea....) You may have an incredible investment in skills that you believe will not commute, and if you've invested poorly in your skill set, you may be right. You may be bound like a Siamese twin to Java by a long-term project or a group based on the language. Like my reasons, many of these are sound.

Shaken to the Core

After living in blissful ignorance for five years or more, I had an experience that shook me to the core. I led a new start-up down a path that required what I'd consider three of the most productive lightweight frameworks out there for web development of persistence applications: Hibernate, Spring, and Web Work. I knew there were slightly more productive environments for this kind of thing, but they either would not scale (in terms of complexity or performance), or were not popular enough to justify the risk.

My partner and I decided to implement a small part of the application in Ruby on Rails, a highly productive web-based programming framework. We did this not to satisfy our customer, but to satisfy a little intellectual curiosity. The results astounded us:

  • For the rewrite, we programmed faster. Much faster. It took Justin, my lead programmer, four nights to build what it had taken four months to build in Java. We estimated that we were between 5 and 10 times more productive.
  • We generated one-fourth the lines of code; one-fifth if you consider configuration files.
  • The productivity gains held up after we moved beyond the rewrite.
  • The Ruby on Rails version of the application performed faster. This is probably not true of all possible use cases, but for our application, the RoR active record persistence strategy trumped Hibernate's Object Relational Mapping (ORM) , at least with minimal tuning.
  • The customer cared much more about productivity than being on a safe Java foundation.

As you can well imagine, this shook my world view down to the foundation. I'm now frantically trying to catch up. It seems that conditions on the river changed without my noticing. I've got to start scouting again.

Boiling Frogs

Let's look at it still another way. You've doubtlessly heard that if you put a frog in hot water, it will leap out, but if you slowly bring tepid water to a boil, the frog will die contentedly. And of course, that's the debate that I hope to trigger in this book. Are the waters around us warming? Notice at the end of my introduction, the owl and the ostrich are exactly the same when it comes to consequences. They may not recognize it, but motivations don't matter one little bit. If the water starts to boil, if the conditions on the river change, they'll both die.

This past year, I decided to wake up to my surroundings to test the water around me. I learned both Ruby and aspect-oriented programming (AOP) . After checking the temperature, I think the water is actually heating up. It's not boiling yet, and I don't know if it will ever boil. But I do know that I'm going to keep a close eye on the temperature for a while, and I hope to convince you to do the same. Let me tell you why.

Danger Signs

A large number of the applications that we write put a web-based frontend over a database, sometimes with additional business rules and sometimes without. Yet, after more than five years of solving this problem over and over, we still can't solve it very quickly in the Java space. Further, most Java framework developers are making incremental changes that won't truly revolutionize web development. Building a new team to solve this problem in the right way is a demanding job. Building a team from, say, COBOL programmers, is nearly impossible. The language is too alien, the frameworks too extensive, and the landscape too unstable. Even with seasoned developers, it takes a surprising amount of code to get even simple applications off the ground.

Complexity

Java seems to be moving away from its base. You might solve the hardest problems more easily, but it's much harder to create simple web apps than it ever has been before. James Duncan Davidson calls this problem approachability . When Java was young, you didn't have to know much to build a basic applet. Now, to build a simple web app using the most popular frameworks, you need to know much more.

True, open source tools are changing the productivity of Java dramatically, in the best possible ways. Tremendous tools like Hibernate and Spring can let you build enterprise-strength applications with much less effort. But it can take a whole year to confidently learn how to wield these tools with skill. AOP can also help, by letting you write plain old Java objects (POJOs) for your business rules, and isolate services in prepackaged aspects like security and transactions. These abstractions, though, make an ever-rising river for the novice to navigate. My question is this: how high is too high? I think we're already getting too high for most novices. I no longer feel comfortable telling a client that they can retrain the average COBOL programmer on Java. There's just too much to learn, and it takes too much time.

In the past, complex problems drove higher abstraction. When computers got too big for people to code with wires, experts programmed with machine code. When those programs got too big for people to understand, they organized the machine codes and data with symbols in assembler language. Rising complexity led to high-level languages, structured programming, and object-oriented programming. My contention is that this higher river of complexity will flood, forcing us to adopt a new abstraction, sooner rather than later.

Rapid revolution

There's been an incredible amount of innovation around Java in the past three years. You've experienced a transition from the heavyweight containers like EJB to lightweight containers like Spring. You've likely moved from EJB or JDBC persistence to iBATIS, JDO, or Hibernate. You're possibly seeing the wisdom of moving beyond Struts to something like Tapestry. It's been my experience that most innovation is driven by need. My theory is that revolution increases dramatically when complexity hits a certain threshold. The only evidence that I have to support this theory is circumstantial:

  • The overpowering new mountains of persistence frameworks
  • The proliferation of model-view-controller (MVC) frameworks
  • The growth of containers
  • The rapid introduction of XML-binding frameworks

I'm suggesting that inventions usually accompany a need. When we get something that's right or merely close enough, like Ant or JUnit, we leave it alone until it doesn't fit our purposes anymore.

Experienced developers likely will not understand the excruciating process of learning enough to build the simplest web application in Java. Many of them will complain that I am overstating this issue. If you're in that group, I challenge you to find a smart, inexperienced Java developer who's learning the whole stack of applications that you need to do enterprise web development, and interview him. The problem is twofold. First, it's hard. Second, the consequences for failure are dire. If you pick the wrong horse once, or get locked up for three years on a big project with dated technology, you'll be just about starting over when you move on to the next project. The implications of the churn are staggering. To me, they may mean that code needs to be happening at a higher level of abstraction, and we've been incapable of finding it in Java.

Unnatural stretching

Increasingly, you're probably stretching Java beyond its intended directions. It's just a plain fact that the object you code with plain Java is not enough anymore. I made the point in Better, Faster, Lighter Java that trying to code all crosscutting services and all behaviors into business objects is folly, and inheritance does not go far enough. You've got to use tricks, like compile-time byte code enhancement or runtime code generation with proxies, to make the object transparent. You are now stretching Java beyond its intended purpose, and that's good...to a point. You're also increasing the barrier to entry. Ask any novice who's tried to troubleshoot a problem with Hibernate's lazy loading, or Spring's proxies.

I've also noticed that other, more dynamic languages rarely use things like AOP or dependency injection. Those features solve critical problems in Java, but more dynamic languages like Smalltalk, Python, and Ruby don't have the same level of pain.

I'm not saying that these are bad technologies. They absolutely destroy the closest heavyweight alternatives, in terms of simplicity and power. They're solving hard problems. It's just that your mind can learn only so much, only so fast. Java's rapidly becoming an effective tool set for elite developers. Hey, maybe that's where programming is going. I'm just saying that this unnatural stretching is one more clue that it may be time to take the temperature of the water around you.

Language evolution

Java 5 is strongly touted as perhaps the most innovative major release of Java in half a decade. I do agree that it's going to have a significant impact. I'm not at all convinced that all of the impact will be positive. I regularly attend a conference called NoFluffJustStuff. The experts at the conference sit on a panel and answer questions. One of my favorite questions deals with new features in the language. The whole panel agrees that generics, as implemented, are a bad idea. That usually shocks the audience.

If you think about it, the Java generics Java Specification Request (JSR) introduces a whole lot of syntax to solve a marginal problem with no corresponding change to the Java virtual machine (JVM). I'm guessing that the typical Java developer rarely gets a class cast exception. And there are plenty of opportunities. Most of the objects in a typical Java application are usually in collections anyway. Whenever you take them out of the collection, you've got to cast them from Object anyway. At that point, type safety gives you about as much protection as a lap belt in a burning, plummeting 747. Yet, the generics syntax is invasive, and the implementation is worse. In an age when more and more experts assert that dynamic typing leads to simpler applications and productive programmers, Java developers are learning how to build stronger enforcement for static types.

Add questionable use of legitimate features like annotations , which can completely change the semantics of your program without conventional code, and you've got all kinds of possible trouble. Does the increase in power offset the increase in complexity and obscurity? Annotations bring a completely new tool, and in many ways a programming model, to the Java community. I don't know enough to say whether we'll learn to use annotations well, but I do feel comfortable predicting a few major disasters while we learn.

I don't want to tip my whole hand too early. I'll talk more about Java limitations in Chapters 3 through 5. Right now, just understand that Java is experiencing some real problems. They may be growing pains of youth, or they might be arthritis in Java's October years. I just don't know, but the temperature is rising fast enough to get my attention.

What's Good Is GOOD

I don't mean to say that Java's bugler is finishing the last few notes of "Taps" as you read this paragraph. Instead of spewing doom and gloom, I'd rather tell owls and ostriches alike to pick up your eyes, and watch and listen. Look at it like this: conditions are ripe for a credible alternative to emerge. At the time of printing, Java's still the king of the hill. In fact, powerful and compelling motivations still drive new investment in Java:

  • The Java community is vibrant. You can find talent to attack hard problems in Java. You can also find supporting staff, like salespeople and project managers, who know Java.
  • Most major commercial vendors support Java, or a close derivative (C#). As a result, you can buy applications, servers, components, tools, services, and even management consoles for Java.
  • Open source is a thriving force in its own right, and it is driving incredible innovation daily.
  • Academic institutions teach Java development, and do research on many Java-related problems. I recently worked with a start-up that's working on a tool, born in a university research lab, that can predict Java performance, given a UML diagram.
  • The JVM is a powerful innovation in its own right, and allows unprecedented portability. Some experts believe that the JVM may be more important than the Java language itself.

Now, you might believe, as I recently did, that all of this vibrant community trumps any language advantage, in all but the most extreme problems. And even if you did find such a problem, what's the compelling alternative? How will it ever find enough developers to reach a critical mass? You're probably thinking: face it, Bruce, there's .NET and Java, and .NET is, by design, as close as legally possible to Java. Adopting .NET would be like overhauling your diet by swearing off McDonalds, and going to Burger King every day. After that, there's nothing.

This much is true. If there is no credible alternative, your best course is to keep looking inside the Java community for answers. In that case, this is a dead book, and you can just let it be. But give me a few more pages, lest you close it too soon.

New Horizons

Keep in mind that I'm a cynic at heart. When it comes to technologies, it takes a whole lot of effort to get me excited. I still have never written a web service, at least with the massive IBM and Microsoft stacks, and I didn't write my first EJB until 2003. I've never written an EJB entity bean unless it was to build a case against them, and never will. I've instead preferred simpler architectures, like REST, POJO programming, transparent persistence, and Spring. Even then, I was late to those parties.

It's even tougher to get me to play with a new language. Dave Thomas, a highly respected programmer and a gifted teacher, is fond of saying that you should learn a new programming language every couple of months. I've probably averaged one every five years, and I rarely do more than dabble. But recently, in my dabbling, I've found a couple of startling innovations. These frameworks had ideas that just about reached out and ripped me out of my chair this year.

I've taken a little more time than usual to survey the interesting innovations around new programming languages. When it comes to building web pages and application servers, two ideas have my undivided attention: metaprogramming (like Ruby on Rails) and continuation servers (like Seaside on Smalltalk). Neither of these two innovations is happening with much impact in Java. You'll get a deeper treatment in Chapters 7 and 8, but it's enough to say for now that they are both many times more productive than their Java alternatives.

Dynamic Languages

Java is a language with many compromises . Many of the features of Java are appropriate for building operating system extensions and middleware, but limit application development. Consider this Ruby fragment:

    something = "Owls and Ostriches"
    4.times {puts something}

These simple little lines of code print Owls and Ostriches four times. Look at the power in this language:

  • You don't have to worry about details like typing, if you don't want to. If it walks like a duck and quacks like a duck, Ruby will type it as a duck. This saves more time than you think.
  • 4 is an object. Everything is an object. You can send methods to a 4, or a string, just like any other object in the system.
  • {puts something} is a code block. You can pass a code block as a parameter, and Ruby lets methods deal with the code blocks. This construct dramatically simplifies things like iteration, and lets you quickly customize the inside of a loop in a library.

Taken by themselves, these features can make you much more productive. But add the other features of a dynamic language, and you can see incredible power and productivity very quickly. Many of the so-called scripting languages make much more sense for application developers.

Metaprogramming

The Java community is now investing enormous energy into programming styles that are more transparent, reflective, and dynamic. These approaches are called metaprogramming , because they spend more time in the realm of the class than the object. It makes sense that you can get more leverage that way. Transparent persistence frameworks like Hibernate teach generic classes and collections to be persistent. AOP lets you extend a specified list of methods with custom code, without requiring modifications of that method. These problems are metaprogramming problems.

When Java experts get excited about metaprogramming, they often wind up adopting other languages. Want some examples? David Geary, one of Java's most successful authors and JSF expert group member, is aggressively learning Ruby on Rails , and is writing a Rails book. James Duncan Davidson, creator of Tomcat and Ant, left the Java community to code Objective C for the Mac environment. And, as you have seen, Justin Gehtland and I are using Rails to implement a web-based application for a start-up.

Think of metaprogramming as building a high-level builder. Ruby on Rails, for example, discovers the columns and relationships in a database schema, and uses that data to build a model, view, and controller for a web application. The characteristics of the environment are striking:

  • It's incredibly productive. It's easily five times as productive as the closest Java competitor, for certain types of problems.
  • It is flexible. Some solutions build a default application and allow common extension points. Rails builds a default application, which you can extend as if you'd written it yourself.
  • It reduces duplication, and leads to more consistency.

To me, for enterprise application development , the overriding characteristic of a language or environment is productivity . I want each line of code to work harder, and I want that to translate into productivity. I don't quit measuring productivity after deployment. If your tiny application is impossible to maintain, you'll lose everything you've gained. For these reasons, I love Ruby on Rails, and I'll talk more about it in Chapter 7.

Continuation Servers

Java web developers spend an incredible amount of time managing state, threads, and the Back button. These problems get significantly more difficult as sites get more dynamic and complex. There's been a recent resurgence in Smalltalk, and most of it centers around a framework called Seaside. Since continuations maintain state, continuation-based servers don't have any problem managing state. They also handle Back buttons and threading with relative ease. This framework uses a language feature called continuations to maintain state within a web-based application.

The Premise

I don't mean to say that Smalltalk or Ruby will take over the world tomorrow. I don't even mean to say that anything will ever achieve the success that Java has, again. But I don't believe that Java is permanent. For five years, it's been a good strategy to ignore the borders beyond Java, but no language will keep its leadership position forever. By now, the premise of this book should be taking shape for you:

  • Java is moving away from its base. Hard-core enterprise problems may be easier to solve, but the simplest problems are getting harder to solve. And...
  • Java is showing signs of wear, and interesting innovations are beginning to appear outside of Java. So...
  • It's time to start paying attention again.

Pick up your eyes. Start by picking up this book. You'll be glad you did.

Personal tools