Josh on Los Techies#

I've started posting updates at Joshua Flanagan on the Los Techies community site. If you are subscribed to my feedburner RSS feed, you should already be getting the new content. If not, update your reader to http://feeds.feedburner.com/JoshuaFlanagan

Wednesday, September 10, 2008 9:21:53 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Sample Opinionated Controller#

In my post on testing opinionated controllers, I mentioned how our controller actions follow a strict convention: one view model object in, one view model object out, and leave the ViewResult creation to the ControllerActionInvoker. Jimmy Bogard asked me to post the controller base class that makes this work. The implementation that we use is too involved to post as a sample, but I was able to create a "pseudo-code" version that demonstrates the ideas. I call it pseudo-code because it is just enough to demonstrate the concept, but it is nowhere near production code. It doesn't account for any edge cases, or really any other case than the single one I tested.

To be clear, neither this, nor the code in my previous post, is straight out of our source tree. It is more "inspired by" as opposed to an accurate representation of our actual code.

The code below shows:

  • OpinionatedController - all of your controllers should derive from this class. Each controller action should take in one view model (DTO) object and return a view model (that optionallyl derives from ResponseViewModel)
  • OpinionatedActionInvoker - does the real work of building the input parameter instance for the controller action, and then creating the default ViewResult from the output. This can very likely cleaned up by taking advantage of the IModelBinder interface in Preview 5 (see ScottGu's post)
  • ResponseViewModel - a base class for action return values for when you want to perform an ActionResult other than ViewResult
public class OpinionatedController : Controller { public OpinionatedController() { ActionInvoker = new OpionatedActionInvoker(); } public class OpionatedActionInvoker : ControllerActionInvoker { protected override object GetParameterValue(ParameterInfo parameterInfo) { var parameterType = parameterInfo.ParameterType; if (parameterType.IsPrimitive) { return getValueFromInput(parameterInfo.Name, parameterType); } var complexActionParameter = Activator.CreateInstance(parameterType); foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(complexActionParameter)) { object propertyValue = getValueFromInput(descriptor.Name, descriptor.PropertyType); if (propertyValue != null) { descriptor.SetValue(complexActionParameter, propertyValue); } } return complexActionParameter; } private object getValueFromInput(string parameterName, Type parameterType) { object propertyValue; ControllerContext.RouteData.Values.TryGetValue(parameterName, out propertyValue); if (propertyValue == null) { propertyValue = ControllerContext.HttpContext.Request.Params[parameterName]; } return TypeDescriptor.GetConverter(parameterType).ConvertFrom(propertyValue); } protected override ActionResult InvokeActionMethod(MethodInfo methodInfo, System.Collections.Generic.IDictionary<string, object> parameters) { object[] actionMethodParams = new object[0]; if (methodInfo.GetParameters().Length > 0) { actionMethodParams = new[] { parameters.Values.ElementAtOrDefault(0) }; } var viewModel = methodInfo.Invoke(ControllerContext.Controller, actionMethodParams); var responseViewModel = viewModel as ResponseViewModel; if (responseViewModel != null && responseViewModel.OverrideResult != null) { return responseViewModel.OverrideResult; } return new ViewResult { ViewData = new ViewDataDictionary { Model = viewModel } }; } } } public class ResponseViewModel { public ActionResult OverrideResult { get; set; } }

I created a solution that I used for testing all of this, to prove it works. It is the adaptation of the codecampserver SpeakerController that I used for my previous post. There is probably a lot of cruft and aborted experiments in there that you can safely ignore. To see it all work, run the website and go the url: /austincodecamp/speakers?displaypage=2&displaypagecount=15 (substituting different values for the code camp name and display page stuff to prove it isn't hardcoded). Download the solution (built with VS2008 and ASP.NET MVC Preview 5)

Tuesday, September 02, 2008 10:07:58 PM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

Testing with Opinionated ASP.NET MVC#

Before joining them at Dovetail, I had heard Chad and Jeremy talk over lunch of how they were building their product with Microsoft's ASP.NET MVC. While all of the published literature still left me with questions on how to best handle URLs or test drive controller actions, they spoke of it as a solved problem. They'd say they were using MVC in a very "opinionated" way by hiding or replacing most of the underlying framework. They spoke of "one in, one out" state based testing, invocation registries, yada yada yada, but I couldn't really grasp the impact without seeing the code. Since they haven't yet published any of their work, I figured I'd kick it off with a post about our controller action tests. If you are interested in more details, let us know, and I'm sure one of us can get a few more blog posts out of it. Even better, come talk to us at the Continuous Improvement in .NET Software Development conference.

Have an opinion

The concepts of "opinionated frameworks" and "convention over configuration" have gained a large following from people rejecting the tedious and noisy declarative code typically associated with shaping a one-size-fits-all framework. Regardless of whether you are trudging through XML, or using a fancier programmatic fluent interface, having to repeatedly "state the obvious" in your code will cloud its true intentions and slow you down. Where a one-size-fits-all framework says "we can't make that assumption, because the developer may want to do x, y, or z", the opinionated framework says "we're going to make some assumptions that fit the most common scenarios, and the developer should bend their design to fit those assumptions" (although the good ones will always allow you to deal with edge cases through some sort of overriding mechanism).

I was reminded of this today when reading Phil Haack's post on How a Method Becomes an Action. He made the side remark: "This is one reason you’ve seen the MVC team resistant to including helper methods, such as Url<T>(…), that use an expression to define the URL of an action. The action is not necessarily equivalent to a method on the class with the same name". Its probably a wise move that the Microsoft MVC team is not embedding "opinions" in such a young platform that hasn't had enough real-world usage to drive out the common scenarios. However, within the confines of an individual development team, you can get a lot of value by using the underlying framework in a more opinionated way. By simply deciding, "an action name IS necessarily equivalent to a method name on a controller class", you can safely use a compiler-checked UrlFor<ProductsController>( c=>c.Edit ) helper method throughout your codebase.

Our opinion on controller actions

At Dovetail, we have simplified our development and testing of controller actions by codifying our opinions and conventions. For example:

  • All controller actions have a single input parameter. All of the data provided by the client that is needed by the action is exposed as properties on this view model object.
  • All controller actions return a single view model object that contains all of the data needed to render the view.
  • Specifically, actions do NOT return instances of ActionResult. Since a large majority of actions display a view, we move the ViewResult creation into the ControllerActionInvoker. We include a mechanism for actions to override this behavior and return a specific ActionResult when needed.

By adhering to these conventions, we get a lot of commonality in our tests that we can pull up into a base class. The individual tests themselves become much easier to write, and much clearer to read, in my opinion. As a point of comparison, I'll take an example from codecampserver, an open source application used to teach concepts with ASP.NET MVC. Let's look at the codecampserver tests for the List action on the SpeakerController (see the original at SpeakerControllerTester):

[Test] public void ShouldListSpeakersForAConference() { var p = new Person("joe", "dimaggio", "jd@baseball.com"); var p2 = new Person("marilyn", "monroe", "m@m.com"); _conference.AddSpeaker(p, "joedimaggio", "bio here...", "avatar.jpg"); _conference.AddSpeaker(p2, "marilynmonroe", "bio here...", "avatar.jpg"); using (_mocks.Record()) { SetupResult.For(_conferenceRepository.GetConferenceByKey("austincodecamp2008")) .IgnoreArguments() .Return(_conference); } using (_mocks.Playback()) { SpeakerController controller = createSpeakerController(); var actionResult = controller.List("austinCodeCamp2008", 0, 0) as ViewResult; Assert.That(actionResult, Is.Not.Null); Assert.That(actionResult.ViewName, Is.Null, "expected default view"); var speakersPassedtoView = controller.ViewData.Get<Speaker[]>(); Assert.That(speakersPassedtoView, Is.Not.Null); Assert.That(speakersPassedtoView.Length, Is.EqualTo(2)); } }

Using a test base class built around our conventions we can specify the same behavior with:

[TestFixture] public class When_listing_the_speakers : ControllerActionTest<SpeakerController, SpeakerListRequest, SpeakerListViewModel> { public When_listing_the_speakers() : base((c, input) => c.List(input)) { } protected override void underTheseConditions() { Conference conference = new Conference("austincodecamp2008", "Austin Code Camp"); var p = new Person("joe", "dimaggio", "jd@baseball.com"); var p2 = new Person("marilyn", "monroe", "m@m.com"); conference.AddSpeaker(p, "joedimaggio", "bio here...", "avatar.jpg"); conference.AddSpeaker(p2, "marilynmonroe", "bio here...", "avatar.jpg"); Input = new SpeakerListRequest { ConferenceKey = "austincodecamp2008" }; GivenThat<IConferenceRepository, Conference>(r => r.GetConferenceByKey(null)).IgnoreArguments().Return(conference); } [Test] public void Should_display_the_default_view() { Output.Override.ShouldBeNull(); } [Test] public void Should_provide_the_speakers_related_to_the_conference() { Output.Speakers.ShouldNotBeNull(); Output.Speakers.Length.ShouldEqual(2); } }

As you can see, the assertions are more easily broken out into individual tests. The test methods themselves are very simple, usually consisting of just the assertions on the output. You could also test slightly different scenarios by making changes to the Input property within your test method. I know some people don't like to use a test base class, but I think those objections stem from the idea that they don't want to hide the details of a test. However, in our case, since all of our controller action tests can use the same base class, it can simply be considered part of our test runner infrastructure. Once its functionality is understood for one test, you understand how it works with all of the other tests, unlike if you had to create one-off test base classes for each action or scenario.

In case it isn't clear what is going on here:

  • The controller under test, and the type of the action's input parameter and return value are specified as generic parameters on the ControllerActionTest base class.
  • The method being tested is declared via the lambda passed to the base class's constructor.
  • The controller under test is created in the base class's [SetUp] method using StructureMap's RhinoAutoMocker.
  • The underTheseConditions method is called as part of the [SetUp] method on the base class.
  • Input and Output are properties on the base class that hold an instance of the input parameter and return value types, respectively.
  • GivenThat() is a method on the base class which stubs behavior using Rhino Mocks.
  • The Should*() methods used on the Output properties perform NUnit assertions under the hood, care of Scott Bellware's specification extensions
Monday, September 01, 2008 10:47:35 PM (Central Daylight Time, UTC-05:00) #    Comments [2]  | 

 

Hello StructureMap#

In a comment on Derik Whittaker's post about using app.config with StructureMap, Brian Johnston asks for a simple "hello world" example. I figured I could re-create the app that I used when I was first learning StructureMap. This is a very simple demonstration of how to make an application use StructureMap. It does not get into the whys and whens for different scenarios. It is simply a piece of code that will let you see StructureMap "work" so that you can play with it. For more introductory details, I would highly recommend reading Chad Myers' posts that cover Basic and Medium-level usage scenarios for StructureMap.

Create the app

  1. Open Visual Studio
  2. Go to File | New | Console Application (hopefully you have Tools | Options | Projects and Solutions | "Save new projects when created" UNCHECKED so you aren't forced to choose a path for this throwaway code)
  3. Add a reference to StructureMap.dll (agonize over how slow the Add Reference dialog box is to open because it needs to populate the list on the .NET tab which will go unused when we switch to the Browse tab)
  4. Replace the contents of Program.cs with the code at the bottom of this post
  5. Run the application to see the English greeting.

Notes

  • The call to ObjectFactory.GetInstance in the Main method demonstrates how you get an object from StructureMap. Notice that it only specifies the interface for the type you'd like to retrieve so the caller is decoupled from the actual implementation that is used.
  • The ConfigureDependencies method is where I tell StructureMap which concrete implementations I would like to use for my interfaces. You can accomplish this same goal by decorating your interfaces and classes with attributes, or by using a configuration file.
  • Aside from the two bullet items above in the Program class, none of the rest of the code has any reference to or knowledge of StructureMap.
  • Notice that I only ever ask for an IAppEngine. I never had to explicitly ask for an IGreeter or IOutputDisplay. StructureMap was smart enough to recognize these dependencies of AppEngine and injected them automatically.
  • Change the second line in ConfigureDependencies so that TheDefaultIsConcreteType<FrenchGreeter> and run the application again. Notice that you now see the French greeting. You have changed the implementation that is used by AppEngine, without changing any of the application code (if you agree that the Program class is just your launching point, and not really part of the application logic). If you were using a config file to configure StructureMap, you wouldn't have had to change any code at all to see the different behavior.

Code

Update: I've created a gist that shows the original example, but using the cleaner syntax introduced in more recent versions of StructureMap.

The original code from this post that used older StructureMap syntax:

using System; using StructureMap; namespace ConsoleApplication1 { class Program { private static void Main(string[] args) { ConfigureDependencies(); IAppEngine appEngine = ObjectFactory.GetInstance<IAppEngine>(); appEngine.Run(); } private static void ConfigureDependencies() { StructureMapConfiguration.ForRequestedType<IAppEngine>().TheDefaultIsConcreteType<AppEngine>(); StructureMapConfiguration.ForRequestedType<IGreeter>().TheDefaultIsConcreteType<EnglishGreeter>(); StructureMapConfiguration.ForRequestedType<IOutputDisplay>().TheDefaultIsConcreteType<ConsoleOutputDisplay>(); } } public class AppEngine : IAppEngine { private readonly IGreeter greeter; private readonly IOutputDisplay outputDisplay; public AppEngine(IGreeter greeter, IOutputDisplay outputDisplay) { this.greeter = greeter; this.outputDisplay = outputDisplay; } public void Run() { outputDisplay.Show(greeter.GetGreeting()); } } public interface IAppEngine { void Run(); } public interface IGreeter { string GetGreeting(); } public class EnglishGreeter : IGreeter { public string GetGreeting() { return "Hello"; } } public class FrenchGreeter : IGreeter { public string GetGreeting() { return "Bonjour"; } } public interface IOutputDisplay { void Show(string message); } public class ConsoleOutputDisplay : IOutputDisplay { public void Show(string message) { Console.WriteLine(message); } } }
Friday, July 25, 2008 9:11:05 AM (Central Daylight Time, UTC-05:00) #    Comments [3]  | 

 

Losing your (type) religion#

As I stated in my last post, the var keyword is an acknowledgement that I do not care what the type of the variable is - I only care what it can do.

Into the IUknown

Most developer start on the path to this revelation when they discover interface-based programming.

Consider: we need to write a method that returns a collection of strings. Callers of the method will only need to loop over the items and perform some action. The number of elements to return is not known at compile time, so we'll declare a generic List<string>, populate it within a loop, and then return it to the caller.

The junior developer will declare the return type of the method as List<string>:

List<string> GetNames(){}

Acknowledging that callers should not be bothered with having to know an implementation detail (the fact that a List was used instead of a fixed-sized array), and knowing that they only need to loop over the returned items, a more experienced developer might declare the method:

IEnumerable<string> GetNames() {}

Which means any variable the receives the return value will also be typed as IEnumerable<string>:

IEnumerable<string> names = GetNames();

Here's the kicker - in both scenarios, the GetNames method is really returning an object of type List<string>! When the supposedly more experienced developer chooses to return a more abstract type like IEnumerable<string>, type information is lost. Yikes! The names local variable above holds a List<string> instance, but you (the client developer) don't know it. As scary as that might sound, you probably realize that you don't care. As long as you can do the things you need to do with names (loop over it), you are happy.

Walking like a duck

Now let's take that train of thought and consider duck typing in a dynamic language like Python. I can declare the following method:

def Recycle(service):
    service.Stop()
    service.Start()

It takes a single parameter named service. What is the type of the parameter that is expected? I don't know. And after the initial anxiety settles, there is the liberating realization that I don't have to care! All I know, or care, is that any object instance that is passed to this method must implement a Start() and a Stop() method. The same method can be used with instances of a Lawnmower, AuditLogger, or SongPlayer class (assuming they all have Start and Stop methods).

Getting closer to the goal

Let me be clear - I am not suggesting that implicit typing in C# 3.0 is the same as duck typing. What I am suggesting is that the 2 examples above are points along the "progression of understanding" of the same concept: it is the behavior of an object that really matters, as opposed to the type name that is attached to it. Interface-based programming is near the start. Implicit typing is further along the progression. Duck typing is closer to the end.

I think we will find that programmers who have been exposed to and understand languages which support duck typing will be more likely to be comfortable with and embrace the var keyword. They have already made the mental leap that type information serves the computer more than it serves the human. If you haven't yet, do yourself a favor and learn a dynamic programming language, even if you know you will continue to spend your days with static typing.

Wednesday, June 25, 2008 2:05:02 AM (Central Daylight Time, UTC-05:00) #    Comments [0]  | 

 

All content © 2012, josh
About this site
Send mail to the author(s) Contact me
Feed your aggregator (RSS 2.0)
Joshua Flanagan
I am a software developer focused on continuous improvement in the .NET community
Los Techies

On this page
Archives
Rest of the world

Acknowledgements

Powered by: newtelligence dasBlog 2.1.8209.14743

Special thanks to LosTechies.com

Site theme based on the essence design by Jelle Druyts

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.