Archive for September, 2003

Holub is at it again

Allen Holub is at it again. I already commented on his previous column about inheritance and I pointed out his usual habit of coming up with a provocative title to get readership and then try to turn his ideas into an article, usually very unconvincing.

This one is no exception. Worse, it is actually a rehash of an article he wrote a few years ago.

This (in)famous article is an unconvincing attempt at proving that getters and setters are evil.

Can you make massive changes to a class definition—even throw out the whole thing and replace it with a completely different implementation—without impacting any of the code that uses that class’s objects?

And what does this have to do with accessors? Besides, getters and setters are part of the contract of the class, they are no different than business methods. If you modify anything that’s part of the public interface of the class, you are going to break existing code.

Holub’s thought is basically "A program is made of code only", which is a terrible simplification. Programs are made of code and data and refusing to acknowledge this is the sure way to catastrophic designs.

Don’t ask for the information you need to do the work; ask the object that has the information to do the work for you

What if this work absolutely doesn’t belong in the object in the first place? What if you need to gather data from different objects and then process it in a way that clearly doesn’t belong anywhere else than in your object? Of course, you can create an intermediary object to do that, but wait… you already did this on your current object! Following Holub’s advice in this particular case basically means turning everything into an object, even when this is not really needed. This screams "over design" to me.

Though getIdentity starts with "get," it’s not an accessor because it doesn’t just return a field. It returns a complex object that has reasonable behavior.

Oh but wait… then it’s okay to use accessors as long as you return objects instead of primitive types? Now that’s a different story, but it’s just as dumb to me. Sometimes you need an object, sometimes you need a primitive type.

Also, I notice that Allen has radically softened his position since his previous column on the same topic, where the mantra "Never use accessors" didn’t suffer one single exception. Maybe he realized after a few year that accessors do serve a purpose after all…

Bear in mind that I haven’t actually put any UI code into the business logic. I’ve written the UI layer in terms of AWT (Abstract Window Toolkit) or Swing, which are both abstraction layers.

Good one. What if you are writing your application on SWT? How "abstract" is really AWT in that case? Just face it: this advice simply leads you to write UI code in your business logic. What a great principle. After all, it’s only been like at least ten years since we’ve identified this practice as one of the worst design decisions you can make in a project.

In 1989, Kent Beck and Ward Cunningham taught classes on OO design, and they had problems getting people to abandon the get/set mentality. They characterized the problem as follows:

The most difficult problem in teaching object-oriented programming is getting the learner to give up the global knowledge of control that is possible with procedural programs, and rely on the local knowledge of objects to accomplish their tasks. Novice designs are littered with regressions to global thinking: gratuitous global variables, unnecessary pointers, and inappropriate reliance on the implementation of other objects.

Ah, what a subtle way to twist a message to make it match your own. Back then, the concern was not about accessors. OO advocates were simply trying to change the minds of procedural developers who were used to consider everything in terms of method calls. The idea was to introduce the concept of an object, which encapsulates both behavior and data.

If there is one thing that survived the switch from procedural to OO techniques, it’s the fact that data is central to programming. The paradigm shift comes from the fact that we access this data differently, not that we stop accessing it altogether.

Allen keeps repeating that "Calling accessors to get your data makes your code less maintainable" but I don’t see an ounce of proof in this article. Tying maintainability to accessors is a very naive and simplifying assumption. It’s even misleading in the sense that developers might now be tempted to write code without accessors and assume that it will automatically be more maintainable.

Maintainability of code is connected to several factors, and one of them is coupling. Coupling can happen in a variety of ways and accessors are just a very tiny fraction of them. Ignore the bigger picture at your own risk.

Thousands of bugs in the Character class

I received an interesting bug report on ejbc recently.  It’s very
simple:  one of our Japanese customers is using his native alphabet to name
CMP fields but ejbc complains because the said CMP fields do not start with a
lowercase letter, as mandated by the specification.

None of the three Japanese alphabets have the concept of uppercase/lowercase
letters, so I immediately suspected a bug in the Unicode support of the JDK. 
I wondered how the Character API implemented the toLowerCase() method for these
alphabets that do not have lowercase letters, so I wrote the following test
case:

public static void main(String[] argv)
{
  int count = 0;
  for (char i = 0; i < 65535; i++) {
    if (! Character.isLowerCase(Character.toLowerCase(i)))
      count++;
  }
  System.out.println("# of incorrect values: " + count);
}

The idea
is simple:  regardless of whether a certain alphabet has lowercase letters
or not, the call isLowerCase(Character.toLowerCase(…)) should always return
true.

Well, the result is interesting:

# of incorrect values: 64077

Ouch.

This made me wonder how Character.toLowerCase() is implemented…

public static boolean isLowerCase(char ch) {
  return (A[Y[((X[ch>>5]&0xFF)<<4)|((ch>>1)&0xF)]|(ch&0x1)]
          & 0x1F) == LOWERCASE_LETTER;
}

And people say that obfuscated Java is impossible…  (in case you
wonder:  this is the real source, not the decompiled version).

Okay, having said that and after poking some harmless fun at the Sun developers, I
have to say I actually understand why this method would be so obfuscated. 
The call needs to be very fast and it’s not like hundreds of developers are
going to refer to this source for guidance.

Still, the lowercase handling of Unicode characters is severely broken in the
JDK, so beware.

A new kind of components

In "Where are the components", Joseph Ottinger makes some interesting points
about the absence of reusable components in the Java land.  In
many ways, I share his concerns and I said so in a
previous entry
However, there are a few inaccuracies in his editorial that I’d like to address.

Joseph says:

EJBs were the answer to distributed computing,
with a promise of massive scalability.

That’s not at all what EJB’s were supposed to be, nor what they promised. 
Initially, the EJB specification defined a component model, and nothing more. 
Granted, it was ambitious, as it tried to address several "fringe" issues as
well, such as security, remotability and persistence.  The specification
made a few initial errors in its first revisions, which are now addressed for
the most part.

I do agree with Joseph about Stateful Session beans, which qualify as a
failed experiment in my book as they are bested by servlet sessions, but the
following statement needs some precisions:

Sure, you can get some of their promise out of
session beans, and message-driven beans are easily my favorite aspect of the EJB
spec, but getting good performance out of stateful beans or entities can be a
fine art in and of itself.

It’s true that writing Entity beans that scale requires some expertise, but
then again, scalability is a complex problem.  No technology will give you
this feature for free.  Blaming the EJB specification for this is unfair.

Let me turn to a quick example to illustrate my point.

Those of you who are aware of FreeRoller already know about this. 
FreeRoller still has massive scalability problems and the hardware and the
bandwidth can no longer be the culprit.  This leaves two possibilities:

  • Hibernate and/or Roller need to be optimized.
  • Hibernate and/or Roller have a fundamental design flaw that prevents them
    from scaling.

A few very good developers (including Gavin) have been investigating this
issue but so far, the results were inconclusive and FreeRoller is still showing
dire scalability problems.

Now don’t get me wrong:  I love Hibernate and I think it’s a piece of
software
that will pave the way for future persistence frameworks, but right now, it is
showing that scaling and relational persistence are two goals that are extremely
hard to achieve together.

I contend that EJB’s enable this goal, as many WebLogic customers can testify.

But don’t let this distract you from Joseph’s article, which makes good
points about the absence of real Java components.  This problem is not new
and I read about it for the first time in 1994 in Oliver Sims’ seminal book "Business
objects
".  CORBA took a shot at it back then, but didn’t go very far.

Now here is a thought:  what if the components were already here, but
we’re not seeing them because they adopted a shape we are not expecting?

Think about it.

When a corporation buys Microsoft Word, they do it for the end user
application in the first place.  The fact that they suddenly have all these
powerful COM components at their disposal is just a by-product of this choice. 
It’s not advertised, nor does it represent the main use of the software, but it
gets used nevertheless.

Let’s turn to J2EE application servers now.  Aren’t they the epitome of
component reuse?  When you write a J2EE application, you are reusing a
staggering amount of components that have been written and packaged for you by
experts:  web, database, remote access, transaction, security…

These are components right there.  Not the kind that Oliver Sims
envisioned, but components nevertheless.

Components are happening.  Slowly, but surely and pervasively. 
J2EE application servers provide us the equivalent of integrated circuits for
the electronic world:  well-defined blocks of functionalities that
developers can build upon to raise the level of abstraction that they provide. 
We have the plumbing and we are now progressively building the house around it.

And J2EE is the main enabler for this amazing phenomenon.  I can’t wait
to see what the business world will look like in ten years from now…