Thursday, June 25, 2009

Next European VAN on 6th July 2009

This time, Alan Dean is going to do a presentation about REST. If you want to learn more about REST, then here’s you’re chance. Colin had some really nice things to say about his presentations, so it's definitely going to be a learnful experience. If you already know some things about REST and want to get some of your questions answered, then you can add them to this topic on the E-VAN user group.

Start Time: Monday, July 06, 2009 07:00 PM GMT*

End Time: Monday, July 06, 2009 08:30 PM GMT

Attendee URL: http://snipr.com/virtualaltnet (Live Meeting)

VAN Calender: http://www.virtualaltnet.com/Home/Calendar

* For time zone arithmetic, you can consult this world clock site or use this time zone converter.

Stefan Tilkov has also kindly agreed to share some of his wisdom on REST at the start of August. We’re also thinking about organizing an extra E-VAN meeting on REST for mid-July, making this the mostRESTful summer in history. Details of these future E-VAN meetings will be posted soon.

As I already mentioned, Colin has set up a Google group for the E-VAN gatherings. I think we’ve had some good presentations so far, but we would be happy to hear your feedback on the past presentations and possible suggestions for the next ones.

Sunday, June 07, 2009

Generic Value Object

I just wanted to share my attempt for implementing a generic base class for Value Objects, popularized by Eric Evans and the Domain-Driven Design community. I must say that I got heavily inspired by Jimmy Bogard's implementation, which got me thinking about such an approach. Contrary to his implementation, I used static reflection instead of dynamic reflection in order to determine which fields to use for equality and string representation.

public abstract class ValueObject<T> : IEquatable<T>
   where T : ValueObject<T>
{
   private List<PropertyInfo> Properties { get; set; }

   protected ValueObject()
   {
       Properties = new List<PropertyInfo>();
   }

   public override Boolean Equals(Object obj)
   {
       if(ReferenceEquals(null, obj)) return false;
       if(obj.GetType() != GetType()) return false;
      
       return Equals(obj as T);
   }

   public Boolean Equals(T other)
   {
       if(ReferenceEquals(null, other)) return false;
       if(ReferenceEquals(this, other)) return true;
      
       foreach(var property in Properties)
       {
           var oneValue = property.GetValue(this, null);
           var otherValue = property.GetValue(other, null);
          
           if(null == oneValue && null == otherValue)  return false;
           if(false == oneValue.Equals(otherValue)) return false;
       }

       return true;
   }

   public override Int32 GetHashCode()
   {
       var hashCode = 36;
       foreach(var property in Properties)
       {
           var propertyValue = property.GetValue(this, null);
           if(null == propertyValue)
               continue;

           hashCode = hashCode ^ propertyValue.GetHashCode();
       }

       return hashCode;
   }

   public override String ToString()
   {
       var stringBuilder = new StringBuilder();
       foreach(var property in Properties)
       {
           var propertyValue = property.GetValue(this, null);
           if(null == propertyValue)
               continue;
          
           stringBuilder.Append(propertyValue.ToString());
       }

       return stringBuilder.ToString();
   }

   protected void RegisterProperty(
       Expression<Func<T, Object>> expression)
   {
       Check.Argument(expression, "expression").IsNotNull();
  
       MemberExpression memberExpression;
       if(ExpressionType.Convert == expression.Body.NodeType)
       {
           var body = (UnaryExpression)expression.Body;
           memberExpression = body.Operand as MemberExpression;
       }
       else
       {
           memberExpression = expression.Body as MemberExpression;       
       }

       if(null == memberExpression)
       {
           var message = ResourceLoader<ValueObject<T>>
                             .GetString("InvalidMemberExpression");
           throw new InvalidOperationException(message);
       }

       Properties.Add(memberExpression.Member as PropertyInfo);
   }
}

This generic base class takes care of the equality by overriding Equals and GetHashCode from the Object class and implementing the IEquality interface. It also takes care of a default implementation of the ToString method.

Using this base class significantly reduces the amount of code for implementing a value object in the domain.

public class Tag : ValueObject<Tag>
{
   public String Name { get; private set; }

   public Tag(String name)
   {
       Name = name;
       RegisterProperty(value => value.Name);
   }
}

And that is that. The only thing I've omitted in this example is the validation of the specified name.

I've been using this base class in a couple of projects now, and so far, I've been very pleased with the results although it can always be improved. I'd love to read your comments.

Saturday, June 06, 2009

Recording of Udi Dahan on SOA @ E-VAN 01 June 2009

Udi Dahan did a mind blowing talk on SOA as well as on scalable and maintainable architectures. If you missed this great session, then you can watch the recording.

Udi Dahan on SOA @ E-VAN 01 June 2009

Colin and myself have a couple of other interesting guests in mind for the next E-VAN meetings. So stay tuned. Details will be posted shortly.