Non-Object-Oriented Java

Posted on Posted in Concepts of programming languages

Hardly ever have I seen code reuse in business-related code. That’s a puzzling observation, given that Java programmers are expected to write object-oriented programs for many reasons, code reuse being an important reason. My puzzlement even grew when I started to analyze my former company’s SAP programs. They aren’t object oriented. Quite the contrary, the coding conventions discourage using ABAP objects. Does this make the ABAP code any worse?

I don’t think so. The average ABAP program is focused on business code. Plus, ABAP programmers usually prefer customizing over programming. SAP delivers a framework covering most of the technical issues, so there’s no point in creating your own class hierarchy of business classes. It’s better to take the data structures and objects SAP gives you and to customize them. More often than not, the result violates requirements concerning cognitive ergonomics, usability and performance, but that’s not today’s topic. SAP’s ABAP framework allows for efficient programming, and it’s perfectly possible to write huge programs without resorting to object orientation. Dropping OO is even a sensible choice.

The project I’m currently working at supports my suspicion. The framework is as object oriented as can be. It makes use of quite a few design patterns, it’s very clean code and everything that can be refactored into a method or a class has been refactored. But the business code itself isn’t object oriented at all. It uses the classes of the lower layers, but it doesn’t have fancy class hierarchies. Plus, the learning curve is steep. Once you’ve mastered the trainee days the framework allows for extremely efficient programming. But getting there takes some time. The team have traded simplicity for efficiency and for a clean design.

What does non-object-oriented Java code look like?

I suppose most programmers don’t even notice that their Java code isn’t really object-oriented. Their classes swim on top of a complex object-oriented framework like foam on the ocean, but they don’t exhibit an intrinsic object structure. The rules of the team’s architect make sure that the code is distributed among different layers, such as the persistence layer, the presentation layer and so on. But the classes within these layers are just linear code. They are classes because Java doesn’t allow code outside classes, but other than that, they could as well be static methods (much the way you can define global functions in Javascript and static function in C). Nowadays, many programs run on a server shared by many users, so you can’t really use static methods, but you get the idea. Examine your business code, and I bet you’ll be surprised by the simple structure of your code. There’s a lot of complexity, that’s for sure, but it’s unlikely the code can be made more efficient by chosing an object-oriented coding style in favor of a more traditional procedural coding style.

Are objects the best tool for everything?

Over the years I’ve come to believe object orientation isn’t for everyone, and it’s not the right tool for every problem domain. That’s fine by me. I won’t argue with anyone preferring a procedural programming style. These days almost every device in your kitchen contains a microcontroller, and I don’t see any point in writing object oriented controller software for, say, your microwave oven. Object oriented programming adds a whole layer of complexity to your software. Microwave ovens may be complex devices, but they don’t have to be run by complex programs, so why bother with the additional complexity of objects?

I suppose most readers of BeyondJava.net consider object-orientation a tool to reduce complexity, so I guess my claim raises an eye brow or two. Now, that’s because you’re used to program in large enterprise projects. The larger your project, the more the object-oriented approach pays. But maybe you raised your eye brows simply because you’ve been told that object-orientation is better than procedural programming. If so, the rise of functional programming should make you think. Java programmers usually are confronted with an object-oriented version of functional programming. Just think of Java 8 Lambda expressions, or of Scala and Groovy, both of which are clearly both object-oriented and functional languages. However, from an historical perspective functional programming doesn’t have anything to do with objects. But that doesn’t stop functional programming languages like LISP (or nowadays its JVM counterpart, Clojure) or Haskell from being successful. They are great tools to solve a certain class of problems which are hard to solve with classical object-oriented programming languages like Smalltalk.

Java could benefit from a more extensive support of objects

By the way, Java isn’t a pure object-oriented programming language. It’s a hybrid between a procedural programming language and an object-oriented language. Most people won’t ever notice this as a shortcoming, but you can derive from a primitive data type like int. That’s a major point of grief for framework programmers like me. We solve the problem by inventing tools like XML configuration files, annotations or autoboxing. Wouldn’t it be nice to define JSR303 validation constraints and JPA entities by adding a trait to the base type?

public class Person with Entity {

   private int width with MinValue(0) with Column age;
}

(Before you ask: as far as I know this particular construction (hiding the declaration of a class inheriting from traits in a variable declaration) isn’t possible in any programming language. The idea is to add the two classes MinValue and Column to the int class. That’s multiple inheritance, but since multiple inheritance brings a lot of problems, it’s better to use traits instead of classes. If you aren’t familiar with traits, just think of them as classes).

Instead, we use annotations which actually look nicer, but can’t be debugged as easily because they don’t bear any meaning by themselves. It’s the job of the framework to add semantics to the annotations:

@Entity
public class Person {

  @Min(0)
  @Column
  private int age;
}

Did you notice I’ve started to defend object-oriented programming? Adding validation constraints is one of the domains that make object-oriented programming shine. But I wouldn’t consider this kind of task a part of the business domain. It’s one of those technical tasks that are simple enough to allow for code reuse.

Trying to deploy the object-oriented approach in business code

Higher-level business code is much more unwieldy to code reuse. Let’s think of an example that looks like a natural candidate for code reuse at first glance. Both your customers and your employees are persons, so it’s natural to define a class hierarchy like so:

public class Person {
  private Address address;
  private String fistname;
  private String lastname;
}

public class Employee {
  private String age;
}

public class Customer {
  private Address deliveryAddress;
}

Actually, employees can also be customers. We could solve this problem by multiple inheritance, like Scala’s traits. But customers aren’t necessarily people. They can also be companies. Companies have a name, but they don’t have a first name, and they can have a multitude of addresses. Talking of addresses, there are all kinds of addresses once you have to deal with international customers.

Thinking code reuse to the end

These problems can be solved, but the result is a scary entity like SAP’s business partner object. It’s a superset of more or less every attribute needed by an important customer of SAP. The result is scary. At the time of writing I don’t have access to the ABAP IDE, so I can’t tell you the exact number of attributes, but as far as I remember it exceeds one hundred attributes. It’s flexible, it covers almost every requirement mentioned by any of the countless customers of SAP (with the possible exception of your particular requirement), but is it really a good idea to create a class of 100+ attributes just to enable code reuse?

The business partner class is what you get when you follow the idea of code reuse to its logical end. It’s a bit extreme. However, it shows a common problem: it’s possible to enforce code reuse in business classes, but more often than not, the cost exceeds the synergy effect.

As a consequence, I’ve met a surprising number of teams who don’t even try to implement object-orientation or code reuse in business code. In most cases the problem domain isn’t complex enough to make things like class hierarchies the tool of choice. The code is organized in classes, but that’s basically because it’s impossible to place code outside a class in Java. Plus, classes and packages are a good way to organize your code. But that’s possible in other languages, too. Business code tends to have a simple structure. It doesn’t require patterns like factories, inheritance or composition.

But doesn’t dependency injection require objects?

Interesting enough, dependency injection is a very useful tool in business code. It’s difficult to implement DI without objects. However, business code simply uses the objects injected by DI. It simply assumes the objects are there. The business code itself doesn’t have to be object-oriented itself just because it uses DI. Once again, my suspicion is supported: DI is one of the technical aspects that make object-orientation shine. OO works best in technical code.

Do we teach students the wrong things?

I wonder if we should rethink programming courses. Java courses concentrate on object-orientation. Unfortunately, that often leads to unwanted results. Newbies and even seasoned programmers use object attributes for everything. That’s logical: they’ve learned it in their programming courses. What they’ve not learned is to avoid side-effects. It’s better to pass a parameter to function instead of using an attribute of the object. However, that’s the classical procedural approach that’s been abandoned in favor of object-oriented programming.

Wrapping it up

No doubt about that, object-oriented programming is a great tool. I take it every day to good use. But I’m a framework programmer who often delves deep into technical code. If you happen not to create complex class hierarchies everyday, don’t worry. You don’t have to know the famous Gang of Four design patterns to be a good programmers. Chances are you simply don’t need the full power of objects. More to the point, they may even stand in your way. It’s always a good idea to keep things simple. Sometimes abandoning object-oriented programming simplifies things a lot. However, that doesn’t mean you should abandon the virtues of procedural programming, too. I’ve seen a single method consisting of 6.000 lines. The programmer defended his programming style (“dividing the method into several smaller methods obfuscates the structure of the code”), but there’s a reason why procedural programming introduces procedures (nowadays more commonly know as methods), so we should use them. The same holds for object-oriented programming: there’s a reason why objects have been invented, so we should use them when appropriate – but only then.

3 thoughts on “Non-Object-Oriented Java

    1. Simple: I wrote the article after an animated discussion whether procedural programming is bad or not. These days, so many people take object oriented programming for granted that they consider older programming styles wrong. DSLs and functional programming are interesting alternatives indeed. But hardly anybody will object when I defend these programming styles, so writing an article about them is kind of boring.

Leave a Reply

Your email address will not be published.