- According to Reuters surgeons who play video games are more skilled. Remind me to ask the doctor if s/he owns an XBOX 360 the next time I am getting operated on.
- I have reached the National Championship game in dynasty mode of NCAA Football 2007. The opponent of my BYU Cougars…why that would be Harry’s alma mater, the USC Trojans. Funny how that worked out.
- Nicholas Allen writes in his blog about when you should use Indigo to write a channel, and more importantly when you should not. As most of you know Harry and I are doing quite a bit of work with WCF so we are interested in this type of advice.
- Our team has been thinking about how to manage a large number of services in an automated fashion. This would include deploying new services, monitoring the services, automatically handling scaling, service discovery, and automated provisioning to name a few possible capabilities. I almost think of it like the next version of UDDI, especially when it comes to provisioning. I think that as systems become more distributed that the ability to automatically manage these systems is going to be key to their success. I know that some thought has already gone on in this area by people far smarter than I, but as I consider how to operate an infrastructure with thousands of services in it it is apparent that the opportunity is there for us to design and implement a system management framework that automates the majority of the tasks. I need to spend some time to consider how the framework would work, and document the capabilities.
Internal DSLs in PowerShell
(Harry is on a secret mission in uncharted space this week, so instead of the daily Morning Coffee post, you get a series of autoposted essays. This post combines both some leftover learnings about Ruby from Harry’s Web 2.0 days with his recent obsession with PowerShell.)
My first introduction to the idea of internal DSLs was an article on Ruby Rake by Martin Fowler. Rake is Ruby’s make/build utility. Like most build tools like Ant and MSBuild, Rake is a dependency management system. Unlike Ant and MSBuild, Rake doesn’t use an XML based language. It uses Ruby itself, which has huge benefits when you start doing custom tasks. In Ant or MSBuild, building a custom task requires you to use a external environment (batch file, script file or custom compiled task object). In Rake, since it’s just a Ruby file, you can start writing imperative Ruby code in place.
Here’s the simple Rake sample from Fowler’s article:
task :codeGen do
# do the code generation
end
task :compile => :codeGen do
# do the compilation
end
task :dataLoad => :codeGen do
# load the test data
end
task :test => [:compile, :dataLoad] do
# run the tests
end
The task keyword takes three parameters: the task name, an array containing the task dependencies and a script block containing the code to execute to complete the task. Ruby’s flexible syntax allows you to specify task without any dependencies (:codegen), with a single dependency (:compile => :codegen), and with multiple dependencies (:test => [:compile,:dataLoad])
So what would this look like if you used Powershell instead of Ruby? How about this:
task codeGen {
# do the code generation
}
task compile codeGen {
# do the compilation
}
task dataLoad codeGen {
# load the test data
}
task test compile,dataLoad {
# run the tests
}
Not much different. PS uses brackets for script blocks while Ruby uses do / end, but that’s just syntax. Since it lacks Ruby’s concept of symbols (strings that start with a colon), PS has to use strings instead. Otherwise, it’s almost identical. They even both use the # symbol to represent a line comment.
There is one significant difference. For tasks with dependencies, Rake uses a hash table to package the task name and its dependencies. The => syntax in Ruby creates a hash table. Since the hash table has only a single value, you can leave of the surrounding parenthesis. The key of this single item hash table is the task name while the value is an array of task names this task depends on. Again, Ruby’s syntax is flexible, so if you have only a single dependency, you don’t need to surround it in square brackets.
In Powershell, the hash table syntax isn’t quite so flexible, you have to surround it with @( ). So using Rake’s syntax directly would result in something that looked like “task @(test = compile,dataLoad) {…}” which is fairly ugly. You don’t need to specify the square brackets on the array, but you having to add the @( is a non-starter, especially since you wouldn’t have them on a task with no dependencies.
So instead, I thought a better approach would be to use PS’s variable parameter support. Since all tasks have a name, the task function is defined simply as “function task ([string] $name)”. This basically says there’s a function called task with at least one parameter called $name. (All variables in PS start with a dollar sign.) Any parameters that are passed into the function that aren’t specified in the function signature are passed into the function in the $args variable.
This approach does mean having to write logic in the function to validate the $args parameters. Originally, I specified all the parameters, so that it looked like this: “function global:task([string] $name, [string[]] $depends, [scriptblock] $taskDef)”. That didn’t work for tasks with no dependencies, since it tried to pass the script block in as the $depends parameter.
Here’s a sample task function that implements the task function shown above. It validates the $args input and builds a custom object that represents the task. (Note, the various PS* objects are in the System.Management.Automation namespace. I omitted the namespaces to make the code readable.)
function task([string] $name) {
if (($args.length -gt 2) -or ([string]::isnullorempty($name))) {
throw "task syntax: task name [<dependencies>] [<scriptblock>]"
}
if ($args[0] -is [scriptblock]) {
$taskDef = $args[0]
}
elseif ($args[1] -is [scriptblock]) {
$depends = [object[]]$args[0]
$taskDef = $args[1]
}
else {
$depends = [object[]]$args[0]
#if a script block isn't passed in, use an empty one
$taskDef = {}
}
$task = new-object PSObject
$nameProp = new-object PSNoteProperty Name,$name
$task.psobject.members.add($nameProp)
$dependsProp = new-object PSNoteProperty Dependencies,$depends
$task.psobject.members.add($dependsProp)
$taskMethod = new-object PSScriptMethod ExecuteTask,$taskDef
$task.psobject.members.add($taskMethod)
$task
}
Of course, you would need much more than this if you were going to build a real build system like Rake in PowerShell. For example, you’d need code to collect the tasks, order them in the correct dependency order, execute them, etc. Furthermore, Rake supports other types of operations, like file tasks and utilities that you’d need to build.
However, the point of this post isn’t to rebuild Rake in PS, but to show how PS rivals Ruby as a language for building internal DSLs. On that front, I think PowerShell performs beautifully.
I’m looking forward to using PowerShell’s metaprogramming capabilities often in the future.
Morning Doughnuts 3
- What does it take to be an architect? Skyscrapr.net attempts to answer this question by asking a bunch of architects.
- I have started teaching my children about astronomy. I found an open source product called Stellarium that is excellent for learning about the celestial objects visible in your area.
- A Methodology for SOA adoption? I read an interesting blog on this subject from a couple of weeks ago. It’s not a long article, but the author makes some interesting points including an outline for SOA adoption.
- I finally picked up Gears of War on Friday. It really isn’t a game I can see playing much, although I can see why it’s popular. I guess the best and the worst part of the game is having to utilize cover so you don’t die right away.
- Windows Live Writer is a great tool! I use it to author the blogs for my website, and this week I have been using it on these Morning Doughnuts posts. My favorite feature is that you can preview your post and see exactly how it will appear on your website. This has been particularly useful since Devhawk and my site look quite different.
Reliably Beating a Dead Horse
(Harry is on a secret mission in uncharted space this week, so instead of the daily Morning Coffee post, you get a series of autoposted essays. This post builds on Harry’s recent epiphany about WCF and long running services)
Way, way, way back in March of 2003, IBM and Microsoft published an “overview and roadmap” white paper entitled “Reliable Message Delivery in a Web Services World“. It contained the following paragraph under the section “Exchanging Messages Reliably”:
WS-ReliableMessaging is not bound to underlying transport protocols or sessions. This means that the lifetime of a WS-ReliableMessaging conversation can span long periods of time (days, weeks) even when one or both systems are rebooted. This allows conversations to be suspended mid-stream (for example, to allow system maintenance) and then resumed without needing to retransmit the entire conversation. [emphasis added]
Now I know how I got confused about WCF and long running services in the first place. Support for long running services was part of the original web services vision!
About three years after that white paper was published, Shy Cohen wrote a post entitled Reliable Messaging Demystified on his blog. Shy was at one time the feature owner of WS-RM in WCF (according to his post) and wrote the following:
Reliable sessions [in WCF] are implemented using the WS-ReliableMessaging protocol. This protocol is yet another misnamed WS-* protocol, as it actually only deals with the reliability of the transfer and says nothing about durability, delivery acknowledgments, TTL for a message, long running sessions where a particular message is lost forever, etc.
At some point in the three years between March 2003 and February 2006, WS-RM went from being the enabler of long running services to “yet another misnamed WS-* protocol”. And with it, WCF lost (never had?) the ability to support long running services (as I’ve written previously).
Now all and all, this isn’t a big deal. I agree with Shy that WS-RM is under specified as mechanism for durable messaging (Shy calls this “queued messaging”). Attempting to build durable messaging on top of WS-RM sounds like it would have been both difficult and unlike to broadly interoperate. So implementing WS-RM for TCP style reliability and leveraging MSMQ as a transport for people that need durable messaging sounds like a pretty good compromise, especially for a v1 product. Of course, it is not exactly unheard of for a project’s end result not to completely live up to the original vision. But I have a specific requirements in this case, so I wanted to know more.
By calling it “misnamed”, it sounds like WS-RM was never really intended to be used for durable messaging. However, the July 2003 Reliable Messaging Feedback Workshop indicates that it was. In particular, Rodney Limprecht’s “Reliable Messaging Scenarios” deck describes WS-RM as supporting scenarios requiring “either volatile or durable endpoint state”. His list of scenarios included both an “Intermittent Connectivity” scenario where “messages pending transfer are staged to disk and exchanged when connected” as well as a “Message Queue Integration” scenario that used WS-RM to interop between JMS and MSMQ. Seems safe to say that WS-RM was originally intended to support durable messaging. So what happened? How did it become “misnamed”?
Rodney’s deck describes WS-RM as having the “flexibility to meet scenario requirements”. But flexibility comes at a cost. For example, the flexibility of WCF’s configuration comes at the cost of significant complexity. In the case of WS-RM, it appears that by trying to make it flexible enough to support both volatile and durable reliability, the authors might have made it too flexible. WS-RM implementers have broad latitude in building the capabilities Shy mentions (durability, acknowledgements, TTL, etc) as well as describing said capabilities in policy. By providing that latitude, we lost the ability to broadly interop durable messaging, which I would suspect is why it ended up out of scope for WCF v1.
As I said before, lack of support for WS-RM based durable messaging isn’t that big a deal. As long as you understand WCF’s sweet spot - the current version’s sweet spot anyway – and don’t try and make it be something it’s not, you should be fine. Furthermore, Shy mentions the need for an “interoperable Queued Messaging specification” and wrote that it’s something he “expect[s] that we will get to it in the near future”. Here’s hoping that spec is less flexible than WS-ReliableMessaging.
Morning Doughnuts 2
- Joel Dehlin, the CIO of the LDS church has an interesting blog entry on buy versus build this morning. His main point is that buying is often cheaper, but only if you can move your business processes to match the processes in the off-the-shelf software.
- The search for Jim Gray by his friends and colleagues has been called off. Even with a massive high-tech effort no new clues have been turned up. For the sake of his family I do hope that the mystery is solved. I would imagine it is very hard to not know what happened to him.
- I am currently running a Build and Deployment Task Force. We are trying to ensure that our team follows best practices when building new applications. The project that Harry and I are working on seems to be a good test bed for the process.
- For those of you who read my blog you know I am passionate about how we implement Service-Oriented Architecture in the real world. I have been reading a book titled Service-Oriented Architecture: A Planning and Implementation Guide for Business and Technology. I find the description of real business objections, and how to solve them quite refreshing.
- It appears that the San Diego Chargers are going to hire Norv Turner to replace Marty Schottenheimer as their head coach. I don’t see how fans of the Chargers can possibly see this as an improvement.