In 1990, I discovered white water. I thought I was completely in control. Whenever my friends and I ran the smallest rapid, we'd leave one boater at the end of the rapid and put two boaters on the banks with throw ropes. We thought we could prevent anything bad from ever happening. While it was nice to have that illusion of perfect control, it just wasn't practical. We learned to scout the easier rapids from the cockpit of the boat and take steps to look out for each other. We took more time to set up good safety measures for the most dangerous rapids. And in a few instances, that extra time made all the difference in the world.
In kayaking, a lightweight strategy born on southeastern steep creeks saved me time so I could paddle longer rivers and have more fun without compromising safety. In business, lightweight development lets you finish on time and react to your customers, saving you time and money.
In this series of articles, I focus on the basics of lightweight development -- an overloaded term if ever there was one. This first article sets the groundwork and defines lightweight development. Future articles will move freely from process to principles to tools. I'll also focus on implementation philosophy and architecture at a higher level, and provide actual implementation details in code.
This series is for developers who haven't done much lightweight development. If you've used the Spring lightweight container for two years with an agile process, you might not gain much. However, if you've worked with Enterprise JavaBeans™ (EJBs) in a traditional development process, but want to move to lightweight development, this series may be just the thing for you.
More than anything, I want to shed some light on this impressive movement sweeping through the Java™ technology community. The lightweight buzzword graces containers like Spring and Pico. And techniques from lightweight processes, such as automated unit testing, now infiltrate many, if not most, development shops.
"Lightweight development" is usually attached to a set of development methods, frameworks, and design philosophies that go well together.
- Lightweight methodologies include agile processes like extreme programming (XP) and Scrum. They emphasize test-first development, heavy customer involvement, and refactoring.
- Lightweight frameworks usually encourage programming with plain old Java objects (POJOs) over heavier component-oriented models like EJB.
- Lightweight design patterns let you loosen coupling between objects and integrate services without forcing code into business logic or the domain model.
As we investigate these ideas and technologies, you'll learn more about each one. But first, let's clear up a few myths.
Some development tools, like Microsoft® Visual Basic or PHP, often don't scale or manage complexity well enough for large enterprise projects, so they earn the toy label. Lightweight technologies like Spring and Hibernate are often dismissed as such. In fact, most lightweight techniques evolved in enterprise development because other techniques let us down. The Spring framework evolved as a lightweight alternative to EJB. Similarly, the XP method evolved based on some failures in an enterprise setting. The principles in my Jolt-winning book Better, Faster, Lighter Java provide information about tools successfully deployed at my customer sites, including some Fortune 500 companies. Lightweight technologies thrive in the enterprise realm.
Likewise, you might be tempted to believe that lightweight development is useful only for building toy applications. Your goal is to deliver precisely what your customers want and need. Let me be clear: Lightweight technologies can build things that scale. In fact, the most impressive scaling usually happens because simple, elegant, stateless designs let the infrastructure do its job.
In lightweight development, you need to carefully plan and negotiate requirements, and you have to build rigorous automated unit tests to enable better refactoring. You fully integrate when you drop changes, and the automated build notifies you when a test case fails or a change induces errors. Lightweight development must be more disciplined than other techniques, but the discipline comes from different sources.
I'm suggesting that this development style goes beyond a single technology or process. If you want to lighten up, you need to select principles, processes, and technologies that make it easy to work that way.
When all is said and done, you need to decide what you value and make decisions based on those values. If I feel that clients are misguided or unfocused, I'll often help them establish some core principles first. The following list is a good starting point:
- Strive for simplicity. This value should permeate all that you do. Your process should produce only enough artifacts to get the job done. Developers should always try the simplest approach that can solve a problem. Your tools should let you build clear, simple solutions.
- Fix what's broken. Some development methods may discourage refactoring or changes in a process because those activities do not directly contribute to generating customer code. Lightweight development demands the freedom to fix code that gets too complex or bug-ridden. Budget for it. Demand it.
- Automate unit tests. Preferably, you should code test cases first. You may not have success with test-first development, but accumulating test collateral gives you the freedom to refactor your code. I'll go even further: Extensive unit testing improves your customer experience and the design in your code because it forces you to decouple code that's bound too tightly together.
- Use short cycles and active customer participation. Many of the best programming shops simplify by eliminating unnecessary artifacts. If you've got great customer participation, massive functional specifications become increasingly unnecessary. Customers will enjoy the interaction and appreciate your short cycle times because you'll be delivering business value at regular increments.
These principles don't completely encompass your technology choices and development process, but they go a long way toward defining your development experience. When managers know and follow these principles as well, developers have some ammunition when combating an ineffective technology choice or unnecessary bureaucracy. After you establish principles, it's time to carve out an effective process.
A tighter, faster development process usually takes ideas from a family of methods known as agile development methods. These methods aren't for everyone, though. If you have a large team and no real access to the customer or a suitable surrogate, you're better off with a more traditional method. But many projects have small enough teams -- no more than about a dozen people -- and sufficient access to a customer to make such methods fly. Usually, agility embraces principles like these:
- Focus on an on-site customer and code, rather than other design artifacts. You can use other artifacts, but only if they help you do your job. The process doesn't require it.
- Simplify the documentation that you need. For requirements, prefer a line in a spreadsheet to a fancy use-case diagram.
- Do only enough design work to get the job done. Don't anticipate design or performance problems, and don't back yourself into a corner.
- For development, strive for simplicity, integrate your build at least daily, and refactor when necessary.
- Automate your testing.
Even if you work in a traditional organization, you can take advantage of a trimmed-down development process. The trick is to sell principles rather than methodologies. While selling your manager on extreme programming -- or anything else with extreme in the title -- can be tough, selling principles like improved unit testing often makes more sense. In fact, many of my customers use this technique to work an agile development process into their conservative organizations, but their bosses have no idea that anything is different.
Think of this technique in terms of rhetoric. Principles are lightweight ideas that pack a punch. A process is heavyweight rhetoric, and you'll have a much bigger problem implementing it.
I've provided an overview of the design philosophies that most lightweight developers need to know and the important open source technologies out there that leverage these philosophies.
The new breed of containers, called lightweight containers, all use a common design philosophy: dependency injection. It's a complicated term for a simple idea. Dependency injection lets you give an object and its dependencies to a third party. The third party then creates all the objects and wires them together. For example, say a data access object called
myDao needs a data source called
ds. The container creates them both and sets a property:
Listing 1. Creating a third-party assembler
myDao = new Dao(); ds = new DataSource(); myDao.setDataSource(ds);
Of course, instead of creating a third-party assembler like this one, you could rely on a framework to do it for you and to do additional work like providing configuration support. The Spring framework, Pico, and HiveMind take on this role. Other frameworks, like JavaServer Faces (JSF), also leverage dependency injection.
With aspect-oriented programming (AOP), you can code common blocks of functionality (called aspects) -- such as logging, transactions, security, or persistence -- in one place. AOP lets you attach these aspects to POJOs, then specify a point in time (like the beginning of a method or exception generation) and another aspect to attach. For example, you might want to make a facade object-transactional. You would attach a
TransactionBegin aspect to the facade's methods when the method fired. Then you attach a
RollBack aspect to the facade's exception when an exception fired. Finally, you attach a
Commit aspect to the facade's method when the method ended. You do this work in configuration, rather than in code. With this ability, you can make a simple POJO transactional, secure, or remote-accessible.
You've essentially got declarative transactions on a POJO, an extremely useful capability for enterprise applications. With these tools at your disposal, you might decide to forgo EJB altogether or at least minimize its role. And that's precisely what lightweight containers let you do.
Persistence, too, is settling on a simpler programming model. Transparent persistence frameworks let you add persistence to applications through configuration rather than code. Because most of the applications written these days are object-oriented and access a relational database, some experts assert that the time for object-relational mapping is finally upon us. The top persistence solutions that I have found are SolarMetric's Kodo JDO and Hibernate (see Resources). I'll compare these solutions in detail later in this series. Other lightweight solutions, such as iBATIS and the Active Record design pattern, don't try to do object-relational mapping at all.
Basically, in lightweight development, you:
- Incorporate process, technology, and philosophy.
- Prefer simpler technologies.
- Build on a solid, lightweight foundation.
- Strive for the best possible transparency.
- Use ideas that give you leverage, like dependency injection and AOP.
It's important to understand that neither technologies nor processes can completely define lightweight development. It's an all-encompassing philosophy. As this series progresses, you'll see different types of discussions about lightweight technologies and philosophies. I'll focus first on open source frameworks with an emphasis on lightweight containers. In future articles, I'll talk about implementing lightweight methods in conservative companies and even some alternatives that go beyond Java technology. I'm excited about this series, and hope you enjoy it.
Read Better, Faster, Lighter Java by Bruce Tate and Justin Gehtland for a good overview of lightweight development.
Spring: A Developer's Notebook by Bruce Tate and Justin Gehtland can help you get started quickly on Spring.
Pro Spring provides a more comprehensive treatment of Spring.
Heavyweight architectures, such as Enterprise Java Beans can be overkill for everyday problems. "Secrets of lightweight development success, Part 2: How to lighten up your containers" introduces lightweight containers and explains how they can provide the services your business needs without tying you to a given programming model.
Learn the basics of lightweight containers in "Secrets of lightweight development success, Part 3: The emergence of Spring."
In Part 4 of the series, three popular containers are compared: Spring, HiveMind, and PicoContainer.
Lightweight development works best with a lightweight process, but it can be tough to get a conservative company to adopt agile methodologies. Learn how you can propose and promote lightweight processes in your organization in Part 5 of this series.
The developerWorks article "Object-relation mapping without the container" shows you how to use Spring persistence with Hibernate.
Read the developerWorks article "AOP@Work: AOP tools comparison, Part 1" for a treatment of AOP, a lightweight technique that can give you much better transparency.
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
Get products and technologies
Innovate your next open source development project with
IBM trial software, available for download or on DVD.
Get involved in the developerWorks community by participating in developerWorks blogs.
Bruce Tate is a father, mountain biker, and kayaker in Austin, Texas. He's the author of three best-selling Java books, including the Jolt winner Better, Faster, Lighter Java. He recently released Spring: A Developer's Notebook. He spent 13 years at IBM and is now the founder of the J2Life, LLC, consultancy, where he specializes in lightweight development strategies and architectures based on Java technology and Ruby.