Archive for November, 2011

Fresh Brewed Code

I mentioned in my post this morning that it was cross posted from Fresh Brewed Code, and I thought it would be good to introduce what's going on over there. Fresh Brewed Code is a blogging community started by several of my friends and myself. We've only been live for a few days, but there has already been a flurry of activity. Every single one of those guys is incredibly smart, you would be crazy not to point your feed reader that direction.

How does this affect this site? It really doesn't. I plan to post technical articles to both sites. This site will still be the home to all of my projects and announcements related to them. In addition, I'll still be blogging non-technical things here. If anything, I hope that joining a blog community will inspire me to write more here.

Convention Based Application Settings via Autofac

Cross posted from Fresh Brewed Code. A little more on that in a soon to be blog post.

A while back I stumbled on a blog post from Chad Myers about a cool feature of FubuCore around handling application configuration. It was one of those "duh, why didn't I think of this years ago" moments. You see, I've inherited an application which has a bunch of configurable options in the app.config. The code had already isolated those settings to classes with virtual members and a lot of calls to ConfigurationManager.AppSettings. It was testable by inheriting the settings class and overriding all of the properties. After seeing Chad's post though, I had to scrap it. POCO Settings -- yes please.

I've started a project to provide this functionality with Autofac. The project is still very new, currently I've only implemented sourcing settings via (app|web).config. I'm hoping to push in support for environment variables and the registry as sources for settings. Additionally I'm going to make the conventions easier to override since you might not like your classes ending in "Settings".

Let's go through some of the code and see how it all works together.

The coordinator for the whole shebang is the Autofac registration source:

public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor) {
    var s = service as IServiceWithType;
    if (s != null && s.ServiceType.IsClass && s.ServiceType.Name.EndsWith("Settings")) {
        yield return RegistrationBuilder.ForDelegate((c, p) => c.Resolve<ISettingsFactory>().Create(s.ServiceType))
            .As(s.ServiceType)
            .SingleInstance()
            .CreateRegistration();
    }
}

This looks for types to resolve whose name ends with "Settings". When it's time to actually create the type, we'll ask the container for a Settings Factory and tell it to create the type being asked for. Then we'll register that in the container as a singleton. Not too much going on there.

The Settings Factory is responsible for creating the settings object, polling each settings provider for values, setting the values and verifying that it's all good before shipping it off:

public class SettingsFactory : ISettingsFactory {
    readonly IEnumerable _providers;

    public SettingsFactory(IEnumerable<ISettingsProvider> providers) {
        _providers = providers;
    }

    public object Create(Type type) {
        var obj = Activator.CreateInstance(type);

        var propertiesMissed = PopulateProperties(type, obj);

        if (propertiesMissed.Any()) {
            var message = String.Format("{0} is missing the following properties in configuration: {1}", type.Name, String.Join(",", propertiesMissed));
            throw new ConfigurationErrorsException(message);
        }

        return obj;
    }

    List<string> PopulateProperties(Type type, object obj) {
        var propertiesMissed = new List<string>();

        var props = type
            .GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Where(p => p.CanWrite);

        foreach (var prop in props) {
            var value = _providers
                .Select(p => p.ProvideValueFor(type, prop.Name))
                .FirstOrDefault(p => p != null);
            if (value != null)
                prop.Set(obj, value);
            else
                propertiesMissed.Add(prop.Name);
        }
        return propertiesMissed;
    }
}

This class is where most of the work is happening. I'm not totally sold on the implementation, but it will do for now. Right now I'm just taking the first value I get which will prioritize the first registrations.

The last bit is an implementation of a Settings Provider. ConfiguraionManager.AppSettings is just a NameValueCollection, so that makes things stupid easy. The Name/Value Provider looks like this:

public class NameValueSettingsProvider : ISettingsProvider {
    private readonly NameValueCollection _source;

    public NameValueSettingsProvider(NameValueCollection source) {
        _source = source;
    }

    public object ProvideValueFor(Type type, string propertyName) {
        var key = type.Name + "." + propertyName;
        return _source[key];
    }
}

If we have a FooSettings class with a property Bar then we'd expect to see "FooSettings.Bar" as a key. Really easy, nothing to see here.

The Payoff
Now, let's see it all together. Here's the spec that shows everything in play:

class FooSettings {
    public string Bar { get; set; }
}

class NeedsSomeSettings {
    public NeedsSomeSettings(FooSettings settings){
        Settings = settings;
    }

    public FooSettings Settings { get; private set; }
}

public class when_resolving_a_class_that_depends_on_settings {
    static IContainer _container;
    static NeedsSomeSettings _needsomeSettings;

    Establish context = ()=> {
        var builder = new ContainerBuilder();
        builder.RegisterSource(new SettingsSource());
        builder.RegisterType<SettingsFactory>().AsImplementedInterfaces();
        builder.RegisterType<NameValueSettingsProvider>()
            .WithParameter("source", new NameValueCollection() {{"FooSettings.Bar", "w00t!"}})
            .AsImplementedInterfaces();
        builder.RegisterType<NeedsSomeSettings>().AsSelf();
        _container = builder.Build();
    };

    Because of = () => _needsomeSettings = _container.Resolve<NeedsSomeSettings>();

    It should_resolve_type = () => _needsomeSettings.ShouldNotBeNull();
    It should_have_settings = () => _needsomeSettings.Settings.ShouldNotBeNull();
    It should_have_settings_populated = () => _needsomeSettings.Settings.Bar.ShouldEqual("w00t!");
}

No more mucking around with problematic configuration. Just take a dependency on your POCO settings and off you go. If you forget to configure something you get a friendly error message. Like I said, there are bits of the API I'm not toally sold on and I have few more sources to implement. I also need to add a proper Autofac module to hide a lot of the registration noise.

So far I'm liking this a lot better than having random references to ConfigurationManager.AppSettings littered throughout the code. What do you think? Follow along on github and let me know what you like or hate.

Open Source

I had the opportunity to sit on a panel at the Nashville .NET user group tonight on developer careers. The goal was to open the floor and try to help tear down some walls between developers and recruiters. On the panel were several recruiters from our local area to represent that side. I got to sit up there with Elijah Manor and Derek Greer to represent the developers. Overall I think it was a good experience to let everyone ask some questions.

I was there to represent how I feel about developers contributing to open source projects. It's late, but I want to get my thoughts down in writing before sleep washes them away.

Contributing to open source software has had a positive impact on my career. I really haven't really contributed anything major, but my point tonight wasn't that you need to go out and write the next big thing. You see, there are gaps and voids all around us. Everyone is capable of finding something that needs to exist and creating it. I've benefited so much from open source software, it's only fair I give back.

There was a lot of apprehension for me leading up to pulling the trigger on my first project. Should I put it out in the open? Will anyone find it useful? Are people going to ridicule me on how crappy my code is? The answer to those questions turned out to be yes, yes and sometimes. When I put my stuff out there for people to see, I got feedback (both good and bad) and I was able to iterate on my project and make it better. Any feedback you get is a good thing because that means people care at least a little. It was really a learning experience to see how people use the thing you've created.

To potential employers getting a product "out there" means a few key things:

  • You care enough about something to take initiative  and make it a reality.
  • You are capable of finishing something you started.
  • You are detailed. There is a big difference between a proof of concept and live production ready code. A polished project has been tested and documented.
  • You love what you do so much that you used your own free time to improve yourself.
If you are a developer reading this I can only encourage you to open yourself up and throw some code to the wild. Writing some code that gets used is a very rewarding experience. You WILL get criticized by some, even if what you made is the best thing ever. None of that matters though, because you did something that you liked and shared it with others. Take that feedback and make your project better. I guarantee it will make you better.