Bitter Java
Bruce A. Tate
  • March 2002
  • ISBN 9781930110434
  • 368 pages
  • printed in black & white

It is a well-known fact that most software projects fail. Drawing important lessons from common failures is the goal of Bitter Java.

Reusing design patterns is not enough for success: patterns are like partial maps of dangerous terrain. They help, but don't prevent you from getting lost. Bitter Java teaches you how to recognize when you are lost, and how to get back on the right path. It illustrates common pitfalls of Java programming through code examples; it then refactors the code and explains why the new solutions are safe.

Table of Contents detailed table of contents




about this book

about the cover illustration

Part 1 The basics

1. Bitter tales

1.1. A Java development free fall

1.1.1. Antipatterns in life

1.2. Using design patterns accentuates the positive

1.2.1. Design patterns online

1.2.2. UML provides a language for patterns

1.3. Antipatterns teach from the negative

1.3.1. Some well-known antipatterns

1.3.2. Antipatterns in practice

1.3.3. Antipattern resources

1.4. Antipattern ideas are not new

1.4.1. Learning from the industry

1.4.2. Detective work

1.4.3. Refactoring antipatterns

1.5. Why Bitter Java?

1.5.1. The Bitter Java approach

1.5.2. Bitter Java tools

1.5.3. The Bitter Java organization

1.5.4. The Bitter Java audience

1.6. Looking ahead

2. The bitter landscape

2.1. Fertile grounds for antipatterns

2.1.1. The benefits of layering

2.1.2. Layering can work against us

2.2. Internet technologies

2.2.1. Internet topologies affect our applications

2.2.2. Enterprise layers add security and overhead

2.2.3. Standards enable the Internet and add layers

2.2.4. TCP and IP provide low-level communications

2.2.5. HTTP provides application-level transport

2.2.6. HTML and XML

2.2.7. Mini-antipattern: Too Many Web Page Items

2.3. Object technologies and antipatterns

2.3.1. Encapsulation helps to isolate change

2.3.2. Inheritance enables packaging of common behavior

2.3.3. Polymorphism enables flexible reuse

2.3.4. Mini-antipatterns: Excessive Layering

2.3.5. Setting the stage for Java

2.4. Java technologies solve antipatterns

2.5. Major problems with the waterfall

2.5.1. Iterative methodologies

2.5.2. Mini-antipatterns: Incomplete Process Transitions

2.5.3. Programming horizons: Extreme programming

2.6. A quick survey of the bitter landscape

2.7. Antipatterns in this chapter

Part 2 Server-side Java antipatterns

3. Bitter servlets

3.1. Getting off on the wrong foot

3.1.1. An early antipattern: The Magic Pushbutton

3.1.2. Building with Model-View-Controller

3.1.3. Failing to separate model and view

3.1.4. Breaking out the model

3.2. Antipattern: The Magic Servlet

3.2.1. Can we use servlets as the model?

3.2.2. Stumbling into the Magic Servlet trap

3.2.3. Causes of the Magic Servlet

3.3. Solution: Refactor using commands

3.3.1. Break out the model

3.3.2. Wrapping the model with command objects

3.3.3. Separating the model logic

3.3.4. Separating the return trip

3.3.5. Using a JSP for the return trip

3.4. Summary

3.5. Antipattern in this chapter

4. Bitter JSPs

4.1. Getting only halfway home

4.1.1. Recognizing the danger signs

4.2. Antipattern: Monolithic JSPs

4.2.1. This program lacks model-view separation

4.2.2. Solution: Refactor to Model-View-Controller

4.3. Antipattern: Compound JSPs

4.3.1. Should we combine multiple JSPs?

4.3.2. An example combining two interfaces

4.3.3. Solution: Split the JSP

4.3.4. Making decisions in the controller servlet

4.4. Mini-antipatterns: Coarse and Fine Commands

4.4.1. Too many commands in a group

4.4.2. Solution: Refactor to appropriate granularity

4.4.3. Tips for granularity

4.5. Mini-antipattern: Fat Commands

4.6. Reviewing the JSP antipatterns

4.7. Antipatterns in this chapter

5. Bitter cache management

5.1. We need caches!

5.2. Antipattern: The Cacheless Cow

5.2.1. Bitter BBS with no cache

5.2.2. Building the model, view, and controller for ShowBoard

5.2.3. Building the model, view, and controller for ShowThread

5.2.4. Building the model, view and controller for AddPost

5.2.5. Performance problems

5.3. Solution: Cache

5.3.1. Solution 1: Use a hardware cache

5.3.2. Solution 2: Cache commands

5.3.3. Adding a cache to our BBS

5.3.4. Possible enhancements to cached commands

5.4.1. Concurrent access to static cache

5.4.2. The ever-growing cache

5.5. Antipattern: Synchronized Read/Write Bottlenecks

5.5.1. Collisions between readers can hurt performance

5.5.2. Read/write locks allow correct shared access

5.6. Cooking the Cacheless Cow

5.7. Antipatterns in this chapter

6. Bitter memories

6.1. Understanding memory leaks and antipatterns

6.1.1. Managing memory

6.1.2. Understanding garbage collection

6.1.3. Reference counting

6.1.4. Reachable objects

6.2. Trading C++ for Java

6.2.1. Circumstances that cause Java memory leaks

6.2.2. Finding Java leaks

6.3. Antipattern: Lapsed Listeners Leak

6.3.1. Examining some dangerous practices

6.3.2. Solution 1: Explicitly remove the listeners

6.3.3. Solution 2: Shorten the life cycle of the anchor

6.3.4. Solution 3: Weaken the reference

6.3.5. Reference objects simplify memory management

6.4. Antipattern: The Leak Collection

6.4.1. Causing trouble with caches and session state

6.4.2. Solution 1: Search for common warning signs

6.4.3. Solution 2: Aggressively pair adds with removes

6.4.4. Solution 3: Use soft references for caches

6.4.5. Solution 4: Use collections with weak references

6.4.6. Solution 5: Use finally

6.5. Shooting memory leaks

6.5.1. Make sure there is a leak

6.5.2. Determine that the leak should be fixed

6.5.3. Isolate the problem

6.5.4. Determine the source and fix the problem

6.5.5. Protect against the problem for the future

6.6. Mini-Antipatterns: Little Hogs

6.6.1. String manipulation

6.6.2. Collections

6.6.3. Inheritance chains

6.7. Summary

6.8. Antipatterns in this chapter

7. Bitter connections and coupling

7.1. Making connections

7.2. Antipattern: Connection Thrashing

7.2.1. Creating and terminating with every access

7.2.2. Solution: Reuse connections with a pool

7.2.3. Refactoring our BBS to add pooled connections

7.2.4. Using getPooledConnection

7.2.5. Using the J2EE connector architecture

7.3. Antipattern: Split Cleaners

7.3.1. Exceptions can lead to Split Cleaners

7.3.2. Solution: Pair connection with cleanup, in finally

7.4. Antipattern: Hardwired Connections

7.4.1. The communications buffer

7.4.2. Premature binding

7.4.3. Solution 1: Decouple with XML messages

7.4.4. Solution 2: Delay binding with web services

7.5. Mini-antipatterns for XML misuse

7.5.1. XML’s Golden Hammers

7.5.2. XML’s bitter transitions

7.6. Mini-antipatterns: Rigid XML

7.6.1. Name collisions

7.6.2. Rigid constructs

7.6.3. Restrictive variable-content containers

7.6.4. XML versioning

7.7. Summary: Sweetening bitter connections

7.8. Antipatterns in this chapter

8. Bitter beans

8.1. A brief Enterprise JavaBeans review

8.1.1. The component-based distributed architecture

8.1.2. Types of EJBs

8.2. Bitter BBS with EJBs

8.2.1. Elements of an EJB application

8.2.2. Building the remote interface

8.2.3. Creating the home interface

8.2.4. Implementing the bean class

8.2.5. Defining the primary key

8.2.6. Creating a deployment descriptor

8.2.7. Using the model

8.3. Antipattern: Round-tripping

8.3.1. Computing the cost of a distributed deployment

8.3.2. Chatty interfaces

8.3.3. Solution: Group together round-trips with a facade

8.3.4. Roots of round-tripping

8.3.5. Refactoring the BBS with a facade

8.4. Antipattern: Square Bean in a Round Hole

8.4.1. Mini-antipattern: Bean-Managed Joins

8.4.2. Solution: Views, mappers, bean-managed joins

8.4.3. Mini-antipattern: Entity Beans for Lightweight Functions

8.4.4. Mini-antipattern: Entities for Read Only

8.4.5. Mini-antipattern: Entity Beans for Write but Not Read

8.4.6. Troublesome scrollable lists

8.4.7. Overall solution: Pick the right bean for the job

8.5. Mini-antipattern: Everything Is an EJB

8.6. EJBs and caching

8.6.1. Implementing a cache with a facade

8.7. Smoothing out the bitter beans

8.8. Antipatterns in this chapter

Part 3 The big picture

9. Bitter hygiene

9.1. Why study programming hygiene?

9.1.1. Extreme programming requires good hygiene

9.1.2. Coding standards protect against antipatterns

9.2. Mini-antipatterns: Unreadable code

9.2.1. Names matter

9.2.2. Standards for names

9.2.3. Braces and indentation


9.2.5. Tabs vs. spaces

9.2.6. Editors

9.3. Mini-antipatterns: Organization and visibility

9.4. Mini-antipatterns: Structure

9.4.1. Basic object-oriented philosophy

9.4.2. Low-level design considerations

9.4.3. Exceptions

9.5. Mini-antipatterns: Leaks and performance

9.6. Conventions for testing

9.7. Building a good style guide

9.7.1. Buy, borrow, or steal?

9.7.2. A sample style guide from Contextual, Inc.

9.8. Summary of coding standards

10. Bitter scalability

10.1. Good topologies for performance

10.1.1. Layering hardware in homogeneous groups

10.1.2. Other topology variations

10.2. Antipattern: Performance Afterthoughts

10.2.1. Developing without performance planning

10.2.2. Some real-world examples

10.2.3. Solution: Plan for performance!

10.3. Antipattern: Round-tripping

10.3.1. Solution: Cache and Facade

10.4. Antipattern: Bad Workload Management

10.4.1. Solution: Workload Management

10.4.2. True load balancing

10.5. Antipattern: Chaotic Session Management

10.5.1. Solution 1: Dispatching with session affinity

10.5.2. Solution 2: Using a distributed state management service

10.5.3. Using custom session bean solutions

10.5.4. Using custom entity bean solutions

10.6. Antipattern: Thrash-tuning

10.6.1. Solution: Use sound performance methodologies

10.7. Taming the performance beast

10.8. Antipatterns in this chapter

11. Sweet parting thoughts

11.1. Antipatterns help us on many levels

11.1.1. Antipatterns ignite careers

11.1.2. Understanding antipatterns improves programs

11.1.3. Understanding antipatterns makes you a better programmer

11.2. Integrating antipatterns with process

11.3. Next steps, last steps

Appendix A: Cross-references of antipatterns



About the book

This book is a systematic account of common server-side Java programming mistakes, their causes and solutions. It covers antipatterns for base Java and J2EE concepts such as Servlets, JSPs, EJBs, enterprise connection models, and scalability.

What's inside

After studying antipatterns in this book such as:

  • Round-tripping
  • The magic servlet
  • The cacheless cow
  • Performance thrashing

You will be standing on the shoulders of those who failed before you.

About the reader

If you are an intermediate Java programmer, analyst or architect eager to avoid the bitter experiences of others, this book is for you.

About the author

Bruce A. Tate is an Internet architect who developed the bitter Java concept after seeing a set of customer problems repeated and decided to collect these stories and publish their solutions. He is the coauthor of Objects for OS/2. He lives in Austin, Texas.

  • combo $44.95 pBook + PDF
  • eBook $35.99 PDF only

FREE domestic shipping on three or more pBooks