Awesome Information Radiation with Yammer and Pivotal Tracker

I have integrated Pivotal Tracker (our project management software) with Yammer (our messaging software), and now everyone on the dev team can all stay up to date with what everybody else is doing in near real-time!

 

Why?

When we started doing Agile (XP) here at my work 2.5 years ago, we used physical index cards for writing and organizing stories.  We have a big ferrous whiteboard in the team room, and we had a swim-lane for cards in the current iteration, and another for the backlog (and others at various times as we experimented with our process).  We had colored magnets that indicated the status of each story (red=not started, yellow=in progress and green=”done done”).  I had advocated for the use of physical story cards over project management software because I felt that physical cards in the team room was a more ambient information radiator for us than a system that a developer might check every few hours.  Also, it seemed like most of the project management tools at the time weren’t a great fit for our process, and physical cards couldn’t get any easier to organize into groups, write, toss, etc.

After a while, we discovered that our information radiator (the physical story board) wasn’t so radiant for stakeholders that aren’t developers (eg. executives and support) who don’t often come into the team room.  In the time since we had initially adopted Agile, light-weight tools became available that were a better fit for our process.  After working for a while with Agile Zen, we wound up deciding that Pivotal Tracker was an even better fit for us.  Non-devs can log in and prioritize stories in the backlog, and check on our progress with ease.  However, we missed the information radiation within the dev team that had been offered by our physical story board.  (We had to actually pull up the app to see what’s going on with the rest of the team rather than just swivel your head, prompted by hearing someone walk up to the board.)  Since we had also started using Yammer (to keep in sync using more real-time, less formal messages than emails), we decided that integrating Pivotal Tracker with Yammer would be a great way to get the best of both worlds.  Although Pivotal Tracker already has Twitter integration, since we’re working on commercial (non-OSS) software, we thought Yammer would be a better way for us to stay synced up without potentially leaking our business strategy on a public Twitter account.

 

The upshot

It turns out that both Pivotal Tracker and Yammer have well-documented public APIs, so integrating the two wasn’t that hard.  (Pivotal Tracker can post XML to a URL you supply any time a story is updated, and Yammer has an OAuth interface for publishing messages.)  We created an email address for pivotal tracker on our corporate domain name, and created a Yammer account for it so that messages from Tracker would be visually distinct from everybody else’s normal messages.  Using the integration I created, that account sends a Yammer message every time the status of a story changes, and includes a link to the story.  It looks like this:

pivotaltracker-yammer

 

The awesomeness

With this integration in place, we now get awesome information radiation for the dev team, along with accessibility for other stakeholders.  As a bonus, any devs working outside the team room (or any other team members) get the same awesomeness as those in the team room as soon as they hook up to Yammer!  I published the source code for the integration to github, along with a README explaining how you can set this up for your own team: http://bit.ly/hWzW9Y

Branching with gitflow

If you work on a fairly big team and you haven’t checked out gitflow yet, you should.  It’s an all-encompassing git branching strategy for dealing with production bug fixes occurring simultaneously with on-going feature development and the like.  I did some research on it today to evaluate its suitability for our team, so I’ve decided to write up a post summarizing the gist of the methodology for those of you that haven’t looked into it already.

Using the gitflow branching model, there are 5 (!) different types of branches.  I’ll summarize each type of branch, and while reading that, it may be useful to refer to the this diagram illustrating the interactions between the different branch types: http://github.com/downloads/nvie/gitflow/Git-branching-model.pdf

 

Branch Types

master: The master branch always contains production-ready code.  It should have either the same copy of the code that is running in production, or the copy of the code that is imminently being deployed to production.  Naturally, this branch is persistent and is never removed.  It exists in the central repository (origin), as well as on developer workstations.

develop: This branch is the copy of the code that is being developed for the next prospective release.  Small features can be committed directly into this branch, but larger features should be developed in feature branches.  This branch is persistent and is never removed.  It exists in the central repository (origin), as well as on each developer workstation.  This is the branch that the CI process uses.

features: These branches are named after a particular feature.  They are created (based on the “develop” branch) when work on the feature begins, and incremental work on the feature is committed to that branch.  They exist only on developer workstations.  If multiple developers are working on the same feature, they push/pull to/from each other’s feature branch, it would seem.  When work on the feature is code-complete, this branch is merged into the “develop” branch, and then the feature branch is deleted.  Merging a feature branch into develop signifies that the feature will be included in the next release.  By contrast, feature branches may be long-lived, and may not be merged into develop until several releases have passed, for a large feature.  Once a developer has installed gitflow, they can create a new feature branch by typing ‘git flow feature start [feature-name]’.  (That just does ‘git checkout –b [feature-name] develop’.)  When the feature is done and ready to be merged into ‘develop’, the developer types “git flow feature finish [feature-name]”.  (This does a ‘git checkout develop’, ‘git merge –no-ff [feature-name]’, ‘git branch –d [feature-name]’, and ‘git push origin develop’.)

releases: These branches are named after a particular release version: a major (2.0) or minor (2.1) release version.  They are created (based on the “develop” branch) when all the features for the next release are code complete in the “develop” branch.  While the release is being tested, bug fixes are made into this branch.  New functionality, however, will continue to be made in the “develop” branch (and associated feature branches), and will not be included in the release.  (These branches are created at the same point in the development cycle when a “code freeze” might be declared in a development shop that doesn’t use any sort of branching.)  These branches are created with ‘git flow start [version]’, which it seems like it must just do a ‘git checkout –b release-[version] develop’, and then you probably still need to manually increment any applicable version files and then commit those changes.  When the release has been tested and is ready to go to production, it is merged into master, and also merged back into “develop” (so that any bug fixes made will be applied to future versions as well), then the branch is deleted, all with the command ‘git flow release finish [version]’.  (This does a ‘git checkout master’, ‘git merge –no-ff release-[version]’, ‘git tag –a [version]’, ‘git checkout develop’, ‘git merge –no-ff release-[version]’ and ‘git branch –d release-[version]’.)

hotfixes: These branches are created for urgent bug fixes on the version that’s currently in production, and they are normally named after a point release (eg. ‘hotfix-1.2.1’).  They are very similar to release branches, except that are created from master.  They are created with ‘git flow hotfix start [version]’, then later merged (into master and develop) and deleted using ‘git flow hotfix finish [version]’.  These commands do very similar things to their equivalent release commands, as one might expect.

 

More information

Original post on the branching model is here: http://nvie.com/posts/a-successful-git-branching-model/

Gitflow tool is here: https://github.com/nvie/gitflow

Introductory post on basic gitflow usage is here: http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/

 

Conclusion

If I was on a bigger team, I think this would make a lot of sense, but for our small team (three developers, including myself and our manager), I think its a bit of overkill.  We are probably going to adopt a limited subset of this methodology: We will create hotfix branches and perhaps occasionally feature branches for very large features, in addition to the two permanent branches (master and develop), and we will probably use the gitflow tooling.  However, we probably won’t use specific release branches, and our use of feature branches will probably be limited at most (and they would exist on github for the duration of their life, contrary to the gitflow methodology).

Why Ruby Rocks, In A Nutshell

I read a great description of my favorite aspect of Ruby in The RSpec Book, by David Chelimsky, et al.  It was so apt, I had to share it. Here it is (emphasis mine):

When first learning Ruby, you might get a sense that the language is
reading your mind. Say you need a method to iterate through the keys
of a Ruby hash so you type hash.each_pair {|k,v| puts k} just to see if it
works, and, of course, it does! And this makes you happy!
Ruby is filled with examples of great, intuitive APIs like this, and it
seems that
developers who write their own code in Ruby strive for the
same level of obvious, inspired by the beauty of the language. We all
want to provide that same feeling of happiness to developers that they
get just from using the Ruby language directly.

 

Well put.

Rake Runs RSpec Tests Twice

We had a problem where running individual specs worked as expected, but running rake ran the whole test suite twice.  (BTW, We are running Rails 3.0.1 and RSpec 2.0.1.)  It looks like the problem is that we had run ‘rails generate rspec:install’ back when we were running RSpec 2.0.0.beta.22, and since, we upgraded to RSpec-2.0.1.  It appears that the RSpec installer for the beta version created an rspec.rake file under lib/tasks, which is no longer required for RSpec 2.0.1, and is effectively duplicitous of what is invoked through the gem’s own rake tasks (it would seem).

I removed rspec.rake and now rake only runs the test suite once!  Leave a comment if it this was helpful.

WebSockets presentation materials

Attached is the source code I used to demonstrate WebSockets and my slide-deck (in the Open Office .odp format as well as exported to .ppt) at the NBNUG meeting yesterday (10/19/10).  Client.html is the HTML/Javascript client, Server.cs is the C# server that just needs to be compiled into a console app project, referencing Nugget.dll (source is here: http://nugget.codeplex.com/).

Presentation Materials WebSocketsPresentation.zip

UPDATE: When I presented on WebSockets for NBNUG a few months ago, someone asked if it was possible to host WebSockets using IIS.  Microsoft just released a prototype demonstrating a WCF-based WebSockets application that is hosted in IIS.  You can check that out here: http://jclaes.blogspot.com/2011/01/html5-installing-microsoft-websockets.html

Innovation Is More About Hard Work and Salesmanship Than Genius

I am about 75% done reading The Myths of Innovation by Scott Berkun (first edition), but I decided to post about what I’ve learned from it already since it’s Myths of Innovation day.  The book has been a great read, challenging our perceptions about how innovation occurs by examining the roots of those perceptions, and looking closely at how it actually occurs.

One of the first things that I found interesting was the way it highlighted the common view that innovation occurs by some chance event, or because something magical happened to a worthy intellect.  In fact, the word “Muse”, used to describe sources of inspiration, is derived from a set of Greek goddesses that were believed to provide that inspiration.  Clearly, early civilizations viewed innovation as purely magical, and to an extent, that view has carried over into today.

Similarly, innovators are immortalized as having carried out a piece of our collective destiny by executing on some mammoth realization.  In reality, innovations generally occur as incremental improvements upon the ideas of others, conceived of to solve a specific problem, often without having any idea of the degree of change that would be ushered in by their innovation.  (Facebook, ne, FaceMash anyone?)

Both the source of innovation and the people who contributed to it are vastly over-simplified in the historical accounts that we typically read about in the news or learn about in school.  The reason is that the real explanation for how innovation occurs is more complex and much less romantic, for lack of a better word.

Innovation is typically the result of someone putting in a lot of hard work for a long time refining the efforts of others to solve a specific problem.  Even hard work on the right problem must be accompanied by the right circumstances to achieve any results.  Furthermore, for those results to be developed into a significant innovation, the results must be delivered to people around them in the right way.  People need to understand the advancement, how they will benefit from it, and not be scared of any potential risks associated with it (and they need to hear about it in the first place).  At that point, it’s possible that if the stars are aligned in such a way that the right people will benefit from applying the innovation to a series of unforeseen (and possibly larger) problems, then the innovator be recognized by the annals of history and lauded in the media, unlike all the intermediate works that were built upon and their inventors, as well as technically superior inventions that weren’t successfully presented to the world.

Want to know more? Read the book! I highly recommend it.

Software Developer Maturity Stages

In the software industry (as in many other industries), developers are commonly categorized as either Junior-level, intermediate, or Senior-level.  The most typical definition for these distinctions is based on the number of years of experience (0-2 years = junior, 2-5 years = intermediate, >5 years = senior, or something along those lines).  This post describes an alternative basis for making these distinctions that is based on the type of designs that a developer creates, rather than the number of years they have been creating software professionally.

Since our trade is fairly difficult intellectually, I don’t think that the number of years of experience accurately dictates the effectiveness of a developer, and thus it’s a poor basis for distinction.  If you’re not actively trying to improve, additional years of experience probably doesn’t make you much more effective, and my experience working with a fair amount of developers at a number of different companies reflects that.

Here is the basis I’m going to start using for categorizing developers:

Junior: Creates overly-simple designs with lots of duplication. Their apps are easy to understand, but hard to maintain.

Intermediate: Creates overly-complex designs with lots of unnecessary indirection. Typical code smells that indicate an intermediate developer are very long, convoluted class names that don’t convey much meaning, unnecessary abstractions and use of frameworks that aren’t adding any value in the context (but increase complexity). Their apps have a high learning curve to understand the architecture, but then are fairly maintainable (for at least intermediate-level developers) once you’ve successfully grokked all the indirection.

Senior: Creates simple, elegant designs.  Their apps are fairly easy to understand (for at least intermediate-level developers), maintain and enhance. They use abstractions where they make sense and frameworks that add value to the particular application.

Am I right/wrong/silly? Leave a comment!

XP vs Kanban: New Product Development

Our Situation

My team and I are currently working on a new line-of-business web application, and we had a discussion today about what the best Agile process would be for our current endeavor. Up until last Friday, we have been practicing Extreme Programming (XP). We generally have week-long iterations, starting on Friday mornings and ending on Thursday evenings (so that end-of-iteration crunch time to meet our iteration commitment doesn’t fall on a Friday evening).  Friday mornings we have our stand-up, then our retrospective, and then we plan our next iteration.  Last Friday, we decided to try out a Lean/pull process for a week.  This morning at our stand-up, I was trying to pick between working on a rather large story that was at the top of our “Ready” queue, which I probably could not have finished by the end of the day, and a smaller story just below that is more manageable for today.  If we were to continue using Lean/Pull, having the story half-finished at the end of the day is not such a problem, but if we’re going back to XP and fixed-length iterations, I need to make sure there’s no work-in-progress by EOD.  This post is about which process we decided to use and why.

 

Extreme Programming

MotorcycleAn advantage of XP over Kanban is our perception that its easier to convey rough estimates of a batch of work to upper management.

My boss (the CTO) routinely meets with the CEO and COO of our small company and they will discuss a strategic new product, or a fairly large module to be added to an existing product.  They will collaboratively write a set of stories, and then on the following Friday, the development team will meet to give a rough estimate to each of those stories (or each of the “must haves” if there are a lot of stories).  Once we’ve done that, my boss will divide the sum of estimates by our weekly velocity (the average amount of work we complete per week), then multiply by a risk-factor, to produce an estimate of when that chunk of work will be done, and conveys that back to upper management.  The estimate and the scope it represents are not set in stone, and everyone understands that. This still has value to upper management, because they can choose to cancel or defer that chunk of work if its expected value isn’t roughly commensurate with the required effort. Also, it serves as a signal to whether or not they should be brainstorming new strategic products/modules, or whether we’re busy enough that it’s not worth-while for the moment. Additionally, the iteration commitment in XP provides a bit of security in knowing that the work currently under construction will be done by the end of the week, which can be communicated to other stakeholders if asked.

In an ideal world (eg. textbook Agile/XP), we would be able to deliver the most valuable features to production in one iteration, generate some value, and build from there. In the real-world (or in our world in any case), there is often a minimum marketable feature set that must be completed in order for a new application to deliver any value in its business context. In our business, our customers are busy and selective, so if you demonstrate something for them that doesn’t do the core functions that sparked their interest, at best: they’re not going to use it in its current state. At worst: they will lose interest in the new product and decline to dedicate any more attention to it in the future. Another factor that can result in a minimum marketable feature set like this is a marketing push. Given a fixed marketing budget, are you going to spend those valuable dollars running that full-page ad in a trade journal after the product has had just a week of development?  I think that would probably be unwise in most situations. All of this is certainly not to say we should return to waterfall and decide the scope up front, then do it ‘til it’s ‘done’, etc., but merely that like most things in life, selecting when to ‘launch’ a new application is a balance. You want to launch with the minimum set of functionality that will actually garner the attention of your intended audience, without doing so much up front that you need to do a ton of re-work after it’s used in production and the users tell you everything that’s wrong with it.  The trick is to implement A, B and C (if those are the features that are absolutely critical) without trying to deliver D, E and F (the nice-to-haves) at the same time. The problem is that the effort required to build A, B and C often takes more than one reasonably-sized iteration, in the case of a new application.

To sum up, the fixed length iterations used in XP enable us to deliver valuable timeframe estimates to upper management, and I don’t see a way around that in our business context.

 

Kanban

Kanban Kanban is Japanese for “signboard” or “billboard”. “Kanban is a signaling system to trigger action. As its name suggests, kanban historically uses cards to signal the need for an item.” (Wikipedia)  We have actually been using a virtual Kanban board for a little while now, as in it’s simplest usage, it’s effectively similar to the XP-style story board (index cards stuck on a ferrous whiteboard with colored magnets) we were using previously.  The process change I referred to previously is that we briefly tried out a pull system, where our stakeholders added and prioritized stories in the “Ready” queue at will, theoretically signaled by our completion of work.  We tried this rather than having a fixed-length iteration this week, prompted in part by it being a short week due to the 4th of July holiday recognized on Monday.

What attracted us to a pull-system is the flexibility it gives stakeholders to introduce new cards or prioritize cards in the middle of an iteration. (Both are prohibited in XP: scope is fixed for the current iteration and the order of story implementation is selected by dev team members based on the logical flow of work occurring during the iteration.)  The other nice thing about it is that it avails us to interesting approaches (like Value Stream Mapping) for maximizing the throughput of new features.  (In other words, minimizing the amount of time it typically takes a story to go from conception to production.) It definitely sounds nice in principal, and seems to have worked out well for Toyota.

The down-side of using Kanban when developing a new application is that there’s no apparent way to do the broad estimates that we currently communicate to upper management.  Although you can use your calculated cycle time (the average amount of time it takes a feature to go from conception to production) to estimate when a particular feature will be delivered to production, what about the time required to deliver the minimum marketable set of features?  It doesn’t seem possible to use cycle time to calculate that, and you can’t use velocity if you don’t have fixed length iterations.  Furthermore, the chunks of work represented by the minimum set of marketable features doesn’t seem very compatible with a pull system.  The stakeholders aren’t adding a feature to the queue as we get work done, they’re telling us the minimum set of features that are needed before they’re willing to call a meeting with a key client to demonstrate a new application, and that seems logical given the circumstances.  Lastly, calculating cycle time and identifying bottle necks becomes much more difficult if the stories moving through the value stream are not similarly sized, and they commonly are not toward the beginning of an applications lifetime, since there is little or no infrastructure in place at the beginning.

 

Decision

Since the value of being able to produce rough estimates for new applications to upper management exceeds the value of them being able to add and prioritize stories in the middle of an iteration, we decided to go back to using XP for our next iteration.  We will continue to use XP on this application (and all new functionality which can’t be fully launched after one iteration) until it is actually being used in production. We will deliver it to a production environment at regular intervals prior to that, and demonstrate it there for upper management. Once the intended users are actually using it in production and getting value from it, we have tentatively decided to try out a pull system again, since it will make more sense to have new features be pulled through the system in response to work being completed once we are getting feedback from the intended audience, and rough estimates will not need to be communicated back to upper management for that application.  Does ‘XP for brand new apps, Kanban for enhancements’ seem like a good modus operendi?  One thing that occurs to me as I’m reading back over my post is that if had decided to go with a pull system from the start, we could use some estimation methodology that is unrelated to our process (for example some flavor of COCOMO, or SWAG, or you name it), although I gather that the velocity-based estimates we have been using since we adopted XP have been a lot more accurate than estimates given before the company used an Agile process (although I guess that could have to do with adoption of other Agile practices keeping us focused).  If anybody reading this has implemented a new application using a pull system under similar constraints, how did you deal with estimation (was it anywhere near accurate?), and was your work queue much larger at the beginning of the project, or was it small throughout?

Writing WPF apps using Kiddo/IronRuby and the MVVM pattern

Kiddo is a Ruby DSL for building simple WPF and Silverlight applications, inspired by the Shoes library.  It’s still an early alpha, but a very cool concept none-the-less.  I rather like the idea of being able to produce a slick looking WPF (or Silverlight) UI using a simple Ruby API.  The basic syntax looks like this (taken from the post linked to above):

require "kiddo"

Kiddo.start do

  draw :stack do
    draw :text, "Text to reverse:", :font_size => 18
    draw :edit_box, :named => "input"
    draw :text, "Your string will show up here.", :named => "result"
    draw :button, "Reverse It!", :named => "fun_button"
  end

  after :fun_button.is_clicked do
    :result.text = :input.text.reverse
  end

end

If you run this, you’ll get something like this on your screen:


You type in some text in the textbox, click the button, and the app will reverse the string and show it above the button.  I think the sample code is fairly self explanatory, but if you’re not sure what it’s doing, check out the link above.

The only issue I had with Kiddo is that it wasn’t clear how one could test the logic that was occurring in one of the event handlers (like the string reversing logic in the “after” clause above).  I wasn’t able to figure out how I could plug in an MVVM (Model View View-Model: the approximate thick-client equivalent of the Model View Controller pattern for web applications) framework without modifying Kiddo, so I went ahead and monkey patched it to support a very basic type of MVVM that would enable me to easily test the logic that handled UI events.  The MVVM extension would need enhancing to be used for probably anything significant, but I think that’s probably true of Kiddo also.  Here is the modified Kiddo example, hooking into the extensions I added…

require "kiddo"
require "kiddo_mvvm"
require "main_view_model"


Kiddo.start(:view_model => MainViewModel) do
  draw :stack do
    draw :text, "Text to reverse:", :font_size => 18
    draw :edit_box, :named => "input"
    draw :text, "Your string will show up here.", :named => "result"
    draw :button, "Reverse It!", :named => "fun_button"
  end 

  command :fun_button.is_clicked, :reverse_text
end

There are three differences between this and the original example.  First, the updated example requires the file with the Kiddo extension I added (kiddo_mvvm.rb) and file with the ViewModel that has the logic that will respond to the button press (main_view_model.rb)  Next, the ViewModel class is associated with the sample UI by passing it in as an option on the Kiddo.start method call.  Finally, instead of having an “after” clause with the actual logic that responds to the button click, we have a call to the new “command” method which ties the button click event (:fun_button.is_clicked) to the method on the ViewModel that should be executed when the event fires (reverse_text).

Here is the code for the ViewModel class containing the logic (main_view_model.rb):

class MainViewModel
  attr_accessor :input
  attr_accessor :result

  def reverse_text
    @result = @input.reverse
    @input = "thank you"
  end
end

It defines public getter/setter properties that correspond to the text of the “input” textbox and the “result” text (label).  It also defines the “reverse_text” method that is invoked by the MVVM extensions to Kiddo in response to the button being clicked.  That method reverses the string in “input” and sets it into “result”.  To illustrate the advantage that this approach has to simply calling a method on a business object in an “after” clause (that the command can easily read from and write to several bound widgets), it also sets “input” to “thank you”.  Now, you can run the revised sample which behaves like the original sample except that it also puts “thank you” in the input box after you click the button.

Now you can write a test directly against MainViewModel to test the logic without bringing the actual UI into play.  Here is a simple example of that (test_MVVM_custom.rb), using the very simple Test::Unit ruby testing framework:

require "test/unit"
require "main_view_model"

class MainViewModelTest < Test::Unit::TestCase
  def test_reversing
    vm = MainViewModel.new
    vm.input = "mytest"
    vm.reverse_text
    assert_equal "tsetym", vm.result
  end
end

The fixture defines a single test that instantiates the ViewModel, sets the input to “mytest”, calls reverse_text and verifies that the result is “tsetym”.  Running a test/unit test is very simple, simply execute the ruby file! (ir test_MVVM_custom.rb)
Finally, here is the code for the MVVM extensions I added to Kiddo (kiddo_mvvm.rb):

module Kiddo
  class App
    attr_accessor :view_model
  end

  class << self
    alias_method :original_start, :start
  end

  def self.start(options={}, &block)
    view_model = options.delete(:view_model)
    if view_model
      App.instance.view_model = view_model.new
    end
    original_start options, &block
  end

  def command(hash, view_model_method)
    view_model = App.instance.view_model
    if !view_model
      raise "Must pass a ViewModel instance to Kiddo.start in order to bind a command"
    end
    hash[:instance].send hash[:method] do |sender, args|
      #Copy data from widgets into ViewModel
      view_model.methods.each do |method|
        if method.index("=") == method.length - 1
          property = method.chop 
                 widget = App.instance.locate property 

                 if widget and defined?(widget.text) 
                   view_model.send method, widget.text 
                 end
        end
      end
      view_model.send view_model_method
      #Copy data from ViewModel back into widgets
      view_model.methods.each do |method|
        if method.index("=") != method.length - 1
          property = method
          widget = App.instance.locate property
          if widget and widget.respond_to?("text=")
            new_text = view_model.send method
            widget.text = new_text
          end
        end
      end
    end
  end
end

This code theoretically shouldn’t need to get modified on an app by app basis (except to enable new types of controls, etc.)  It essentially just adds in support for the “view_model” option on Kiddo.start and then defines the new “command” method.  That method loops through all the methods on the ViewModel that end in “=” (Ruby property setters) and tries to match them to UI widgets based on their name.  When a match is found, it sets the ViewModel property to the text of the corresponding widget.  (Obviously this approach won’t work for all types of widgets, but it’s a start!)  Next, it calls the method on the ViewModel that has the name passed in from the caller.  Finally, it loops through all the methods on the ViewModel that don’t end in “=” and tries to match those to widget names.  When a match is found, it sets the text on the widget to the corresponding property value from the ViewModel.  This enables the ViewModel class to effectively “bind” to widgets simply by creating a getter/setter property with the same name as the widget.

I’m contemplating porting MongoDB Management Studio to use Kiddo, so if that comes to pass, then there will likely be a number of enhancements to this extension.

Introduction to IronRuby - presentation materials

Attached is the Powerpoint slide deck and two sample applications (application plug-in and simple DSL) that I used for my presentation for NBNUG on Tuesday, 4/20/10.