Wednesday, October 28, 2009

Spring.Net and AOP

When dealing with cross cutting concerns in your application (logging, exception handling, performance monitoring, etc) you want to do it as unobtrusive as possible. AOP (Aspect Oriented Programming) helps you with this by using attributes, code weaving or dynamic proxies to dynamically add cross cutting functionality throughout your application.

Attributes are known to be quite slow. Code weaving is a very popular technique but unfortunately stack traces you receive from debugging or logging is not accurate because of the code being injected at run time. Thus I lean more to dynamic proxies.

I recently took a look at Spring.Net to see what they have to offer. Spring.Net uses dynamic proxies to implement their AOP solution. They implement AOP using Advice and Aspects. An advice can be created in separate assemblies and by using configuration can apply the advice to any object in your domain.

Spring.Net has 4 built in advice types you can use:
  • Before - applied before method call
  • After - applied after method call
  • Around - applied before and after method call
  • Throw - applied when an exception is raised (you defined which exception types you want advice to be applied)
I created a POC using the Around advice to apply some performance monitoring to my method calls so that I can easily spot bottlenecks occurring in production.

I created a separate assembly which will contain all my commonly used Aspects:

public class PerformanceLoggingAroundAdvice : IMethodInterceptor
{
public object Invoke(IMethodInvocation invocation)
{
Stopwatch stopwatch = new System.Diagnostics.Stopwatch();

// Start timing the method
stopwatch.Start();

// Execute the method
Object returnValue = invocation.Proceed();

// Stop timing the method
stopwatch.Stop();

// Log method runtime
Console.Out.WriteLine("ExampleAroundAdvice: '" + invocation.Method.Name + "' took " + stopwatch.ElapsedMilliseconds + " milliseconds to run.");

return returnValue;
}
}


Next, I created my Model which will contain my entities and domain services. I am going to apply my advice to my services. Note that the service has no Spring.Net specific information at this point - which keeps your domain nice and clean.

public interface IExampleService
{
Object GetObject(long id);
void SaveObject(Object obj);
void RunOperation(Object obj);
void RunOperationWithError(Object obj);
}


 public class ExampleService : IExampleService
{
public Object GetObject(long id)
{
// Run some logic to retrive an object
return "testObject";
}

public void SaveObject(Object obj)
{
// Run some logic to save an object
Thread.Sleep(100);
Console.WriteLine("saved the object");
}

public void RunOperation(Object obj)
{
// Run some logic
Thread.Sleep(50);
Console.WriteLine("ran an operation");
}

public void RunOperationWithError(Object obj)
{
// Run some logic and throw an error...
throw new ApplicationException("This method threw an error!!!");
}
}


Because Spring.Net uses proxy generation for its AOP, whenever you need to create an new object to which advice will be applied you need to ask Spring.Net to create it for you. Spring.Net will use you class definition and combine it with any configuration information specified for it. Because you dont want Spring.Net code everywhere throughout your code it is best to create a Factory which is a nice pattern to abstract the object creation for you.

public class Factory
{
public static IExampleService CreateService()
{
IApplicationContext ctx = ContextRegistry.GetContext();
IExampleService exampleService = (IExampleService)ctx.GetObject("exampleService");
return exampleService;
}
}


Next we have our client application which will use your domain. This is where the configuration will be placed. Below is the configuration for the advice and to which object it is applied and also to what methods you want to apply them.

<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>

<spring>

<context>
<resource uri="config://spring/objects" />
</context>

<objects xmlns="http://www.springframework.net">
<description>An example that demonstrates use of a poincut.</description>

<object id="PerformanceMonitoringAroundAdvisor" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
<property name="Advice">
<object type="SpringExample.Aspects.PerformanceLoggingAroundAdvice, SpringExample.Aspects" />
</property>
<property name="MappedNames">
<list>
<value>*GetObject</value>
<value>*SaveObject</value>
</list>
</property>
</object>

<object id="exampleService" type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="Target">
<object type="SpringExample.Model.ExampleService, SpringExample.Model" />
</property>
<property name="InterceptorNames">
<list>
<value>ConsoleAroundAdvisor</value>
<value>PerformanceMonitoringAroundAdvisor</value>
</list>
</property>
</object>

</objects>

</spring>


Our calling application will then use our domain:

class Program
{
static void Main(string[] args)
{
try
{
IExampleService exampleService = Factory.CreateService();

Console.WriteLine("Example: Get Object");
exampleService.GetObject(25);

Console.WriteLine("\nExample: Save Object");
exampleService.SaveObject("testSaveObject");

Console.WriteLine("\nExample: Run Operation");
exampleService.RunOperation("testRunObject");
}
catch (Exception ex)
{
System.Console.Error.WriteLine("Error occured: " + ex.Message);
}

Console.WriteLine("\nPress enter to continue...");
Console.ReadLine();
}
}


As you can see there are numerous advantages to using Spring.Net. Some disadvantages/drawbacks worth noting is that all service to which you want to apply advice needs to have an interface. Second, as seen above, Spring.Net is quite XML heavy so the maintenance of the XML could become problematic. It would be best to use an nice XML editor to maintain the XML.

Hope this has been helpful. Try it out and enjoy.

Tuesday, October 27, 2009

DDD vs Data Driven Applications

I listened to a podcast yesterday on dotnetrocks - "ten things that annoy miguel castro". One of the points Miguel raised was the strong debates between Domain Driven Design (DDD) and Data Driven design. I agree with him that I hate Zealots every software solution has a multitude of designs that could work for it.

I think however on the DDD point that he made he only gave the Microsoft point of view with Data Driven design. Microsoft has been heavily focused for the past decade on building applications that are basically CRUD applications. I have always been against this type of approach because you might as well expose an Access client or SQL Server client to the user. However I know there are benefits to this approach - fast to get off the ground, a lot of Microsoft technology support for it and most junior to mid level developers will understand it (small learning curve).

Miguel notes that Data Driven applications are faster to get started with than DDD and for most clients all they want is to get their solution out the door as fast as possible. As a person that would like to work in a field, which we would like to call Software Engineering, I have a big problem with this.

As soon as you build an application for a client you are building an application that has one or many competitive advantages over other competitors. That model should be built according to the business's ubiquitous language. The main reason for this (and Miiguel failed to mention this) is that although it may take a longer to start the project, it has huge return on investment on the later parts of the project. Any second, third, or nth iteration you will start seeing the benefits of your initial investment because your design is modeled according to the business model. It is easier to express the business processes in code accordingly. The only reason you would have to do major rewrites is if the business's model changes (which is a strategic shift it direction).

Software is a craft and should be spoken about passionately. I do not mean to rant and rave but while I believe most technologies and designs have their place I do not want developers to default to the Data Driven design because it is an easier paradigm. We are software engineers and have an ethical obligation to the client and business to build systems which is catered to their needs and model their business process to help expose their competitive advantages. We know how to build systems and which way is the correct way. It is our duty to advise them and not the other way around.

Any questions on DDD don't hesitate to contact me.

Good books to get started with DDD:
  • Applying Domain Driven Design by Jimmy Nilson
  • Domain Driven Design by Eric Evans (the original :))
  • Domain Driven Design Quickly (located on InfoQ)


Monday, October 19, 2009

Fluent Nhibernate

I have always been skeptical on ORMs. There are a lot of options out there... Nhibernate, LinqToSql, Entity Framework, etc. I have always found them to be lacking it some regard. LinqToSql and Entity Framework in my opinion especially have been a complete failure because they only have data driven applications in mind.

Even NHibernate which is a well known ORM and very flexible has it drawbacks. Its main drawback is that its very XML heavy. You have the power to design your model separate from your database but you are required to map all your entities and fields using XML to the relevant database tables and fields. Not something you want to manage in the long run....

But behold a new version of NHibernate is available. This is called Fluent NHibernate. They have removed the XML configuration and replaced it with mapper files (similar to Data Mappers for those who are familiar with the pattern) that uses LINQ to map properties to database fields.

An example below:

public class SessionAudit : Audit
{
public virtual Guid SessionIdentifier { get; set; }
public virtual string ChannelAddress { get; set; }
public virtual SessionAuditTypes SessionAuditType { get; set; }
}


Here we have a Session Audit entity. There is nothing special about the entity except that Fluent NHibernate requires you to mark the fields you want to map with the virtual keyword. The reason for this is that they override those properties to do the actual mapping.

Next we have the mapper file:

public class SessionAuditMap : ClassMap<SessionAudit>
{
public SessionAuditMap()
{
Id(x => x.Id);
Map(x => x.DateModified);
Map(x => x.ChannelAddress).Unique();
Map(x => x.SessionIdentifier).Column("Session_Id"); ;
Map(x => x.SessionAuditType).CustomType<int>();
References(x => x.RoyaltyAgreement);
HasMany(x => x.ShareAgreements)
.Cascade.All()
.Inverse();
}
}


As you can see this class will do the mapping for you. It inherits from the generic ClassMap namespace which lets Fluent NHibernate know that you want to map a specific entity. Next, in the constructor, you define the fields that you want to map. Pretty Straightforward. They include a lot of overrides for you to use in the mapping. As seen in the example this includes mapping to specific column names, having one (or many) references to other entities. It also allows cascading changes made to all entities.

You can also enforce unique constraints and also specify indexes and composite keys. Fluent NHibernate allows allows custom queries to be called and even stored procedures for those that are included to use them.

In an added benefit Fluent NHibernate allows you to export the schema to the database and create it for you. For those of you relying on TDD and unit tests this is especially helpful because you can focus clearly on the model without the worry of integration (and maintaining) and mapping to the database. This allows you also to start writing integration tests early in your development because setup and initialize of the database is done for you.

For those of you interested in patterns, Fluent NHibernate supports Identity Map and a basic form of Unit of Work (using the ITransaction namespace).

An example of persisting:

using (var session = _SessionFactory.OpenSession())
{
// populate the database
using (var transaction = session.BeginTransaction())
{
try
{
foreach (object entity in UpdatedObjects)
{
session.SaveOrUpdate(entity);
}
transaction.Commit();
return true;
}
catch (Exception ex)
{
transaction.Rollback();
}
}
}


There are certain situations you want to use ORMs and our team debated this concept and decided that you could use it with great success in situations where you have few reads and numerous updates. The only real scenario that you wont use an ORM is when doing high volume transactions (some where in the range of 100 per second or more). Even if you have a lot of reads you can get around it using the Command/Query seperation pattern. But that is all the the architecture design of your application. Just make sure you know what you are getting in to :).

Till next time... live as clean as you code.