Showing posts with label DRY. Show all posts
Showing posts with label DRY. Show all posts

5 August 2012

T-shirt Update

D.R.Y. - don't repeat yourselfI love t-shirts and keep wearing them regardless of my employer's dress code. I had only two complaints about them in the last year, so things worked out quite well ;-) The last time I wrote about Code Cop t-shirts was more than two years ago, so it is definitely time for an update.

Don't Repeat Yourself
The Don't Repeat Yourself or DRY principle states that every piece of knowledge must have a single, unambiguous, authoritative representation within a system. In simple terms this means that there should be no duplicates or repetition. The dark blue DRY shirt reminds me to write things once and only once. It is also my best selling shirt ever, as a friend bought one after he was exposed to horrible duplicated code at the client's site. Unfortunately I did not get rich as I bought him a beer in return.

Green Bar Test RunnerKeep the bar green to keep the code clean
Keeping the bar green is the primary motto of JUnit, the popular unit-testing framework for Java. This grey shirt displays a simplified image of the Eclipse JUnit runner together with a green bar. I had problems finding the right dimensions for the characters and the green check marks and threw away at least three versions until I got it right. One day I wore it in the office and one of my colleagues, a project manager, asked me "green is good, right?" I just love them.

Red Green RefactorRed-Green-Refactor
Red-Green-Refactor is the cycle of Test Driven Development. You write a failing test which results in a red bar. Then you write some code until the bar is green. Finally you clean up the code you just wrote, e.g. improve the names or remove duplication. (Remember DRY?) For the white shirt I used typefaces according to these phases: Red is scary, I do not like it, so I used a Halloween typeface for it. Then I go for a green bar as fast as possible, so I used a dynamic typeface for that. My result after refactoring is sorted and tidy symbolized by a regular typeface.

(Buy Code Cop shirts)

15 August 2009

Type Parameters and Reflection

Last week I had an opportunity to participate in the development of XMAdsl, an Xtext based model driven development extension of openXMA. In the new release we want to use Value Objects for all relevant values. E.g. the birth date of a person should not be an arbitrary java.util.Date, but a specific BirthDateValue instance. The Value Object hierarchy looks like that:
abstract class ValueObject<T> {
private final T value;
public ValueObject(T pValue) {
value = pValue;
}
// shortened for brevity...
}

class ValueObjectDate extends ValueObject<Date> {
public ValueObjectDate(Date pDate) {
super((Date) pDate.clone()); // Date is mutable
}
// shortened for brevity...
}

class BirthDateValue extends ValueObjectDate {
public BirthDateValue(Date pValue) {
super(pValue);
}
}
ValueObject, ValueObjectDate and all other Value Object base classes are packaged in the platform used by the generator. BirthDateValue and all other concrete subclasses are generated depending on the model. Such method signatures are more readable and passing a date of payment as a birth date by accident gets impossible. (Value Objects have other advantages, e.g. being read only, but that's not the point here.)

Reflection PoolAll Value Objects use the ValueObjectType Hibernate User Type for persistence. Obviously the User Type has to know the type of the Value Object to create new instances and the type of the value inside it to map it onto the database column. But how to get the inner type? Our first approach was to configure it. As the Hibernate configuration is generated as well, that's no big deal. Nevertheless it's a bit lame and definitely not DRY.

So the question is how to find the type parameter of a generic super class. In the given case the inner value is passed as constructor argument, so we can easily do better using reflection on the constructor parameter:
for (Constructor<?> c : pValue.getConstructors()) {
if (c.getParameterTypes().length == 1) {
return c.getParameterTypes()[0];
}
}
// throw an exception
Nice. That fixed our problem but made me think further. What if there would would be no method or field with the concrete type of the type parameter, e.g. when using collections as super classes and not defining any new methods? It's also possible to find the type using reflection:
public Class<?> findType(Class<?> pValue) {
if (pValue == Object.class) {
// throw an exception
}

// is it generic itself?
if (pValue.getTypeParameters().length > 0) {
return (Class<?>) pValue.getTypeParameters()[0].getBounds()[0];
}

// is the super class typed?
if (pValue.getSuperclass().getTypeParameters().length > 0) {
Type superClass = pValue.getGenericSuperclass();
ParameterizedType type = (ParameterizedType) superClass;
return (Class<?>) type.getActualTypeArguments()[0];
}

// go up to super class
return findType(pValue.getSuperclass());
}
A class knows if it's super class had type parameters using getGenericSuperclass(). If the class has a type parameter itself we don't know it due to erasure, but at least we get its lower bound. In all other cases we go up the class hierarchy. Finally a little test if it works as expected...
@Test
public void testFindType() {
assertSame(Date.class,
userType.findType(ValueObjectDate.class));
assertSame(Date.class,
userType.findType(BirthDateValue.class));
}

24 February 2009

equals and hashCode Generation

Recently we discussed equals() and hashCode() implementations. A proper implementation is not trivial, as "father" Bloch showed us years ago. Back in 2004 I wrote a plugin for Eclipse 2 to generate these methods. (Unfortunately I never managed to publish it. I know I am weak ;-) My home grown solution would produce something like
public int hashCode() {
  long bits;
  int result = 17;
  result = 37 * result + (aBoolean ? 1231 : 1237);
  result = 37 * result + (int)
    ((bits = Double.doubleToLongBits(aDouble)) ^ (bits >> 32));
  result = 37 * result + (int) (aLong ^ (aLong >> 32));
  result = 37 * result + anInt;
  if (anObject != null) {
    result = 37 * result + anObject.hashCode();
  }
  if (anArray != null) {
    result = 37 * result + anArray.hashCode();
  }
  return result;
}
public boolean equals(Object obj) {
  if (this == obj) {
    return true;
  }
  else if (obj == null || getClass() != obj.getClass()) {
    return false;
  }
  final Homegrown o = (Homegrown) obj;
  return (aBoolean == o.aBoolean &&
         aDouble == o.aDouble &&
         aLong == o.aLong &&
         anInt == o.anInt &&
         (anObject == o.anObject ||
           (anObject != null && anObject.equals(o.anObject))) &&
         (anArray == o.anArray ||
           (anArray != null && anArray.equals(o.anArray))));
}
I know, I know the implementation for arrays is most likely not what you want. (Did I say that I am weak? :-) Since Java 5 one could use the java.util.Arrays class to fix it. Nevertheless, it served me well for some years. There are several other plugins for Eclipse, and Scott McMaster wrote about in 2006. Since version 3.3 (Europa) Eclipse can finally do it on its own:
public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + (aBoolean ? 1231 : 1237);
  long temp;
  temp = Double.doubleToLongBits(aDouble);
  result = prime * result + (int) (temp ^ (temp >>> 32));
  result = prime * result + (int) (aLong ^ (aLong >>> 32));
  result = prime * result + anInt;
  result = prime * result +
                   ((anObject == null) ? 0 : anObject.hashCode());
  result = prime * result + Arrays.hashCode(anArray);
  return result;
}
public boolean equals(Object obj) {
  if (this == obj) {
    return true;
  }
  if (obj == null) {
    return false;
  }
  if (getClass() != obj.getClass()) {
    return false;
  }
  final Eclipse33Java5 other = (Eclipse33Java5) obj;
  if (aBoolean != other.aBoolean) {
    return false;
  }
  if (Double.doubleToLongBits(aDouble) !=
      Double.doubleToLongBits(other.aDouble)) {
    return false;
  }
  if (aLong != other.aLong) {
    return false;
  }
  if (anInt != other.anInt) {
    return false;
  }
  if (anObject == null) {
    if (other.anObject != null) {
      return false;
    }
  }
  else if (!anObject.equals(other.anObject)) {
    return false;
  }
  if (!Arrays.equals(anArray, other.anArray)) {
    return false;
  }
  return true;
}
Using the ternary operator the hashCode method gets quite compact, but equals is a bit too verbose for my liking. IntelliJ IDEA could always generate these methods. IDEA 7.0 creates something like
public int hashCode() {
  int result;
  long temp;
  result = (aBoolean ? 1 : 0);
  temp = aDouble != +0.0d ? Double.doubleToLongBits(aDouble) : 0L;
  result = 31 * result + (int) (temp ^ (temp >>> 32));
  result = 31 * result + (int) (aLong ^ (aLong >>> 32));
  result = 31 * result + anInt;
  result = 31 * result +
                (anObject != null ? anObject.hashCode() : 0);
  result = 31 * result +
                (anArray != null ? Arrays.hashCode(anArray) : 0);
  return result;
}
public boolean equals(Object o) {
  if (this == o) {
    return true;
  }
  if (o == null || getClass() != o.getClass()) {
    return false;
  }
  Idea70Java5 original = (Idea70Java5) o;
  if (aBoolean != original.aBoolean) {
    return false;
  }
  if (Double.compare(original.aDouble, aDouble) != 0) {
    return false;
  }
  if (aLong != original.aLong) {
    return false;
  }
  if (anInt != original.anInt) {
    return false;
  }
  if (anObject != null ? !anObject.equals(original.anObject) :
                         original.anObject != null) {
    return false;
  }
  // Probably incorrect - comparing Object[] with Arrays.equals
  if (!Arrays.equals(anArray, original.anArray)) {
    return false;
  }
  return true;
}
Typical IDEA, with a little fix for +0.0/-0.0 and some warning concerning Arrays.equals, but else totally the same. In fact, all these implementations suck (including my own, which sucks most). All these result = prime * result ... and if ... return false; are definitely not DRY. I always favour Apache Commons Lang builders. A hand-coded solution using them would look like
public int hashCode() {
  return new HashCodeBuilder().
         append(aBoolean).
         append(aDouble).
         append(aLong).
         append(anInt).
         append(anObject).toHashCode();
}
public boolean equals(Object other) {
  if (this == other) {
    return true;
  }
  if (other == null || getClass() != other.getClass()) {
    return false;
  }
  ApacheCommons o = (ApacheCommons) other;
  return new EqualsBuilder().
         append(aBoolean, o.aBoolean).
         append(aDouble, o.aDouble).
         append(aLong, o.aLong).
         append(anInt, o.anInt).
         append(anObject, o.anObject).
         append(anArray, o.anArray).isEquals();
}
Well, that's much shorter, isn't it.