LA.NET [EN]

Dec 08

One of the open source projects I’ve been following in these last months is the S#arp project (pronounced Sharp Architecture) started and coordinated by Billy McCafferty. According to the homepage, this framework “is a solid architectural foundation for rapidly building maintainable web applications leveraging the ASP.NET MVC framework with NHibernate”.  The framework adheres to the following principles (again, taken from their homepage):

  • Focused on Domain Driven Design
  • Loosely Coupled
  • Preconfigured Infrastructure
  • Open Ended Presentation

The current release (which is stable) introduces several reusable assemblies with many classes and interfaces that can be reused in your apps. You’ll also find some samples that show how to use the framework and a VS template that will automatically build you a solution with everything set up for using this framework in your apps! As you can see, there’s already lots of stuff to look at. Today, I’ll concentrate on the SharpArch.Core assembly (to me, this is probably the most important project).

In this project, you’ll find several interfaces and base classes for your domain objects. Lets start with the interfaces…

The IPersistentObjectWithTypeId is the base interface for database interaction. It looks like this:

public interface IPersistentObjectWithTypedId<IdT> {
        IdT ID { get; }
        bool IsTransient();
}

As you can see, it’s a generic interface which only introduces the ID (mapped to your ID on the database table) and a method which indicates if the current object is transient (a transient object is an object which hasn’t still been persisted on the database). As we’ll see, you don’t really have to implement this interface; instead, you can inherit from one of the base classes that already do all that work for you (this is the recommended approach, because those base classes already do some extra work which might be hard to get done right). More about this on the next paragraphs…

The IHasAssignedId generic interface is there for letting you set the ID of a domain object. It has only one method: SetAssignedIdTo. Here’s its signature:

public interface IHasAssignedId<IdT> {
        void SetAssignedIdTo(IdT assignedId);
}

Your objects will have to implement this interface if you want to explicitly set the ID of your object (at least, that’s the idea).

There’s also a IRepository interface which extends the IRepositoryWithTypeId interface by setting the ID type to an integer (System.Int32). Here are their signatures:

public interface IRepository<T> : IRepositoryWithTypedId<T,int> { } public interface IRepositoryWithTypedId<T,IdT>    {
     T Get(IdT id);      
     List<T> GetAll();
     List<T> GetByProperties(IDictionary<string, object>
                           propertyValuePairs); 
     T GetUniqueByProperties(IDictionary<string, object>
                                             propertyValuePairs); 
     T SaveOrUpdate(T entity); 
     void Delete(T entity);

     IDbContext DbContext { get; }
}

As you can see, IRepositoryWithTypeId defines the public methods that the repositories will implement. To be honest, I’m not really a fan of having the GetByProperties, GetUniqueByProperties and GetAll methods on this interface since I’d really prefer to have a separate context for querying (ie, I’d like to maintain my domain model as a transactional/write model).

There are also more specifics NHibernate interfaces, appropriately called INHibernateRepository and INHibernateRepositoryWithTypeId. This last interface extends the IRepositoryWithTypeId interface with several methods which let you interact explicitly with the NH API:

public interface INHibernateRepositoryWithTypedId<T, IdT> :
                IRepositoryWithTypedId<T, IdT>    {
    T Get(IdT id, Enums.LockMode lockMode); 
    T Load(IdT id); 
    T Load(IdT id, Enums.LockMode lockMode); 
    List<T> GetByExample(T exampleInstance, params string[] propertiesToExclude); 
    T GetUniqueByExample(T exampleInstance, params string[] propertiesToExclude);

      T Save(T entity); 
      T Update(T entity); 
      void Evict(T entity);
}

If it depended on me, and since the framework has a DDD focus, I wouldn’t add these interfaces to the core project.

There’s also one more thing that keeps bothering me when I look at these interfaces: the List<T> types that are returned from the GetXXX methods. I don’t really like it and I have changed my customized version of the assembly so that all those members return an IEnumerable<T> instead (just think about it: why do we need List<T> when we aren’t really allowed to add elements to those collections? And even if we needed to to that, wouldn’t it be better to return ICollection<T> or IList<T>?).

Before delving into the classes, I’d like to mention the IDomainObject interface:

public interface IDomainObject {
        bool IsValid();
        InvalidValue[] ValidationMessages { get; }
}

This interface lets you check for validity. Unfortunately, it’s tied up with the NHibernate Validator framework and, again, this is something that I don’t really like. I’d really prefer to have a validation framework based on the concept of domain rule, but this is what we have and we’ll have to live with it…

Now, the main thing you’ll get from the SharpArch.Core assembly are the classes that implement the previous interfaces and that you can reuse in your code. With these classes you’ll automatically get code for checking for equality and code that implements the hash code in a correct way (do notice that implementing the GetHashCode method is really hard work!). We’ll start with the DomainObject class. This class implements the IDomainObject interface and overrides the Equal and GetHashCode methods inherited from the System.Object class.

Before looking at the code, we need to understand the concept of Domain Signature. The domain signature is a value (or combination of values) that doesn’t change during the lifetime of a domain object and that uniquely identify an object (do notice that domain objects do have longer lifetimes than “programming” objects). Do notice that domain signatures aren’t good database keys !

SharpArch introduces the DomainSignatureAttribute for annotating properties of classes that are used in its domain signature. The DomainObject class will look at these attributes when it needs to check fo
r equality or to calculate the hash code of an object. For instance, lets assume that you have a Person class where you’ve reached the conclusion that each instance is uniquely identified by its name (this is just an example!). Here’s how you’d write the code when you’re reusing this framework:

class Person:DomainObject{
   public Person(String name){
      Name = name;
   }
   [DomainSignature]
   public String Name{ get; private set; }
}

As you can see, you just need to annotate the property (or properties) that define the domain signature with the attribute and the base class will automatically add code for checking for equality and for calculating the hash code. Lets start by looking at the code used for checking for equality (defined by the DomainObject class):

public override bool Equals(object obj) {
            IDomainObject compareTo = obj as IDomainObject;

            if (ReferenceEquals(this, compareTo))
                return true;

            return compareTo != null && GetType().Equals(compareTo.GetType()) &&
                HasSameDomainObjectSignatureAs(compareTo);
}

Several interesting things are happening here. First, the method uses the static Object.ReferenceEquals to see if we’re comparing two objects that point to the same object reference. When that doesn’t happen, the method sees if the object that has been passed implements the IDomainObject interface (personally, I’d prefer that it would check for DomainObject instead of the interface, but…) and if it does (and if the object has the same type as the current instance over which the Equals method is called), it’ll will defer the equality calculation to the helper HasSomeDomainObjectSignatureAs method.

protected virtual bool HasSameDomainObjectSignatureAs(IDomainObject compareTo) {
    foreach (PropertyInfo property in DomainSignatureProperties) {
      object valueOfThisObject = property.GetValue(this, null);
      object valueToCompareTo = property.GetValue(compareTo, null);

      if (valueOfThisObject == null && valueToCompareTo == null)
                    continue;

      if ((valueOfThisObject == null ^ valueToCompareTo == null) ||
         (!valueOfThisObject.Equals(valueToCompareTo))) {
                    return false;
       }
   }

   return DomainSignatureProperties.Any() || base.Equals(compareTo);
}

As you can see, equality is calculated by checking the properties annotated with the DomainSignatureAttribute (the DomainSignatureProperties uses LINQ to get the collection of PropertyInfo objects for the properties annotated with the DomainSignatureAttribute). Notice that we can get to the last line of the method in two cases: when there aren’t any properties signed with the DomainSignatureAttribute or when there are and their values match. In the first scenario, we simply redirect to the base class (System.Object) and will let it do its work. In the latter, we’ll just return true (notice the clever use of the Enumerable.Any extension method on the last line of the Equals method).

The GetHashCode method follows the same principles introduced by the Equals method: use the domain signature properties and redirect to the base whenever there aren’t any properties annotated with DomainSignatureAttribute. The method will also use the type and a random number for making sure that you get a good hash code.

public override int GetHashCode() {
    unchecked {
        int hashCode = GetType().GetHashCode();

        foreach (PropertyInfo property in DomainSignatureProperties) {
          object value = property.GetValue(this, null); 
          if (value != null)
             hashCode = (hashCode * RANDOM_PRIME_NUMBER) ^
                                 value.GetHashCode();
         }

         if (DomainSignatureProperties.Any())
                    return hashCode;

         return base.GetHashCode();
   }
}

One thing you might be tempted to do is using the hash for checking for equality. Don’t do that! The only guarantee that hash codes give you is that the equal instances will return the same hash code. It doesn’t say anything about different instances. In practice, you might have two different instances produce the same hash code and that’s ok (really!)

Since the DomainObject class implements the IDomainObject interface, it will also add code for checking for the validity of an object. Currently, these checks are performed by the NHibernator Validator. So, if you’re a fan, reusing this class as a base will let you use their attributes for validation…

The last important class introduced by the core assembly is the PersistentObjectWithTypeId class (there’s also a PersistentObject  class that inherits from the previous class and sets the TypeId to System.Int32). The class expands the DomainObject class and implements the IPersistendObjectWithTypeId interface that was presented earlier.

The most important thing the class does is override the Equals method. Here’s the code:

public override bool Equals(object obj) {
   PersistentObjectWithTypedId<IdT> compareTo = obj as PersistentObjectWithTypedId<IdT>;

   if (ReferenceEquals(this, compareTo))
                return true;

   if (compareTo == null || !GetType().Equals(compareTo.GetType()))
                return false;

   if (HasSameNonDefaultIdAs(compareTo))
                return true;

   return IsTransient() && compareTo.IsTransient() &&
                HasSameDomainObjectSignatureAs(compareTo);
}

As you can see, if we’re talking about non transient objects of the same type, then equality will be performed by checking the value of the ID property (remember that this ID is the one that is used as a primary key on the database table). Domain signature comparison will only be used if both of the objects are transient (if only one of them is transient, then the instances are different).

As you ca
n see, the framework introduces two important base classes: DomainObject and PersistentObject. If you’re doing DDD, then I recommend that you use the DomainObject class, especially if you’re following the domain signature concept. If you’re also using NHibernate, then do reuse the PersistentObject(XXX) class.

As you can see, the S#arp Architecture project is still young, but it’s also interesting and it might be a good framework for supporting your code. I’m already using several of its ideas (not all, because I still don’t agree with some of the options that have been taken) and I’ve been pleased with the overall results.

In the next posts I’ll dig into the repository implementation code.

3 comments so far

  1. Billy McCafferty
    9:10 pm - 12-12-2008

    Good call on the “IDomainObject compareTo = obj as IDomainObject;”…it should be casting to DomainObject instead. I”ve updated the trunk. 😉

  2. Umer
    10:22 am - 3-23-2009

    I am also using S#arp what i have done is
    move all functionality ( Services) like, save /saveupdated /delete , find , GetList in another project like services
    and returning IList
    am really really enjoying it
    core is another project just contain domain entity

  3. vnleonki
    4:37 pm - 11-2-2009

    WnyjwZ kmxawooynxwn, [url=http://ayamgviidztz.com/]ayamgviidztz[/url], [link=http://vdszekguakjt.com/]vdszekguakjt[/link], http://evjncbnkpukc.com/