Entries
RSS 2.0

Comments
RSS 2.0

Generic Variance in C# 4.0

Although I’m not cool enough to actually go to PDC, I’ve been watching some of the things that have been announced. One of the things I’m most excited about is co- and contra-variance in generics, which is something that the CLR has lacked since generics were first introduced in 2.0. (Note: some of the examples on here are pulled from the excellent description of new features release by Microsoft.)

In versions of C# prior to 4.0, generics were invariant. For example, consider this simple type definition:


public class Foo<T>
{
  //...
}

Since the generic type parameter T was not constrained, the compiler understands that T should be treated as type object. That means that since a string is an object, a Foo<string> is functionally equivalent to a Foo<object>. However, because of generic invariance, ian instance of Foo<string> cannot be assigned to a variable of type Foo<object>.

C# 4.0 introduces the ability to declare covariant and contravariant generics. For example:


public class Foo<out T>
{
  //...
}

This class is covariant in T, meaning that if you create a Foo<string>, you can use it effectively as a Foo<object>, since a string is a subclass of object. The example given is the new IEnumerable<T> interface that comes with the BCL in C# 4.0:


public interface IEnumerable<out T> : IEnumerable
{
  IEnumerator<T> GetEnumerator();
}
public interface IEnumerator<out T> : IEnumerator
{
  bool MoveNext();
  T Current { get; }
}

Since these interfaces are covariant in T, an IEnumerable<string> can be used as an IEnumerable<object>. The same is true for List<T>, so you’ll be able to do this, which was previously impossible:


IList<string> strings = new List<string>();
IList<object> objects = strings;

Note, however, that you can only declare that your type is covariant for generic type parameters that appear in output positions — basically, return values.

Like the out keyword, you can also use the in keyword:


public interface IComparer<in T>
{
  int Compare(T left, T right);
}

This interface is contravariant in T, meaning that if you have an IComparer<object>, you can use it as though it was a IComparer<string>. Contravariance carries a similar restriction to covariance, in that contravariant type parameters can only be used in input positions (arguments) on the type.

I didn’t quite understand variance until I considered the changes to the Func delegate:


public delegate TResult Func<in TArg, out TResult>(TArg arg);

Func is contravariant in TArg, and covariant in TResult. For example, consider this (less-than-useful and slightly-contrived) method:


public string Convert(object obj)
{
  return obj.ToString();
}

With the new variance rules, I can do this:


Func<object, string> func1 = Convert;
Func<string, object> func2 = Convert;

Since the delegate is contravariant in TArg, I can pass in a string, since a string is an object. Since the delegate is covariant in TResult, I can use it in a situation where an object is expected as a result from the function.

This might seem a little overwhelming if you’re not a language geek like myself, but it basically means that things that seemed like they should work in previous versions (like the List<T> example above), now will just work. Eric Lippert also has a great series of posts about the topic.

If you’d like to tinker with C# 4.0 (and Visual Studio 2010), Microsoft has published a VPC image. Kudos to the C# and CLR teams for getting this stuff to work!

Be the Underdog

Last night, I watched my Cleveland Browns wipe the floor with the New York Giants. The Browns were 1-3, and if they didn’t win this game, their season was effectively over. The Giants, reigning Superbowl champions, came into the game undefeated at 5-0, and it wasn’t believed the Browns had a snowball’s chance in hell to win. In response, the Browns beat them by three touchdowns, without punting or turning the ball over once. They had their problems, but it was a night of complete dominance for Cleveland.

Even if you’re not interested in sports, there’s a lesson to be learned. The Browns came into the game as major underdogs, with nothing to lose. They used it to their advantage, and their gameplan became aggressive and creative. They successfully ran trick plays like reverses and direct snaps, and the only successful execution of the UFO defense that I’ve seen… well, ever. The Giants didn’t see it coming, and by the time it hit them, there was nothing they could do but sit on the sidelines with puzzled looks on their faces.

37signals suggests that when developing a product, you should choose an enemy to compare with. By recognizing what’s wrong with the competition, you can find a niche that you can fill.

I’d take it one step further and see yourself as David, and choose a Goliath to attack. Embrace your role as underdog, unleash your creativity, and hold nothing back. Even if you’re already the industry leader, don’t get cocky — choose the company with the second-largest market share, and attack.

Most importantly, don’t allow yourself to be constrained by the way your competition or the industry-at-large thinks. That’s where real innovation comes from.

Custom Selection Heuristics in Ninject

I haven’t blogged about Ninject for awhile, but that doesn’t mean that the project is entirely dormant. :) Version 1.5 will be coming out relatively soon, but I wanted to give a preview of a new feature that I think is pretty damn cool. It’s currently available in the Subversion trunk if you’d like to flex the bytes yourself.

Every dependency injection framework needs to have some sort of convention or marker to indicate dependencies — spots where the framework should resolve a value to inject. When I originally wrote Ninject, I made the decision to use [Inject] attributes as this marker. In fact, I still advocate the use of attributes to indicate dependencies, because I like the declarative nature. I’ve found that even if you don’t completely understand Ninject, or dependency injection in general, using attributes at least indicates that a value comes from somewhere. It can be a great conversation starter — something you put in your code that when another developer sees it, it makes them ask questions.

Anyhow, I’ve found that the reliance on attributes was a major turnoff to other people. Ninject has always been (and will remain) opinionated software, but I’ll always add flexibility as long as I’m not compromising the core goals of ease of use and efficiency. As a result, I’ve been building in more control over these selection heuristics — the conditions that Ninject uses to test members of a type to determine which should be considered injectable members. The first step of this was to create the auto wiring extension, which alters the heuristic to determine whether a binding exists for a given member’s type — and if so, it will inject it.

Ninject 1.5 builds on this idea by moving to a collection of heuristics rather than just one. Now, when Ninject examines a member on a type to determine if it should be injected, it evaluates all of the related heuristics, and if any of them match, the member will be injected. There are now also two levels of heuristics:

  1. Global heuristics: As the name suggests, these apply to all bindings. You set them directly on the newly-created IMemberSelector component.
  2. Binding-level heuristics: These are set directly on a specific binding, so you can set up your own conventions for a specific type.

When examining a member, the member is first tested with the global heuristics, and then with the binding-level heuristics for the binding that is being used to activate the instance.

Heuristics are specific to the type of member they inspect. The types of members that Ninject considers are constructors, properties, methods, and fields, and each has a matching type of heuristic. When a property is considered for injection, Ninject will only test it using all applicable IHeuristic<PropertyInfo>s, but won’t consider IHeuristic<ConstructorInfo>s, for example.

The easiest way to control heuristics en masse is by defining your own IMemberSelector. By default, Ninject uses the StandardMemberSelector, which registers heuristics that look for the [Inject] attribute on the members — or, if you’ve overridden the attribute via KernelOptions, it will examine that. However, if you prefer a more conventions-based approach, you can use the ConventionMemberSelector:


public class OurKillerAppMemberSelector : ConventionMemberSelector
{
  public override DeclareHeuristics()
  {
    InjectProperties(When.Property.Name.StartsWith("Foo"));
    InjectConstructors(When.Constructor.HasAttribute<MarkAttribute>());
    InjectMethods(m => m.Name.Length < 4);
  }
}

This will cause all properties beginning with Foo, and all constructors with the (fictional) [Mark] attribute to be injected. Methods with names less than 4 characters will also be injected, as as you can see, you can specify conditions using lambdas (predicates) instead of using the conditional infrastructure.

If you want finer-grained control over your selection heuristics, you can also declare them on individual bindings as I said before:


Bind<IService>().To<ServiceImpl>()
  .InjectConstructors(c => c.Arguments.Length == 1)
  .InjectMethods(When.Method.Name == "Prepare")
  .InjectProperties(p => p.Name.EndsWith("Service"))

In this situation, when Ninject activates an instance of ServiceImpl, it will call the constructor on the type declared with one argument. It will then call the method called Prepare (resolving values for each of the method’s arguments), and resolve and inject values into each property whose name ends in Service.

Hopefully now you can see why I’m so excited about the new selection heuristics in Ninject. Out of the box, Ninject will continue to rely on the [Inject] attribute for simplicity, but you now have an incredible amount of flexibility in setting up your application, your way.

Working from home

Today ended my sixth week working for Telligent. Like most of the other members of the product development team, I’m working remotely from home. It’s been a very interesting adjustment, and I figured I’d share my experiences.

First, the good stuff:

  1. You can control your working environment. For the first three weeks, I sat in an old cheapo Staples desk chair at my old uncomfortable desk, until I was able to barter with my wife to let me re-organize the office. I’m now sitting in a Herman Miller Mirra chair at a much more ergonomic desk from Ikea. I have a comfortable (cushioned) chair in my office where I can sit, relax, and think. I can play music through speakers without needing to worry about coworkers, and I can close my office door to talk on the phone, video-conference, or if it just gets too noisy. I’m a natural control freak when it comes to environment while I work, and after working in a “bullpen” environment (one big room without cubes), this is a huge improvement. Incidentally, if you’re wondering, yes, the Mirra is expensive, and I was skeptical too, but it’s worth every penny. It’s so comfortable that I actually look forward to sitting in it.
  2. You can’t beat the commute. I’ve been fortunate not to have to drive more than 35 minutes or so to work for any job I’ve held, but just knowing that I don’t have to get in the car and drive across town is a nice feeling. Not to mention the savings on gas is great, and I suspect that once the Ohio winter strikes, I’ll like the fact that I don’t have to leave the house even more! I’ve also found that my days seem longer, and once I get through the transition period I’m hoping to devote my newfound spare time to side projects like Ninject and Ideavine, as well as a couple of other things I have up my sleeve. Who knows, I might even blog more than once a month! :)
  3. You get to spend more time with your family. My wife is a graduate student, and she’s able to work from home most of the time. It’s nice to be able to spend additional time with her, even if it’s just having lunch or taking a break to talk with her for a few minutes every couple of hours. For others, being able to spending time with children is great. My wife and I don’t have any children, but we do have a couple of dogs, and it’s nice to be able to have them around while I work. They tend to cry sometimes, but they’re starting to learn that when I’m sitting at my desk, they need to relax and wait for me to pay attention to them.
  4. Working without pants is finally a reality. Just kidding. :)

Of course, working at home isn’t without some challenges:

  1. It’s easy to get distracted. Being at home brings with it a certain mindset. It’s important to keep in mind that when you’re working, you’re working, and while you can take short breaks, you need to stay on task or it’s easy to meander off. It’s easier to get off-task when you’re in the “at home” mindset. I think this is largely because of the transition — although I’m used to working on side projects and moonlighting consulting from home, I’m not used to doing it for my “day job”. I’ve noticed as I’ve gotten more accustomed to it, I’ve become more effective at remaining on task.
  2. It’s even easier to work too much. Since your office is your home, your home is also your office, and so you never really “punch out”. I’m also a natural workaholic — programming is more “fun” to me than “work” a lot of the time — so it’s easy for me to come back into the office after dinner and continue to work, even though I really should be done for the day. As part of my transition into telecommuting, I’m trying to draw stronger lines between work-time and off-time.
  3. Communication with the rest of the team is more difficult. Fortunately, Telligent has a pretty firm grasp on how to manage remote workers. Video conferencing makes a huge difference in terms of ease of communication — for whatever reason, seeing the other person’s face as they speak makes a dramatic difference both in the efficiency and quality of the conversation. We use a pretty lightweight Agile practice, and instead of daily stand-ups, we have daily video conferences via Tokbox. (The tool isn’t the best, but so far it’s better than any others that I’ve tried for multi-party video chat.) In terms of communication, the continuum is (with increasing efficiency): Twitter, email, IM, IRC, voice, video, then real-life.
  4. You become even more reliant on technology. Our cable internet was knocked out by the remnants of Hurricane Ike a few weeks ago, and was out for 3 days. We were fortunate enough not to lose power for more than a few minutes, but I was forced to go to my wife’s office at the University in order to work. When you telecommute, losing your internet connection is kind of like having your car break down — except you can’t get a rental or bum a ride to work. We’ve since invested in business-class cable, and while it doesn’t help with widespread outages, I at least get a guarantee of same-day or next-day service. At least I have my wife’s office to fall back on if need be — although I suppose I could always be a wifi leech at Panera. :)

All in all, I have to say that so far the benefits vastly outweigh the detriments. Maybe I’m biased, though, since I’m really interested in the products that Telligent makes, and am jazzed by the stuff I get to work on. (They actually pay me to do this stuff! Suckers. :D)

Announcing Ideavine!

Today, James Avery and I launched Ideavine, a new open source community for .NET applications. While there are a lot of existing sites that provide hosting for open source projects, Ideavine provides full-stack hosting for mature projects, to help them succeed over the long term. Once your project is stable, has a dedicated user base, and long-term objectives, Ideavine can help you take it to the next level.

Open source has traditionally been a second-class citizen in the .NET ecosystem, but lately, through efforts like CodePlex and ALT.NET, it’s started to gain more traction. We hope to build on that, and through Ideavine, help to bring more legitimacy to open source development on the .NET framework.

You can read more at the Ideavine blog. If you have a project that you think might be a good fit for hosting on Ideavine, feel free to submit an application!

Joining the Telligenti

When I first graduated from college, the job market was pretty bad, and most companies were cutting back rather than hiring new employees. A few months before I graduated, I sent out over 100 copies of my resume to various IT and software shops around the area. I got only one call back, and it was from CTI, where I’ve now worked for most of my career. They took a chance on me when I was greener than grass, and challenged me with some very interesting and difficult projects. I’ve learned a tremendous amount about software development and business in my time here, and while there have been ups and downs, the experience I’ve gained has been invaluable. However, a couple of months ago I decided that it was time for the company and I to part ways.

In May of this year, I met Dan Hounshell, Joe Fiorini, and Leon Gersing at the Cleveland Day of .NET, and Dan asked if I would be interested in applying for a position at Telligent. I’ve had a lot of respect for the company and followed the blogs and Twitter streams of several employees, and when he mentioned that they would consider people for telecommuting positions, my curiosity was piqued. At the time I hadn’t made up my mind to leave my current job, but once I did I pinged Dan to see if they might have an opening for a ninja-obsessed codephile such as myself. :)

After going through their interview process (which was very impressive), I’m happy to announce that I’ve accepted a position on Telligent’s Product Development Team as a Senior Software Development Engineer, starting at the beginning of September. The company is based in Dallas, Texas, but I’ll be working remotely from my home in Ohio — which should prove to be an interesting experience in and of itself. (Oddly enough, several of the people in Product Development that work remotely are in Ohio, although as far as I know, only Joe Fiorini is in the greater Cleveland area like myself.)

I’m very excited to be joining the team, and working on some very cool products with some of the industry’s best and brightest minds!

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.

Coming Soon: Ideavine

My blog has been kind of quiet lately. I’ve been pouring a lot of attention into a new project that I’ve been working on with James Avery, called Ideavine. We’re still not ready to spill the beans completely, but the site will launch within the next few weeks. Watch the website and stay tuned for updates…

Conventions-Based Binding

In episode six of the ALT.NET podcast, Brad Wilson mentioned that we’ve only just touched the tip of the iceberg when it comes to dependency injection. He lamented that the existing frameworks have a configuration-based mindset, where you’re forced to wire your application’s components up in a very declarative fashion. He said he would prefer to see a DI framework that would allow you to favor convention over configuration.

This is a great idea, and it started the gears turning in my mind. Going with a more conventions-based mindset will let you wire your application up without the use of attributes, which helps to keep infrastructure concerns from cluttering your codebase. After an interesting question was posted to the Ninject user group, it occurred to me that Ninject supports a “conventions over configuration” mindset already.

For example, let’s say you have two sources for configuration in your application, a LocalConfigurationSource that loads configuration information from a local file, and a RemoteConfigurationSource that loads configuration from a remote database. Services that depend on configuration information will need one or the other of these services to set up configuration. Let’s say you have a consuming service that loads some of its configuration from the local source, and some from the remote source:


public class Service {
  public Service(IConfigurationSource remoteConfig, IConfigurationSource localSource) {
    //...
  }
}

In order to get Ninject to resolve these dependencies and call this constructor, you will need to declare bindings that differentiate between the two implementations of IConfigurationService. If you favor a declarative approach, you could create [Remote] and Local attributes, and use them to decorate the individual constructor arguments:


public class Service {
  public Service([Remote] IConfigurationSource remoteConfig, [Local] IConfigurationSource localSource) {
    //...
  }
}

Then your bindings would look like this:


Bind<IConfigurationSource>().To<RemoteConfigurationSource>()
  .WhereTargetHas<RemoteAttribute>();
Bind<IConfigurationSource>().To<LocalConfigurationSource>()
  .WhereTargetHas<LocalAttribute>();

However, if you’d rather not have to put the attributes in your constructor, you can rely on a conventions-based approach instead. For example, you can create a rule that says that if you want an instance of RemoteConfigurationSource, your argument has to begin with “remote”, and if you want an instance of LocalConfigurationSource, it has to begin with “local”. To do this, you would create bindings like this:


Bind<IConfigurationSource>().To<RemoteConfigurationSource>()
  .Only(When.Context.Target.Name.BeginsWith("remote"));
Bind<IConfigurationSource>().To<LocalConfigurationSource>()
  .Only(When.Context.Target.Name.BeginsWith("local"));

By using these bindings, your consuming service could have a constructor with no attributes, as shown in the first code example.

I’ve added an additional page to the Ninject dojo describing these ideas, and I’d like to hear some feedback. If you have ideas on how to improve upon this, I’d be very interested to hear them!

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.