DekGenius.com
Previous Section  < Day Day Up >  Next Section

1.3 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.3.1 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.

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


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.

1.3.2 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.

Figure 1-4. Each rectangle encapsulates a single aspect of an application
figs/bflJ_0104.gif


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.

1.3.3 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.

1.3.4 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.

1.3.5 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.

    Previous Section  < Day Day Up >  Next Section