MEFfing Disappointed

Working on a highly modular service offering this week, and I took a looksy at the Microsoft Extension Framework as a way to wireup the service components.  I made the choice to pass MEF over, but it was a tough call.  It’s not that MEF doesn’t offer enough features; quite to the contrary I’m pleased with the focus of its feature set.  The reason I didn’t use it was simply that is rubs me the wrong way.  Lemmie splain, and yes this post is a little persnickety, but maybe someone can set me straight…

Things I Don’t Like

MEF requires decoration of dependency objects, and I don’t see the point to that.  Here’s an example of what I mean from the MEF wiki:

1 [Export(typeof(IMessageSender))] 2 public class EmailSender : IMessageSender { 3 ... 4 } 5 6 [Export(typeof(IMessageSender))] 7 public class TCPSender : IMessageSender { 8 ... 9 }

I fail to understand why the Export attribute is necessary in this standard (and according to the MEF wiki, recommended) usage pattern.  I see many issues here…

The ExportAttribute simply duplicates information that is already available via the .NET typing system.  By definition, any public type is exported by the assembly that contains it.  If you argue that you may have public types that you don’t want to export for consumption, I would want to know why they’re public instead of internal types.  So why would I want yet another vector on my type that just duplicates information I already have?

Someone pointed out the ExportMetadataAttribute as a counter to this argument.  I responded by asking why the export metadata shouldn’t be expressed as properties on the object being exported.

It’s not that I mind contract-based object graph wireups like this, but I don’t like that the contract is part of the type definition.  I want to allow the object that is consuming this dependency to choose how to consume it, not the other way around.  In fact, cramming the wireup contract into the type definition is a cost, not a benefit – if you need to modify the wireup, you need to recomplie both the consuming and dependency objects.  Why would I want that when I can specify the wireup elsewhere, like an IoC assembly or XML file?

In short, setting up these exports seems like duplicate work with no payoff.

Things I Do Like (and Some I Would Change)

I like the assembly catalog concept in MEF – of building a list of assemblies the consumer deems appropriate for importing its dependencies.  I like that because enables the application behavior to be dynamic, which is really the point of frameworks like these isn’t it? 

I also like the idea of decorating a consuming object with attributes to describe what they want or need.  Well, sort of.  At first the ImportAttribute and her sisters looked a lot like the ExportAttribute, and I had the same qualms about them:

1 public class Notifier { 2 [ImportMany] 3 public IEnumerable<IMessageSender> Senders {get; set;} 4 public void Notify(string message) { 5 foreach(IMessageSender sender in Senders) 6 sender.Send(message); 7 } 8 }

If the ImportManyAttribute were missing, would anyone looking at the object not know that it needs a collection of IMessageSenders?  Of course not.  So at first I thought it was another redundant framework construct.  Then I realized that it wasn’t expressing a dependency of the object, it was marking a object dependency as a point for extensibility.

In other words, the ImportAttribute says “you can use whatever type you find in the dynamic catalog here.”  That’s beyond expressing a dependency – it’s defining how that dependency should be resolved.  I don’t mind that as much, and I’m even okay with having that expressed in the type definition.  I think I would still prefer expressing the dependency resolution outside of the consuming type, but I’m warming up to the idea.

However, if MEF wants me to work this way I see some significant improvements that can be made.  First and foremost, support for standard object patterns.  E.g., I would prefer to implement the Notifier example this way:

1 public class Notifier { 2 [ImportAsComposite] 3 public IMessageSender Sender {get; set;} 4 public void Notify(string message) { 5 Sender.Send(message); 6 } 7 }

It’s less code, and my intent is just as clear.  Moreover, I would want to be able to apply decorators:

1 public class Notifier { 2 [Import] 3 [DecorateWith(InstrumentingMessageSender)] 4 public IMessageSender Sender {get; set;} 5 public void Notify(string message) { 6 Sender.Send(message); 7 } 8 }

and chains of responsibility:

1 public class Notifier { 2 [ImportAsChain] 3 public IMessageSender Sender {get; set;} 4 public void Notify(string message) { 5 Sender.Send(message); 6 } 7 }

oh and of course default behaviors for when there is no import or chain or whatever:

1 public class Notifier { 2 [ImportAsChain] 3 [Default(NullMessageSender)] 4 public IMessageSender Sender {get; set;} 5 public void Notify(string message) { 6 Sender.Send(message); 7 } 8 }

.. etc, etc, etc.  These are just ideas though, I have no code to back them up, but I certainly want it.  I like these because they help the consuming object express what it wants and how it will behave, and they realistically require nothing unique on the dependency objects.

You smell that too?  It’s another project brewing…

kick it on DotNetKicks.com
E-mail • Permalink • Comments (0)

Open Sourcing of the ASP.NET Membership PowerShell Provider

Over the past year I've blogged and presented about the benefits of targeting PowerShell as a framework for supporting the applications you develop.  I firmly believe PowerShell is the most appropriate choice of platforms for creating interactive and flexible toolsets.  Today I'm proud to announce that one of the original projects that led to this belief - the ASP.NET Membership PowerShell Provider - is being released by Code Owls LLC as open source.

You can find the project hosted on CodePlex here.

My reasons for this don't really center around wanting to share the code.  That is, I've already written detailed blogs about creating this particular provider, and plan to round those out with a few more posts:

So in my mind, the code is already public.  The primary reason I wanted to get this project public and posted was to get people using it and contributing to the project.  At the moment, the glaring omission is Active Directory support, and this is where I need the most help since I don’t have ready access to an Active Directory environment.  If you’re interested in helping out, by all means contact me through this blog or through the CodePlex project page.

I realize this project may be a bit niche, but its a niche is begging to be filled.  The existing Membership toolset is atrocious, and the applicable PowerShell offering is robust, interactive, and full of chewy goodness.

Enjoy!

kick it on DotNetKicks.com
E-mail • Permalink • Comments (2)

CodeStock 2010: PowerShell as a Tools Platform

At long last, I'm home from my working vacation and have a chance to do some CodeStock postprocessing.  Several people have asked me for the resources from my PowerShell presentation.  You'll find downloadable RARs of the powerpoint and code below.  I've also placed the deck on SlideShare for convenience:

The bulk of the code is described in the following posts:

I will be adding a few posts soon to round out the code coverage.  Feel free to drop me any questions or concerns you have.  I'd love the chance to give this talk to any .NET user groups in the area!

ASPNETMembership.rar (284.35 kb)

PowerShell as a Tools Platform.rar (1.17 mb)

kick it on DotNetKicks.com
E-mail • Permalink • Comments (0)

there is always a bigger fish

In my previous post I mentioned I'd post a detailed story related to "Community," and here it is.

About two years ago my good friend and colleague Brady Gaster accompanied me to a meeting of the Enterprise Developer's Guild.  Brian Hitney was presenting on ASP.NET MVC.  This was the first users group I had ever attended.  For realsies.

I'm not a terribly social bird in these situations.  It's not that I'm afraid or antisocial, I just don't really know how to engage someone I don't know anything about.  But Brady seemed to know just about everyone, and everyone seemed to know him.  It was amazing to watch him flow in and out of conversations, as if he were simply the breeze that carried the discussion.  So I took a deep breath and started to look around the room for someone to talk to. 

That's when Brady scolded me: "Don't do that."

"What dude?" I replied.

Brady refit his baseball cap and said, "You're being a dick."

I was dumbfounded.  I remember feeling like I had broken some unwritten code of user group geek etiquette by rubbernecking for a familiar face.  "What did I do?"

Brady: "You're scanning the pond."

Me: *blink*

Brady followed on, "You're looking around the room trying to see if you're a shark or a fish.  That's a dick thing to do.  Don't do that."

I eeked out of Brady that he thought I was visually guesstimating my mental abilities against the others in the room.  This is one of his pet peeves, if you didn't know already.  I don't think that's what I was doing, but that's outside the real issue.  I want to focus on Brady's intent...

Pigeon-holeing an idea or belittling a person is easy.  Unfortunately it says more about you than it does the other person.  If you chose to act this way around your peers, you're a dick.  No one wants to work with you or have you around because you make them feel devalued.

Building someone up or enabling them to succeed is hard.  Fortunately it says as much about you as it does the other person.  People will be comfortable with you, maybe even look forward to your involvement with things.

It's a Community.  We're all fish here, and regardless of the state of your self-esteem, there is always a bigger fish.

 

kick it on DotNetKicks.com
E-mail • Permalink • Comments (1)