Red Hat

On Religion (why I'm an ignorant C programmer and don't know what an object is)

Posted by Gavin King    |    Nov 12, 2007    |    Tagged as

Well, this post really brought out the crazies. Folks told me that I don't know what an object is, called me ignorant twice, quoted Alan Kay at me, and accused me of being a C programmer. :-)

(What is it about the Internet that makes it okay to call someone ignorant just because you happen to disagree with them?)

Best I can tell, what infuriated these (well-informed, intelligent, passionate) people was the following statement:

Objects are stateful, and one of the main purposes of the methods of an object is to export that state (data) to the world.

A typical objection was:

The fundamental tenet of Object Orientation is that the state of an object is not exported out through the public behavioral API.

The fundamental tenet. Got that? ;-)

Okay, so let's take this idea seriously, and see what kind of impact it would have upon the design of our system. Let's start with Order. According to these guys, this is the perfect object:

class Order {
        private Status status;
        private List<OrderLine> orderLines;
        private Customer customer;
}

This class obeys the fundamental tenet. It exposes no state to its clients. Unfortunately, it's also totally useless for anything except looking at and admiring its pure, beautiful objectyness. If we want to actually use it for something, we're going to need to be able to add new OrderLines.

class Order {
        ...
        private List<OrderLine> orderLines;
        ...
        void addOrderLine(OrderLine line) {
                orderLines.add(line);
        }
}

Does this violate the fundamental tenet? I'm not sure. It's not clear to me whether a mutator method exports the state of an object. I would say it does, but we've already established that I don't know what an object is.

Unfortunately, we're not quite done. We can only add new OrderLines if the Order is in a certain state. Let's fix this:

class Order {
        private Status status;
        private List<OrderLine> orderLines;
        ...
        void addOrderLine(OrderLine line) {
                if ( status.isSubmitted() ) {
                        throw new IllegalStateException();
                }
                orderLines.add(line);
        }
}

Nice! We obeyed the fundamental tenet!

But ... when we display an order to our user we really need to know in advance whether its okay to add new lines. It's not okay to let them find out when the addOrderLine() method blows up!

class Order {
        private Status status;
        private List<OrderLine> orderLines;
        ...
        boolean canAddNewOrderLines() {
                return !status.isSubmitted();
        }
}

Oooop! Wrong! We violated the fundamental tenet! We exposed the state of the object to its clients! What can we do to fix this? Well, we could try to make the object responsible for rendering itself to the user interface:

class Order {
        private Status status;
        private List<OrderLine> orderLines;
        ...
        public void render(Panel panel) {
                ...
                if ( !status.isSubmitted() ) {
                        panel.addButton( .... );
                }
        }
}

But ... doesn't this approach just expose the state of another object (the user interface for Order) to the Order class? Worse, it creates a dependency from the domain model to the user interface, a deep error in terms of architecture. But this is just the beginning of our problems! We really need to be able display the total price of the order to our users:

class Order {
        ...
        private List<OrderLine> orderLines;
        public Amount getTotal() {
               Amount amount = ZERO;
               for (OrderLine ol: orderLines)
                       amount.add( ol.getAmount() );
               }
               return amount;
        }
}

This method also exposes the state of the object; and so it also violates the fundamental tenet.

And, sometimes, the user interface needs to display information about what Customer an Order belongs to.

class Order {
        ...
        private Customer customer;
        
        public Customer getCustomer() {
                return customer;
        }
}

Clearly, this one of those evil getter methods we've heard about; it exports the internal state of Order directly to the world!

So, where do we go from here? How can we design our system so that we obey the fundamental tenet of Object Orientation? Well, one approach we could take is that we could just accept that this fundamental tenet is not so fundamental after all! Perhaps it is more of a recommendation, a guideline that we take into account along with many other conflicting constraints that apply when we design software. Some of these constraints are general principles of good design. Some are architectural practices. Some are special restrictions of the programming environment we are working in. Some are simply concessions to practicality!

Another possibility is that we've misunderstood this tenet. Perhaps what it is really saying is not that objects never expose their state, but rather that they expose it in a controlled fashion, via intermediating methods that abstract the internal data structure and control access to it.

Well, it's not for me to say which of these interpretations is the correct one, since, as we've already established, I don't know what an object is. Besides, this is not really what I want to write about today. The topic I really want to talk about is religion.

The folks who got upset over this issue displayed the classic symptoms of a religious mindset:

  • Appeal to authority: In the Bible, it says..., Alan Kay writes..., What would Jesus do?
  • Argument from overly broad principle: The fundamental tenet..., The Golden Rule...
  • Intolerance of dissenting opinion: Ignorant, Heathen, Infidel
  • Application of principle, without concern for consequence, and without sufficient understanding of the justification and motivation underlying the principle.

Worst of all, religions set up absurd laws that no adherant of the religion can possibly obey (do not covet thy neighbours wife, getter methods are evil), and then demand shame of those that breach the rule. On the other hand, the absurd law is taken, by adherants, as a license for denunciation of free-thinkers: those of us who believe it's perfectly okay to check out the bangin' ass on the chick next door, even as we're being faithful to our gorgeous wives and girlfriends. And those of us who think a getter method is a perfectly natural construct, the simplest and most natural solution to many problems. The great thing about denouncing free-thinkers is that the religious person gets to characterize their own opinions as the Word of God (or Alan Kay).

In general, the religious approach is very unhelpful in the field of technology. It blinds us to innovative new ideas and novel ways of viewing a problem. By contrast, the inquiring mindset is characterized by:

  • A tendency to argue from consequence: If we followed this approach....
  • Comfort with cost/benefit analysis: On balance, I think the advantages of this approach outweigh the disadvantages....
  • A willingness to search for the limits of applicability of general principles.
  • An openness to other paradigms and opposing points of view.

And so I'm back where I started: the ObjectMentor article. Why did I characterize this post as silly? Because it attempted to justify a new, unnecessary, architectural layer, without a single attempt at argument from consequence. Without even asking what the consequences of this horrible architecture would be! The ObjectMentor was in full religious mode, arguing from principle, without concern for practicality. And, as is often the case when we argue from principle alone, the ObjectMentor managed to forget some other principles along the way. More important principles. Principles like:

  • Simplicity
  • Don't Repeat Yourself
  • Ya Ain't Gunna Need It

The introduction of an extra layer would violate all these principles. But I suppose religions have always been big on unnecessary complexity and self-repetition. And religion is something that a person with a curious mind and self-confidence in his (her) own judgment and insight truly Ain't Gunna Need (in technology, or life).

back to top