Entries
RSS 2.0

Comments
RSS 2.0

Convenience Kills, or the Case Against RAD Tools

A rather heated discussion erupted last week on Twitter and IRC concerning so-called “drag-and-drop demos” — point-and-click demonstrations of “software development” that just involve dragging controls around on a graphical designer without a lot of actual coding involved. Being entirely unable to resist joining in on debates, I had to chime in and give my two cents.

At root, drag-and-drop (D&D) demos are really nothing more than a marketing tool, and they do little to illustrate the actual way software is written. It’s kind of like the scene in Swordfish where the main character is “programming,” but all the audience actually sees is a spinning cube with nodes flying on and off. Why? Because real software development isn’t interesting in the least to a layperson. Real software development means hammering away on a keyboard for hours, drawing squiggly boxes on a whiteboard, and debating design with your team. People with passion for software relish this process, but if you don’t understand what you’re looking at, I imagine watching it would be pretty mind-numbing.

This is also why programming, sadly, will never be an Olympic sport, nor will we tune in on Sundays to National Software League competitions. :)

D&D demos, on the other hand, provide visual indicators and guides which allow people with any level of technical skill to understand the basic process. However, any software developer will tell you that drag-and-drop tools fall very far on the 80% side of the 80/20 rule — the second you try to do something more complex (read: useful), you have to write code.

This is why D&D demonstrations are actually extremely dangerous. They only serve to blow smoke up the asses of non-technical people, and convince them that software development is easier than it actually is. For example, let’s say a non-technical manager sees a demonstration of ASP.NET WebForms, with a data-bound grid control. It can become very difficult to convince them that, in order to support our actual requirements, we need to create a real domain model, and write the HTML directly so we can get better support for CSS, and write some tests so we can make sure it actually does what we claim. None of that was in the product demonstration, so it’s not surprising that non-technical people balk at estimates that include more of the nitty-gritty tasks.

I’ll take this argument a step further, also, and say that all tools geared around RAD (rapid application development) are harmful when considered out of context. Microsoft in particular has had a long-standing obsession with RAD, and you can see it in many of the graphical features of Visual Studio. Since the vast majority of the work on software is maintenance and extensibility, rapid development is the antithesis of good software design. If tool vendors were really interested in making software developers’ lives easier, they would focus more on providing features to maintain software rather than develop it quickly and shove it out the door. That’s why refactoring tools like ReSharper have become so popular — their entire focus is on making it easy to mold your code into a useful application.

However, vendors are in business to make money, and RAD tools are much easier to sell than tools for refactoring. You can only sell a refactoring tool to someone that understands code, but you can sell a RAD tool to anyone — “look how fast we wrote this useful application!” I’m not faulting Microsoft or other vendors for wanting to make money, and I’m not saying that drag-and-drop tools are never useful. If you’re writing disposable code, that you’re certain you’re going to throw away, there’s nothing wrong with slamming something quick and dirty out. If you’re writing something for keeps, though, you better spend at least a few cycles thinking about how to make it maintainable.

Writing software is all about managing change. You start by building a core, and then you start building layers on top of it. With each added feature, you are applying changes to the application as a whole. This is why most of the tenets of good software design focus on limiting the impact of change on your system as a whole — or maximizing orthogonality, if you prefer. This is true throughout the software’s life, both before and after the initial release (the only real difference being the risk associated with adding each change).

Real software design cannot be drag-and-drop, because it’s an organic process, where your code is molded, sculpted, and cultivated over time. I commonly refer to malleable software, which evokes the right idea — flexible software that can be molded into something that solves your business problem. I would argue that there will never be a visual design tool that is more effective long-term than writing code manually, or at least not in the foreseeable future.

The bottom line is that the more you can limit the impact of change, the more easily you can mold and sculpt your software. The idea of RAD and drag-and-drop tools are only smoke and mirrors that mask the real difficulties that go into creating good software.

ALT.NET Podcast on IoC and DI

I’m a few days late on this, but I participated in the latest episode of the ALT.NET Podcast. In it, Brad Wilson, Mike Moore, and I talk about inversion of control and dependency injection and how it can help you write better software. I had a great time recording it, and I thought it was a good conversation. Major thanks to Mike for organizing the podcast and inviting me to participate, and to Brad for not showing me up big time and making me look like a complete dunce. ;)

Part two is coming soon now available, where we get into other fun things like inversion of control with dynamic languages, and Microsoft’s relationship with the open source community.

Playing Nice With Service Locators

When I introduce dependency injection to developers, I often receive the complaint that it’s not significantly better than the service locator pattern. The main disadvantage of a service locator is that you’re required to couple all of the services in your application to the service locator in order for them to resolve their dependencies. By using a DI framework instead, you can keep your services very loosely-coupled.

However, there are some advantages of the service locator pattern. In particular, it’s much easier to implement hybrid activation — when some of the values in a constructor are provided by the consuming code, and some are provided by the framework. Hybrid activation is common in situations where you don’t need (or want) your DI framework to control the instantiation behavior of the type, but you still want to be able to resolve dependencies that are required for the instance.

In Ninject, hybrid activation is possible through the use of context parameters, which allow you to provide values for specific constructor arguments when you request the instance. However, context parameters can only be used for active requests — that is, calls to the kernel’s Get() method. If you often call Get() on the kernel, you’re using it as a service locator anyway.

The reality is, there’s nothing inherently wrong with using a service locator — when used in the right way, it can greatly simplify your code. I don’t think that service locator and dependency injection are mutually exclusive; in fact, I’ve found that it can actually be very effective when used in conjunction with a dependency injection framework like Ninject.

For example, let’s say you have an EventWatcher service that listens for a named event on an IMessageBroker, reads event information from the message, and triggers a specified callback. The implementation of such a service might look like this:


public class EventWatcher<T> {
  public EventWatcher(string eventName, Action<T> callback, IMessageBroker messageBroker) {
    //...
  }
}

You can’t easily activate a service like this using the Ninject kernel (at least without using context parameters), since the first two constructor arguments have to be supplied from the consuming code, and only the third is actually a dependency that should be activated via the kernel.

However, let’s introduce a simple service locator, which just delegates activation requests to a Ninject kernel:


public static class ServiceLocator {
  private static IKernel _kernel;
  public static void Initialize(IKernel kernel) {
    _kernel = kernel;
  }
  public static T Get<T>() {
    return _kernel.Get<T>();
  }
  public static object Get(Type type) {
    return _kernel.Get(type);
  }
}

Then, when we initially create our kernel, we just have to pass it to the Initialize() method of the ServiceLocator:


public static class Program {
  public static void Main() {
    using (var kernel = new StandardKernel(...)) {
      ServiceLocator.Initialize(kernel);
      //...
    }
  }
}

Using the service locator, we can alter our implementation of EventWatcher to make it easy to pass in the event name and callback method arguments, while still leaving it flexible enough to swap out the implementation of IMessageBroker. This is particularly useful for testability, since you can easily swap in a mock implementation of IMessageBroker in your tests.


public class EventWatcher<T> {
  public EventWatcher(string eventName, Action<T> callback)
    : this(eventName, callback, ServiceLocator.Get<IMessageBroker>())
  { }
  [Inject]
  public EventWatcher(string eventName, Action<T> callback, IMessageBroker messageBroker) {
    //...
  }
}

As you can see, if the more limited constructor is called, the EventWatcher asks the ServiceLocator to resolve the instance that should be used. Notice also that I’ve still kept the [Inject] attribute on the second constructor, in case you want to activate the type using the kernel and context variables.

While this is a useful technique in limited use, it’s important to be careful how much you rely on it. Remember that every time you use a service locator instead of dependency injection, you’re coupling your type to the service locator — and since it’s a static method call, it’s coupled just about as tightly as you can get. Again, though, taken in small doses, this technique can actually simplify your code and make it much more flexible.

Ninject Featured in InfoQ

Rob Bazinet, an editor for InfoQ, was kind enough to interview me about Ninject for the 1.0 release! Check out the article if you’d like to read more about the ideas behind Ninject and what went into its creation.

Attributes? We Don’t Need No Stinkin’ Attributes

Ninject will reach 1.0 later this month. As the project has gained traction, I’ve received a common complaint concerning the use of the [Inject] attribute to decorate dependencies. Ninject was originally designed to match my own tastes, and I don’t personally mind the attribute in this case. The common argument against attributes is that it hurts the readability of your code, but I would suggest that in this case it actually improves its readability by making it more declarative. At a minimum, it says “this value comes from somewhere special,” so even if there are other developers working with your codebase that don’t entirely understand dependency injection, the use of [Inject] is enough to get them asking questions.

However, while I would consider Ninject to be opinionated software, I also want to make sure it’s useful to people with differing tastes, as long as I can do so without sacrificing the common case. To that end, I’ve been working to make it easier to dodge the attribute requirement. There are actually four different ways of avoiding the use of [Inject], depending on the level of control you want over your codebase. Note that this article describes features available in the subverison trunk, which will become version 1.0 with very few modifications, but most are not available in RC1. However, I do my utmost to make sure that the trunk build of Ninject remains stable, and I am currently using it in production applications without trouble.

1. Use Automatic Constructor Injection

The first, and easiest way to avoid the attribute is to use automatic constructor injection. If a type only has a single constructor, Ninject will attempt to inject it regardless of whether or not it is decorated with an [Inject] attribute. Therefore, if you’re willing to accept the limitation of only using constructor injection, you can avoid using [Inject] anywhere in your code.

2. Use a Custom Injection Attribute

If it’s not the requirement of the attribute that bothers you, but the fact that it means you have to have a dependency on Ninject.Core throughout your code, you can customize the attribute that Ninject will look for to inject dependencies. This is done via KernelOptions. For example:


public class MyInjectAttribute : Attribute {}

public static class Program {
  public static void Main() {
    var options = new KernelOptions { InjectAttributeType = typeof(MyInjectAttribute) };
    var kernel = new StandardKernel(options, ...);
  }
}

Now, rather than decorating your dependencies with [Inject], you instead use [MyInject], and avoid the dependency on Ninject.Core. If you use optional dependencies, you can override the [Optional] attribute in this way as well.

3. Use the Auto-Wiring Extension

A recent addition to Ninject is Ninject.Extensions.AutoWiring, which provides a way to inject dependencies without ever needing to decorate them with attributes. Instead, which dependencies that are injected will be based on what bindings you register with the kernel. When a type is activated, Ninject will do the following things:

  1. It will find a constructor on the type whose parameters all have types for which bindings are registered. If there are multiple constructors available, it will select the one with the most parameters with bindings defined.
  2. Similar logic will be applied to methods — if the type defines methods whose parameters all have valid bindings defined, dependencies will be resolved for the arguments and the methods will be called.
  3. Finally, all properties and fields will be considered as well. If their types have bindings defined, they will be injected.

To use auto-wiring, you just need to load the AutoWiringModule into your kernel, and the extension re-wires the kernel components as necessary. A couple caveats:

  1. Auto-wiring does not work with implicit self-binding, so you will have to explicitly register self-bindings for all of your types to get Ninject to resolve them.
  2. As you might imagine, auto-wiring will slow down activation. However, it’s unlikely you’ll notice a change in performance unless you’re activating millions of instances via Ninject — and if you are, you might want to rethink your design. :)
4. Roll Your Own Heuristics

Ninject is designed to be ultra-customizable. The core is built around a collection of kernel components, which the kernel orchestrates in order to activate types, resolve dependencies, and do all the fun stuff that you’ve come to love from Ninject. My latest work leading up to 1.0 has been to adjust the model of Ninject to favor composition more over inheritance (a good design principle in general, by the way). Ninject ships with a collection of standard implementations of components, but you are free to remove them and replace them with your own custom implementations. Since most of the components are very granular, this is easier than it may seem… all you need to do is create a type that implements one of the components’ interfaces, and connect them to your kernel.

There are four components, called selection heuristics, that can be replaced to customize which members are chosen for injection. As you might imagine, they are:

  1. IConstructorHeuristic
  2. IPropertyHeuristic
  3. IMethodHeuristic
  4. IFieldHeuristic

You may replace any or all of these to take full control over which members are injected. If you’d like to see an example of how to implement your own selection heuristics, take a glance at the code for the auto-wiring extension. (All the extension does is plug in its own selection heuristics when you load the AutoWiringModule.)

As always, if you have questions about any of this, feel free email me at nkohari at gmail dot com or find me on Twitter, and I’d be happy to help!

Cleveland Day of .NET Aftermath

Yesterday, I presented at the first annual Cleveland Day of .NET in Beachwood, and it was a fantastic experience. I was able to meet some brilliant people — although at times it was a little surreal, since I already “knew” them from Twitter and it was like I was meeting them all over again. The presentations that I attended were all excellent, and the conversations in the hallways and at lunch and dinner were even better.

Off the top of my head, it was great to meet: Dan Hounshell, Alan Stevens, Joe Fiorini, Mike Eaton, Leon Gersing, Sarah Dutkiewicz, John Stockton, Corey Haines, and Brian Prince. I know that I’ve forgotten some people from this list, and I’m sorry… the day was really a whirlwind, and my memory is horrible. If I’ve forgotten you, please post a comment or send me a tweet and I’ll make it right! Thanks very much to everyone involved in organizing, sponsoring, and attending the event.

For my first time presenting in front of a larger audience, I felt like it went pretty well. I was admittedly a little intimidated — although very excited — when it ended up being standing-room-only during my presentation. Thanks to everyone that came to watch me speak, and I hope you found it useful! Thanks also for the kind words and great feedback afterwards, and a special thanks to Alan Stevens for “refactoring” the projector when it decided to overheat halfway through. :D

Here are my slides, and you can also download them below:

As promised, a more complex code sample that illustrates some of the principles I discussed in the talk is available to download here. The code sample illustrates some of the more advanced uses of Ninject — stuff that I never could fit on a Keynote slide. I encourage you to tear it apart and get your hands dirty. The best way to learn the value of IoC is definitely to try it for yourself.

Slides (Keynote): designing-for-change.key.zip
Slides (PDF): designing-for-change.pdf.zip
Sample project: wargame.zip

Great IoC Presentation by Justin Etheredge

Justin Etheredge gave a great presentation on dependency injection and inversion of control last week at the Richmond Code Camp. It gives a very good introduction to DI, which is something that I’m going to try to tackle at the Cleveland Day of .NET in a few weeks. Plus, he uses Ninject in the examples and was kind enough to quote me in the presentation, so it’s got to be good, right? :)

Seriously, though, if you weren’t able to see the presentation, Justin’s posted the slides and related code samples on his blog. I highly recommend you check them out if you’re interested in learning more about dependency injection!

Come Hear Me Ramble

I will be speaking at the Cleveland Day of .NET on May 17th. If you’ve heard of this inversion of control and/or dependency injection stuff and would like to hear more, by all means come on up to sunny Cleveland! Here’s the abstract for my talk:

The old adage states that the only thing that remains constant is change, and nowhere is this more true than in software development. In this presentation, Nate Kohari describes how to apply the principles of inversion of control and dependency injection to create software that can adapt to changing requirements. Learn to break your monolithic app into loosely-coupled, highly-cohesive pieces… then glue them back together with an inversion of control container to create ultra-flexible code that you can bend to your will.

If you’ve never used dependency injection, this talk should prove to be a good introduction, and I’ll be happy to answer any and all questions. Or, if you’re already experienced with dependency injection, come see how Ninject can free you from the pain of XML!

Also, I’m still relatively new to public speaking, so there’s always the chance that I’ll completely choke and you can throw tomatoes. What’s more fun than that?

Announcing Ninject Contrib!

A few days ago, I accepted the first patch for Ninject, an NLog integration extension by Ivan Porto Carrero. Ivan subsequently created a couple other extensions for Ninject, and rather than put them directly into the main project, we decided to launch Ninject Contrib to collect contributions from the community.

If you’ve got any ideas for Ninject extensions, or if you come up with any examples that you’d like to share with the rest of Ninject users, feel free to post your idea in the Ninject developers group and I’ll set you up with commit access.

Major thanks to Ivan for his contributions, and his excellent ongoing series of Ninject-related articles!

Frameworks and the Break-Even Point

I read a good post by Joel Ross the other day. In the post, Joel implements a simple project using Castle Windsor to drive dependency injection. In one of the comments, Matt Blodgett says that it seems like it takes a lot of code to implement, and that the code isn’t pretty. Naturally, I figured I’d use this an opportunity to point out the advantages of Ninject’s fluent interface vs. XML configuration. :)

The way I see it, every framework library has a cost that you have to pay up-front in order to use the library in your code. This cost might be in a learning curve, a performance penalty, or the fact that you have to write some boilerplate code to make the library work its magic. Typically, the argument is that by paying this up-front cost, you get a benefit that’s significantly larger. This creates a break-even point, where you make up for the “debt” you paid to use the library, and start becoming more effective because of it. The best libraries are the ones that keep the up-front cost as low as possible, so you reach your break-even point faster. Libraries that accomplish this goal can be used in significantly smaller projects, because it becomes easier to justify the up-front cost if you know that you’re going to quickly begin to see benefits in terms of efficiency.

Ninject was written to support enterprise applications, but aims to treat small projects as first-class citizens. To that end, I’ve gone to great pains to try to keep things simple in simple situations, and mask any complexity required for advanced scenarios from everyday use. Here’s the same example that Joel presented, written with Ninject.

First, the User class:


public class User {
  public IServiceApi Service { get; private set; }
  public string UserName { get; private set; }

  [Inject]
  public User(string userName, IServiceApi service) {
    UserName = userName;
    Service = service;
  }

  public void SendMessageTo(string message) {
    Service.SendMessage(String.Format("@{0} - {1}", UserName, message));
  }
}

One caveat: I typically try not to combine service logic with my domain model, and so I wouldn’t put the IServiceApi dependency directly in the User class. Not that there’s anything wrong with this, but it means that you have to activate every User that you load in your application via the DI framework, and that can interfere with scalability. It also makes activating the User a little bit more difficult, as you’ll see below.

Next, rather than creating the XML configuration to wire up the components, we create a module, and bind the IServiceApi interface to the TwitterApi implementation:


public class TwitterModule : StandardModule {
  public override void Load() {
    Bind<iserviceApi>().To<twitterApi>();
  }
}

(You could also add a self-binding for User, but you don’t have to since it’s a concrete type.) Maybe it’s just me, but those 4 lines of code (complete with IntelliSense!) are much simpler than the 20 or so lines of XML. You’re using a big powerful IDE, so why not take advantage of it to set up your DI framework?

Lastly, we need to load the module into a kernel and activate our User. Because of our userName parameter, we need to do a “hybrid” activation by passing a transient parameter to the Get() method. (This is what I meant about separating the domain model from the service model. It lets you avoid things like this.)


public static class Program {
  public static void Main() {
    IKernel kernel = new StandardKernel(new TwitterModule());
    User user = kernel.Get<user>(
      With.Parameters.ConstructorArgument("userName", "RossCode")
    );
    user.SendMessageTo("test");
  }
}

You could also just make the User’s UserName property writable, and set it after activating the object.

Now, this is a pretty simple example, and I’d say we still haven’t reached the break-even point with Ninject. However, if we had a couple more services like IServiceApi, each implementation of which had its own dependencies, the power of DI would start to make itself apparent. For example, consider the following scenario:

1. Our TwitterApi depends on a TwitterWebService.
2. We add a JabberApi which depends on a JabberClient.
3. We add a SmtpApi which depends on a SmtpClient, which depends on an EmailMessageFactory.

Assuming JabberClient, SmtpClient, and EmailMessageFactory are all concrete types, your existing application could support all of these new features without adding anything new to your type bindings. (This is because Ninject will automatically create “self-binding” when it encounters concrete dependencies.) You could then easily flip between the different options by altering the binding between IServiceApi and one of your *Api classes. Also, since your module is executable code like anything else, you could make it more intelligent, reading configuration files, command line parameters, or even a database to determine which messaging service implementation should be used.

The flexibility that inversion of control brings to your application benefits you the first time you need to add additional features, or make changes on the fly. Sometimes it’s difficult to understand what the benefit is by reading example code, and it takes some time to get used to writing your code to work with DI. It’s well worth the up-front cost though!