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
| |
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
| |
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
| |
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
| |
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….