Tuesday, July 29, 2008

The Onion Architecture

This is what I consider to be a good architecture for long-lived business applications and how I like to design them. Actually, our current and past two projects apply this design and its far more superior to a traditional layered approach. Check out this well written blog post and keep an eye out for the next episodes.

Monday, July 28, 2008

A Professional Software Developer Never Says ...

"Let us cleanup and fix this code later so we can meet our deadline".

Three Qualities that Every Piece of Code Should Have ...

  1. It should solve a problem and thus it must be valuable to its users. In short, it should do what it must do and simply work.
  2. It should be very easy to change. Every piece of code is subject to change, so it should be darn easy to alter its behavior without complete rewrites. Some piece of software that is difficult to change should be fixed, even though it works correctly.
  3. It should unmistakably communicate its intent to the developers who need to maintain it. If this is not the case, then it should be fixed, even though it works correctly.

Most software I've seen throughout my career as a developer only satisfies  the first category. Heck, I've even seen a lot of code that doesn't even has any of these qualities. 

The second item is something that almost every business implicitly demands, but that is also never added to the requirements.

As for the the third quality, most developers think that its all about writing code but they are wrong. Its all about reading the code. This is why I believe in fluent interfaces and DSL's (and by DSL, I mean the one-and-only language DSL and not the inferior graphical DSL as popularized by Microsoft).

Are there some additional qualities that I missed?

Thursday, July 24, 2008

Windows Vista vs Windows Server 2008 (Workstation)

Last week, I decided that the time has come to replace my current desktop PC. I've been skimming through a couple of articles and reviews in order to put together a new home developer rig. Now I've come to the point that I know what I want, except for the operating system that I want to install.

I've recently upgraded my current desktop from Windows XP to Windows Vista and I must say that I'm not particularly happy about it. Its slow, slow, slow and did I already mention that it is slow? Sure you say, an older desktop that is up for replacement is always slow. Not really actually. I've never had any performance problems when running XP, even while running a VM.

With Vista, its a whole different ball-game. I was completely baffled by looking at the amount of processes/services that were running after I performed a clean install. I tried some tweaking, but nothing really helped. Besides being slow, the whole operating system hangs sometimes with for no apparent reason (no processor or disk activity whatsoever).

There are also a couple of applications I couldn't get to work correctly:

  • Windows Live Messenger (not that I'm using this much, but I figured this should at least work).
  • RapidSvn (can't even get it to start).
  • AVG anti-virus (doesn't want to automatically download virus updates).
  • A Haupauge Win-TV card I bought not that long ago.
  • ...

Well, if you don't like it, go back to XP then. Vista has its improvements as well. As you may or may not know, I'm a big fan of LUA (Least User Access). This was a real PITA in XP, but Vista SP1 comes with a lot of improvements on this. Besides, I wanted to play around with IIS 7, so an upgrade to Vista looked like the right thing to do.

Last week, I found this link on Twitter accompanied by this article that really got me interested in using Windows Server 2008 as a workstation. I downloaded a trial version last weekend and I must say that I'm very impressed by its performance (although I was running it as a VM on Vista :-)). According to some other articles and benchmarks I've read, Windows Server 2008 outperforms Vista with 11% to 17%. This article mentions that Visual Studio 2008 really flies and that VM's also run better. Windows 2008 also ships with IIS 7.0 and MSMQ 4.0, some technologies I want to learn in the near future. Hyper-V, also a feature of Windows Server 2008, got me interested as well.

There is one major downside to Windows Server 2008: the price tag of the standard edition is well beyond my range. Unfortunately, there is no "workstation edition". I would love to use 2008 on my new desktop PC, but its price really puts me off. I don't mind paying for software, but there are limits to my budget as well.

If you, my dear reader, want to share your advice then I would be happy to hear from you. If you know how to get a cheap Windows Server 2008 license, then please contact me as well ;-).

Maybe I should just get over it ...

Saturday, July 19, 2008

Binsor : The Castle Windsor XML Configuration Killer

As you might have noticed from my previous post, I'm having a look at some of the stuff on my ever growing cool-tools-and-technologies-I-have-to-grock list. The next one that was high on my list is Binsor. It's part of the Rhino Commons library and provides an internal DSL for configuring Castle Windsor, thus eliminating the need for XML configuration.

This DSL is written in Boo, a "wrist-friendly" statically typed programming language that targets the CLR. I've been playing around with this language for a couple of months now, and it's gaining my respect ever since. Besides, Ayende is writing a book about Building Domain Specific Languages in Boo, so make sure to pick it up if you're into DSL's. Should be a fun read, no doubt.

Now, back to Binsor. Just because I have a huge aversion to XML, I'm always enthusiastic when I can eliminate some angled brackets. Let's see some examples.

Suppose we have a class CustomerController that implements an interface called IController (couldn't control my creativity there). I used to configure this class in XML like this:

<component id="CustomerController" service="MyWebApp.IController, MyWebApp" type="MyWebApp.CustomerController, MyWebApp"/>

Now, behold the simplicity of the Binsor DSL:

import MyWebApp Component("CustomerController", IController, CustomerController)

Nice, huh? They call it "wrist-friendly" for a reason. Let's have another one. In my previous post, I needed to add some configuration to Castle Windsor in order to make use of the Rhino Commons repositories:

<!– Rhino commons –> <component id="nhibernate.repository" service ="Rhino.Commons.IRepository`1, Rhino.Commons.NHibernate" type="Rhino.Commons.NHRepository`1, Rhino.Commons.NHibernate"/> <component id="nhibernate.unit-of-work.factory" service ="Rhino.Commons.IUnitOfWorkFactory, Rhino.Commons.NHibernate" type="Rhino.Commons.NHibernateUnitOfWorkFactory, Rhino.Commons.NHibernate"> <parameters> <configurationFileName>web.config</configurationFileName> </parameters> </component>

Behold the Binsor equivalent:

# Rhino Commons Component("nhibernate.repository", IRepository, NHRepository) Component("nhibernate.unit-of-work.factory", IUnitOfWorkFactory, NHibernateUnitOfWorkFactory, configurationFileName: "web.config")

Binsor also supports facilities. Registering the WCF facility using XML configuration looks like this,

<facilities> <facility id="wcf" type="Castle.Facilities.WcfIntegration.WcfFacility, Castle.Facilities.WcfIntegration" /> </facilities>

while Binsor can do this in a single line of code:

Facility("wcf", WcfFacility)

Lets make it more interesting. Suppose you have lots and lots of controllers similar to the one in the first example. Every controller class implements the IController interface. Because Boo is a full-fledged programming language, you can make use of its entire syntax:

myWebAppAssembly = Assembly.Load("WindsorService") for type in myWebAppAssembly.GetTypes(): if typeof(IController) != type and typeof(IController).IsAssignableFrom(type): Component(type.Name, IController, type)

This small piece of code ensures that every controller that exists in my application is registered. From now on, every new controller class that I add to the application gets automatically configured. I don't know about you, but I'm hooked.

From what I know so far, I noticed one small disadvantage: a lack of IntelliSense in Visual Studio. Whenever I'm messing around with Boo, I use SharpDevelop because it has extensive support for Boo. There is no support for Boo for Visual Studio (yet), but help is on the way. Maybe Charles Petzold is right? Maybe Visual Studio does rot the mind?

I'll keep telling myself that I should not be so spoiled by IntelliSense, embrace the goodness of Boo and Binsor and stop acting like a cry-baby and take it like a man. Real programmers program in Notepad2 anyway :-).

Next item on the list ...

Thursday, July 17, 2008

It's the little things

A while ago, I wrote a blog post regarding Test Data Builders Refined. Earlier this week, I wrote a very simple base class that provides an implicit cast operator for the builder class:

public abstract class TestDataBuilder<TSubject> { public abstract TSubject Build(); public static implicit operator TSubject(TestDataBuilder builder) { return builder.Build(); } }

Even I can't get it more complex than this :-).

Monday, July 14, 2008

Integrating Castle Windsor and NHibernate with WCF - Throwing the WCF facility and some Rhino Tools in the mix

A while ago, I wrote this post about how to integrate Castle Windsor and NHibernate with WCF. Last weekend, I used the WCF integration facility of Castle Windsor to accomplish pretty much the same thing, but with less code. We all want that, now don't we?

As a first step, I created a class that implements the ICallContextInitializer.

public class UnitOfWorkContext : ICallContextInitializer { private IUnitOfWork _unitOfWork; public Object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message) { _unitOfWork = UnitOfWork.Start(); return null; } public void AfterInvoke(Object correlationState) { if(_unitOfWork != null) { _unitOfWork.Dispose(); _unitOfWork = null; } } }

Notice that I'm not using the SessionFactory and Session classes of NHibernate directly. Instead, I'm using the UnitOfWork classes of Ayende's most excellent Rhino Tools library.

Next an implementation of the IServiceBehavior interface needs to be created in order to apply the UnitOfWork context to the service operations.

public class UnitOfWorkBehavior : IServiceBehavior { public void ApplyDispatchBehavior( ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { foreach(var channelDispatcher in serviceHostBase.ChannelDispatchers) { var channelDispatcher = cdb as ChannelDispatcher; if(null != channelDispatcher) { foreach(var endpointDispatcher in channelDispatcher.Endpoints) { foreach(var dispatchOperation in endpointDispatcher.DispatchRuntime.Operations) { dispatchOperation.CallContextInitializers .Add(new UnitOfWorkContext()); } } } } } public void AddBindingParameters( ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } }

So far, nothing really new actually. In my previous post, I needed to create a custom ServiceHost and ServiceHostFactory class. This is now taken care of by the WCF integration facility of Castle Windsor. I'm using IIS hosting, so I need to add the DefaultServiceHostFactory of the facility to the ServiceHost file:

<%@ ServiceHost Language="C#" Debug="true" Service="WindsorService.MyWindsorService" Factory="Castle.Facilities.WcfIntegration. DefaultServiceHostFactory, Castle.Facilities.WcfIntegration" CodeBehind="MyWindsorService.svc.cs" %>

Next, we need to add the facility and the service behavior to the Windsor configuration file:

<facilities> <facility id="wcf" type="Castle.Facilities.WcfIntegration.WcfFacility, Castle.Facilities.WcfIntegration" /> </facilities> <components> ... <!-- Service behavior --> <component id="UnitOfWorkBehavior" type="WindsorService.Wcf.UnitOfWorkBehavior, WindsorService"/> ... </components>

We're almost done. As I also mentioned in my previous post, I have this wrapper class for Castle Windsor named DependencyContainer. The last thing we need to do is register the Windsor container for the WCF integration facility:

public DependencyContainer() { _windsorContainer = new WindsorContainer( new XmlInterpreter()); // For Windsor WCF facility DefaultServiceHostFactory .RegisterContainer(_windsorContainer.Kernel); // For Rhino Commons IoC.Initialize(_windsorContainer); }

An instance of the DependencyContainer is now created in the Global.ApplicationStart method:

public class Global : HttpApplication { private IDependencyContainer _dependencyContainer; protected void Application_Start(object sender, EventArgs e) { _dependencyContainer = new DependencyContainer(); } protected void Application_End(object sender, EventArgs e) { _dependencyContainer.Dispose(); _dependencyContainer = null; } }

Voila, no rocket science there either. We're done. What are we exactly gaining here? The biggest benefit is that we can now add WCF behaviors for other concerns, like exception handling, logging, transactions, etc. by just adding them to the Windsor configuration file.

Now, to round off this post I want to show the usage of the Repository library that can also be found in the Rhino Tools Library. The following needs to be added to the Windsor configuration file:

<!-- Rhino commons --> <component id="nhibernate.repository" service ="Rhino.Commons.IRepository`1, Rhino.Commons.NHibernate" type="Rhino.Commons.NHRepository`1, Rhino.Commons.NHibernate"/> <component id="nhibernate.unit-of-work.factory" service ="Rhino.Commons.IUnitOfWorkFactory, Rhino.Commons.NHibernate" type="Rhino.Commons.NHibernateUnitOfWorkFactory, Rhino.Commons.NHibernate"> <parameters> <configurationFileName>web.config</configurationFileName> </parameters> </component>

Now we can use the Repository class like so:

public IEnumerable<Customer> GetAll() { return Repository<Customer>.FindAll( DetachedCriteria.For(typeof(Customer)) .SetFetchMode("Orders", FetchMode.Eager)); } public Customer GetFor(String code) { return Repository<Customer>.Get(code); }

These repositories even have support for fetching strategies, which is actually pretty neat.

I'm happy to hear some feedback on this.

Till next time,

Saturday, July 12, 2008

Book review: Code Leader - Using People, Tools and Processes to Build Successful Software

Code Leader Like Karl Seguin's most excellent book about the Foundations of the Programming (which is highly recommended), this book covers the basics that each programmer should live and breathe.

Software developers with only a couple of years of experience will benefit the most from this book. Patrick Cauldwell nicely introduces essential topics like Test-Driven Development, Continuous Integration, Source Control, Static Analysis, Design by Contract, Tracing, Error Handling, Dependency Injection and Inversion of Control, etc. ... . These are all practices that are applied by every self-respecting software development shop.

For example, the first chapter nicely discusses the much needed "Buy, Not Build" approach for those who think they can conquer the world by reinventing the wheel for the quintillionth time. Why build yet-another-date-picker-control if money can buy one that covers most of your needs? Why build yet-another-DI-container when there are so many of them out there? Seems like common sense, right?

Although I am practicing these basic things for quite some time now, I managed to get away with some things I hadn't though about before, like working out a policy for tracing, exception handling, etc ... that everyone on the team agrees upon.

Due to the fact that the book is only about 200 pages, the author only scratches the surface of all these topics. The one thing that I feel is missing from this book, is a comprehensive appendix chapter that provides resources for a more in depth view. This is much needed for those readers that are new to these topics and want to read more.

In conclusion, this book provides a nice introduction for those who are new to these essential development techniques. The how and why is nicely laid out. If you are already practicing these techniques, then this book is not for you.

Till next time

Friday, July 04, 2008

Dutch ALT.NET User Group

Yesterday, me, myself and Peter went to the first Dutch ALT.NET gathering. Besides being stuck in traffic for more than an hour, I had a great time. There were some great conversations going on and it was really empowering already. Make sure to read Yves's summary of the whole thing (only in Dutch). We talked about doing some small to medium-sized events in the near future, so stay tuned. Let the learning and  knowledge sharing begin!

Wednesday, July 02, 2008

Active Conventions with NDepend - Part Deux

I want to put out a short sequel to my previous post on Active Conventions with NDepend. Also make sure to read Patrick Smacchia's follow-up if your interested.

As you may or may not know, I'm a huge fan of using Test Data Builders for setting up the context for the domain objects in my BDD specifications.

[TestFixture] public class When_performing_something_action_with_an_order { [SetUp] public void Establish_context() { _order = new OrderBuilder() .WithCustomer(new CustomerBuilder() .WithFirstName("Homer") .WithLastName("Simpson")) .ForProduct(new ProductBuilder() .WithName("Saxomofoon")) } ... }

The biggest benefit of using the Builder pattern this way, is the fact that the creation of domain objects gets decoupled from the specifications itself. The constructor of a domain object gets called only at a single place in the code. If I wanted to add a new parameter to the constructor, I only have to change it in one place.

The following CQL statement ensures that the Test Data Builders are used instead of directly calling the constructors of the domain objects:

// <Name>Test data builders are not used by SetUp methods.</Name> WARN IF Count > 0 IN SELECT METHODS WHERE (HasAttribute "NUnit.Framework.SetUpAttribute" OR NameIs "Before_each_specification") AND ((IsDirectlyUsing "NAMESPACE:MyProject.Domain.Model" OR IsDirectlyUsing "NAMESPACE:MyProject.Domain.DTO") AND !IsDirectlyUsing "NAMESPACE:MyProject.Domain.UnitTests.Builders")

Although its probably not 100% foul proof, this CQL constraint detects the most blatant violations.

Till next time,

Jan, the NDepend addict.