OO is Irrelevant! 33

Posted by Brett Schuchert Sun, 22 Feb 2009 21:59:00 GMT

On one of Bob’s recent blogs, way near the bottom of the commens, was the following “argument”:

One can comment critically on the “Employee” class example, though. Frankly, it IS bureaucratic. So either it’s a bad example and you have mispresented your principles, or Joel is right.

Since no one has the authority to define OO, I’ll even venture to say that “Employee” is not OO.

This got me to thinking because the SOLID principles are not about writing OO software. What follows is my original response, but it seemed to warrant a blog entry.


Something being OO or not OO is irrelevant. The original point of OO was an experiment in adding a new kind of scope to see what happens (go back to mid to late 60’s). Then it was to make it easier for kids to program (I’m thinking of Ala Kay and Smalltalk in the very early 70’s). Eventually it was to make more maintainable code.

Ultimately, doing X to get Y often promotes X as the original goal. We do OO to make maintainable code so we can deliver faster and respond to change. This eventually becomes we do OO and not doing is OO is bad.

Same can be said for agile, TDD, scrum, XP, pretty much anything …

There was another “worthy” comment from another poster:
There is no executive summary that explains the SOLID principles well enough that you can comment on them critically.

The SOLID principles are about a goal. That goal is understanding what makes code better or harder to maintain. They come from several people. Bob wrote some of them, he collected others and he’s got even more (component coupling and cohesion principles, e.g. Reuse/Release Equivalence Principle). He experienced pain developing large systems in many languages including C and C++. These principles are meant to make our life easier, not to develop OO software. They do suggest using tools available in OO to enable building better software (e.g., the OCP and polymorphism – not just method overloading but selecting a method from message based on type of the receiver done by class-based OO languages, arguably the manifestation of polymorphism in prototype-based languages like JavaScript and self, are different mechanisms to accomplish the same effect).

If code is hard to work with, the SOLID principles are one way to identify problems. Using Martin’s code smells is another. You can go back to good old coupling and cohesion, code analysis tools, etc.

In the end, suggesting that OO is a goal is equivalent to creating UML diagrams because “the process” says so. It is a form of cargo culting. It just furthers the point that critiquing based on an executive summary is a problem.

One might argue that because something is hard to understand, therefore it is of little use. I have two responses to this:
  1. I don’t think they are hard. They do take effort and lots of experience to really internalize, but most things worth learning are like that.
  2. An effective practitioner of any complex profession eventually has internalized thousands and thousands of rules, guidelines and principles such that s/he just “sees” (or in Fowler’s case “smells”) problems not seen by the novice. The SOLID principles are a mix of beginning, intermediate and ancillary rules that fit into the toolbox of effective practitioners.

Let the flames continue!

I'm glad that static typing is there to help... 13

Posted by Brett Schuchert Sat, 25 Oct 2008 10:24:00 GMT

The Background

A colleague was using FitNesse to create a general fixture for setting values in various objects rendered from a DTD. Of course you can write one per top level object, but given the number of eventual end-points, this would require a bit too much manual coding.

This sounds like a candidate for reflection, correct? Yep, but rather than do that manually, using the Jakarta Commons BeanUtils makes sense – it’s a pretty handy library to be familiar with if you’re ever doing reflective programming with attributes.

So far, so good. However, the auto-generated classes included one-to-many relationships represented with arrays. Before getting any further, let’s define this problem (at least partially) with a test:
package com.objectmentor.arraycopyexample;

import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class ArrayPropertySetterTest {
   @Test
   public void assertCanAssignToArrayFieldFromArrayOfObject() {
      Object[] arrayOfBars = createArrayOfBars();
      Foo foo = new Foo();

      ArrayPropertySetter.assignToArrayFieldFromObjectArray(foo, "bars", arrayOfBars);

      assertEquals(3, foo.getBars().length);
   }

   private Object[] createArrayOfBars() {
      Object[] objectArray = new Object[3];
      for (int i = 0; i < objectArray.length; ++i)
         objectArray[i] = new Bar();

      return objectArray;
   }
}
For completeness, you’ll need to see the Foo and Bar classes:

Bar

package com.objectmentor.arraycopyexample;

public class Bar {
}

Foo

package com.objectmentor.arraycopyexample;

public class Foo {
    Bar[] bars;

    public Bar[] getBars() {
        return bars;
    }

    public void setBars(Bar[] bars) {
        this.bars = bars;
    }

}

So an instance of a Foo holds on to an array of Bar objects; and the Foo class has the standard java-bean-esque setters and getters.

With this description of how to set an array field on a Java bean, let’s get this to actually work.

First question, how do you deal with arrays in Java? Sounds trivial, right. If you don’t mind a little pain, it’s not that bad… By dealing, I mean what happens when someone has given you an array created as follows:
   Object[] arrayOfObject = new Object[3]:
Note that this is very different from this:
   Object[] arrayOfBars = new Bar[3]:

The runtime type of these two results is different. One is array of Object; the other is Array of Bar.

This will not work:
   Bar[] arrayOfBar = (Bar[])arrayOfObject;
This will generate a runtime cast exception. You cannot simply take something allocated as an array of objects and cast it to an array of a specific type. NO, you have to do something more like the following:
    Array.newInstance(typeYouWantAnArrayOf, sizeOfArray);

That’s not too bad, right? You can then either use another method on the Array class to set the values, or you can cast the result to an appropriate array.

That’s enough information to write a generic method to copy from an array of Object to an array of a subtype of Object:
   public static Object[] copyToArrayOfType(Class destinationType, Object[] fromArray) {
      Object[] result = (Object[])Array.newInstance(destinationType, fromArray.length);

      for(int i = 0; i < fromArray.length; ++i)
         result[i] = fromArray[i];

      return result;
   }
This is a bit unruly because the caller still needs to cast the result:
   Object[] arrayOfObject = new Object[] { new Foo(), new Foo(), new Foo() };
   Foo[] arrayOfFoo = (Foo[])copyToArrayOfType(Foo.class, arrayOfObject);
We can get rid of this cast if we use generics:
   public static <T> T[] copyToArrayOfType(Class<T> destinationType, Object[] fromArray) {
      T[] result = (T[])Array.newInstance(destinationType, fromArray.length);

      for(int i = 0; i < fromArray.length; ++i)
         result[i] = (T) fromArray[i];

      return result;
   }
This doesn’t quite work because of type erasure, so to get this to “compile cleanly – no warnings”, you’ll need to add the following line above the method:
   @SuppressWarnings("unchecked")

That’s just me telling the compiler I really think I know what I’m doing.

With this change, you can now write the following:
   Object[] arrayOfObject = new Object[] { new Foo(), new Foo(), new Foo() };
   Foo[] arrayOfFoo = copyToArrayOfType(Foo.class, arrayOfObject);

The original problem was to take an array of Object[] and set it into a destination object’s attribute. Now we can create an array with the correct type, what next?

There are several things still remaining:
  1. Given the name of the property, determine its underlying array type.
  2. Create the array (above)
  3. Assign the value to the underlying field
  4. Do some suficient hand-waving to handle exceptions

Here are solutions for each of those things:
Determine underlying type

   PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor( destObject, fieldName);
   Class<?> destType = pd.getPropertyType().getComponentType();

Create the array

   Object[] destArray = copyToArrayOfType.(destType, fromArray);

Assign the value
   PropertyUtils.setSimpleProperty(destObject, fieldName, destArray);
Here’s all of that put together and simply capturing all of the checked exceptions (that’s a whole other can of worms):
   public static void assignToArrayFieldFromObjectArray(Object destObject, String fieldName, Object[] fromArray) {
      try {
         PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(destObject, fieldName);
         Class<?> destType = pd.getPropertyType().getComponentType();
         Object[] destArray = copyToArrayOfType(destType, fromArray);
         PropertyUtils.setSimpleProperty(destObject, fieldName, destArray);
      } catch (Exception e) {
         throw new RuntimeException(e);
      }
   }

That’s all it takes to copy an array and then set the value in the field of a destination object.

Simple, right?

Sometimes static (and strong) typing can get in the way. This is one of those cases. Luckily, you can write this one and use it all over. Maybe it’s a part of the BeanUtils that I was unable to track down (probably).