LA.NET [EN]

Apr 18

This marks the beginning of a new series. I’ve already written about it in the past, but I thought that now would be a good idea to go back and take a deep dive on the existing code. What is the S#arp? Here’s the official definition: “Pronounced "Sharp Architecture," this is a solid architectural foundation for rapidly building maintainable web applications leveraging the ASP.NET MVC framework with NHibernate.”

As you can see, it focus on two areas which are dear to my heart: DDD and NHibernate. As we’ll see along this series, this framework will surely help you, especially if you’re building MVC applications and you’d like to apply some of the concepts defined by DDD. Our study of this framework will start in the base SharpArch.Core assembly and today we’re taking a close look at the abstract BaseObject class.

The BaseObject class is one of the base classes that is reused by other classes. As we’ll see, its main objective is to test for equality between two BaseObjects instances (ie, override the default implementation of the Equals method) and to correctly implement the GetHashCode method.

The first thing you’ll notice about this class is that it’s serializable (ie, it’s annotated with the SerializeAttribute attribute) and that it can be converted (or serialized)  into JSON by using the JSON.NET framework. This might throw you off at first, but it is needed if you’re reusing your domain objects through several layers/contexts (which is something I’ve been staying away for months now – honestly, I’m really convinced that I’d have more hair if I had started doing this earlier, but we’ll leave that talk to another day).

As I said,one of the main purposes of this class is to implement equality. It does that by overriding the the Equals method and performs several steps:

  • first,the received object is “casted” to BaseObject by using the as operator;
  • a reference check is performed: if both objects point to the same memory location, true is immediately returned;
  • if that isn’t the case, then equality depends on a last test which involves comparing the current types and seeing if the object received by method and “casted” to BaseObject is not null and has the same business signature as the current object.

The concept of business signature is fairly important. You can see it as something that uniquely identifies your object. For now, that is all we’ll say about it because uniquely identifying an object depends on the fact you’re using a value object or an entity (DDD concepts which we’ll explore in the future).

Business signatures comparison is performed by the HasSameObjectSignatureAs method. It’s really a simple method which tries to get a list of PropertyInfo objects that represent the current business signature of the type and checks for equality between the values of each property in that list (between the BaseObject instances that are being compared). Obtaining the list of properties is a simple process that ends up calling the abstract GetTypeSpecificSignatureProperties method. If you’re a pattern guy, then you’ll probably recognize the template method pattern here, where a specific step of an algorithm is implemented in a more derived class.

Calculating the hash code depends (also) in the business properties. When there are business signature properties, the GetHashCode returns a hash based on the current type’s hash code and on the hash of the each property (affected by a specific constant). When there aren’t any, it will simply reuse the base Object’s GetHashCode method for getting the hash.

Now that we’ve seen the internals, it’s time to see how we can reuse the class in our code. Even though you won’t be using this class often (the future posts we’ll present other more interesting  classes), I believe that it’s interesting to present a simple example of its usage. Here’s a very simple class which will reuse the BaseObject class to get the correct behavior for equality:

public class SimpleAddress:BaseObject {
  public String Street { get; set; }
  public String ZipCode { get; set; } 
  protected override IEnumerable<PropertyInfo> GetTypeSpecificSignatureProperties( ) {
            return GetType().GetProperties();
        }
}

As you can see, we’re using all the public properties for the business signature of this class (in fact, we could probably represent this class a a value object!). In practice, this means that 2 instances of this type are equal when the values of both properties are equal. It’s important to mention that the base class caches the properties so you don’t need to worry with that.

Now, try running the following code:

var address1 = new SimpleAddress {
                                      Street = "Street X",
                                      ZipCode = "SomethingElse"
                              };
var address2 = new SimpleAddress {
                                      Street = "Street X",
                                      ZipCode = "SomethingElse"
                              };
var address3 = new SimpleAddress {
                                      Street = "Street X",
                                      ZipCode = "DifferentAddress"
                              };
Console.WriteLine( "address1 == address2 : {0}", address1.Equals( address2));
Console.WriteLine( "address1 == address3 : {0}", address1.Equals(address3));
Console.WriteLine("Hash codes:");
Console.WriteLine( "address1: {0} naddress2: {1} naddress3: {2}",
     address1.GetHashCode(), address2.GetHashCode(), address3.GetHashCode() );

If everything goes well, then you’ll see that address 1 equals address 2 and that both of them are different from address3.

Notice that by reusing y
ou only need to indicate the properties that should be used for equality comparisons. This is great because the base class already takes care of several small details that do matter (believe me: implementing a good hash algorithm and equality are more difficult than it might appear at first sight).

And that’s it for today. Keep tuned for more on the S#arp framework.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>