Thursday, August 13, 2009

Exploring a WPF Business Application Architecture 4

I've finally gotten around to starting coding up a little GUI for my little petshop sample. It follows the MVVM pattern. After doing just a couple of windows it's clear that any GUI implemented using MVVM will have a lot of view models and a lot of commands. So where should I put all those classes in terms of folders? I see two possibilities:
  1. Put all the view models in one folder, and all the commands in another folder. There might be more structure below these folders.
  2. Put each view in a separate folder and put the view models and commands belonging to the view in the same folder.
As to what works out best...I'm on the fence...

Sunday, July 5, 2009

Refactoring vs. Re-architecting

I was recently gave a talk about refactoring. Beforehand I was asked to include something about "refactoring on a small scale" and "refactoring on a large scale". And how the two compare. I sort of just accepted that at first, but while preparing the talk I realised that "refactoring on a large scale" doesn't really make a lot of sense: Refactoring is about doing code changes that enhances readability, but doesn't change the observable behaviour of the software. That works out really well for localized changes such as extracting a method, renaming something, extracting an interface etc. But large scale changes (like splitting a single-process-application into several processes working together or moving from a voluntary scheduling scheme to a preemptive scheme) are very different beasts. Such changes aren't just large scale refactorings, they are re-architectings, and very different rules apply to the two.

Contrasting refactoring and re-architecting
To contrast the two let me list some important characteristics of refactoring:
  • Observable behaviour is not changed
  • The goal is to improve readability
  • Refactoring is pretty safe when you have good unit tests around the refactored code
  • Refactoring should be applied in an incremental fashion as a series of small steps
  • Refactoring can usually be done pretty quickly. I.e. the cost is low.
  • Refactoring helps keep the code base clean, which in turn helps keep the team velocity up (this is the real motivation for refactoring)
By contrast I find the following to be some of the important characteristics of re-architecting:
  • Re-architecting is usually done to improve one or more non-functional aspects, such as performance, scalability, availability, etc.
  • Re-architecting thus changes the observable behaviour
  • Re-architecting can't practically be done through a series of small steps. It must be done in a couple of big steps followed by a long series of small (refactoring) steps
  • The big steps are risky
  • The big steps are expensive/time consuming
  • Unit tests don't offer much help when doing the big steps
  • Re-architecting requires all levels of tests to be successful (integration, system, functional, non-functional, automated, manual)
To conclude I think that re-architecting is risky business that should only be done after thorough analysis of the cost vs. the benefit of doing the re-architecting. It's not "just" refactoring on a larger scale. That makes it sound too easy.

Wednesday, June 24, 2009

Exploring a WPF Business Application Architecture 3

It's time to add some DDD style repositories to the pet shop sample's domain model. While I don't want to go down the one-IRepository-fits-all route, I do want to reuse code between the specific repositories. In this post I'll show how to do that using interfaces and extension methods in conjunction to create repository traits that can be mixed and matched to implement specific repositories.

One Size Does Not Fit All
As argued in a nice blog post by Richard Dingwall a one size fits all approach along the lines of:










is not going to work out well: Some of the methods in the one-size-fits-all interface might be inappropriate for some domain classes. So what do we do? -We introduce a number of interfaces each representing specific traits of a repository.

Traits
As proposed by Mr. Dingwall we create a number of interface each specifying one specific trait that a repository might have. Like these:
























and probably others. Now that enables us to pick and choose which traits a specific repository should have. For instance a repository for the pet shops category objects would probably need all the traits listed above, hence it implements all those interfaces:








Incidentally implementing each of these traits is made really easy by Castle.ActiveRecord. All the smae I still don't want to implement them in each and every of the concrete repositories where they are used. This is where extension methods comes in.

Mixins
To be able to provide reusable implementations of the traits I implement an extension method for each method on the trait interfaces:

public static class ActiveRecordRepositoryImpl
{
internal static IEnumerable<Entity> GetAllImpl<Entity>(this ICanGetAll<Entity> self)
where Entity : class
{
return ActiveRecordMediator<Entity>.FindAll();
}

internal static Entity GetByIdImpl<Entity, Key>(this ICanGetById<Entity, Key> self, Key id)
where Entity : class
{
return ActiveRecordMediator<Entity>.FindByPrimaryKey(id);
}

internal static void RemoveImpl<Entity>(this ICanRemove<Entity> self, Entity entity)
where Entity : class
{
ActiveRecordMediator<Entity>.Delete(entity);
}

internal static void SaveImpl<Entity>(this ICanSave<Entity> self, Entity entity)
where Entity : class
{
ActiveRecordMediator<Entity>.Save(entity);
}

internal static int GetCountImpl<Entity>(this ICanGetCount<Entity> self)
where Entity : class
{
return ActiveRecordMediator<Entity>.Count();
}
}
Notice how easy Castle.ActiveRecord makes this. That's nice.
Right; then these *Impl extension methods are used in the concrete repositories:

public class CategoryRepository :
  ICanGetAll<Category>,
ICanGetById<Category, int>,
ICanGetCount<Category>,
ICanRemove<Category>,
ICanSave<Category>
{
public IEnumerable<Category> GetAll()
{
return this.GetAllImpl();
}
public Category GetById(int id)
{
return this.GetByIdImpl(id);
}
public int GetCount()
{
return this.GetCountImpl();
}

public void Remove(Category entity)
{
this.RemoveImpl(entity);
}

public void Save(Category entity)
{
this.SaveImpl(entity);
}
}

And that's it.

So there still the duplication of calling *Impl methods in each concrete implementation method, but the methods actually implementing the repository traits are shared. I think that's pretty nice.