Fickle Bits

You're doing it wrong.

Shame on Me

Someone decided to publicly criticize my example code in my previous post by saying that it was “bad.”  While I don’t agree with the nature of the criticism (my blog *does* have comments, you know) I totally agree with the message.  It was bad code.  I would never place that in a production application.

The intent of the post was to demonstrate some ajax techniques, not to talk about how to write testable, decoupled controllers.  I suppose that example code should come with a bit of a disclaimer that says “hey, we are doing this here for simplicity’s sake, but obviously you’d abstract this out.”  Ideally I would have commented out the entire flickr section, because it’s totally not important in the context of the example.

In light of this topic, here is how a perfectly testable PhotosController might be written:

`

1
public class PhotosController : Controller{private readonly IPhotoRepository _photoRepository;public PhotosController(IPhotoRepository photoRepository){_photoRepository = photoRepository;}[ControllerAction]public void Search(){RenderView("Search", new Photo[] { });}[ControllerAction]public void Find(string query, bool? ajax){ var photos = _photoRepository.SearchPhotos(query);ViewData["query"] = query;ViewData["photos"] = photos;if(ajax == true){RenderView("_images", photos);}else{RenderView("results");}}}
`

Here you can clearly see our dependency on IPhotoRepository.  This guy can be anything we want, from a Flickr implementation, google images implementation, a file system directory, or even (gasp) a TEST implementation for writing unit tests!

Here is the IPhotoRepository, that we are using in the example:

`

1
public interface IPhotoRepository{Photo[] SearchPhotos(string query);<p>asdf</p>}
`

This returns a Photo object (that I defined), which means whatever implementation you choose, you need to map to this object. This is a good thing because it removed my dependency on “FlickrPhoto” in the view itself.

Our FlickrPhotoRepository now looks like this:

`
1
public class FlickrPhotoRepository : IPhotoRepository{private readonly IConfigSource _ConfigSource;public FlickrPhotoRepository(IConfigSource configSource){_ConfigSource = configSource;}public Photo[] SearchPhotos(string query){var flickr = new Flickr(_ConfigSource.GetSetting("flickr.api.key"));var results = flickr.PhotosSearch(query, TagMode.AnyTag, query, 40, 1);var photos = new List<Photo>();foreach (var item in results.PhotoCollection){photos.Add(new Photo(item.SquareThumbnailUrl, item.Title, item.PhotoId));}return photos.ToArray();}}
`

Wait a minute! This class now has it’s own dependency on IConfigSource? Craziness! In our example code from before, I had accessed the Configuration singleton directly, which is punishable by hand-removal in Albonia. Thank goodness I don’t live there. Now this class is decoupled from the actual configuration implementation and it could really be coming from a text file or database (whatever you want).

Wiring all this up is easy.  You could do it via XML, but I chose to do it directly in code: `

1
private void InitializeWindsor(){_container = new WindsorContainer();_container.AddComponent("config-source", typeof(IConfigSource), typeof(AppDomainConfigSource));foreach(Type type in Assembly.GetExecutingAssembly().GetTypes()){ if(type.IsSubclassOf(typeof(Controller))){_container.AddComponent(type.Name, type);}}}
`

Also note that I’m using WindsorControllerFactory from MVCContrib, so now my controller can be created (and each of it’s dependencies ( and their dependencies (and their Dependencies)))… I think you get the idea.

And there you have it.  A perfectly decoupled and testable modification for my previous example code.  As you were….

Comments