Chapter 1. The Inevitable Bloat

Java development is in crisis. Though Java’s market share has been steadily growing, all is not well. I’ve seen enterprise Java development efforts fail with increasing regularity. Even more alarming is that fewer and fewer people are surprised when things do go wrong. Development is getting so cumbersome and complex that it’s threatening to collapse under its own weight. Typical applications use too many design patterns, too much XML, and too many Enterprise JavaBeans. And too many beans leads to what I’ll call the bloat.

Bloat Drivers

I’ll illustrate the bloat by comparing it with the famous Lewis and Clark expedition. They started with a huge, heavily loaded 55-foot keel boat. Keel boats were well designed for traversing massive rivers like the Missouri and the Mississippi, but quickly bogged down when the expedition needed to navigate and portage the tighter, trickier rivers out West. Lewis and Clark adapted their strategy; they moved from the keel boats to canoes, and eventually to horseback. To thrive, we all must do the same. Java has not always been hard, and it doesn’t have to be today. You must once again discover the lighter, nimbler vessels that can get you where you need to go. If the massive, unwieldy frameworks hinder you, then don’t be afraid to beach them. To use the right boat, you’ve got to quit driving the bloat.

Over time, most successful frameworks, languages, and libraries eventually succumb to bloat. Expansion does not happen randomly—powerful forces compel evolution. You don’t have to accept my premise blindly. I’ve got plenty of anecdotal evidence. In this chapter, I’ll show you many examples of the bloat in applications, languages, libraries, frameworks, middleware, and even in the operating system itself.

Enterprise Mega-Frameworks

Java developers live with a painful reality: huge enterprise frameworks are en vogue. That might be good news to you if you’re among the 10% of Java developers who are working on the hardest problems, and your applications happen to fit those enterprise frameworks perfectly. The rest of us are stuck with excruciating complexity for little or no benefit. Successful J2EE vendors listen to the market:

  • Vendors can charge mega-dollars for mega-frameworks. Selling software means presenting the illusion of value. Big companies have deep pockets, so vendors build products that they can sell to the big boys.

  • It’s hard to compete with other mega-frameworks if you don’t support the same features. Face it. Software buyers respond to marketing tally sheets like Pavlov’s dogs responded to the dinner bell.

  • Collaboration can increase bloat. Whenever you get multiple agendas driving a software vision, you get software that supports multiple agendas, often with unintended consequences. That’s why we have two dramatically different types of EJB. The process satisfied two dramatically different agendas.

You can almost watch each new enterprise framework succumb to the bloat, like chickens being fattened for market. In its first incarnation, XML was slightly tedious, but it provided tremendous power. In truth, XML in its first iteration did almost everything that most developers needed it to. With the additions of XML Schema and the increased use of namespaces, XML is dramatically more cumbersome than ever before. True, Schema and namespaces make it easier to manage and merge massive types. Unfortunately, once-simple web services are taking a similar path.

But none of those frameworks approach the reputation that Enterprise JavaBeans (EJB) has achieved for bloat. EJB container-managed persistence (CMP) is the poster child for tight coupling, obscure development models, integrated concerns, and sheer weight that are all characteristic of the bloat (Figure 1-1).

In theory, EJB’s beans simplify enterprise programming
Figure 1-1. In theory, EJB’s beans simplify enterprise programming

Figure 1-1 shows the EJB container-based architecture. Beans plug into a container that provides services. The premise is sound: you’d like to use a set of system services like persistence, distribution, security, and transactional integrity. The EJB is a bean that snaps into the container, which implements the set of services that the bean will use. Within the bean, the developer is free to focus on business concerns in the bean.

My favorite childhood story was The Cat in the Hat by Dr. Seuss, who should have been a programmer. I loved the game called “Up, up, with the fish,” in which the Cat tries to keep too many things in the air at once. As an EJB programmer, it’s not quite as funny, because you’re the one doing the juggling. Consider this very simple example in Example 1-1. I want a simple counter, and I want it to be persistent. Now, I’ll play the Cat, and climb up on the ball to lob the first toy into the air.

Example 1-1. Counter example: implementation
    package com.betterjava.ejbcounter;

    import javax.ejb.*;
    import java.rmi.*;

    /**
     *  CMP bean that counts
     */


[1] public abstract class Counter implements EntityBean{

        private EntityContext context = null;

        public abstract Long getID( );
        public abstract void setID(Long id);

        public abstract int getCount( ); 
        public abstract void setCount(int count);
        
Ͽ      
                  public abstract Object ejbCreate(Long id, int count);

          throws CreateException {

          setId(id);
          setCount(count);

          return null;
        }


        public void ejbPostCreate(Long id, int count)
          throws CreateException { }

        public void setEntityContext(EntityContext c) {
          context = c;
        }

        public void unsetEntityContext( ) {
          context = null;
        }

        public void ejbRemove( ) throws RemoveException { }
        public void ejbActivate( ) { }
        public void ejbPassivate( ) { }
        public void ejbStore( ) { }
        public void ejbLoad( ) { }

[3]       public void increment( ) {

          int i=getCount( );
          i++;
          setCount(i);
       }

         public void clear( ) {

           setCount(0);
         }

      }

The first file, called the bean, handles the implementation. Note that this class has the only business logic that you will find in the whole counter application. It accesses two member variables through getters and setters, the counter value and ID, which will both be persistent. It’s also got two other methods, called clear and increment, that reset and increment the counter, respectively.

For such a simple class, we’ve got an amazing amount of clutter. You can see the invasive nature of EJB right from the start:

  1. [1] This class implements the EJB interface, and you’ve got to use it in the context of an EJB container. The code must be used inside a container. In fact, you can use it only within an EJB container. You cannot run the code with other types of containers.

  2. [2] You see several lifecycle methods that have nothing to do with our business function of counting: ejbActivate, ejbPassivate, ejbStore, ejbLoad, ejbRemove, setEntityContext, and unsetEntityContext.

  3. [3] Unfortunately, I’ve had to tuck all of the application logic away into a corner. If a reader of this application did not know EJB, he’d be hard-pressed to understand exactly what this class was designed to do.

I’m not going to talk about the limitations of container-managed persistence. If you’re still typing along, you’ve got four classes to go. As the Cat said, “But that is not all, no that is not all.” Example 1-2 shows the next piece of our EJB counter: the local interface.

Example 1-2. Local interface
package com.betterjava.ejbcounter;

import javax.ejb.*;

/**
 *  Local interface to the Counter EJB.
 */

public interface CounterLocal extends EJBLocalObject {

  public abstract Long getID( );
  public abstract void setID(Long);
  public abstract int getCount( ); 
  public abstract void setCount(int count);
  
}

This is the interface, and it is used as a template for code generation. Things started badly, and they’re deteriorating. You’re tightly coupling the interface to EJBLocalObject. You are also dealing with increasing repetition. Notice that I’ve had to repeat all of my implementation’s accessors, verbatim, in the interface class. This example shows just one instance of the mind-boggling repetition that plagues EJB. To effectively use EJB, you simply must use a tool or framework that shields you from the repetition, like XDoclet, which generates code from documentation comments in the code. If you’re a pure command-line programmer, that’s invasive. But, “`Have no fear,’ said the Cat.” Let’s push onward to Example 1-3.

Example 1-3. LocalHome interface
package com.betterjava.ejbcounter;

import javax.ejb.*;
import java.rmi.*;
import java.util.*;

/**
 *  Home interface to the local Counter EJB. 
 */
public interface CounterLocalHome extends EJBLocalHome {

  public Collection findAll( ) throws FinderException;

  public CounterLocal findByPrimaryKey(Long id) throws FinderException;

  public CounterLocal create(Long id, int count)
    throws CreateException;
}

In Example 1-3, you find the methods that support the container’s management of our persistent object. Keep in mind that this class is a generic, standalone persistent class, with no special requirements for construction, destruction, or specialized queries. Though you aren’t building any specialized behavior at all, you must still create a default local home interface that builds finder methods and templates for the lifecycle of the bean, like creation and destruction.

At this point, I’m going to trust that you’ve gotten the message. I’ll omit the painful deployment descriptor that has configuration and mapping details and the primary key object. I’m also not going to include a data transfer object (DTO), though for well-documented reasons, you’re not likely to get acceptable performance without one. Dr. Seuss sums it up nicely: “And this mess is so big and so deep and so tall, we cannot pick it up. There is no way at all.”

You’d be hard-pressed to find a persistence framework with a more invasive footprint. Keep in mind that every persistent class requires the same handful of support interfaces, deployment descriptors, and classes. With all of this cumbersome, awkward goo, things get dicey. Some Cats have enough dexterity to keep all of those toys in the air. Most don’t.

Progress

Developers do not want their programming languages to stay still. They want them to be enhanced and improved over time; so, we must continually add. Yet language vendors and standards boards can’t simply remove older interfaces. In order to be successful, languages must maintain backwards compatibility. As a result, additions are not usually balanced with subtractions (Figure 1-2). That’s a foolproof recipe for bloat.

Backwards compatibility with progress leads to bloat
Figure 1-2. Backwards compatibility with progress leads to bloat

If you’d like to see an example of this principle in action, look no further than the deprecated classes and methods in Java. Deprecated literally means “to disapprove of strongly,” or “to desire the removal of.” In Java, Sun warns against the use of deprecated classes and methods, because they may be removed in some future release. I assume that they are defining either remove or future very loosely, because deprecated methods never disappear. In fact, if you look at the AWT presentation library for Java, you’ll find many methods that have been deprecated since Version 1.1, over a half a decade ago. You can also look at the other side of the equation. The next few versions of Java are literally packed with new features.

If you’re wondering about the impact of these changes on the overall size of the Java runtimes, then you’re asking the right questions. Let’s take a very basic metric: how big was the Zip file for the Windows version of the standard edition SDK? Table 1-1 shows the story. In Version 1.1, you would have to download just under 3.7 megabytes. That number has grown to 38 megabytes for JDK 1.4!

Table 1-1. Zip file size for standard edition Java developer kit in Version 1.1 and Version 1.4

JDK version, for Windows

Zip file size

JDK 1.1

3.7 MB

J2SE 1.2

20.3 MB

J2SE 1.3

33.2 MB

J2SE1.4

38.0 MB

You may ask, so what? Computers are getting faster, and Java is doing more for me than ever before. It may seem like you’ve got a free ride, but the ever-growing framework will cost you, and others:

  • Some of the growth is occurring in the standard libraries. If the bloat were purely in add-on libraries, then you could perhaps avoid it by choosing not to install the additional libraries. But you can’t dodge the standard libraries. That means that your resource requirements will increase.

  • Java is harder to learn. Early versions of Java allowed most programmers to pick up a few books, or go to class for a week. Today, the learning curve is steeper for all but the most basic tasks. While the steep curve may not directly affect you, it does affect your project teams and the cost of developers.

  • It’s harder to find what you need. Since the libraries continue to grow, you need to wade through much more data to find the classes and methods that you need to do your job.

  • You need to make more decisions. As alternatives appear in the basic Java toolkits (and often in open source projects), you’ve got to make more decisions between many tools that can do similar jobs. You must also learn alternatives to deprecated classes and methods.

  • You can’t fully ignore old features: people still use deprecated methods. How many Vectors have you seen in the past couple of years?

Platforms are not immune to the bloat. That’s a fact of life that’s beyond your control. My point is not to add needless anxiety to your life, but to point out the extent of the problems caused by the bloat.

Economic Forces

To be more specific, success drives bloat. The marketplace dictates behavior. Microsoft does not upgrade their operating systems to please us, or to solve our problems. They do so to make money. In the same way, commercial drivers will continue to exert pressure on Java to expand, so you’ll buy Java products and align yourself with their vision. Beyond license fees, Sun does not make money directly from Java, but it’s far from a purely altruistic venture. The Java brand improves Sun’s credibility, so they sell more hardware, software, and services.

Market leaders in the software industry cannot stay still. They must prompt users to upgrade, and attract new customers. Most vendors respond to these challenges by adding to their feature set. For just one example, try installing Microsoft Office. Check out the size of the Word application. Though most users do little more than compose memos and email, Word has grown to near-Biblical proportions. Word has its own simple spreadsheet, a graphics program, and even web publishing built in. Most Word users have noticed few substantive changes over the years. To me, the last life-changing enhancements in Word were the real-time spelling checker and change tracking. Upgrade revenue and the needs of the few are definitely driving Word development today. Keep in mind that I’m an author, and spend way too much time in that application. Of course, we can’t blame Microsoft. They’re trying to milk a cash cow, just like everyone else. Yet, like many customers, I would be much happier with a cheaper word processor that started faster, responded faster, and crashed less.

Within the Java industry, BEA is an interesting illustration of this phenomenon. To this point, BEA has built a strong reputation by delivering an outstanding application server. From 2001 to the present, BEA and IBM have been fighting a fierce battle to be the market-leading J2EE application server. IBM increased their WebSphere brand to include everything from their traditional middleware (the layer of software between applications and the operating system) to extensions used to build turnkey e-commerce sites and portals. Two minor competing products, JBoss and Oracle9iAS, were starting to eat away at BEA’s low-end market share. Both of these products were inexpensive. Oracle priced their product aggressively for users of their database, and JBoss was an open source project, so BEA was under tremendous pressure to build more value into their product and stay competitive. They responded by extending their server to enterprise solutions for building portal software, messaging middleware, and business integration. They also started a number of other initiatives in the areas of data (Liquid Data), user interface development (NetUI), and simplified application development (WorkBench). Building a great J2EE application server is simply not enough for BEA any more. They, too, must expand—and extend the inevitable bloat.

Misuse

Nothing drives bloat more than misuse. If you go to Daddy’s toolkit and borrow his cool pipe wrench when you need to drive a nail, something’s going to go awry. The book Antipatterns, by William J. Brown, et al. (Wiley & Sons), refers to this problem as the golden hammer. When you’ve got a golden hammer, everything starts to look like a nail. Misuse comes in many forms:

Framework overkill

I’ve seen a departmental calendar built with Enterprise JavaBeans. I’ve also seen tiny programs use XML for a two-line configuration file.

Design patterns

These days, it’s almost too easy to use a design pattern. When you trade power for simplicity too many times, you get bloat.

Sloppy reuse

If you try to stuff a round peg in a square hole, you’ll have to adapt the hole or the peg. Too many adaptations will often lead to bloat. Cut-and-paste programming also leads to bloat.

Poor process

Like fungus in a college refrigerator, bloat best grows in dark, isolated places. Isolated code with no reviews and one owner lets bloat thrive unchecked.

Many developers wear golden hammers as a badge of honor. Reaching for the wrong tool for the job is nearly a rite of passage in some of the places that I’ve worked. It’s a practice that may save a few minutes in the short term, but it will cost you in the end.

Options

There are many possible solutions for dealing with the bloat in Java. Head-on is but one possibility. It takes courage and energy to take on the bloat, and you may not wish to fight this battle. You’ve got alternatives, each with a strong historical precedent:

Change nothing; hope that Java will change

This strategy means letting your productivity and code quality slide. Initially, this is the option that most developers inevitably choose, but they’re just delaying the inevitable. At some point, things will get too hard, and current software development as we know it will not be sustainable. It’s happened before, and it’s happening now. The COBOL development model is no longer sufficient, but that doesn’t keep people from slogging ahead with it. Here, I’m talking about the development model, not the development language. Java development is just now surpassing COBOL as the most-used language in the world, begging the question, “Do you want to be the COBOL developer of the 21st century?”

Buy a highly integrated family of tools, frameworks, or applications, and let a vendor shield you from the bloat.

In this approach, you try to use bloat to your best advantage. You may put your trust in code generation tools or frameworks that rely on code generation, like EJB, Struts, or Model Driven Architecture (MDA). You’re betting that it can reduce your pain to a tolerable threshold, and shield you from lower-level issues. The idea has some promise, but it’s dangerous. You’ve got to have an incredible amount of foresight and luck to make this approach succeed. If you previously bet big on CORBA or DCE, then you know exactly what I mean.

Quit Java for another object-oriented language.

Languages may have a long shelf-life, but they’re still limited. For many, the decision to switch languages is too emotional. For others, like author Stuart Halloway, the decision is purely pragmatic. The long-time CTO of the respected training company DevelopMentor and tireless promoter of their Java practice recently decided to choose Objective C for an important project because Java was not efficient enough for his needs. Alternatives are out there. C# has some features that Java developers have long craved, like delegation, and C# hasn’t been around long enough to suffer the bloat that Java has. Ruby is surprisingly simple and productive, and works very well for GUI prototyping and development.

Quit object-oriented languages for another paradigm

Every 15 to 20 years, the current programming model runs out of gas. The old paradigms simply cannot support the increasing sophistication of developers. We’ve seen programming languages with increasingly rich programming models: machine language, assembly languages, high-level languages, structured programming languages, object-oriented languages. In fact, today you’re probably noticing increased activity around a new programming model called aspect-oriented programming (see Chapter 11). Early adopters were using object technology 15 years before it hit the mainstream. Unfortunately, new programming paradigms traditionally have been very difficult to time. Guess too early and you’ll get burned.

Spend time and effort becoming a master craftsman.

An inordinate amount of bloated code comes not from people who know too much about writing software, but from people who know too little. The temptation when faced with a problem that you don’t fully understand is to put everything and the kitchen sink into the solution, thus guarding against every unknown. The problem is that you can’t guard against unknowns very effectively; frankly, all the extra complexity is likely to generate side effects that will kill the application. Thoroughly understanding not just your problem domain but the craft of software development as well leads to better, smaller, more focused designs that are easier to implement and maintain.

Each of these techniques has a time and a place. Research teams and academics need to explore new programming models, so they will naturally be interested in other programming paradigms. Many serious, complex problems require sophisticated enterprise software, and the developers working on these problems will look to complex frameworks that can hopefully shield them from the bloat. Small, isolated development projects often have fewer integration requirements, so they make effective use of other programming languages, or paradigms. But for most day-to-day Java applications, the alternatives are too risky. My choice is to actively fight the bloat.

Five Principles for Fighting the Bloat

You can’t fight the bloat by being simple-minded. You can’t simply fill your programs with simple cut-and-paste code, full of bubble sorts and hardwiring. You cannot forget everything you’ve learned to date. It’s an interesting paradox, but you’re going to need your creativity and guile to create simple but flexible systems. You’ve got to attack the bloat in intelligent ways.

The bloat happened because the extended Java community compromised on core principles. Many of these compromises were for good reasons, but when core principles slide often enough, bad things happen. To truly fight the bloat, you’ve got to drive a new stake in the ground, and build a new foundation based on basic principles. You’ve got to be intentional and aggressive. In this book, I’ll introduce five basic principles. Together, they form a foundation for better, faster, lighter Java.

1. Keep It Simple

Good programmers value simplicity. You’ve probably noticed a resurgence of interest in this core value, driven by newer, Agile development methods like eXtreme Programming (XP). Simple code is easier to write, read, and maintain. When you free yourself with this principle, you can get most of your code out of the way in a hurry, and save time for those nasty, interesting bits that require more energy and more attention. And simple code has some more subtle benefits as well. It can:

  • Give you freedom to fail. If your simple solution doesn’t work, you can throw it away with a clear conscience: you don’t have much invested in the solution anyway.

  • Make testing easier. Testability makes your applications easier to build and more reliable for your users.

  • Protect you from the effects of time and uncertainty. As time passes and people on a project change, complex code is nearly impossible to enhance or maintain.

  • Increase the flexibility of your team. If code is simple, it’s easier to hand it from one developer to the next.

  • Self-document your code, and lessen the burden of technical writing that accompanies any complex application.

More than any core principle, simplicity is the cornerstone of good applications, and the hallmark of good programmers. Conversely, complexity is often a warning sign of an incomplete grasp of the problem. This doesn’t mean that you need to build applications with simple behavior. You can easily use simple constructs, like recursion, and simple classes, like nodes, to get some complex structures and behaviors. Figure 1-3 shows one simple node class consisting of a collection and a string. That’s a simple structure, but I use it to represent a family tree, with many complex relationships. I’ve captured the complex relationships in concept, including children, spouses, parents, grandparents, uncles, and nieces.

A simple node class, a string, and a collection form the foundation of a family tree
Figure 1-3. A simple node class, a string, and a collection form the foundation of a family tree

I’m not advocating simplicity across the board, above all else. I’m merely suggesting that you value simplicity as a fundamental foundation of good code. You don’t have to over-simplify everything, but you’ll be much better off if you pick the simplest approach that will work.

2. Do One Thing, and Do It Well

Focus is the second principle, and it builds upon simplicity. This basic premise has two underlying concepts: concentrate on one idea per piece, and decouple your building blocks. Object-oriented programming languages give you the power to encapsulate single ideas. If you don’t take advantage of this capability, you’re not getting the full benefits of object-orientation.

Focus is the premise behind perhaps the most popular design pattern ever, model-view-controller (MVC), shown in Figure 1-4. Each component of this design pattern elegantly separates the concerns of one particular aspect of the problem. The view encapsulates the user interface, the model encapsulates the underlying business logic, and the controller marshals data between them.

Each rectangle encapsulates a single aspect of an application
Figure 1-4. Each rectangle encapsulates a single aspect of an application

These ideas seem simple, but they carry incredible power:

  • Building blocks, designed with a single purpose, are simple. By maintaining focus, it’s easier to maintain simplicity. The converse is also true. If you muddy the waters by dividing your focus, you’ll be amazed at how quickly you get bogged down in complex, tedious detail.

  • Encapsulated functionality is easier to replace, modify, and extend. When you insulate your building blocks, you protect yourself from future changes. Don’t underestimate the power of decoupled building blocks. I’m not just talking about saving a few hours over a weekend—I’m talking about a principle that can change your process. When you decouple, you have freedom to fail that comes from your freedom to refactor.

  • You can easily test a single-purpose building block. Most developers find that testing drives better designs, so it should not come as a surprise that decoupled designs are easier to test.

3. Strive for Transparency

The third principle is transparency. When you can separate the primary purpose of a block of code from other issues, you’re building transparent code. A transparent persistence framework lets you save most any Java object without worrying about persistence details. A transparent container will accept any Java object without requiring invasive code changes.

The EJB counter in Example 1-1 is a framework that is not transparent. Look at the alternative counter, in Hibernate or JDO, shown in Example 1-4.

Example 1-4. Transparent counter
package com.betterjava.ejbcounter;

import java.util.*;

public class Counter {

  private string name;
  private int count;

  public void setName(long newName) {
    name = newName;
  }

  public string getName( ) {
    return name;
  }

  public int getCount( ) {
        return count;
  }

  public void clear( ) {
    count = 0;
  }

  public void increment( ) {
    count += 1;
  }
}

That’s it. The code is transparent, it’s simple, and it encapsulates one concept—counting. Transparency, simplicity, and focus are all related concepts. In fact, in this example, we used transparency to achieve focus, leading to simplicity.

4. Allow for Extension

Simple applications usually come in two forms: extensible and dead-end. If you want your code to last, you’ve got to allow for extension. It’s not an easy problem to solve. You probably want your frameworks to be easy to use, even when you’re solving hard problems. OO design principles use layered software (which we call abstractions) to solve this problem. Instead of trying to organize millions of records of data on a filesystem, you’d probably rather use a relational database. Rather than use native networking protocols like TCP/IP, you’d probably rather use some kind of remote procedure call, like Java’s remote method invocation (RMI). Layered software can make complex problems much easier to solve. They can also dramatically improve reuse and even testability.

When you build a new abstraction, you’ve got to engage in a delicate balancing act between power and simplicity. If you oversimplify, your users won’t be able to do enough to get the job done. If you undersimplify, your users will gain little from your new abstraction level. Fortunately, you’ve got a third choice. You can build a very simple abstraction layer and allow the user to access the layer below yours. Think of them as convenient trap doors that let your users have access to the floors below.

For example, you might want to build a utility to write a message. You might decide to provide facilities to write named serialized messages. Most users may be satisfied with this paradigm. You might also let your users have full access to the JMS connection, so they can write directly to the queue if the need arises.

5. You Are What You Eat

My mother always told me that I am what I eat. For once, she was right. Applications build upon a foundation. Too many developers let external forces easily dictate that foundation. Vendors, religion, and hype can lead you to ruin. You’ve got to learn to listen to your own instincts and build consensus within your team. Be careful of the concepts you internalize.

Look at it this way: a little heresy goes a long way. You can find a whole lot of advice in the Java community, and not all of it is good. Even commonly accepted practices come up short. If you’ve been around for 10 years or more, you’ve probably been told that inheritance is the secret to reuse (it’s not) or that client-server systems are cheaper (they’re not) or that you want to pool objects for efficiency (you don’t). The most powerful ideas around the whole high-tech industry bucked some kind of a trend:

  • Java lured C++ developers away with an interpreted, garbage-collected language. C++ developers typically demand very high performance. Most conventional wisdom suggested that customers would be much more interested in client-side Java than server-side Java due to performance limitations. So far, the opposite has been true.

  • Many Java experts said that reflection was far too slow to be practical. Bucking the trend, many new innovative frameworks like Hibernate and Spring use reflection as a cornerstone.

  • Whole consulting practices were built around EJB. We’re only now beginning to understand how ugly and invasive that technology is, from top to bottom.

Java development without a little heresy would be a dull place, and a dangerous one. You’ve got to challenge conventional thinking. When you don’t, bloat happens.

Summary

In this book, I’m going to take my own medicine. I’ll keep it simple and short. At this point, you’re probably wondering how five simple principles can change anything at all. Please indulge me. In the pages to come, I’ll lay out the five simple principles. I’ll then show you the ideas in practice. You’ll see how two successful and influential frameworks used these principles, and how to build applications with these frameworks. You’ll see an example of a persistent domain model, an enterprise web application, a sophisticated service, and extension using these core concepts. My plan is simple. I’ll show you a handful of basic principles. I’ll show you how to succeed with the same ideas to build better, faster, lighter Java.

If you tend to value a book by the weight of its pages, go find another one. If you’d rather weigh the ideas, then welcome aboard. It all begins and ends with simplicity. And that’s the subject of Chapter 2.

Get Better, Faster, Lighter Java now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.