Becoming a Better Programmer: A Conversation With Java Champion Heinz Kabutz

   
By Janice J. Heiss, October 2007    

Interviews Index

This marks the first in a series of interviews with Java Champions, individuals who have received special recognition from Java developers across industry, academia, Java User Groups (JUGs), and the larger community.

  Bio: Heinz Kabutz was born of German parents and raised in Cape Town, South Africa, where he developed a love of programming in junior high school through his explorations on a ZX Spectrum computer. He received a B.S. from the University of Cape Town, and at 25, a Ph.D., both in computer science, with a dissertation titled Analytical Performance Evaluation of Concurrent Communicating Systems Using SDL and Stochastic Petri Nets. In 1998, he started his own software development company, Java Specialists, where he writes contract software, consults, and offers courses on Java technology and design patterns.

Kabutz is best known as the creator of the free Java Specialists' Newsletter, targeted to expert Java developers. Since its inception in November 2000, the newsletter has grown from an initial audience of 80 friends and colleagues to, after 150 issues, one that includes more than 30,000 programmers in 114 countries.

In 2006, he and his family left South Africa to live on the island of Crete in Greece, where he can more easily consult in European countries and enjoy the seaside delights of an island culture.

"The java.util.Arrays class is a good example of bad code. It contains two mergeSort(Object[]) methods, one taking a Comparator, the other using Comparable. The methods are virtually identical and could have been merged into one with the introduction of a DefaultComparator that would use the Comparable method."
 
 
Dr. Heinz Kabutz
Java Specialists
 

Java Sun (JSC): When I asked Sun's Brian Goetz the key to writing fast Java code, he said developers should write "dumb code," by which he meant straightforward, clean code that follows the most obvious object-oriented principles in order to get the best compiler optimization. Compilers are big pattern-matching engines, written by humans who have schedules and time budgets, so they focus their efforts on the most common code patterns, in order to get the most leverage. Goetz argues that clever, hacked-up, bit-banging code will get poorer results. Your thoughts?

Kabutz: In my experience, good object-oriented design tends to produce faster and more maintainable Java code. But what is good code? I find it easier to classify "goodness" by using good object-oriented design patterns. I usually encourage software development companies to train all of their programmers in design patterns, from the most junior to the wise architect.

Teams that employ good design patterns find it much easier to tune their code, which will be less brittle and require less copying and pasting. The java.util.Arrays class is a good example of bad code. It contains two mergeSort(Object[]) methods, one taking a Comparator, the other using Comparable. The methods are virtually identical and could have been merged into one with the introduction of a DefaultComparator that would use the Comparable method. The strategy pattern would have avoided this design flaw.

Coding by Ctrl-C and Ctrl-V can also hide performance problems. Let's assume you have several algorithms, all virtually identical, but in different parts of your system.

If you measure performance, you might find that each of the algorithms takes 5 percent of your CPU, but if you add them up, they amount to 20 percent. Good design allows you to more easily change code and detect bottlenecks. Let me give an example to prove Brian Goetz's point.

In the early days of Java programming, I sometimes resorted to "clever" coding. For example, when I was optimizing a system written by a company in Germany, I changed the String addition to use StringBuffer after we had optimized the architecture and design of the system and wanted to improve things a bit. Don't read too much into microbenchmarks. Performance advantages come from good design and an appropriate architecture.

We start with a basic concatenation based on +=:

  public static String concat1(String s1, String s2, String s3,
                               String s4, String s5, String s6) {
    String result = "";
    result += s1;
    result += s2;
    result += s3;
    result += s4;
    result += s5;
    result += s6;
    return result;
  }
 

String is immutable, so the compiled code will create many intermediate String objects, which can strain the garbage collector. A common remedy is to introduce StringBuffer, causing it to look like this:

public static String concat2(String s1, String s2, String s3,
                               String s4, String s5, String s6) {
    StringBuffer result = new StringBuffer();
    result.append(s1);
    result.append(s2);
    result.append(s3);
    result.append(s4);
    result.append(s5);
    result.append(s6);
    return result.toString();
  }
 

But the code is becoming less legible, which is undesirable.

Using JDK 6.0_02 and the server HotSpot compiler, I can execute concat1() a million times in 2013 milliseconds, but concat2() in 734 milliseconds. At this point, I might congratulate myself for making the code three times faster. However, the user won't notice it if 0.1 percent of the program becomes three times faster.

Here's a third approach that I used to make my code run faster, back in the days of JDK 1.3. Instead of creating an empty StringBuffer, I sized it to the number of required characters, like so:

  public static String concat3(String s1, String s2, String s3,
                               String s4, String s5, String s6) {
    return new StringBuffer(
        s1.length() + s2.length() + s3.length() + s4.length() +
            s5.length() + s6.length()).append(s1).append(s2).
        append(s3).append(s4).append(s5).append(s6).toString();
  }
 

I managed to call that a million times in 604 milliseconds. Even faster than concat2(). But is this the best way to add the strings? And what is the simplest way?

The approach in concat4() illustrates another way:

  public static String concat4(String s1, String s2, String s3,
                               String s4, String s5, String s6) {
    return s1 + s2 + s3 + s4 + s5 + s6;
  }
 

You can hardly make it simpler than that. Interestingly, in Java SE 6, I can call the code a million times in 578 milliseconds, which is even better than the far more complicated concat3(). The method is cleaner, easier to understand, and quicker than our previous best effort.

Sun introduced the StringBuilder class in J2SE 5.0, which is almost the same as StringBuffer, except it's not thread-safe. Thread safety is usually not necessary with StringBuffer, since it is seldom shared between threads. When Strings are added using the + operator, the compiler in J2SE 5.0 and Java SE 6 will automatically use StringBuilder. If StringBuffer is hard-coded, this optimization will not occur.

When a time-critical method causes a significant bottleneck in your application, it's possible to speed up string concatenation by doing this:

  public static String concat5(String s1, String s2, String s3,
                               String s4, String s5, String s6) {
    return new StringBuilder(
      s1.length() + s2.length() + s3.length() + s4.length() +
          s5.length() + s6.length()).append(s1).append(s2).
        append(s3).append(s4).append(s5).append(s6).toString();
  }
 

However, doing this prevents future versions of the Java platform from automatically speeding up the system, and again, it makes the code more difficult to read.

Optimizing Code Optimally

JSC: Goetz also made the point that developers love to optimize code because it's so satisfying and fun. But he claims that Java developers generally are bad at identifying performance problems in an application and don't know when to optimize code. Your reaction?

Kabutz: I agree -- this is common. Sometimes managers contribute to the confusion by second-guessing the problem. I often find that the more technical the manager, the more dangerous they are. You need to measure, not guess. There's an example of this in my third secret of Java concurrency.

You need a certain finesse in dealing with management and programmers during a code or performance review. The key is to offer solutions and not blame people. Solving the problem might entail more training for the developers or restructuring the team.

Java Concurrency -- Corruption, Politicians, Greek Driving, and Micromanagers

JSC: Tell us about your 10 laws of Java concurrency.

Kabutz: Programmers overuse threads, which leads to problems, and "The Law of the Corrupt Politician," whereby the absence of adequate controls leads to corrupt objects. Programmers typically respond by adding controls everywhere, leading to "The Law of the Micromanager," in which the performance is severely hampered by contention.

I call the biggest misconception about Java concurrency "The Law of Greek Driving," which I will be describing in my newsletter in detail. The Java memory model is quite clear about what you can and cannot do, and like Greek driving, the laws are also quite clear here. You may not exceed the speed limit, you have to wear a seat belt, stop at stop signs, etc. However, the available JVMs are more forgiving than they need to be. Similarly, in Greece and Crete where I live, you are unlikely to be caught or fined for breaking traffic laws, which leads to bad driving. At stop signs, it's wise to slow down but not stop completely because you risk being rear-ended by a Cretan. The laws are strict but often aren't enforced.

In the same way, the Java memory model rules are not always enforced or obeyed by the JVMs. Your concurrent code may seem correct and may test out on all available JVMs and hardware but might still be incorrect. As hardware changes, the JVM manufacturers might be forced to apply the rules more strictly, in which case your code might break. Anyone using multiple threads must have a solid understanding of what is and isn't allowed. Even the best test may fail to flush out one's mistakes.

The Importance of Unit Testing
"Very few companies have the discipline to enforce the use of unit tests."
 
 
Dr. Heinz Kabutz
Java Specialists
 

JSC: What are some of the big mistakes that even experienced Java developers make?

Kabutz: Not unit testing. At conferences, I ask, "How many of you have unit tests for your code?" Almost no one raises their hands -- and these are experienced professionals. While programmers start projects believing they should have unit tests, they often don't take the time to write them up front, and they end up spending time fixing bugs. We should always perform unit tests.

A good unit test will not only flush out problems before you get close to production, but it will help regression test your system as well. I see it over and over -- very few companies have the discipline to enforce the use of unit tests.

 
Reacting to Open Source -- "Huh?"

JSC: What is your reaction to open sourcing the Java platform?

"Open sourcing the Java platform provoked the greatest 'Huh?' of my technical life. I immediately struggled to understand how anyone would benefit."
 
 
Dr. Heinz Kabutz
Java Specialists
 

Kabutz: Open sourcing the Java platform provoked the greatest "Huh?" of my technical life. I immediately struggled to understand how anyone would benefit. I worried that Sun was trying to delegate responsibility for maintaining the platform onto the "community."

Perhaps I was surprised because the Java platform has always been extremely open. Since JDK 1.0, the Java source code together with the JDK was available to download. Because of its availability, I spent many hours reading how things worked inside the classes. I remember asking someone to show me the String class in VB.NET and was surprised when he didn't have access to their source code.

For 10 years, I've set up all my IDEs so I can quickly browse the Java classes' source code. When Sun announced they were going open source, I didn't see how this differed from what they were already doing.

"NetBeans 6.0 has some incredible features, with UML support, performance tuning, and full support for the latest features of Java EE."
 
 
Dr. Heinz Kabutz
Java Specialists
 

JSC: What are the greatest problems companies encounter with regard to Java applications?

Kabutz: Their biggest problem is finding good Java programmers. With apparently 6 million Java developers, you'd expect a glut of talent, but sadly, there isn't. Companies embarking on a new project using Java technology should plan to either recruit programmers from competitors or train programmers versed in other languages. Much of my training work still involves teaching basic Java programming to VB programmers.

Once a company has solved the skills issue, they need to consider tooling. There are some fine IDEs nowadays. The most popular is probably still Eclipse, but NetBeans 6.0 has some incredible features, with UML support, performance tuning, and full support for the latest features of Java EE.

From what I've seen, Sun is putting considerable effort into improving their product and marketing it as a one-stop solution. I personally still use IntelliJ IDEA for most of my work.

Popular Newsletters

JSC: Your newsletter has published 150 issues covering many topics related to Java programming. What has received the most response?

Kabutz: Surprisingly, I'm totally unable to predict what will be popular.

One popular newsletter issue that I thought was particularly interesting involved sending entire graphical user interfaces over a socket.

Developers liked an issue about how to hook into the event queue in AWT/Swing, which allowed them to write global hot-key managers for Java applications and other things.

One of our most popular newsletters, conceived by my friend Sydney Redelinghuys, was a SoftReference based HashMap. We later wrote a new version using generics.

"The TristateCheckBox" was extremely popular -- the code is used by many major companies.

A scary concept with GUIs is that you can place components on top of each other. For example, this code works:

  JButton button = new JButton();
  button.setLayout(new BorderLayout());
  button.add(new JLabel("Press me"), BorderLayout.NORTH);
  button.add(new JTree());
  button.add(new JCheckBox("Weird?"), BorderLayout.SOUTH);
 

The result is this:

 
 

Issue 41 demonstrates how it can be done.

To my surprise, Swing hacking issues have been very popular. Issue 45 and issue 106 show how to make multiline cells in JTable, something that should be easy.

Laptop on the Beach

JSC: What's it like living in Chania, Crete, by the Mediterranean and working as a Java consultant?

Kabutz: When people hear that I live on the island of Crete, they conjure up images of a geek sitting on the beach with a laptop -- in fact, that's exactly what I sometimes do! I take two batteries to the beach for backup.

I had this romantic fantasy of living on an island, going snorkeling in the morning, eating delicious food, and playing backgammon into the night with friends. I thought of how creative I could be, unencumbered by the constant hustle and bustle of day-to-day living in a city. It turned out to be true! This morning, for instance, I went for a one-mile swim in the Cretan sea, where I saw fish, sea urchins, and lots of sardines.

My wife and I chose Crete because it's big enough to support a technical career but small enough to be personable and friendly. It's part of Greece, and since my wife and children are Greek citizens, it was easy for me to get permission to live here. Greeks are among the nicest people on earth.

When working on the beach, the sun is your biggest enemy. You either need a very bright monitor, or to set up the shade to fall in the right places. Ideally, you want shade on your laptop, so you should face shade. Sunglasses don't work well, since they make the LCD too dark to read. The contrast between the screen and the white sand behind the screen poses the biggest challenge. One solution is to take a thin sheet and cover your head and the laptop. It looks ridiculous, of course, but probably not as ridiculous as a geek sitting on the beach with a laptop.

Keys to Being a Good Java Programmer

JSC: What's the key to being a good Java programmer?

Kabutz: Good Java programmers need a solid understanding of the underlying classes they're using. Sun has always published the source code of the Java classes together with the JDK -- that has been my reference.

When you call a method, like Arrays.sort(), take a moment to see what's happening under the hood. Most of Sun's code is fairly well written, so by studying it, you'll learn how to write Java code.

Then read, read, and read some more. We're in an industry with a knowledge half-life of at most 18 months. Keep in mind that half of what you knew 18 months ago is worthless today, so you need to keep learning new things.

There are several books that I've featured on my site: Java Generics and Collections , Java Concurrency in Practice , Java Puzzlers , and Head First Design Patterns .

JSC: What do you do if a program confuses or surprises you?

Kabutz: If I encounter strange behavior with a Java program, I look at the source code of the classes I am using to figure out what's going on under the hood. Sometimes I'll decompile a class with JAD -- Java Decompiler -- just to see what the compiler produced. Other times, I'll disassemble the class with the javap -c command.

My newsletter subscribers send me interesting snippets of information. For example, in the beta release of JDK 5.0, they managed to break the ternary if-else command. Also, someone discovered that the "final" keyword is not as final as it used to be.

Closing Thoughts: Feed the Brain

JSC: Any closing thoughts?

Kabutz: Programmers need to be careful that their brains don't turn to stone. You may specialize in one field and find that, when the technology changes, you end up on the street. Because your brain is your single biggest asset, you need to continually feed it new information and ideas.

To really learn, you need to choose the technology that you want to experiment in and take the time to study and read, which will require sacrificing your personal time. If you follow this advice, you'll grow more valuable over time and won't become a computer dinosaur.

I've taught many courses to contented programmers, ranging from Y2K consultants to COBOL programmers, who have stuck their head in the sand for so long that it's downright impossible for them to adapt to new paradigms and languages.

If you are currently a Java programmer, you owe it to yourself to experiment in other technologies. Try out Squeak, JRuby, and other languages. Install and use a different IDE. Never stop learning. The moment you stop, you can lose the wave, and it will require a lot of paddling to catch up with it again.

See Also

Java Specialists
Java Specialists' Newsletter Archives
Java Champions
Brian Goetz Interview
Java Champion Geert Bevin and His Work With JavaScript

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.