<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <generator uri="https://pub.dev/packages/jaspr">Jaspr</generator>
  <link href="https://kevmoo.com/feed.xml" rel="self" type="application/atom+xml"/>
  <link href="https://kevmoo.com/" rel="alternate" type="text/html"/>
  <updated>2026-05-11T01:42:32.000Z</updated>
  <id>https://kevmoo.com/feed.xml</id>
  <title type="html">kevmoo @ Work</title>
  <subtitle>Googler working on Dart and Flutter web technology</subtitle>
  <entry>
    <title type="html">Migrating to Jaspr</title>
    <link href="https://kevmoo.com/2026/05/migrating-to-jaspr.html" rel="alternate" type="text/html" title="Migrating to Jaspr"/>
    <published>2026-05-11T01:42:32.000Z</published>
    <updated>2026-05-11T01:42:32.000Z</updated>
    <id>https://kevmoo.com/2026/05/migrating-to-jaspr.html</id>
    <content type="html" xml:base="https://kevmoo.com/2026/05/migrating-to-jaspr.html">&lt;p>Hey folks! It’s high time I modernize this blog. Almost 8 years ago, I &lt;a href="https://work.j832.com/2018/04/hello_firebase.html">moved this blog to Firebase Hosting&lt;/a> using a Jekyll static pipeline.&lt;/p> &lt;p>Today, I took the ultimate leap: &lt;strong>I migrated the entire blog to Dart and Jaspr!&lt;/strong>&lt;/p> &lt;p>Here is the complete migration commit: &lt;a href="https://github.com/kevmoo/work.j832.com/commit/c79f4743677ba7cb86b6b7f77efa59aa203d0f96">c79f474367&lt;/a>.&lt;/p> &lt;hr /> &lt;h3>🛠️ The New Shiny Tech Stack&lt;/h3> &lt;p>By moving away from Ruby and Jekyll, I’ve unified the blog entirely under the Dart ecosystem. Here are the core packages driving the new static blog under the hood:&lt;/p> &lt;ul> &lt;li>&lt;strong>&lt;a href="https://pub.dev/packages/jaspr">Jaspr&lt;/a> &amp;amp; &lt;a href="https://pub.dev/packages/jaspr_router">Jaspr Router&lt;/a>:&lt;/strong> Serves as the core component and declarative routing engine, generating lightweight, static HTML page crawls at compile-time.&lt;/li> &lt;li>&lt;strong>&lt;a href="https://pub.dev/packages/markdown">package:markdown&lt;/a>:&lt;/strong> Reading from the old &lt;code>_posts/&lt;/code> into HTML at build time. I need to figure out if there is a new, better way to do this. At the moment I had to make zero changes to the posts, so that's a win.&lt;/li> &lt;li>&lt;strong>&lt;a href="https://pub.dev/packages/yaml">package:yaml&lt;/a>:&lt;/strong> Parses the legacy Jekyll Frontmatter headers (titles, dates, tags, permalinks) to populate our static &lt;code>content.dart&lt;/code> database.&lt;/li> &lt;li>&lt;strong>&lt;a href="https://pub.dev/packages/xml">package:xml&lt;/a>:&lt;/strong> Generate the sitemap and the Atom. Wow. So weird to touch XML again.&lt;/li> &lt;li>&lt;strong>Tailwind CSS v4:&lt;/strong> Provides all utility-first CSS stylings compiled natively via the npm CLI.&lt;/li> &lt;/ul> &lt;p>I don't like having to work around &lt;a href="https://github.com/ShubhamVG/jaspr_tailwind/issues/11">jaspr_tailwind issue #11&lt;/a>. I'll need to investigate if there is a way to wire all of this up without a custom build script calling out to &lt;code>npx&lt;/code>.&lt;/p> &lt;p>In the mean time, at least I have a place to put my &amp;quot;think pieces&amp;quot;.&lt;/p> &lt;p>&amp;quot;thought pieces&amp;quot;?&lt;/p> &lt;p>🤷‍♂️&lt;/p> &lt;p>Happy hacking!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="general"/>
  </entry>
  <entry>
    <title type="html">Hello, Firebase!</title>
    <link href="https://kevmoo.com/2018/04/hello_firebase.html" rel="alternate" type="text/html" title="Hello, Firebase!"/>
    <published>2018-04-20T07:00:00.000Z</published>
    <updated>2018-04-20T07:00:00.000Z</updated>
    <id>https://kevmoo.com/2018/04/hello_firebase.html</id>
    <content type="html" xml:base="https://kevmoo.com/2018/04/hello_firebase.html">&lt;p>&lt;img src="/assets/2018-04-20-firebase_hosting.png" alt="Hello, Firebase!" />&lt;/p> &lt;p>Hey, folks! Almost 3 years ago, I blogged about &lt;a href="/2015/07/hello-github.html">moving my blog from Blogger to GitHub&lt;/a>. It's high time I moved back to Google, right?&lt;/p> &lt;p>Here's &lt;a href="https://github.com/kevmoo/work.j832.com/commit/141d0d9c61">the commit&lt;/a> that updated my config.&lt;/p> &lt;p>The only other wiring was setting the &lt;code>FIREBASE_TOKEN&lt;/code> in Travic-CI to the value returned by running &lt;code>firebase login:ci&lt;/code>. That's about it.&lt;/p> &lt;p>&amp;quot;push to deploy&amp;quot; still works like a champ. The turn-around is super fast. Oh, and it's all on HTTPS.&lt;/p> &lt;p>Cool.&lt;/p> &lt;p>I promise I'll post something before 2020!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="firebase"/>
    <category term="github"/>
    <category term="travis-ci"/>
  </entry>
  <entry>
    <title type="html">Git aliases are awesome, even locally</title>
    <link href="https://kevmoo.com/2015/10/git-alias.html" rel="alternate" type="text/html" title="Git aliases are awesome, even locally"/>
    <published>2015-10-19T07:00:00.000Z</published>
    <updated>2015-10-19T07:00:00.000Z</updated>
    <id>https://kevmoo.com/2015/10/git-alias.html</id>
    <content type="html" xml:base="https://kevmoo.com/2015/10/git-alias.html">&lt;p>&lt;img src="/assets/2015-10-19-git-logo.png" alt="git" />&lt;/p> &lt;p>&lt;em>tl;dr: Define personal, project-specific shell commands as a git alias. It's nice.&lt;/em>&lt;/p> &lt;p>I moved to Jekyll for my blog in July. To run the blog on my dev machine I need to run&lt;/p> &lt;pre>&lt;code class="language-console">&amp;gt; bundle exec jekyll serve --baseurl '' &lt;/code>&lt;/pre> &lt;p>Not too crazy, but it's a pain to remember &lt;em>every time&lt;/em> I want to run the dev server.&lt;/p> &lt;p>I could put a helper script in the root of the directory for my personal blog, but that's not an option with something like the Dart SDK.&lt;/p> &lt;pre>&lt;code class="language-console">&amp;gt; ./tools/build.py --mode=release --arch=ia32 create_sdk &lt;/code>&lt;/pre> &lt;p>I could put an a shell alias in my &lt;code>.profile&lt;/code>, but it doesn't make sense anywhere except the Dart SDK directory.&lt;/p> &lt;p>Enter &lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases">git aliases&lt;/a>.&lt;/p> &lt;p>I've &lt;a href="http://work.j832.com/2013/09/my-global-git-aliases.html">written about my global git aliases&lt;/a>, but I've started using project-local aliases and I'm loving 'em.&lt;/p> &lt;p>For my blog, I tweak &lt;code>.../myblog/.git/config&lt;/code> with:&lt;/p> &lt;pre>&lt;code>[alias] jekyll-serve = !bundle exec jekyll serve --baseurl '' &lt;/code>&lt;/pre> &lt;p>For my clone of the Dart SDK:&lt;/p> &lt;pre>&lt;code>[alias] create-sdk = &amp;quot;!./tools/build.py --mode=release --arch=ia32 create_sdk&amp;quot; &lt;/code>&lt;/pre> &lt;p>Try it out.&lt;/p> &lt;ul> &lt;li>Scoped to the current directory.&lt;/li> &lt;li>Doesn't add any extra files to the repo that need to be ignored.&lt;/li> &lt;li>Auto-complete nicely with &lt;code>git&amp;lt;tab&amp;gt;&lt;/code>.&lt;/li> &lt;/ul></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="git"/>
  </entry>
  <entry>
    <title type="html">Dart: #byojsl - Bring Your Own JavaScript Library</title>
    <link href="https://kevmoo.com/2015/10/byojsl.html" rel="alternate" type="text/html" title="Dart: #byojsl - Bring Your Own JavaScript Library"/>
    <published>2015-10-15T07:00:00.000Z</published>
    <updated>2015-10-15T07:00:00.000Z</updated>
    <id>https://kevmoo.com/2015/10/byojsl.html</id>
    <content type="html" xml:base="https://kevmoo.com/2015/10/byojsl.html">&lt;p>&lt;img src="/assets/2015-10-15-byojsl.png" alt="Bring your own JavaScript to Dart" />&lt;/p> &lt;p>There's a lot of JavaScript libraries. It'd be nice if you could use them seamlessly from Dart, while maintaining Dart's developer-friendly ergonomics.&lt;/p> &lt;p>At the Dart Summit in April, Dan and I &lt;a href="https://www.youtube.com/watch?v=2Ef3ALvbkhA&amp;t=20m53s">talked about our plans&lt;/a> for the future of JavaScript interop: the hashtag-able &lt;code>#byojsl&lt;/code> – &lt;em>Bring Your Own JavaScript Library&lt;/em>.&lt;/p> &lt;p>With the latest preview release of Dart 1.13 – &lt;em>1.13.0-dev.7&lt;/em>, you can now play with this feature.&lt;/p> &lt;p>Check out the &lt;a href="https://github.com/dart-lang/sdk/tree/master/pkg/js/example">example&lt;/a> in the &lt;a href="https://github.com/dart-lang/sdk/tree/master/pkg/js">source code&lt;/a>.&lt;/p> &lt;p>Nice, huh?&lt;/p> &lt;p>Creating the Dart interop libraries using &lt;code>@Js()&lt;/code> annotations allows &lt;code>dart2js&lt;/code> to create very efficient Javascript connections to the source library. The interop libraries also give the users of the interop library the developer experience you expect from Dart code: completions, warnings, errors, etc.&lt;/p> &lt;p>If you want to try it out&lt;/p> &lt;ul> &lt;li>Download the latest &lt;em>dev&lt;/em> release of the Dart SDK - &lt;a href="https://www.dartlang.org/downloads/archive/">dartlang.org/downloads/archive&lt;/a>&lt;/li> &lt;li>The package is published at &lt;a href="https://pub.dartlang.org/packages/js">pub.dartlang.org/packages/js&lt;/a>.&lt;/li> &lt;li>Make sure you specify the right constraint in &lt;code>pubspec.yaml&lt;/code> – &lt;code>js: ^0.6.0-beta&lt;/code>&lt;/li> &lt;/ul> &lt;p>We'll have &lt;em>proper&lt;/em> documentation on the site when 1.13 is ready for release. In the mean time, we'd love feedback as we prepare for the final release.&lt;/p> &lt;p>&lt;em>&lt;a href="https://github.com/kevmoo/work.j832.com/commits/main/_posts/2015-10-15-byojsl.md">Updates since initial publish&lt;/a>&lt;/em>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dart"/>
    <category term="interop"/>
    <category term="javascript"/>
  </entry>
  <entry>
    <title type="html">Hello, GitHub!</title>
    <link href="https://kevmoo.com/2015/07/hello-github.html" rel="alternate" type="text/html" title="Hello, GitHub!"/>
    <published>2015-07-17T07:00:00.000Z</published>
    <updated>2015-07-17T07:00:00.000Z</updated>
    <id>https://kevmoo.com/2015/07/hello-github.html</id>
    <content type="html" xml:base="https://kevmoo.com/2015/07/hello-github.html">&lt;p>As I &lt;a href="https://plus.google.com/+KevinMoore314/posts/GqaQTKm7EdJ">posted&lt;/a> and &lt;a href="https://twitter.com/kevmoo/status/621840012586323968">tweeted&lt;/a> about yesterday, I wanted to see if anyone had experience going from Blogger to &lt;a href="http://jekyllrb.com/">Jekyll&lt;/a> on &lt;a href="http://jekyllrb.com/docs/github-pages/">GitHub&lt;/a>.&lt;/p> &lt;p>No one chimed in, so I dove it.&lt;/p> &lt;p>I need to do some work on theming, but things seem great so far.&lt;/p> &lt;p>Finally blogging in Markdown. So nice.&lt;/p> &lt;p>If you want to take a look at my (evolving) configuration, the &lt;a href="https://github.com/kevmoo/work.j832.com">source is here&lt;/a>.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Dart Dev: do you have unittest:any in your pubspec?</title>
    <link href="https://kevmoo.com/2015/04/dart-dev-do-you-have-unittestany-in.html" rel="alternate" type="text/html" title="Dart Dev: do you have unittest:any in your pubspec?"/>
    <published>2015-04-21T21:40:00.001Z</published>
    <updated>2015-04-21T21:40:00.001Z</updated>
    <id>https://kevmoo.com/2015/04/dart-dev-do-you-have-unittestany-in.html</id>
    <content type="html" xml:base="https://kevmoo.com/2015/04/dart-dev-do-you-have-unittestany-in.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://2.bp.blogspot.com/-lvqT8eit3LQ/UzDpnVcvETI/AAAAAAAAAWg/mLnYDueon8o/s1600/dart_dev_y_u_no.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://2.bp.blogspot.com/-lvqT8eit3LQ/UzDpnVcvETI/AAAAAAAAAWg/mLnYDueon8o/s1600/dart_dev_y_u_no.jpg" />&lt;/a>&lt;/div>&lt;br />&lt;b>tl;dr&lt;/b>&amp;nbsp;If you're using &lt;a href="https://pub.dartlang.org/packages/unittest">unittest&lt;/a>, make sure you have an upper-bound on the package version in your &lt;b>pubspec.yaml&lt;/b>.&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-F2UjocYu7Rw/VTbCWmHSNzI/AAAAAAAADPc/tWalfkmzGl0/s1600/Screen%2BShot%2B2015-04-21%2Bat%2B2.33.55%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/-F2UjocYu7Rw/VTbCWmHSNzI/AAAAAAAADPc/tWalfkmzGl0/s1600/Screen%2BShot%2B2015-04-21%2Bat%2B2.33.55%2BPM.png" height="50" width="320" />&lt;/a>&lt;/div>&lt;br />The new &lt;a href="https://pub.dartlang.org/packages/test">(unit)test&lt;/a> package is almost ready and it's awesome.&lt;br />&lt;br />The 0.12.0 release will be the migration point from &lt;a href="https://pub.dartlang.org/packages/unittest">unittest&lt;/a> to &lt;a href="https://pub.dartlang.org/packages/test">test&lt;/a>.&lt;br />&lt;br />Folks who use unittest will be able to upgrade to 0.12.0 and will get an exported version of test. You'll notice some breaking changes and a lot of deprecations. All future work will happen in the test package, so you'll want to migrate eventually.&lt;br />&lt;br />In the mean time, if you're not ready to migrate, make sure you don't end up with 0.12.0 accidentally.&lt;br />You might wonder why your tests start acting weird.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">Enforce formatting for your Dart projects</title>
    <link href="https://kevmoo.com/2015/04/enforce-formatting-for-your-dart.html" rel="alternate" type="text/html" title="Enforce formatting for your Dart projects"/>
    <published>2015-04-08T21:33:00.005Z</published>
    <updated>2015-04-08T21:33:00.005Z</updated>
    <id>https://kevmoo.com/2015/04/enforce-formatting-for-your-dart.html</id>
    <content type="html" xml:base="https://kevmoo.com/2015/04/enforce-formatting-for-your-dart.html">A while ago, &lt;a href="http://work.j832.com/2015/02/testing-dart-projects-with-latest.html">I wrote&lt;/a> about &lt;a href="https://travis-ci.org/">using Travis&lt;/a>&amp;nbsp;to add continuous integration to your Dart projects.&lt;br />&lt;br />I've started adding a new trick to &lt;code>tool/travis.sh&lt;/code>: format verification.&lt;br />&lt;br />I add a script to my tool directory:&lt;br />&lt;br />&lt;pre>#!/bin/sh&lt;br />dart_files=$(git ls-tree --name-only --full-tree -r HEAD | grep '.dart$')&lt;br />[ -z "$dart_files" ] &amp;amp;&amp;amp; exit 0&lt;br />&lt;br />unformatted=$(dartfmt -n $dart_files)&lt;br />[ -z "$unformatted" ] &amp;amp;&amp;amp; exit 0&lt;br />&lt;br /># Some files are not dartfmt'd. Print message and fail.&lt;br />echo &amp;gt;&amp;amp;2 "dart files must be formatted with dartfmt. Please run:"&lt;br />for fn in $unformatted; do&lt;br /> echo &amp;gt;&amp;amp;2 " dartfmt -w $PWD/$fn"&lt;br />done&lt;br />&lt;br />exit 1&lt;br />&lt;/pre>&lt;br />Then I add a line to the top of &lt;code>travis.sh&lt;/code>: &lt;br />&lt;br />&lt;pre># Ensure the source is formatted&lt;br />$(dirname -- "$0")/ensure_dartfmt.sh&lt;br />&lt;/pre>&lt;br />Here's &lt;a href="https://github.com/dart-lang/dartdoc/commit/bded05b2f3f9a46e5f592f0bddea52d140b7fa67">a commit&lt;/a> that adds this support to the &lt;a href="https://github.com/dart-lang/dartdoc">dartdoc project&lt;/a>.&lt;br />&lt;br />I find it's much easier to collaborate on a code base when a whole pile of formatting arguments are settled upfront.&lt;br />&lt;br />Cool? Let me know if you try this on your project.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Angular.ts.js.at.dart.wtf</title>
    <link href="https://kevmoo.com/2015/03/angulartsjsatdartwtf.html" rel="alternate" type="text/html" title="Angular.ts.js.at.dart.wtf"/>
    <published>2015-03-07T08:41:00.000Z</published>
    <updated>2015-03-07T08:41:00.000Z</updated>
    <id>https://kevmoo.com/2015/03/angulartsjsatdartwtf.html</id>
    <content type="html" xml:base="https://kevmoo.com/2015/03/angulartsjsatdartwtf.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/--u3Tld4-1WM/VPq5f154QaI/AAAAAAAADKw/x7-OX-B-30g/s1600/dart_angular.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/--u3Tld4-1WM/VPq5f154QaI/AAAAAAAADKw/x7-OX-B-30g/s1600/dart_angular.png" />&lt;/a>&lt;/div>&lt;p>You might have heard that &lt;a href="http://blogs.msdn.com/b/somasegar/archive/2015/03/05/typescript-lt-3-angular.aspx">Angular is going to be using TypeScript&lt;/a>.&lt;/p> &lt;p>This has &lt;a href="https://twitter.com/jponge/status/573770185338920960">lead to questions&lt;/a> about the relationship between Angular and Dart.&lt;/p> &lt;p>Let me see if I can help.&lt;/p> &lt;p>&lt;strong>First, Angular 1.&lt;/strong>&lt;/p> &lt;p>Angular 1 JS is crazy popular. Mountains of folks use it. It’s awesome.&lt;/p> &lt;p>&lt;a href="https://github.com/angular/angular.dart">Angular 1 Dart&lt;/a> was a hand-rolled port of Angular 1 JS. It tried to follow the JS flavor of the framework, while being a true Dart framework. While a lot of folks have used Angular 1 Dart, especially within Google, it turned out to be tough to maintain two separate versions of the same framework for two languages.&lt;/p> &lt;p>&lt;strong>Enter Angular 2.&lt;/strong>&lt;/p> &lt;p>Angular 2 &lt;a href="http://angularjs.blogspot.com/2014/10/ng-europe-angular-13-and-beyond.html">was pitched in October&lt;/a> as a better/faster framework built on AtScript – AtScript was an extension of TypeScript from the beginning.&lt;/p> &lt;p>&lt;strong>Important point: Angular 2 has always been built on TypeScript.&lt;/strong>&lt;/p> &lt;p>The &lt;a href="http://blogs.msdn.com/b/somasegar/archive/2015/03/05/typescript-lt-3-angular.aspx">Angular/TypeScript announcement&lt;/a> is amazing news. The features that were added to AtScript are being pulled into TypeScript.&lt;/p> &lt;p>&lt;strong>Important point: AtScript has been merged into TypeScript – one less language to worry about.&lt;/strong>&lt;/p> &lt;p>TypeScript lets the Angular folks build a framework that targets both Javascript and Dart simultaneously. Check out the Angular &lt;a href="https://travis-ci.org/angular/angular">Travis page&lt;/a> to see build output for both languages.&lt;/p> &lt;p>&lt;strong>Important point: Angular 2 has first class support for Javascript AND Dart out of the box.&lt;/strong>&lt;/p> &lt;p>This leaves us with &lt;strong>THE BIG QUESTION:&lt;/strong>&lt;/p> &lt;p>&lt;strong>Why isn’t Angualr 2 just built in Dart?&lt;/strong>&lt;/p> &lt;p>&lt;strong>Answer&lt;/strong>: the Angular folks want to deliver a great framework for BOTH Javascript and Dart.&lt;/p> &lt;p>Dart generates great Javascript for browsers, but we have work to do to generate reusable Javascript libraries.&lt;/p> &lt;p>The Angular team needs to generate reusable Javascript libraries.&lt;/p> &lt;p>&lt;em>&lt;strong>That’s it.&lt;/strong>&lt;/em>&lt;/p> &lt;p>One of my personal goals is to make Dart great for generating JS libraries. We’ll have more to discuss at the &lt;a href="https://www.dartlang.org/events/2015/summit/">Dart summit&lt;/a> in April – &lt;em>psst – &lt;a href="https://dartdevelopersummit.eventfarm.com">you should register&lt;/a>&lt;/em>.&lt;/p> &lt;p>In the mean time, check out the alpha of &lt;a href="https://pub.dartlang.org/packages/angular2">Angular2 Dart package&lt;/a>.&lt;/p> &lt;p>Check out the &lt;a href="https://github.com/angular/angular">Angular GitHub project&lt;/a> if you want to play with Angular for Dart or Javascript – &lt;em>OR BOTH&lt;/em>.&lt;/p> &lt;p>File bugs. File feature requests. Send pull requests.&lt;/p> &lt;p>&lt;em>I’ve had fun using the Dart analyzer to do a &lt;a href="https://github.com/angular/angular/commit/fa259659395cf9f5b5f754af0c145302cafd9385">bunch&lt;/a> of &lt;a href="https://github.com/angular/angular/commit/fb5b168b1928769d5680d78243f7e17e6e4a9457">cleanup&lt;/a> in the Angular source – it’s nice.&lt;/em>&lt;/p> &lt;p>Happy hacking – &lt;em>now with 20% less &lt;a href="http://en.wikipedia.org/wiki/Fear,_uncertainty_and_doubt">FUD&lt;/a>&lt;/em>.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Testing Dart projects with latest release and code coverage</title>
    <link href="https://kevmoo.com/2015/02/testing-dart-projects-with-latest.html" rel="alternate" type="text/html" title="Testing Dart projects with latest release and code coverage"/>
    <published>2015-02-17T23:39:00.000Z</published>
    <updated>2015-02-17T23:39:00.000Z</updated>
    <id>https://kevmoo.com/2015/02/testing-dart-projects-with-latest.html</id>
    <content type="html" xml:base="https://kevmoo.com/2015/02/testing-dart-projects-with-latest.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-q17Mwb3d_no/VOPQ4vgSgGI/AAAAAAAAC4I/3SwQSPTnQuM/s1600/Screen%2BShot%2B2015-02-17%2Bat%2B3.23.02%2BPM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-q17Mwb3d_no/VOPQ4vgSgGI/AAAAAAAAC4I/3SwQSPTnQuM/s1600/Screen%2BShot%2B2015-02-17%2Bat%2B3.23.02%2BPM.png" height="222" width="640" />&lt;/a>&lt;/div>&lt;h3 id="test-your-package-stable-and-dev">Test your package stable and dev&lt;/h3> &lt;p>If you’re using &lt;a href="https://travis-ci.org">Travis CI&lt;/a>, it’s as easy as adding a &lt;code>dart:&lt;/code> entry to your &lt;code>.travis.yml&lt;/code> file. You can specify &lt;code>dev&lt;/code>, &lt;code>stable&lt;/code> or &lt;strong>both&lt;/strong> to make sure your code works great on current and future build of the Dart SDK.&lt;/p> &lt;pre class="prettyprint">&lt;code class="language-yaml hljs haml">language: dart&lt;br />dart: &lt;br /> -&lt;span class="ruby"> dev&lt;br />&lt;/span> -&lt;span class="ruby"> stable&lt;/span>&lt;/code>&lt;/pre> &lt;p>See the &lt;a href="https://github.com/dart-lang/dartdoc/blob/master/.travis.yml">dartdoc project&lt;/a> for an example.&lt;/p> &lt;p>Here’s a &lt;a href="https://travis-ci.org/dart-lang/dartdoc/builds/51143376">build report&lt;/a> for &lt;code>dartdoc&lt;/code> on Travis CI.&lt;/p> &lt;h3 id="getting-code-coverage-with-coverallsio">Getting code coverage with coveralls.io&lt;/h3> &lt;ol>&lt;li>Setup an account on &lt;a href="https://coveralls.io">coveralls.io&lt;/a> using your GitHub account.&lt;/li>&lt;li>Pick the GitHub repo for your project&lt;/li>&lt;li>Get the Coveralls “repo token” for the project.&lt;/li>&lt;li>Populate it in &lt;a href="http://docs.travis-ci.com/user/environment-variables/#Using-Settings">Travis CI Settings&lt;/a> as &lt;code>COVERALLS_TOKEN&lt;/code> – or whatever you like.&lt;/li>&lt;li>Add Coveralls to your &lt;code>travis.sh&lt;/code> script.&lt;/li>&lt;/ol> &lt;pre class="prettyprint">&lt;code class="language-bash hljs ">&lt;span class="hljs-shebang">#!/bin/bash&lt;br />&lt;/span>&lt;br />&lt;span class="hljs-comment"># Fast fail the script on failures. &lt;/span>&lt;br />&lt;span class="hljs-keyword">set&lt;/span> &lt;span class="hljs-operator">-e&lt;/span>&lt;br />&lt;br />&lt;span class="hljs-comment"># Run the tests.&lt;/span>&lt;br />dart --checked test/test_all.dart&lt;br />&lt;br />&lt;span class="hljs-comment"># If the COVERALLS_TOKEN token is set on travis&lt;/span>&lt;br />&lt;span class="hljs-comment"># Install dart_coveralls&lt;/span>&lt;br />&lt;span class="hljs-comment"># Rerun tests with coverage and send to coveralls&lt;/span>&lt;br />&lt;span class="hljs-keyword">if&lt;/span> [ &lt;span class="hljs-string">"&lt;span class="hljs-variable">$COVERALLS_TOKEN&lt;/span>"&lt;/span> ]; &lt;span class="hljs-keyword">then&lt;/span>&lt;br /> pub global activate dart_coveralls&lt;br /> pub global run dart_coveralls report \&lt;br /> --token &lt;span class="hljs-variable">$COVERALLS_TOKEN&lt;/span> \&lt;br /> --retry &lt;span class="hljs-number">2&lt;/span> \&lt;br /> --exclude-test-files \&lt;br /> test/test_all.dart&lt;br />&lt;span class="hljs-keyword">fi&lt;/span>&lt;/code>&lt;/pre> &lt;p>See the &lt;a href="https://github.com/kevmoo/source_gen.dart/blob/master/tool/travis.sh">source_gen project&lt;/a> for an example.&lt;/p> &lt;p>Here’s the &lt;a href="https://coveralls.io/r/kevmoo/source_gen.dart">coverage report&lt;/a> for &lt;code>source_gen&lt;/code> on Coveralls.&lt;/p> &lt;p>Happy hacking!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="CI"/>
    <category term="dart"/>
    <category term="unit testing"/>
    <category term="coverage"/>
    <category term="testing"/>
    <category term="code coverage"/>
    <category term="Dart SDK"/>
    <category term="continuous integration"/>
  </entry>
  <entry>
    <title type="html">Equality and Dart</title>
    <link href="https://kevmoo.com/2014/05/equality-and-dart.html" rel="alternate" type="text/html" title="Equality and Dart"/>
    <published>2014-05-27T01:07:00.001Z</published>
    <updated>2014-05-27T01:07:00.001Z</updated>
    <id>https://kevmoo.com/2014/05/equality-and-dart.html</id>
    <content type="html" xml:base="https://kevmoo.com/2014/05/equality-and-dart.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://2.bp.blogspot.com/-Xj6x0dbVPxA/U1wrVMg0RZI/AAAAAAAALeo/DNGDK-X01Ws/s1600/dart_logo_simple.png" imageanchor="1" style="margin-bottom: 1em; margin-left: 1em;">&lt;img border="0" src="http://2.bp.blogspot.com/-Xj6x0dbVPxA/U1wrVMg0RZI/AAAAAAAALeo/DNGDK-X01Ws/s640/dart_logo_simple.png" />&lt;/a>&lt;/div>&lt;p>A month ago &lt;a href="http://work.j832.com/2014/04/there-are-at-least-two-things-wrong.html">I asked a question on my blog&lt;/a> about a piece of Dart code.&lt;/p>&lt;p>For the below class, what are at least two things wrong with the implementation of &lt;code>operator ==&lt;/code>.&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">Foo&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> _a&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> _b&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> a &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> _a&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> b &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> _b&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;br /> &lt;/span>&lt;span class="pun">...&lt;/span>&lt;span class="pln">&lt;br />&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">operator&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">==(&lt;/span>&lt;span class="typ">Foo&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">return&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">_a &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">_a &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">_b &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">_b&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="pun">}&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;p>A number of guesses were posted to the &lt;a href="https://plus.google.com/+KevinMoore314/posts/KK2qkT2cJ4S">G+ discussion&lt;/a>.&lt;/p>&lt;h1 id="context-designing-types-for-reuse-it-tough">Context: designing types for reuse is tough&lt;/h1>&lt;p>If &lt;code>Foo&lt;/code> is only used within one library – so it should be named &lt;code>_Foo&lt;/code> – the existing implementation &lt;strong>might be totally fine&lt;/strong>.&lt;/p>&lt;p>But if &lt;code>Foo&lt;/code> is…&lt;/p>&lt;ul>&lt;li>Used a lot within a single library or package&lt;/li>&lt;li>Part of a code base with a lot of developers&lt;/li>&lt;li>Part of a public package&lt;/li>&lt;li>Serves as a base class&lt;/li>&lt;/ul>&lt;p>…then you have to think a lot harder about its implementation.&lt;/p>&lt;h1 id="special-equality">Special Equality&lt;/h1>&lt;p>The parameter to &lt;code>operator ==&lt;/code> should always be &lt;code>Object&lt;/code>.&lt;/p>&lt;p>Don’t believe me? Paste the code below into &lt;a href="http://try.dartlang.org/">try.dartlang.org&lt;/a>. I’ll wait.&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">void&lt;/span>&lt;span class="pln"> main&lt;/span>&lt;span class="pun">()&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">var&lt;/span>&lt;span class="pln"> items &lt;/span>&lt;span class="pun">=&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">[&lt;/span>&lt;span class="lit">0&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="lit">1&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">new&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">Bar&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="lit">5&lt;/span>&lt;span class="pun">),&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="lit">6&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="lit">7&lt;/span>&lt;span class="pun">];&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">print&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="pln">items&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">contains&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="lit">6&lt;/span>&lt;span class="pun">));&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;span class="pln">&lt;br />&lt;br />&lt;/span>&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">Bar&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">final&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> value&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="typ">Bar&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">value&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">operator&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">==(&lt;/span>&lt;span class="typ">Bar&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> value &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">value&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;p>&lt;code>operator ==&lt;/code> is used in &lt;code>Iterable&lt;/code> for &lt;code>contains&lt;/code>, &lt;code>where&lt;/code>, and many other methods. &lt;code>Map&lt;/code> also uses &lt;code>==&lt;/code> for its final check after finding matching hash codes. If there is any chance that an instance of your class will have equality checked with any other type – either directly or via &lt;em>very&lt;/em> common Dart classes – you should not make assumptions about the argument to &lt;code>==&lt;/code> except that it’s not &lt;code>null&lt;/code>. Dart takes care of the &lt;code>null&lt;/code> check for you.&lt;/p>&lt;p>This is easy to fix:&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">Bar&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">final&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> value&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="typ">Bar&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">value&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">operator&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">==(&lt;/span>&lt;span class="typ">Object&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> &lt;br /> other &lt;/span>&lt;span class="kwd">is&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">Bar&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> value &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">value&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;h1 id="general-equality">General Equality&lt;/h1>&lt;p>Just like relativistic physics, the special case is pretty straight forward. The general case is a bear.&lt;/p>&lt;p>&lt;em>I read that Special Relativity took Einstein 8 weeks where General Relativity took him 8 years, but I digress.&lt;/em>&lt;/p>&lt;p>The special case is a black-and-white comparison: is the operand the same type as &lt;code>this&lt;/code> or not. The general case introduces a pile of gray.&lt;/p>&lt;p>Dart has &lt;a href="https://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html#ch02-implicit-interfaces">implicit interfaces&lt;/a>. This means anyone can implement your &lt;code>Foo&lt;/code> or &lt;code>Bar&lt;/code> class.&lt;/p>&lt;p>Let’s say we fixed our original example for the special case:&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">Foo&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> _a&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> _b&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> a &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> _a&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> b &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> _b&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">operator&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">==(&lt;/span>&lt;span class="typ">Object&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">return&lt;/span>&lt;span class="pln"> other &lt;/span>&lt;span class="kwd">is&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">Foo&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">_a &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">_a &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">_b &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">_b&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="pun">}&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;p>What if someone &lt;code>implements Foo&lt;/code> in another library.&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">import&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="str">'package:foolib/foolib.dart'&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;br />&lt;/span>&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyFoo&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">implements&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">Foo&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> a &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="lit">41&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> b &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="lit">42&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;p>Try doing &lt;code>if (foo == myFoo)&lt;/code>.&lt;/p>&lt;p>You’ll get a runtime error along the lines of &lt;code>MyFoo does not have instance property _a&lt;/code>.&lt;/p>&lt;h1 id="general-equality-simple-fix">General Equality: simple fix&lt;/h1>&lt;p>The simple fix is, well, simple. Avoid using private members of objects you don’t completely control. In the case of &lt;code>==&lt;/code> that means any private members on &lt;code>other&lt;/code>.&lt;/p>&lt;p>This problem goes beyond &lt;code>operator ==&lt;/code> and extends to &lt;em>any&lt;/em> method &lt;em>anywhere&lt;/em> in your library.&lt;/p>&lt;p>Consider the static &lt;code>distance&lt;/code> method below.&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> num _x&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> num _y&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> num &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> x &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> _x&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> num &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> y &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> _y&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">static&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">double&lt;/span>&lt;span class="pln"> distance&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pln"> a&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pln"> b&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="com">// should you access _x or _y here?&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="pun">}&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;p>See what I mean?&lt;/p>&lt;h1 id="general-equality-simple-mistakes">General Equality: simple mistakes&lt;/h1>&lt;p>Avoiding private members is only part of the problem. Let’s look at &lt;code>MyPoint&lt;/code> again.&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">final&lt;/span>&lt;span class="pln"> num x&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> y&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">x&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">y&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">operator&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">==(&lt;/span>&lt;span class="typ">Object&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln">&lt;br /> other &lt;/span>&lt;span class="kwd">is&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">x &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> x &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">y &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> y&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;p>No private members. No type assumptions. We’re home free! Right?&lt;/p>&lt;p>Try this in &lt;a href="http://try.dartlang.org/">try.dartlang.org&lt;/a>:&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">final&lt;/span>&lt;span class="pln"> num x&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> y&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">x&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">y&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">operator&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">==(&lt;/span>&lt;span class="typ">Object&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln">&lt;br /> other &lt;/span>&lt;span class="kwd">is&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">x &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> x &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">y &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> y&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;span class="pln">&lt;br />&lt;br />&lt;/span>&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint3&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">extends&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">final&lt;/span>&lt;span class="pln"> num z&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="typ">MyPoint3&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="pln">num x&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> num y&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">z&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">:&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">super&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="pln">x&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> y&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">operator&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">==(&lt;/span>&lt;span class="typ">Object&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln">&lt;br /> other &lt;/span>&lt;span class="kwd">is&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint3&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">x &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> x &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">y &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> y &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">z &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> z&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;span class="pln">&lt;br />&lt;br />&lt;/span>&lt;span class="kwd">void&lt;/span>&lt;span class="pln"> main&lt;/span>&lt;span class="pun">()&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">var&lt;/span>&lt;span class="pln"> mp &lt;/span>&lt;span class="pun">=&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">new&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="lit">1&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="lit">2&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">var&lt;/span>&lt;span class="pln"> mp3 &lt;/span>&lt;span class="pun">=&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">new&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">MyPoint3&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="lit">1&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="lit">2&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="lit">3&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln">&lt;br />&lt;br /> &lt;/span>&lt;span class="kwd">print&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="pln">mp &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> mp3&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="com">// true&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">print&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="pln">mp3 &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> mp&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="com">// false&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;p>You’ve just broken one of the &lt;a href="http://mathworld.wolfram.com/EquivalenceRelation.html">three laws of equality&lt;/a>. &lt;/p>&lt;p>Cue &lt;a href="http://youtu.be/JmzuRXLzqKk">mass hysteria&lt;/a>.&lt;/p>&lt;p>There &lt;em>are&lt;/em> solutions to this problem, but they are not simple. We’ll have to bother &lt;a href="https://www.google.com/+FlorianLoitsch">Florian Loitsch&lt;/a> for details.&lt;/p>&lt;p>…and I haven’t even gotten into implementing &lt;code>hashCode&lt;/code> and handling mutable fields – &lt;a href="http://blog.mgm-tp.com/2012/03/hashset-java-puzzler/">here’s a taste&lt;/a>.&lt;/p>&lt;h1 id="now-what">Now what?&lt;/h1>&lt;p>Keep calm, but be paranoid.&lt;/p>&lt;ul>&lt;li>Be careful when implementing &lt;code>==&lt;/code>. &lt;br />&lt;ul>&lt;li>Make sure it’s something you want to sign up for.&lt;/li>&lt;li>Read up on implementing &lt;code>hashCode&lt;/code> correctly.&lt;/li>&lt;li>If you’re class has mutable state, be afraid!&lt;/li>&lt;/ul>&lt;/li>&lt;li>Always type the argument to &lt;code>operator ==&lt;/code> as &lt;code>Object&lt;/code> and do a type check.&lt;/li>&lt;li>If your class is public, remember: any instance of &lt;code>Foo&lt;/code> may not be &lt;em>my&lt;/em> implementation of &lt;code>Foo&lt;/code>. &lt;br />&lt;ul>&lt;li>Stick to the public interface.&lt;/li>&lt;li>Document what you consider equality.&lt;/li>&lt;/ul>&lt;/li>&lt;/ul>&lt;h1 id="an-alternative-public-class-private-implementation">An alternative: public class, private implementation&lt;/h1>&lt;p>If you’ve dug around the Dart source code, you’ve likely seen this pattern:&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">abstract&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">SomeClass&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> a&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="typ">String&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">get&lt;/span>&lt;span class="pln"> b&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> someMethod&lt;/span>&lt;span class="pun">();&lt;/span>&lt;span class="pln">&lt;br />&lt;br /> factory &lt;/span>&lt;span class="typ">SomeClass&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> a&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">String&lt;/span>&lt;span class="pln"> b&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">new&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">_SomeClassImpl&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="pln">a&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> b&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;p>Besides allowing us to efficiently support both the Dart virtual machine and compiling to Javascript, this pattern also allows one to detect random implementations of a type.&lt;/p>&lt;pre class="prettyprint prettyprinted">&lt;code class="language-dart">&lt;span class="kwd">class&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">_SomeClassImpl&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">implements&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">SomeClass&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">{&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">final&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">int&lt;/span>&lt;span class="pln"> a&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">final&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">String&lt;/span>&lt;span class="pln"> b&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> someMethod&lt;/span>&lt;span class="pun">()&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">...&lt;/span>&lt;span class="pln">&lt;br />&lt;br /> &lt;/span>&lt;span class="typ">_SomeClassImpl&lt;/span>&lt;span class="pun">(&lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">a&lt;/span>&lt;span class="pun">,&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">this&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">b&lt;/span>&lt;span class="pun">);&lt;/span>&lt;span class="pln">&lt;br />&lt;br /> &lt;/span>&lt;span class="com">// No impersonators allowed&lt;/span>&lt;span class="pln">&lt;br /> &lt;/span>&lt;span class="kwd">bool&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="kwd">operator&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">==(&lt;/span>&lt;span class="typ">Object&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">)&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">=&amp;gt;&lt;/span>&lt;span class="pln">&lt;br /> other &lt;/span>&lt;span class="kwd">is&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="typ">_SomeClassImpl&lt;/span>&lt;span class="pln"> &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">a &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> a &lt;/span>&lt;span class="pun">&amp;amp;&amp;amp;&lt;/span>&lt;span class="pln"> other&lt;/span>&lt;span class="pun">.&lt;/span>&lt;span class="pln">b &lt;/span>&lt;span class="pun">==&lt;/span>&lt;span class="pln"> b&lt;/span>&lt;span class="pun">;&lt;/span>&lt;span class="pln">&lt;br />&lt;/span>&lt;span class="pun">}&lt;/span>&lt;/code>&lt;/pre>&lt;p>This pattern also allows you to lock down an object system where an arbitrary instance won’t fly.&lt;/p>&lt;p>&lt;code>Future&lt;/code> and &lt;code>Zone&lt;/code> are examples from the Dart SDK. You won’t get very far trying to implement or extend either of them – at least if you try to use them in place of their native implementations.&lt;/p>&lt;p>&lt;em>This post was edited and published using &lt;a href="https://stackedit.io/">StackEdit&lt;/a>. Freakin’ awesome. I may not ditch blogger after all.&lt;/em>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="Programming"/>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">Delivered: Pop, Pop, Win! ported to StageXL</title>
    <link href="https://kevmoo.com/2014/05/delivered-pop-pop-win-ported-to-stagexl.html" rel="alternate" type="text/html" title="Delivered: Pop, Pop, Win! ported to StageXL"/>
    <published>2014-05-02T21:09:00.001Z</published>
    <updated>2014-05-02T21:09:00.001Z</updated>
    <id>https://kevmoo.com/2014/05/delivered-pop-pop-win-ported-to-stagexl.html</id>
    <content type="html" xml:base="https://kevmoo.com/2014/05/delivered-pop-pop-win-ported-to-stagexl.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-MCYGYo0eisQ/U2P__3NWbTI/AAAAAAAAAdA/SEEoRVF0wAM/s1600/xl_pop_pop_win_on_stage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-MCYGYo0eisQ/U2P__3NWbTI/AAAAAAAAAdA/SEEoRVF0wAM/s1600/xl_pop_pop_win_on_stage.png" />&lt;/a>&lt;/div>&lt;br />The Dart Editor ships with a Minesweeper-inspired game –&amp;nbsp;&lt;i>Pop, Pop, Win!&lt;/i>&amp;nbsp;– that I originally hacked together in late 2012.&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-A5467cMYyCg/U2QGooYU6nI/AAAAAAAAAdQ/X_vaWcgguy4/s1600/Screen+Shot+2014-05-02+at+1.30.39+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/-A5467cMYyCg/U2QGooYU6nI/AAAAAAAAAdQ/X_vaWcgguy4/s1600/Screen+Shot+2014-05-02+at+1.30.39+PM.png" />&lt;/a>&lt;/div>About a month ago, I made &lt;a href="http://work.j832.com/2014/03/wanted-hacker-to-port-pop-pop-win-to.html">an open request&lt;/a> for a Dart community member to port the Pop, Pop, Win! demo to &lt;a href="http://www.stagexl.org/">StageXL&lt;/a> – a powerful and flexible 2D graphics library for Dart&amp;nbsp;written by &lt;a href="https://plus.google.com/+BernhardPichler/">Bernhard Pichler&lt;/a>.&lt;br />&lt;br />&lt;a href="https://plus.google.com/+AlexGann/">Alex Gann&lt;/a> stepped up and delivered.&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://3.bp.blogspot.com/-qRT4nd8W0Aw/U2QHlSxSxXI/AAAAAAAAAdg/JYZoDLKq7o0/s1600/Screen+Shot+2014-05-02+at+2.00.58+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://3.bp.blogspot.com/-qRT4nd8W0Aw/U2QHlSxSxXI/AAAAAAAAAdg/JYZoDLKq7o0/s1600/Screen+Shot+2014-05-02+at+2.00.58+PM.png" height="552" width="640" />&lt;/a>&lt;/div>&lt;div class="separator" style="clear: both; text-align: left;">Once Dart v1.4 is released, you'll be able to explorer the source code and run the game from the welcome page of the Dart Editor.&lt;/div>&lt;div class="separator" style="clear: both; text-align: left;">&lt;br />&lt;/div>&lt;div class="separator" style="clear: both; text-align: left;">In the mean time, you can browse the source on the &lt;a href="https://github.com/dart-lang/bleeding_edge/tree/master/dart/samples/pop_pop_win">GitHub source mirror&lt;/a>.&lt;/div>&lt;div class="separator" style="clear: both; text-align: left;">&lt;br />&lt;/div>I'm also keeping a running copy of the latest code on &lt;a href="http://kevmoo.github.io/pop-pop-win/">this GitHub page&lt;/a>.&lt;br />&lt;br />Alex did a bunch of work to optimize image and audio formats, including turning the audio files into a sprite. The download size of the entire game dropped by over a third: from 1.8MB to 1.1MB.&lt;br />&lt;br />You'll also notice you can play games of arbitrary complexity – click on the logo for help and to switch difficulty.&lt;br />&lt;br />Huge thanks to &lt;a href="https://plus.google.com/+AlexGann/">Alex&lt;/a> for his hard work.&lt;br />&lt;br />Huge thanks to &lt;a href="https://plus.google.com/+BernhardPichler/">Bernhard&lt;/a> for the great &lt;a href="http://www.stagexl.org/">StageXL&lt;/a> package and for helping out Alex with a few feature requests during development.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="dart"/>
    <category term="Dartsweeper"/>
    <category term="Dart SDK"/>
  </entry>
  <entry>
    <title type="html">Method Piping - Dart Syntax Proposal</title>
    <link href="https://kevmoo.com/2014/04/method-piping-dart-syntax-proposal.html" rel="alternate" type="text/html" title="Method Piping - Dart Syntax Proposal"/>
    <published>2014-04-28T15:28:00.002Z</published>
    <updated>2014-04-28T15:28:00.002Z</updated>
    <id>https://kevmoo.com/2014/04/method-piping-dart-syntax-proposal.html</id>
    <content type="html" xml:base="https://kevmoo.com/2014/04/method-piping-dart-syntax-proposal.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://3.bp.blogspot.com/-i2ProaKCWzo/U15ZwRwJdAI/AAAAAAAAAco/GCuOKlPoPF4/s1600/dart-nice-pipes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://3.bp.blogspot.com/-i2ProaKCWzo/U15ZwRwJdAI/AAAAAAAAAco/GCuOKlPoPF4/s1600/dart-nice-pipes.png" height="298" width="320" />&lt;/a>&lt;/div>&lt;br />&lt;i>Update 1: I was delighted, but not totally surprised that someone else thought this was a good idea – 2 months ago. &lt;a href="https://plus.google.com/+PatriceChalin/">Patrice Chalin&lt;/a> wrote up &lt;a href="http://pchalin.blogspot.fr/2014/02/case-for-pipe-operator-in-dart.html">the proposal on his blog&lt;/a> in February and filed a &lt;a href="https://code.google.com/p/dart/issues/detail?id=16900">feature request&lt;/a>. I've closed my request as a duplicate of his.&lt;/i>&lt;br />&lt;i>&lt;br />&lt;/i>&lt;i>Disclaimer: &lt;b>This is not in anyway official.&lt;/b> It's an idea. If you're excited about it, great. Please star &lt;a href="https://code.google.com/p/dart/issues/detail?id=16900">the associated issue&lt;/a>. I'm trying to judge interest in the Dart community.&lt;/i>&lt;br />&lt;br />One of the first Dart issues – the 13th, to be precise – was &lt;a href="https://code.google.com/p/dart/issues/detail?id=13">for C#-style extension methods&lt;/a>.&lt;br />&lt;br />This is not possible in a consistent and performant way due to Dart's type system.&lt;br />&lt;br />But I'm pretty sure that most Dart developers that want C#-style extension methods would be happy with something much more simple.&lt;br />&lt;br />Imagine the following code&lt;br />&lt;pre>...&lt;br />class Foo {&lt;br /> ...&lt;br />&amp;nbsp; void fooMethod() {&lt;br /> &amp;nbsp; ...&lt;br />&amp;nbsp; var items = [true, null, "Test", 42];&lt;br />&amp;nbsp; var isEven = _isEven(countWhere(items, (e) =&amp;gt; e is bool)); &lt;br />&amp;nbsp; }&lt;br />}&lt;br />&lt;/pre>&lt;br />&lt;code>_isEven&lt;/code> could be an instance method on &lt;code>Foo&lt;/code>, or a static method on &lt;code>Foo&lt;/code>, or a top-level method in the current library.&lt;br />&lt;br />&lt;code>countWhere&lt;/code> could also be a instance or static method on &lt;code>Foo&lt;/code>, or a top-level method on the current library or an imported library. It could also be a function defined in-line in &lt;code>fooMethod&lt;/code>.&lt;br />&lt;br />Now imagine an alternative syntax for the same behavior, with a new sugar in the form of &lt;code>|&amp;gt;&lt;/code> – the &lt;b>method pipe&lt;/b>. &lt;br />&lt;br />&lt;pre>...&lt;br />class Foo {&lt;br /> ...&lt;br />&amp;nbsp; void fooMethod() {&lt;br /> &amp;nbsp; ...&lt;br />&amp;nbsp; var items = [true, null, "Test", 42];&lt;br />&amp;nbsp; var isEven = items |&amp;gt;&amp;nbsp;countWhere((e) =&amp;gt; e is bool) |&amp;gt; _isEven(); &lt;br />&amp;nbsp; }&lt;br />}&lt;br />&lt;/pre>&lt;br />&lt;b>Method pipe&lt;/b> is simple. Anything of the form&lt;br />&lt;br />&lt;pre>g(f(expression))&lt;/pre>&lt;br />Can be written as&lt;br />&lt;br />&lt;pre>expression |&amp;gt; f() |&amp;gt; g()&lt;/pre>&lt;br />Basically, the expression on the left side of &lt;code>|&amp;gt;&lt;/code> is passed as the first parameter of the function on the right of &lt;code>|&amp;gt;.&lt;/code>&lt;br />&lt;br />What about multiple arguments? Named arguments?&lt;br />&lt;br />If you had function&lt;br />&lt;br />&lt;pre>int count(int a, int b, int c, {int d}) { ... }&lt;/pre>&lt;br />You can call it as&lt;br />&lt;br />&lt;pre>count(1, 2, 3, d: 4);&lt;/pre>&lt;br />or&lt;br />&lt;br />&lt;pre>1 |&amp;gt; count(2, 3, d: 4);&lt;/pre>&lt;br />What if you try to call a method that has no default parameters? Or you try to call a field like a method?&lt;br />&lt;br />The same thing that happens now.&lt;br />&lt;pre>int value = 5;&lt;br />void run({String arg}) { ... }&lt;br />&lt;br />// Today: Warning in the analyzer and errors at runtime&lt;br />value(10);&lt;br />run("test");&lt;br />&lt;br />// Tomorrow: Warnings in the analyzer and errors at runtime;&lt;br />10 |&amp;gt; value();&lt;br />"test" |&amp;gt; run();&lt;br />&lt;/pre>&lt;br />See where I'm going?&lt;br />&lt;br />The method pipe syntax – &lt;code>|&amp;gt;&lt;/code> – is completely up for debate. But I like the model. One could create and import a library full of top-level methods that consume &lt;code>Iterable&lt;/code> – &lt;code>groupBy&lt;/code>, &lt;code>countWhere&lt;/code>, &lt;code>wrapWithUnmodifiableList&lt;/code>, etc and write.&lt;br />&lt;br />&lt;pre>var items = [1, 2, 3, 4, 5];&lt;br />&lt;br />var groups = items |&amp;gt; groupBy((e) =&amp;gt; ...);&lt;br />var evenCount = items |&amp;gt; countWhere((e) =&amp;gt; ...);&lt;br />var readOnly = items |&amp;gt; wrapWithUnmodifiableList();&lt;/pre>&lt;br />Thoughts?&lt;br />&lt;br />Here's the &lt;a href="https://code.google.com/p/dart/issues/detail?id=16900">feature request&lt;/a>.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">There are (at least) two things wrong with this Dart code</title>
    <link href="https://kevmoo.com/2014/04/there-are-at-least-two-things-wrong.html" rel="alternate" type="text/html" title="There are (at least) two things wrong with this Dart code"/>
    <published>2014-04-26T22:45:00.000Z</published>
    <updated>2014-04-26T22:45:00.000Z</updated>
    <id>https://kevmoo.com/2014/04/there-are-at-least-two-things-wrong.html</id>
    <content type="html" xml:base="https://kevmoo.com/2014/04/there-are-at-least-two-things-wrong.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-Xj6x0dbVPxA/U1wrVMg0RZI/AAAAAAAALek/CcKw-Go-lqk/s1600/dart_logo_simple.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-Xj6x0dbVPxA/U1wrVMg0RZI/AAAAAAAALek/CcKw-Go-lqk/s1600/dart_logo_simple.png" />&lt;/a>&lt;/div>&lt;br />Specifically with &lt;code>operator ==&lt;/code>.&lt;br />&lt;br />&lt;pre>class Foo {&lt;br /> int _a;&lt;br /> int _b;&lt;br />&lt;br /> int get a =&amp;gt; _a;&lt;br /> int get b =&amp;gt; _b;&lt;br />&lt;br /> ...&lt;br />&lt;br /> bool operator ==(Foo other) {&lt;br /> return other._a == this._a &amp;amp;&amp;amp; other._b == this._b;&lt;br /> }&lt;br />}&lt;br />&lt;/pre>&lt;br />Any guesses?</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="Programming"/>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">Wanted: Hacker to port Pop, Pop, Win! to StageXL</title>
    <link href="https://kevmoo.com/2014/03/wanted-hacker-to-port-pop-pop-win-to.html" rel="alternate" type="text/html" title="Wanted: Hacker to port Pop, Pop, Win! to StageXL"/>
    <published>2014-03-30T05:29:00.001Z</published>
    <updated>2014-03-30T05:29:00.001Z</updated>
    <id>https://kevmoo.com/2014/03/wanted-hacker-to-port-pop-pop-win-to.html</id>
    <content type="html" xml:base="https://kevmoo.com/2014/03/wanted-hacker-to-port-pop-pop-win-to.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://2.bp.blogspot.com/-e6ewMin1Gq8/UzZXHlHnZjI/AAAAAAAAAYk/kGtMTLGAQvg/s1600/xl_pop_pop_win_on_stage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://2.bp.blogspot.com/-e6ewMin1Gq8/UzZXHlHnZjI/AAAAAAAAAYk/kGtMTLGAQvg/s1600/xl_pop_pop_win_on_stage.png" />&lt;/a>&lt;/div>&lt;br />&lt;i>tl;dr: Want an interesting Dart project? Port &lt;a href="https://github.com/kevmoo/pop-pop-win">Pop, Pop, Win!&lt;/a> to &lt;a href="http://www.stagexl.org/">StageXL&lt;/a>. If you do a good job, you're code will get into the Dart SDK.&lt;/i>&lt;br />&lt;br />When I wrote &lt;a href="http://kevmoo.github.io/pop-pop-win/">Pop, Pop, Win!&lt;/a>&amp;nbsp;I hacked together an HTML Canvas graphics library into &lt;a href="https://github.com/kevmoo/bot_web.dart">bot_web&lt;/a>. The library –&amp;nbsp;&lt;a href="http://kevmoo.github.io/bot_web.dart/#bot_web/bot_retained">bot_retained&lt;/a>&amp;nbsp;–&amp;nbsp;did everything I needed, but I really haven't done much with it in over a year.&lt;br />&lt;br />In the mean time, &lt;a href="http://www.stagexl.org/">StageXL&lt;/a> has been going nuts. It supports rendering to Canvas and WebGL. It supports &lt;a href="http://www.stagexl.org/runtimes/texture_packer.html">Texture Packer&lt;/a>. &lt;a href="https://github.com/bp74">Bernhard&lt;/a> has been keeping it fresh.&lt;br />&lt;br />I'm actively trying to cleanup a bunch of little projects I've built over the last couple of years. Deprecating my own retained graphics library and moving folks towards StageXL seems like goodness.&lt;br />&lt;br />Interested in doing the port?&lt;br />&lt;br />The source code for PPW now &lt;a href="https://github.com/dart-lang/bleeding_edge/tree/master/dart/samples/pop_pop_win">lives in the Dart SDK&lt;/a>. I'd suggest doing a copy-paste of the project into a new Git repository and starting there. The graphics bits are pretty well isolated. If you're pretty serious and can show that you've made a stab, I'm happy to offer help.&lt;br />&lt;br />Dig in. Send me a link to your project on GitHub if you make progress or hit any bumps.&lt;br />&lt;br />Happy hacking!</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="dart"/>
    <category term="Dartsweeper"/>
    <category term="Dart SDK"/>
  </entry>
  <entry>
    <title type="html">Tracking changes to PART of the Dart SDK</title>
    <link href="https://kevmoo.com/2014/03/tracking-changes-to-part-of-dart-sdk.html" rel="alternate" type="text/html" title="Tracking changes to PART of the Dart SDK"/>
    <published>2014-03-28T16:23:00.000Z</published>
    <updated>2014-03-28T16:23:00.000Z</updated>
    <id>https://kevmoo.com/2014/03/tracking-changes-to-part-of-dart-sdk.html</id>
    <content type="html" xml:base="https://kevmoo.com/2014/03/tracking-changes-to-part-of-dart-sdk.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://3.bp.blogspot.com/-hibCA-ulEZY/UzWfN6MIvHI/AAAAAAAAAXw/dHS7emzlOqI/s1600/dart_github_cool.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://3.bp.blogspot.com/-hibCA-ulEZY/UzWfN6MIvHI/AAAAAAAAAXw/dHS7emzlOqI/s1600/dart_github_cool.png" />&lt;/a>&lt;/div>For historical reasons, &lt;a href="https://code.google.com/p/dart/">the Dart project&lt;/a> uses Subversion for source control.&lt;br />&lt;br />There are &lt;a href="https://code.google.com/p/dart/issues/detail?id=12454">a few folks&lt;/a> who would like to use Git for the project, including me, but it's not the top of our priority list.&lt;br />&lt;br />You can get some of the benefits of Git by looking at or even cloning our &lt;a href="https://github.com/dart-lang/bleeding_edge">GitHub mirror&lt;/a>.&lt;br />&lt;br />One of my favorite uses: tracking changes to an individual package.&lt;br />&lt;h2>Steps&lt;/h2>1 - Navigate to a package of interest, say &lt;a href="https://github.com/dart-lang/bleeding_edge/tree/master/dart/pkg/unittest">unittest&lt;/a>.&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-bin0nzS5VQ4/UzWg18029pI/AAAAAAAAAX8/H4iI_bCJLhY/s1600/Screen+Shot+2014-03-28+at+9.18.19+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img alt="" border="0" src="http://1.bp.blogspot.com/-bin0nzS5VQ4/UzWg18029pI/AAAAAAAAAX8/H4iI_bCJLhY/s1600/Screen+Shot+2014-03-28+at+9.18.19+AM.png" height="398" title="" width="640" />&lt;/a>&lt;/div>2 - Click on the &lt;a href="https://github.com/dart-lang/bleeding_edge/commits/master/dart/pkg/unittest">History link&lt;/a>.&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-WznwA_R9j_A/UzWhJV3g-mI/AAAAAAAAAYE/vAdsrrWFLck/s1600/Screen+Shot+2014-03-28+at+9.19.35+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-WznwA_R9j_A/UzWhJV3g-mI/AAAAAAAAAYE/vAdsrrWFLck/s1600/Screen+Shot+2014-03-28+at+9.19.35+AM.png" height="398" width="640" />&lt;/a>&lt;/div>3 - Notice that kevmoo has been making a lot of changes lately.&lt;br />&lt;br />This is a great way to see what changes have happened since the latest release of a package or just to track individual parts of the Dart project.&lt;br />&lt;br />Nice, huh?&lt;br />&lt;br /></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="dart"/>
    <category term="git"/>
    <category term="github"/>
    <category term="Dart SDK"/>
  </entry>
  <entry>
    <title type="html">Dart Package Devs: Put version constraints in your pubspec</title>
    <link href="https://kevmoo.com/2014/03/pubspec-versions.html" rel="alternate" type="text/html" title="Dart Package Devs: Put version constraints in your pubspec"/>
    <published>2014-03-25T19:15:00.002Z</published>
    <updated>2014-03-25T19:15:00.002Z</updated>
    <id>https://kevmoo.com/2014/03/pubspec-versions.html</id>
    <content type="html" xml:base="https://kevmoo.com/2014/03/pubspec-versions.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-cM2ZP_VJ7jo/UzGun2uOYBI/AAAAAAAAAXE/J0qeM5m_0CQ/s3200/dart_dev_y_u_no.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-cM2ZP_VJ7jo/UzGun2uOYBI/AAAAAAAAAXE/J0qeM5m_0CQ/s3200/dart_dev_y_u_no.jpg" />&lt;/a>&lt;/div>&lt;h2>tl;dr&lt;/h2>&lt;div>&lt;ul>&lt;li>Update: &lt;b>this guidance is specific Dart packages&lt;/b>. &lt;i>I'll write about Dart apps soon.&lt;/i>&lt;/li>&lt;li>Read about the &lt;a href="https://www.dartlang.org/tools/pub/versioning.html">Pub Versioning Philosophy&lt;/a>.&lt;/li>&lt;li>If your package uses new features in the SDK or packages, make sure you set an &lt;b>inclusive minimum&lt;/b> version constraint – &lt;code>&amp;gt;= X.Y.Z&lt;/code> – to avoid breaking folks who have not yet upgraded.&lt;/li>&lt;li>Set &lt;b>exclusive maximum&lt;/b> version constraints – &lt;code>&amp;lt;X.Y.Z&lt;/code> – to make sure major releases of the SDK and packages don't break your code.&lt;/li>&lt;li>Understand how pre-v1.0 are versioned with regard to breaking changes.&lt;/li>&lt;li>Take a look at pubspec files in our SDK to understand how we handle versioning. Example: &lt;a href="https://github.com/dart-lang/bleeding_edge/blob/master/dart/pkg/http/pubspec.yaml">http package pubspec.yaml&lt;/a>.&lt;/li>&lt;/ul>&lt;/div>&lt;h2>New features and minimum version constraints&lt;/h2>Dart v1.3 is coming soon. String has learned a few tricks since v1.2, specifically:&lt;br />&lt;ul>&lt;li>String padLeft(int newLength, String padding)&lt;/li>&lt;li>String padLeft(int newLength, String padding)&lt;/li>&lt;li>String trimLeft()&lt;/li>&lt;li>String trimRight()&lt;/li>&lt;/ul>Awesome, right? I can imagine package authors doing the following:&lt;br />&lt;ol>&lt;li>Download Dart 1.3 Editor and SDK&lt;/li>&lt;li>Replace all internal hacks with new String functions.&lt;/li>&lt;li>Release?&lt;/li>&lt;/ol>No! #3 should be: &lt;b>Update your pubspec.yaml&lt;/b>.&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-6B7qiVFA4Sk/UzGuJGkx1BI/AAAAAAAAAW0/bKC5B0A8xuw/s3200/Screen+Shot+2014-03-25+at+9.25.48+AM.png" imageanchor="1">&lt;img border="0" src="http://1.bp.blogspot.com/-6B7qiVFA4Sk/UzGuJGkx1BI/AAAAAAAAAW0/bKC5B0A8xuw/s3200/Screen+Shot+2014-03-25+at+9.25.48+AM.png" height="54" width="320" />&lt;/a>&lt;/div>&lt;div style="text-align: center;">pubspec.yaml content&lt;/div>&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-X2Vhv83Vxas/UzGuLgVxHfI/AAAAAAAAAW8/mVVslRb7-Sg/s3200/Screen+Shot+2014-03-25+at+9.25.34+AM.png" imageanchor="1">&lt;img border="0" src="http://1.bp.blogspot.com/-X2Vhv83Vxas/UzGuLgVxHfI/AAAAAAAAAW8/mVVslRb7-Sg/s3200/Screen+Shot+2014-03-25+at+9.25.34+AM.png" height="37" width="320" />&lt;/a>&lt;/div>&lt;div style="text-align: center;">In the Dart Editor&lt;/div>&lt;br />Setting the &lt;b>minimum&lt;/b> SDK to 1.3.0 tells the pub tools and your users the users that a package requires at least v1.3 of the Dart SDK. Better to get an error from &lt;b>pub install&lt;/b> or &lt;b>pub update&lt;/b> than to get static warnings or runtime errors about missing functions.&lt;br />&lt;br />You'll also notice more than just an &lt;b>inclusive minimum&lt;/b> SDK constraint – &lt;code>&amp;gt;=1.3.0&lt;/code> – there's also an &lt;b>exclusive maximum&lt;/b> SDK constraint – &lt;code>&amp;lt;2.0.0.&lt;/code>&lt;br />&lt;br />Our promise it to follow &lt;a href="http://semver.org/">semantic versioning&lt;/a> for the SDK and our shipped packages. The short version:&lt;br />&lt;ul>&lt;li>For a version X.Y.Z&lt;/li>&lt;li>Increases to Y indicate new features, but no breaking changes.&lt;/li>&lt;li>Increases to X indicate breaking changes.&lt;/li>&lt;/ul>&lt;div>It should be safe to set your maximum SDK version to be any release up to, but &lt;b>not&lt;/b> including, v2.0.&lt;/div>&lt;h2>Packages and pre-v1.0&lt;/h2>&lt;div>The same applies to packages managed by the Dart team, like &lt;a href="http://pub.dartlang.org/packages/unittest">unittest&lt;/a>, &lt;a href="http://pub.dartlang.org/packages/args">args&lt;/a>, &lt;a href="http://pub.dartlang.org/packages/path">path&lt;/a>, etc.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>We have a number of packages that are pre-v1.0 – &lt;b>unittest&lt;/b> is a great example.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>&lt;b>unittest&lt;/b> is one of our oldest and most used packages. We'd really like to lock it down and clean it up before releasing something we consider v1.0.&amp;nbsp;&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>If you look at the &lt;a href="https://github.com/dart-lang/bleeding_edge/blob/master/dart/pkg/unittest/CHANGELOG.md">changelog&lt;/a> for &lt;b>unittest&lt;/b>, you'll see a number of breaking changes between v0.9.2 and v0.10.0.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>For pre-v1.0 packages, we bump the versioning logic up a level, so for version 0.Y.Z, changes to Y are breaking and changes to Z are non-breaking.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Look again at the &lt;a href="https://github.com/dart-lang/bleeding_edge/blob/master/dart/pkg/unittest/CHANGELOG.md">changelog&lt;/a> for &lt;b>unittest&lt;/b>. You'll see a number of features marked as &lt;b>DEPRECATED&lt;/b>. These are things that will likely go away – stop working – in v0.11.0 of &lt;b>unittest&lt;/b>.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>If you want to make sure you code does not suddenly break, you should set a version constraint on unittest of something like &lt;code>&amp;gt;=0.10.0 &amp;lt;0.11.0&lt;/code>.&lt;/div>&lt;h2>Am I missing new hotness?&lt;/h2>&lt;div>A lot of folks dislike setting maximum version constraints.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>&lt;i>I always want to be running the new hotness!&lt;/i>&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>&lt;i>I don't want to miss out on new features!&lt;/i>&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>&lt;b>pub upgrade&lt;/b> is your friend.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>If you run pub upgrade from the console or within the Dart Editor, you'll see useful hints when there are newer versions of packages than what you currently specify.&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-IzC7p9fPtHI/UzHTkdzWoUI/AAAAAAAAAXU/8mhwrn4T7Q8/s1600/pub_upgrade_notice.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/-IzC7p9fPtHI/UzHTkdzWoUI/AAAAAAAAAXU/8mhwrn4T7Q8/s1600/pub_upgrade_notice.png" height="316" width="400" />&lt;/a>&lt;/div>&lt;br />You can then carefully update and check version constraints before you release.&lt;br />&lt;br />If you want to visualize a complex package with many dependencies, check out &lt;a href="https://github.com/kevmoo/pubviz">pubviz&lt;/a>.&lt;br />&lt;br />Happy hacking!&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="pubspec"/>
    <category term="dart"/>
    <category term="pub"/>
    <category term="versioning"/>
  </entry>
  <entry>
    <title type="html">pkg/unittest: shedding some cruft, getting some awesome</title>
    <link href="https://kevmoo.com/2014/02/pkgunittest-shedding-some-cruft-getting.html" rel="alternate" type="text/html" title="pkg/unittest: shedding some cruft, getting some awesome"/>
    <published>2014-02-07T17:17:00.001Z</published>
    <updated>2014-02-07T17:17:00.001Z</updated>
    <id>https://kevmoo.com/2014/02/pkgunittest-shedding-some-cruft-getting.html</id>
    <content type="html" xml:base="https://kevmoo.com/2014/02/pkgunittest-shedding-some-cruft-getting.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-VPuHWCF_jqo/UvURWg2mQGI/AAAAAAAAARU/xhHZ7u4ShXM/s1600/unittest_the_things.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-VPuHWCF_jqo/UvURWg2mQGI/AAAAAAAAARU/xhHZ7u4ShXM/s1600/unittest_the_things.png" height="300" width="400" />&lt;/a>&lt;/div>&lt;div class="separator" style="clear: both; text-align: center;">&lt;br />&lt;/div>&lt;br />&lt;div style="text-align: center;">&lt;b>9:15am 7 Feb, 2014 These changes have not been released to the &lt;a href="http://pub.dartlang.org/packages/unittest">pub site&lt;/a> yet.&lt;/b>&lt;/div>&lt;br />&lt;a href="http://en.wikipedia.org/wiki/Wikipedia:Too_long;_didn't_read">tl;dr&lt;/a>&lt;br />&lt;ul>&lt;li>If you're testing code using Future, Stream, or anything async, you'll notice a lot fewer crashes and a lot more helpful stack traces.&lt;/li>&lt;li>If you're subclassing &lt;a href="https://api.dartlang.org/apidocs/channels/stable/#unittest/unittest.Configuration">Configuration&lt;/a>, keep reading.&lt;/li>&lt;li>If you're using APIs on &lt;a href="https://api.dartlang.org/apidocs/channels/stable/#unittest/unittest.TestCase">TestCase&lt;/a>, keep reading.&lt;/li>&lt;li>If you're just using test, group, expect, etc. you're likely fine.&lt;/li>&lt;li>Update pub dependencies on unittest to includes 0.10.0 to get the new hotness. (You might have something like &lt;code>&amp;gt;=0.9.0 &amp;lt; 0.10.0&lt;/code>, change it to &lt;code>&amp;gt;=0.9.0 &amp;lt;0.11.0&lt;/code>)&lt;/li>&lt;/ul>The upcoming 0.10.0 release of &lt;a href="http://pub.dartlang.org/packages/unittest">unittest&lt;/a> will have a lot of changes. Here's a copy-paste of&lt;a href="https://github.com/dart-lang/bleeding_edge/blob/master/dart/pkg/unittest/CHANGELOG.md"> the current changelog&lt;/a>.&lt;br />&lt;ul>&lt;li>Each test is run in a separate &lt;code>Zone&lt;/code>. This ensures that any exceptions that occur is async operations are reported back to the source test case.&lt;/li>&lt;li>&lt;strong>DEPRECATED&lt;/strong> &lt;code>guardAsync&lt;/code>, &lt;code>protectAsync0&lt;/code>, &lt;code>protectAsync1&lt;/code>, and &lt;code>protectAsync2&lt;/code>&lt;ul>&lt;li>Running each test in a &lt;code>Zone&lt;/code> addresses the need for these methods.&lt;/li>&lt;/ul>&lt;/li>&lt;li>&lt;code>TestCase&lt;/code>: &lt;ul>&lt;li>Removed properties: &lt;code>setUp&lt;/code>, &lt;code>tearDown&lt;/code>, &lt;code>testFunction&lt;/code>&lt;/li>&lt;li>&lt;code>enabled&lt;/code> is now get-only&lt;/li>&lt;li>Removed methods: &lt;code>pass&lt;/code>, &lt;code>fail&lt;/code>, &lt;code>error&lt;/code>&lt;/li>&lt;/ul>&lt;/li>&lt;li>&lt;code>interactive_html_config.dart&lt;/code> has been removed.&lt;/li>&lt;li>&lt;code>runTests&lt;/code>, &lt;code>tearDown&lt;/code>, &lt;code>setUp&lt;/code>, &lt;code>test&lt;/code>, &lt;code>group&lt;/code>, &lt;code>solo_test&lt;/code>, and &lt;code>solo_group&lt;/code> now throw a &lt;code>StateError&lt;/code> if called while tests are running.&lt;/li>&lt;li>&lt;code>rerunTests&lt;/code> has been removed.&lt;/li>&lt;/ul>&lt;div>These changes cover three big areas:&lt;/div>&lt;div>&lt;ul>&lt;li>Remove unsupported APIs. The interactive test case runner hadn't been touched in a long time and it didn't support a number core test case features, like &lt;b>setUp&lt;/b> and &lt;b>TearDown&lt;/b>. The &lt;b>rerunTests&lt;/b> function only existed to support the interactive runner and introduce a lot of weird state in &lt;b>unittest&lt;/b>.&lt;/li>&lt;li>Make &lt;b>TestCase&lt;/b> immutable. Expect more changes here. &lt;b>TestCase&lt;/b> should contain the logic to run the test. The result of the run should be in another object. We're getting there.&lt;/li>&lt;li>Make testing async code easier. All tests are now run in a &lt;a href="https://api.dartlang.org/apidocs/channels/stable/#dart-async.Zone">Zone&lt;/a>. This means all any errors thrown by async operations are now funneled to the calling test case without requiring &lt;b>guardAsync&lt;/b> or a &lt;b>protectAsyncN&lt;/b> function (these are now deprecated).&lt;/li>&lt;/ul>&lt;div>Going forward, we're looking into more changes:&lt;br />&lt;ul>&lt;li>Remove more state from TestCase. &lt;code>enabled&lt;/code>, &lt;code>isComplete&lt;/code>, &lt;code>passed&lt;/code>, and &lt;code>startTime&lt;/code> may be removed from this class and exposed somewhere else.&lt;/li>&lt;li>I'm hoping to have a model where TestCase exposes &lt;code>Future&amp;lt;TestResult&amp;gt; run([Configuration config])&lt;/code> or similar.&lt;/li>&lt;li>More powerful ways to run unit tests, making it easy to run tests is parallel in zones, for example.&lt;/li>&lt;/ul>&lt;div>I'd like &lt;b>unittest&lt;/b> to evolve to expose a very simple API that others can build on, with a layer of "easy" for those that just want to get something tested without a lot of ceremony.&lt;/div>&lt;/div>&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Your thoughts and suggestions are welcome!&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Happy hacking.&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="unittest"/>
    <category term="dart"/>
    <category term="unit testing"/>
    <category term="testing"/>
    <category term="test"/>
  </entry>
  <entry>
    <title type="html">Google Compute + Docker + Dart</title>
    <link href="https://kevmoo.com/2013/12/google-compute-docker-dart.html" rel="alternate" type="text/html" title="Google Compute + Docker + Dart"/>
    <published>2013-12-31T18:52:00.000Z</published>
    <updated>2013-12-31T18:52:00.000Z</updated>
    <id>https://kevmoo.com/2013/12/google-compute-docker-dart.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/12/google-compute-docker-dart.html">Follow the instructions here:&amp;nbsp;&lt;a href="http://docs.docker.io/en/master/installation/google/">http://docs.docker.io/en/master/installation/google/&lt;/a>&lt;br />&lt;br />Assuming the last instruction works:&lt;br />&lt;br />&lt;pre class="code">sudo docker run busybox echo 'docker on GCE \o/'&lt;/pre>&lt;br />Run this:&lt;br />&lt;br />&lt;pre class="code">sudo docker run sethladd/docker-dart dart --version&lt;/pre>&lt;br />You should see something like:&lt;br />&lt;br />&lt;pre class="code">Pulling repository sethladd/docker-dart&lt;br />3df1fbb95c1f: Download complete&lt;br />8dbd9e392a96: Download complete&lt;br />5581b213d8ed: Download complete&lt;br />5242b0ef847e: Download complete&lt;br />33626c0daf8f: Download complete&lt;br />8b9f8f28678f: Download complete&lt;br />3696f4eade8a: Download complete&lt;br />a805a53d4a72: Download complete&lt;br />Dart VM version: 1.0.0.10_r30798 (Mon Dec 2 10:31:15 2013) on "linux_x64"&lt;/pre>&lt;br />You're now running Dart via Docker on Google Compute Cloud.&lt;br />&lt;br />Cool!&lt;br />&lt;br />Props to&amp;nbsp;&lt;a class="g-profile" href="https://plus.google.com/101325807008281187006" target="_blank">+Brian Dorsey&lt;/a>&amp;nbsp;and&amp;nbsp;&lt;a class="g-profile" href="https://plus.google.com/118397406534237711570" target="_blank">+Seth Ladd&lt;/a>&amp;nbsp;for putting the pieces together.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">Joining Google</title>
    <link href="https://kevmoo.com/2013/12/joining-google.html" rel="alternate" type="text/html" title="Joining Google"/>
    <published>2013-12-07T15:11:00.002Z</published>
    <updated>2013-12-07T15:11:00.002Z</updated>
    <id>https://kevmoo.com/2013/12/joining-google.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/12/joining-google.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://2.bp.blogspot.com/-FHmMPGQEm-k/UqM4ppltgDI/AAAAAAAAJS0/O9xAtu90JrA/s1600/google_logo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" height="140" src="http://2.bp.blogspot.com/-FHmMPGQEm-k/UqM4ppltgDI/AAAAAAAAJS0/O9xAtu90JrA/s400/google_logo.png" width="400" />&lt;/a>&lt;/div>&lt;br />&lt;i>I have much less to say than the last &lt;a href="http://work.j832.com/2007/09/i-leaving-microsoft.html" target="_blank">two&lt;/a> &lt;a href="http://work.j832.com/2008/06/i-freelance.html" target="_blank">times&lt;/a> I posted about changing jobs.&lt;/i>&lt;br />&lt;br />After 5 years freelancing, I'm going (back) corporate.&lt;br />&lt;br />After running around the Southern US and South America, my wife and I are ready to settle back in Seattle.&lt;br />&lt;br />After coding in C#, XAML, Ruby, and Javascript, I've finally found a development platform that I'm totally in love with: &lt;a href="https://www.dartlang.org/" target="_blank">Dart&lt;/a>.&amp;nbsp;I want to make it better full time.&lt;br />&lt;br />I'll be working in the &lt;a href="http://goo.gl/maps/Ealkf" target="_blank">Google office in Seattle&lt;/a> with some great folks working on some amazing technology.&lt;br />&lt;br />December 16 is my start date.&lt;br />&lt;br />I can't wait.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">brew install dart-editor</title>
    <link href="https://kevmoo.com/2013/11/if-you-do-any-open-source-development.html" rel="alternate" type="text/html" title="brew install dart-editor"/>
    <published>2013-11-07T23:57:00.002Z</published>
    <updated>2013-11-07T23:57:00.002Z</updated>
    <id>https://kevmoo.com/2013/11/if-you-do-any-open-source-development.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/11/if-you-do-any-open-source-development.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-HjeZl0eQsNc/UnwnZvhUFuI/AAAAAAAAJNA/WQC3m4tm3o4/s1600/brew-install-dart-editor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-HjeZl0eQsNc/UnwnZvhUFuI/AAAAAAAAJNA/WQC3m4tm3o4/s1600/brew-install-dart-editor.png" />&lt;/a>&lt;/div>&lt;br />If you do any open source development on Mac, you're probably using &lt;a href="http://brew.sh/" target="_blank">Homebrew&lt;/a>. (If you haven't heard of Homebrew, &lt;a href="http://mac.tutsplus.com/tutorials/terminal/homebrew-demystified-os-xs-ultimate-package-manager/" target="_blank">read up here&lt;/a>.)&lt;br />&lt;br />I've created a Homebrew formula that will install the Dart SDK, Dart Editor, and optionally content_shell for headless browser testing.&lt;br />&lt;br />&lt;b>Step 1&lt;/b>: "tap" &lt;a href="https://github.com/kevmoo/homebrew-kevmoo" target="_blank">my Homebrew repository&lt;/a> to add the dart-editor formula to your Homebrew installation.&lt;br />&lt;br />&lt;pre class="terminal">~/&amp;gt; &lt;b>brew tap kevmoo/kevmoo&lt;/b>&lt;/pre>&lt;br />&lt;pre class="terminal">Cloning into '/usr/local/Library/Taps/kevmoo-kevmoo'...&lt;br />remote: Counting objects: 227, done.&lt;br />remote: Compressing objects: 100% (154/154), done.&lt;br />remote: Total 227 (delta 73), reused 225 (delta 71)&lt;br />Receiving objects: 100% (227/227), 27.55 KiB | 0 bytes/s, done.&lt;br />Resolving deltas: 100% (73/73), done.&lt;br />Checking connectivity... done&lt;br />Tapped 2 formula&lt;/pre>&lt;br />&lt;b>Step 2&lt;/b>: Install dart-editor. (Add the optional &lt;code>--with-content-shell&lt;/code> flag if you like.)&lt;br />&lt;br />&lt;pre class="terminal">~/&amp;gt; &lt;b>brew install dart-editor --with-content-shell&lt;/b>&lt;/pre>&lt;br />&lt;pre class="terminal">==&amp;gt; Downloading https://gsdview.appspot.com/dart-archive/channels/dev/release/30821/editor/darteditor-macos-x64.zip&lt;br />Already downloaded: /Library/Caches/Homebrew/dart-editor-30821.zip&lt;br />==&amp;gt; Downloading https://gsdview.appspot.com/dart-archive/channels/dev/release/30821/dartium/content_shell-macos-ia32-release.zip&lt;br />Already downloaded: /Library/Caches/Homebrew/dart-editor--content_shell-30821.zip&lt;br />==&amp;gt; Caveats&lt;br />DartEditor.app was installed in:&lt;br /> /usr/local/Cellar/dart-editor/30821&lt;br />&lt;br />To symlink into ~/Applications, you can do:&lt;br /> brew linkapps&lt;br />&lt;/pre>&lt;br />Note the mention of&amp;nbsp;&lt;code>brew linkapps&lt;/code>. This will put a symbolic link to &lt;code>Dart Editor.app&lt;/code> in &lt;code>/Applications&lt;/code> so it's easy to find.&lt;br />&lt;br />&lt;b>What do I get?&lt;/b>&lt;br />&lt;br />You'll have the following binaries added to your Terminal path:&lt;br />&lt;ul>&lt;li>dart&lt;/li>&lt;li>dart2js&lt;/li>&lt;li>dartanalyzer&lt;/li>&lt;li>dartdoc&lt;/li>&lt;li>pub&lt;/li>&lt;li>content_shell (if you added the option)&lt;/li>&lt;/ul>&lt;div>Now you're ready to hack on Dart from the Editor and the command prompt.&lt;br />&lt;br />&lt;b>Why do it this way?&lt;/b>&lt;br />&lt;ul>&lt;li>You get Homebrew conventions for free, which includes putting part of the Dart SDK in the right spot for use from Terminal.&lt;/li>&lt;li>It's easy to uninstall everything.&lt;/li>&lt;li>It's easy to upgrade. brew update updates the dart-editor formula, too.&lt;/li>&lt;li>It's easy to install development versions. Once they are available, you can use &lt;code>brew install dart-editor --devel&lt;/code>&lt;/li>&lt;/ul>&lt;/div>&lt;div>Let me know if you have questions.&lt;br />&lt;br />Pull requests are welcome!&lt;br />&lt;br />Happy hacking!&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="Programming"/>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">Dart to Javascript output size: what a difference a year makes.</title>
    <link href="https://kevmoo.com/2013/10/dart-to-javascript-output-size-what.html" rel="alternate" type="text/html" title="Dart to Javascript output size: what a difference a year makes."/>
    <published>2013-10-31T23:44:00.000Z</published>
    <updated>2013-10-31T23:44:00.000Z</updated>
    <id>https://kevmoo.com/2013/10/dart-to-javascript-output-size-what.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/10/dart-to-javascript-output-size-what.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-E7Jvd8c5PMA/UnLq4_Or7BI/AAAAAAAAJL0/7VXUA7fKzEI/s1600/dart-minify-blog.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/-E7Jvd8c5PMA/UnLq4_Or7BI/AAAAAAAAJL0/7VXUA7fKzEI/s1600/dart-minify-blog.png" />&lt;/a>&lt;/div>&lt;br />About &lt;a href="http://work.j832.com/2012/11/excited-to-see-dart2js-minified-output.html" target="_blank">a year ago I posted&lt;/a> on the improving output size of Dart to Javascript (dart2js) compiler.&lt;br />&lt;div>&lt;br />&lt;/div>&lt;div>For &lt;a href="http://dart-lang.github.io/pop-pop-win/" target="_blank">Pop, Pop, Win!&lt;/a>, I was taking the ~441KB output from dart2js, pumping it through the &lt;a href="https://developers.google.com/closure/compiler/" target="_blank">Google Closure Compiler&lt;/a> to get a Javascript file around 389K.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>With gzip over the wire, the download size was 90KB.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>My words at the time:&lt;/div>&lt;blockquote class="tr_bq">I certainly don't feel I need to justify the javascript output size for non-trivial apps anymore.&lt;/blockquote>&lt;div>That was with build 15005 of the Dart SDK.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>What a difference a year makes.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Today, with the latest trunk release – v0.8.9, build 29656 – we are doing even better.&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://3.bp.blogspot.com/-OKIyZoySELo/UnLl2yy0RHI/AAAAAAAAJLk/M-1Jum0GaPY/s1600/Screen+Shot+2013-10-31+at+6.40.54+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" height="76" src="http://3.bp.blogspot.com/-OKIyZoySELo/UnLl2yy0RHI/AAAAAAAAJLk/M-1Jum0GaPY/s640/Screen+Shot+2013-10-31+at+6.40.54+PM.png" width="640" />&lt;/a>&lt;/div>&lt;br />The dart2js compiler, without the help of other tools, is generating an output file around 263KB. That's 40% smaller that a year ago.&lt;br />&lt;br />The gzip size – which is what really matters, since it's the cost-on-the-wire – is at 70.5KB. Over 20% smaller.&lt;br />&lt;br />This includes content like the&amp;nbsp;&lt;a href="https://github.com/dart-lang/pop-pop-win/blob/master/web/texture_data.dart" target="_blank">texture mapping data&lt;/a> which is 39KB on disk.&lt;br />&lt;br />For an app with high quality images, audio, and fonts the total cost of the compiled code come in right at 4% of the total download for the app.&lt;br />&lt;br />Impressive!&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="dart"/>
    <category term="Dartsweeper"/>
  </entry>
  <entry>
    <title type="html">My Global Git Aliases</title>
    <link href="https://kevmoo.com/2013/09/my-global-git-aliases.html" rel="alternate" type="text/html" title="My Global Git Aliases"/>
    <published>2013-09-25T15:03:00.002Z</published>
    <updated>2013-09-25T15:03:00.002Z</updated>
    <id>https://kevmoo.com/2013/09/my-global-git-aliases.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/09/my-global-git-aliases.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://git-scm.com/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;" target="_blank">&lt;img border="0" height="165" src="http://1.bp.blogspot.com/-110CupVJZPk/UkL0lsk_ddI/AAAAAAAAJJ8/ZX6cwK8AEbs/s400/Git-Logo-2Color.png" width="400" />&lt;/a>&lt;/div>&lt;br />You know you can create your own git commands right? Git supports &lt;a href="http://githowto.com/aliases" target="_blank">custom aliases&lt;/a>. They rock.&lt;br />&lt;br />The hello world examples are just creating shortcuts for existing commands.&lt;br />&lt;blockquote class="tr_bq">&lt;code>git config --global alias.co checkout&lt;/code>&lt;/blockquote>Simple, right?&lt;br />&lt;br />You can put global aliases in your user Git config file: ~/.gitconfig&lt;br />&lt;br />You can also put them in the config file for a given repository: project/.git/config&lt;br />&lt;br />Here's a list of mine.&lt;br />&lt;br />&lt;b>Safe pull.&lt;/b> Always does a fetch, but only updates your local branch if you can fast forward. As easy way to make sure you don't create a merge with upstream due to local weirdness.&lt;br />&lt;br />&lt;i>Definition:&lt;/i> &lt;code>sp = pull --ff-only&lt;/code>&lt;br />&lt;br />&lt;i>Usage:&lt;/i> &lt;code>git sp&lt;/code>&lt;br />&lt;br />&lt;b>Fetch all.&lt;/b> Fetch all remotes for this repository. Used a lot when I have an upstream branch and my fork.&lt;br />&lt;br />&lt;i>Definition:&lt;/i> &lt;code>fa = fetch --all&lt;/code>&lt;br />&lt;br />&lt;i>Usage:&lt;/i> &lt;code>git fa&lt;/code>&lt;br />&lt;br />&lt;b>Grep with a simple string match.&lt;/b> See the full breakout &lt;a href="http://explainshell.com/explain?cmd=git+grep+-I+-F+-n+-e" target="_blank">here&lt;/a>. Basically lets my search for simple strings across text files explicitly without regex. Move into a subdirectory and grep will search only that dir and below. Use it constantly.&lt;br />&lt;br />&lt;i>Definition:&lt;/i> &lt;code>gp = grep -I -F -n -e&lt;/code>&lt;br />&lt;br />&lt;i>Usage:&lt;/i> &lt;code>git gp 'void main('&lt;/code>&lt;br />&lt;br />&lt;b>Grep TODOs.&lt;/b> Find all instances of TODO. Move into a subdirectory and grep will search only that dir and below.&lt;br />&lt;br />&lt;i>Definition:&lt;/i> &lt;code>g2do = grep -n TODO&lt;/code>&lt;br />&lt;br />&lt;i>Usage:&lt;/i> &lt;code>git g2do&lt;/code>&lt;br />&lt;br />&lt;b>Github!&lt;/b> Open the GitHub page for the current repo. Found &lt;a href="https://gist.github.com/igrigorik/6666860" target="_blank">here&lt;/a>. There are a lot of ways to skin this cat. This works for me on mac.&lt;br />&lt;br />&lt;i>Definition:&lt;/i> &lt;code>gh = "!open https://github.$(git config remote.origin.url | cut -f2 -d. | tr ':' /)"&lt;/code>&lt;br />&lt;br />&lt;i>Usage:&lt;/i> &lt;code>git gh&lt;/code>&lt;br />&lt;br />&lt;b>Find file.&lt;/b> Exactly what it says. Finds file where any part of the file path matches the provided string.&lt;br />&lt;br />&lt;i>Definition:&lt;/i> &lt;code>ff = "!git ls-tree -r --name-only HEAD | grep -F"&lt;/code>&lt;br />&lt;br />&lt;i>Usage:&lt;/i> &lt;code>git ff index.html&lt;/code> -- Note, this will include &lt;code>/index.html.haml&lt;/code> and &lt;code>/index.html/resources/foo.png&lt;/code>.&lt;br />&lt;div>&lt;br />Hope you find some of these useful.&lt;br />&lt;br />Happy hacking!&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="git"/>
  </entry>
  <entry>
    <title type="html">Dart: dynamic vs Object in arguments? Pretty straigtforward</title>
    <link href="https://kevmoo.com/2013/09/dart-dynamic-vs-object-in-arguments.html" rel="alternate" type="text/html" title="Dart: dynamic vs Object in arguments? Pretty straigtforward"/>
    <published>2013-09-11T15:03:00.000Z</published>
    <updated>2013-09-11T15:03:00.000Z</updated>
    <id>https://kevmoo.com/2013/09/dart-dynamic-vs-object-in-arguments.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/09/dart-dynamic-vs-object-in-arguments.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-i3jG2Oz3biE/UjCGDnaX9GI/AAAAAAAAJGc/UkWM2qIAO6Q/s1600/object_or_dynamic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" height="320" src="http://4.bp.blogspot.com/-i3jG2Oz3biE/UjCGDnaX9GI/AAAAAAAAJGc/UkWM2qIAO6Q/s320/object_or_dynamic.png" width="316" />&lt;/a>&lt;/div>&lt;br />It's one of those rules that makes total sense the first time you here it.&lt;br />&lt;br />It's actually outlined concisely in the style guide: &lt;a href="https://www.dartlang.org/articles/style-guide/#do-annotate-with-object-instead-of-dynamic-to-indicate-any-object-is-accepted">DO annotate with Object instead of dynamic to indicate any object is accepted.&lt;/a>&lt;br />&lt;br />&lt;pre>// **Use Object**&lt;br />// Accepts any object.&lt;br />void log(Object object) {&lt;br />&amp;nbsp; print(object.toString());&lt;br />}&lt;br />&lt;br />// **Use dynamic**&lt;br />// Only accepts bool or String, which can't be expressed in a type annotation.&lt;br />// Probably should document what we expect arg to be.&lt;br />bool convertToBool(dynamic arg) {&lt;br />&amp;nbsp; if (arg is bool) return arg;&lt;br />&amp;nbsp; if (arg is String) return arg == 'true';&lt;br />&amp;nbsp; throw new&amp;nbsp;ArgumentError('Cannot convert $arg to a bool.');&lt;br />}&lt;/pre>&lt;br />The way I like to think about it: &lt;code>dynamic&lt;/code> is our crutch until Dart has &lt;a href="https://code.google.com/p/dart/issues/detail?id=4938">union types&lt;/a>.&lt;br />&lt;br />Depending on whom you ask, explicitly specifying &lt;code>dynamic&lt;/code> in &lt;code>convertToBool&lt;/code> is unnecessary. But I like being explicit.&lt;br />&lt;br />Happy hacking!</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">Intent to Implement: CollectionView and SelectionManager in Dart for ObservableList</title>
    <link href="https://kevmoo.com/2013/09/intent-to-implement-collectionview-and.html" rel="alternate" type="text/html" title="Intent to Implement: CollectionView and SelectionManager in Dart for ObservableList"/>
    <published>2013-09-09T20:27:00.004Z</published>
    <updated>2013-09-09T20:27:00.004Z</updated>
    <id>https://kevmoo.com/2013/09/intent-to-implement-collectionview-and.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/09/intent-to-implement-collectionview-and.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="https://www.dartlang.org/polymer-dart/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" height="330" src="http://1.bp.blogspot.com/-b-G4LDluczo/Ui4yiV4X_MI/AAAAAAAAJGM/pVTXW-QnY60/s400/polymer.png" width="400" />&lt;/a>&lt;/div>&lt;br />I'm getting into some non-trivial infrastructure and I wanted to put the word out.&lt;br />&lt;br />The story:&lt;br />&lt;ol>&lt;li>The &lt;a href="http://pub.dartlang.org/packages/observe">Observe package&lt;/a> exposes &lt;code>ObservableList&amp;lt;E&amp;gt;&lt;/code>, which works with &lt;a href="http://pub.dartlang.org/packages/mdv">Model Driven Views (mdv)&lt;/a> to enable dynamic lists in your UI. This is all wrapped up with Polymer.&lt;/li>&lt;li>I'd be nice to have a generic way to sort and filter an input list. &lt;code>CollectionView&amp;lt;E&amp;gt;&lt;/code> wraps an &lt;code>ObservableList&amp;lt;E&amp;gt;&lt;/code> with filter and sort properties. Changes to the source list or the properties cause the &lt;code>CollectionView&lt;/code>, which is a readonly implementation of &lt;code>ObservableList&lt;/code> to update accordingly.&lt;/li>&lt;li>&lt;code>SelectionManager&amp;lt;E&amp;gt;&lt;/code> also wraps an &lt;code>ObservableList&amp;lt;E&amp;gt;&lt;/code>. It appears as &lt;code>ObservableList&amp;lt;Selectable&amp;lt;E&amp;gt;&amp;gt;&lt;/code>. &lt;code>Selectable&lt;/code> has two properties: &lt;code>E get value&lt;/code> and &lt;code>bool get isSelected&lt;/code>. It handles the semi-gnarly process of managing selection (single-selection to start with, then multi-selection at some point--hopefully).&lt;/li>&lt;/ol>&lt;div>These are core infrastructure pieces that, frankly, I miss from .NET/WPF.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>I'm not ready to share code yet, but I wanted to give folks a heads-up.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Ideally, these types of concepts would be once (or rarely), tested like crazy, and used everywhere.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>I may try to get them into the &lt;a href="http://pub.dartlang.org/packages/observe">Observe&lt;/a> package at some point, once they are baked.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>If anyone has suggestions, feedback, other implementations, or interest, please let me know.&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">Dart PSA: noSuchMethod - When in Doubt, Don't</title>
    <link href="https://kevmoo.com/2013/07/dart-psa-nosuchmethod-when-in-doubt-dont.html" rel="alternate" type="text/html" title="Dart PSA: noSuchMethod - When in Doubt, Don't"/>
    <published>2013-07-12T14:30:00.002Z</published>
    <updated>2013-07-12T14:30:00.002Z</updated>
    <id>https://kevmoo.com/2013/07/dart-psa-nosuchmethod-when-in-doubt-dont.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/07/dart-psa-nosuchmethod-when-in-doubt-dont.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-hmV9CVoG6yo/UeASdnuJnxI/AAAAAAAAI_E/592jB70HBM8/s1600/public-service-announcement.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/-hmV9CVoG6yo/UeASdnuJnxI/AAAAAAAAI_E/592jB70HBM8/s1600/public-service-announcement.jpg" />&lt;/a>&lt;/div>&lt;br />Public service announcement for Dart developers, especially those publishing packages on Pub.&lt;br />&lt;h2 style="text-align: center;">Don't go crazy with &lt;b>noSuchMethod&lt;/b>.&lt;/h2>&lt;b>noSuchMethod&lt;/b> is kind of like QR codes.&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-bSp8l5DmB88/UeAR_okhdAI/AAAAAAAAI-8/Vyq-b_HcBdI/s1600/tumblr_mktehdaWUF1qdwy8uo1_400.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-bSp8l5DmB88/UeAR_okhdAI/AAAAAAAAI-8/Vyq-b_HcBdI/s1600/tumblr_mktehdaWUF1qdwy8uo1_400.jpg" />&lt;/a>&lt;/div>&lt;br />While funny, I think this goes a bit too far.&lt;br />&lt;br />I do think there are cases where QR codes are useful, but they are limited. Kinda' like &lt;b>noSuchMethod&lt;/b>.&lt;br />&lt;h3>Don't use noSuchMethod to be lazy&lt;/h3>&lt;blockquote class="tr_bq">I know! I'll use&amp;nbsp;&lt;b>noSuchMethod&lt;/b>&amp;nbsp;to emulate getters and setters on my class instead of writing them out by hand. I'll just store all of the values in a Map.&amp;nbsp;My code will &lt;i>seem&lt;/i> pretty and I won't have to worry about adding new properties as I think them up. Oh, and I won't have to worry about updating the constructor either!&lt;/blockquote>&lt;h3>Don't use noSuchMethod to be clever&lt;/h3>&lt;blockquote class="tr_bq">I know! I'll use &lt;b>noSuchMethod&lt;/b> to automagically support &lt;b>method_name&lt;/b>&amp;nbsp;usage for &lt;b>methodName&lt;/b> using reflection since some people like to access members with underscores!&lt;/blockquote>&lt;h3>Don't use noSuchMethod to make Dart look like Ruby&lt;/h3>&lt;blockquote class="tr_bq">I know! I can use &lt;b>noSuchMethod&lt;/b> to make setting up this...uh...thing look like a DSL...uh...thing because a blog once said that DHH or RMS or BBQ or someone smart said that's cool.&lt;/blockquote>Don't.&lt;br />&lt;br />Creating a mock for testing? Probably.&lt;br />Creating a proxy for something dynamic? Maybe.&lt;br />&lt;br />Next time you think about using &lt;b>noSuchMethod&lt;/b>, right click on something &lt;b>real&lt;/b> in the Dart Editor.&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://3.bp.blogspot.com/-bfsB1NFdU2o/UeAOxf0mWQI/AAAAAAAAI-s/leFfga0sv3I/s1600/Screen+Shot+2013-07-12+at+9.49.53+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://3.bp.blogspot.com/-bfsB1NFdU2o/UeAOxf0mWQI/AAAAAAAAI-s/leFfga0sv3I/s1600/Screen+Shot+2013-07-12+at+9.49.53+AM.png" />&lt;/a>&lt;/div>See all of that awesome!&lt;br />&lt;br />Before the VI guys get all huffy puffy about IDE wimps, let me stress this is not just about the IDE.&lt;br />&lt;ul>&lt;li>This is about getting helpful warnings and errors in checked mode.&lt;/li>&lt;li>This is about generating valid, small, efficient Javascript.&lt;/li>&lt;li>This is about generating helpful documentation, even if you don't annotate anything.&lt;/li>&lt;li>This is about the sanity of future users of your libraries and maintainers of your code.&lt;/li>&lt;/ul>So please.&lt;br />&lt;br />Don't use &lt;b>noSuchMethod&lt;/b> unless you &lt;b>have to&lt;/b>.&lt;br />&lt;br />&lt;b>When in doubt, DON'T!&lt;/b>&lt;br />&lt;br />Please.&lt;br />&lt;br />kthxbye.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="rant"/>
    <category term="dartlang"/>
    <category term="Programming"/>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">Reader's Swan Song: Blog First; Tweet, Plus later</title>
    <link href="https://kevmoo.com/2013/07/readers-swan-song-blog-first-tweet-plus.html" rel="alternate" type="text/html" title="Reader's Swan Song: Blog First; Tweet, Plus later"/>
    <published>2013-07-01T19:15:00.001Z</published>
    <updated>2013-07-01T19:15:00.001Z</updated>
    <id>https://kevmoo.com/2013/07/readers-swan-song-blog-first-tweet-plus.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/07/readers-swan-song-blog-first-tweet-plus.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;img border="0" src="http://3.bp.blogspot.com/-wr0NElHDqXQ/UdHMxAexgSI/AAAAAAAAI9c/WOxxaZBQKbM/s1600/feed-logo.png" />&lt;/div>&lt;div>&lt;br />&lt;i>&lt;b>tl;dr&lt;/b>: Do your opining, ranting, lecturing, and quipping on your blog. Drop a link on Google+, Twitter, whatever. Don't grow your content in a walled garden.&lt;/i>&lt;br />&lt;br />I spend my days swimming in a pool of Google's Kool-Aid: Chrome, Dart, Closure Compiler, Plus, Analytics, oh yeah, and Search.&lt;br />&lt;br />Util today, Google Reader (R.I.P.) was towards the top of that list. I'm now one of many jumping between a handful of want-to-be alternatives with no clear winner. While I'm still not settled on how I'm going to consume blogs, I have come to a conclusion on the production side.&lt;br />&lt;br />I'm going to blog more -- a lot more.&lt;br />&lt;br />I have a mountain of love for Google, but in end it's a company with share holders. While my site is set up via Google Apps and Blogger serves my RSS/ATOM feed, I own the domain and the content. I can move it all to Heroku or Azure tomorrow if I wanted.&lt;br />&lt;br />That's a good thing.&lt;br />&lt;br />You don't need to create a Google+ account or ignore sponsored tweets for Hydraulic Fracturing to see my rants.&lt;br />&lt;br />That's also good thing.&lt;br />&lt;br />So let's take the death of Reader as a call to action.&lt;br />&lt;br />Let's restart discussions...&lt;br />&lt;ul>&lt;li>About ATOM and RSS.&lt;/li>&lt;li>About metadata and aggregation.&lt;/li>&lt;li>About annotation and reputation.&lt;/li>&lt;li>About &lt;a href="http://hypothes.is/">hypothes.is&lt;/a> and &lt;a href="https://app.net/">app.net&lt;/a> and other folks trying to evolve a stagnant space.&lt;/li>&lt;/ul>See you on the open, aggregated, hyperlinked, distributed, web.&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="bet on the web"/>
    <category term="general"/>
    <category term="google"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">Dart is a great language for shell programming, too</title>
    <link href="https://kevmoo.com/2013/02/dart-is-great-language-for-shell.html" rel="alternate" type="text/html" title="Dart is a great language for shell programming, too"/>
    <published>2013-02-06T17:32:00.001Z</published>
    <updated>2013-02-06T17:32:00.001Z</updated>
    <id>https://kevmoo.com/2013/02/dart-is-great-language-for-shell.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/02/dart-is-great-language-for-shell.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="https://twitter.com/kevmoo/status/298897666518155264" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://2.bp.blogspot.com/-KcGu6kTfGlY/URKQXkfObBI/AAAAAAAAIIc/JGTufj9wz1M/s1600/Screen+Shot+2013-02-06+at+12.18.00+PM.png" />&lt;/a>&lt;/div>&lt;br />I asked Twitter nicely yesterday. The only response:&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="https://twitter.com/jnazario/statuses/298961519964737536" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/-ySYuemzcB-c/URKQ0CGL2nI/AAAAAAAAIIk/qfGTK0ABMiA/s1600/Screen+Shot+2013-02-06+at+12.19.51+PM.png" />&lt;/a>&lt;/div>&lt;br />I don't dislike writing bash scripts. I hate it. I also hate the lack of&amp;nbsp;portability, as pointed out by&amp;nbsp;&lt;a class="g-profile" href="http://plus.google.com/101409281065555048852" target="_blank">+Daniel Steigerwald&lt;/a>:&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="https://plus.google.com/110066012384188006594/posts/fXfwP82Uw9N" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-tMWAD3Wmy60/URKRQk501yI/AAAAAAAAIIs/dHZhkXfe-fE/s1600/Screen+Shot+2013-02-06+at+12.21.42+PM.png" />&lt;/a>&lt;/div>&lt;br />Great idea,&amp;nbsp;&lt;a class="g-profile" href="http://plus.google.com/101409281065555048852" target="_blank">+Daniel Steigerwald&lt;/a>, but why use NodeJS when I could use Dart?&lt;br />&lt;br />If you fetch the latest version of the &lt;a href="https://github.com/kevmoo/bot.dart">Dart Bag-of-Tricks&lt;/a>, you'll notice a new binary &lt;code>bin/bench&lt;/code>.&lt;br />&lt;br />If you're running bash and &lt;code>dart&lt;/code> is in your path you can execute this directly. Otherwise run it through dart: &lt;code>dart bin/bench&lt;/code>.&lt;br />&lt;br />If you add &lt;code>bot.dart/bin&lt;/code> to your path you can do things like this:&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://3.bp.blogspot.com/-zRwUjyP8h5Q/URKSud1fO_I/AAAAAAAAII0/gIX789r8Vp8/s1600/Screen+Shot+2013-02-06+at+12.26.47+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://3.bp.blogspot.com/-zRwUjyP8h5Q/URKSud1fO_I/AAAAAAAAII0/gIX789r8Vp8/s1600/Screen+Shot+2013-02-06+at+12.26.47+PM.png" />&lt;/a>&lt;/div>There is also a paramater &lt;code>-r, --run_count &amp;nbsp; &amp;nbsp;(defaults to "20")&lt;/code>&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-D6U8UfEsoCI/URKS8J_iCdI/AAAAAAAAII8/O_vHQcxIfJ8/s1600/Screen+Shot+2013-02-06+at+12.27.02+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/-D6U8UfEsoCI/URKS8J_iCdI/AAAAAAAAII8/O_vHQcxIfJ8/s1600/Screen+Shot+2013-02-06+at+12.27.02+PM.png" />&lt;/a>&lt;/div>Dart is more than just a good tool for web apps.&lt;br />&lt;br />Happy hacking.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="Programming"/>
    <category term="dart"/>
  </entry>
  <entry>
    <title type="html">Headless Browser Testing: Dart, DumpRenderTree, drone.io</title>
    <link href="https://kevmoo.com/2013/01/headless-browser-testing-dart.html" rel="alternate" type="text/html" title="Headless Browser Testing: Dart, DumpRenderTree, drone.io"/>
    <published>2013-02-01T03:29:00.002Z</published>
    <updated>2013-02-01T03:29:00.002Z</updated>
    <id>https://kevmoo.com/2013/01/headless-browser-testing-dart.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/01/headless-browser-testing-dart.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://4.bp.blogspot.com/-el8hBxU7v0I/UQrybo2AZDI/AAAAAAAAIH8/-I1adHW5o_E/s1600/bot_logo_headless.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://4.bp.blogspot.com/-el8hBxU7v0I/UQrybo2AZDI/AAAAAAAAIH8/-I1adHW5o_E/s1600/bot_logo_headless.png" />&lt;/a>&lt;/div>When writing any software, even for the web, I try to do as much testing as possible outside the browser.&lt;br />&lt;br />A lot of great testing can be done of algorithms, data models, and business logic without booting up Chrome.&lt;br />&lt;br />Node.js enabled this with Javascript. Dart has had an out-of-browser--read console--story since day one.&lt;br />&lt;br />But some things you must test in a browser.&lt;br />&lt;br />The &lt;a href="https://github.com/kevmoo/bot.dart">Dart Bag of Tricks (BOT)&lt;/a>&amp;nbsp;has had browser tests since the beginning. There are only a few tests that must be run in the browser, but I make sure to run all tests both on the console and in the browser if they can run both places.&lt;br />&lt;br />Browser tests are great, but they don't fit well into a build workflow or a continuous integration tool.&lt;br />&lt;br />For that you need a way to run and control a browser (or a browser-like thing) via the console and get results out. Enter DumpRenderTree.&lt;br />&lt;h2>DumpRenderTree - Chrome without the chrome&lt;/h2>&lt;div>&lt;a href="http://trac.webkit.org/wiki/Writing%20Layout%20Tests%20for%20DumpRenderTree" target="">DumpRenderTree&lt;/a>&amp;nbsp;(DRT)&amp;nbsp;is a great little tool hidden in the guts of &lt;a href="http://www.webkit.org/">WebKit&lt;/a>.&lt;br />&lt;br />By default, DRT prints out an obscure text format representing the hierarchy of elements on the provided page.&lt;br />&lt;/div>&lt;br />Here's the output for &lt;code>DumpRenderTree example/fract/fract_demo.html&lt;/code>&lt;br />&lt;br />&lt;pre>Content-Type: text/plain&lt;br />layer at (0,0) size 808x820&lt;br />&amp;nbsp; RenderView at (0,0) size 800x600&lt;br />layer at (0,0) size 800x820&lt;br />&amp;nbsp; RenderBlock {HTML} at (0,0) size 800x820&lt;br />&amp;nbsp; &amp;nbsp; RenderBody {BODY} at (8,8) size 784x804&lt;br />&amp;nbsp; &amp;nbsp; &amp;nbsp; RenderHTMLCanvas {CANVAS} at (0,0) size 800x800 [bgcolor=#808080]&lt;br />&amp;nbsp; &amp;nbsp; &amp;nbsp; RenderText {#text} at (0,0) size 0x0&lt;br />#EOF&lt;br />#EOF&lt;/pre>&lt;br />DRT is controlled mostly through Javascript in the test page by via &lt;code>window.testRunner&lt;/code>.&lt;br />&lt;br />Here's the script block that lives in &lt;code>test/harness_browser.html&lt;/code>:&lt;br />&lt;br />&lt;pre>&amp;lt;script&amp;gt;&lt;br /> &lt;span style="color: blue;">// only run if testRunner is defined -- we're in DRT&lt;/span>&lt;br /> if (window.testRunner) {&lt;br />&lt;br /> &lt;span style="color: blue;">// Don't dump the structure. Just the text of the output plus console output&lt;/span>&lt;br /> testRunner.dumpAsText();&lt;br />&lt;br /> &lt;span style="color: blue;">// Don't finish when layout is done. Instead, wait to be notified&lt;/span>&lt;br /> testRunner.waitUntilDone();&lt;br />&lt;br /> &lt;span style="color: blue;">// listen for messages from the test harness&lt;/span>&lt;br /> window.addEventListener("message", receiveMessage, false);&lt;br />&lt;br /> &lt;span style="color: blue;">// listen for unhandled exceptions&lt;/span>&lt;br /> window.addEventListener('error', onError);&lt;br /> }&lt;br />&lt;br /> &lt;span style="color: blue;">// if there is an unhandled exception, tell DRT we're done&lt;/span>&lt;br /> function onError(event) {&lt;br /> testRunner.notifyDone();&lt;br /> }&lt;br />&lt;br /> &lt;span style="color: blue;">// if the test harness sends a done message, tell DRT we're done&lt;/span>&lt;br /> function receiveMessage(event) {&lt;br /> if(event.data == 'unittest-suite-done') {&lt;br /> testRunner.notifyDone();&lt;br /> }&lt;br /> }&lt;br />&amp;lt;/script&amp;gt;&lt;br />&lt;/pre>&lt;br />And since everything is keyed off the existence of &lt;code>window.testRunner&lt;/code>, none of this affects the behavior of tests running normally in a browser.&lt;br />&lt;br />Here's the first few lines of output from &lt;code>DumpRenderTree test/harness_browser.html&lt;/code>:&lt;br />&lt;br />&lt;pre>Content-Type: text/plain&lt;br />PASS&lt;br />All 109 tests passed&lt;br />Collapse All&lt;br />bot&lt;br />&amp;nbsp;&lt;br />(4/4)&lt;br />bot - Enumerable&lt;br />&amp;nbsp;&lt;br />(19/19)&lt;br />bot - Enumerable - group&lt;/pre>&lt;br />Compare to the content running the tests in the browser:&lt;br />&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-7w_EmaAPcYw/UQsyPjvYFAI/AAAAAAAAIIM/NYL4js5hnEk/s1600/Screen+Shot+2013-01-31+at+10.09.37+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/-7w_EmaAPcYw/UQsyPjvYFAI/AAAAAAAAIIM/NYL4js5hnEk/s1600/Screen+Shot+2013-01-31+at+10.09.37+PM.png" />&lt;/a>&lt;/div>&lt;br />&lt;h2>Getting DumpRenderTree&lt;/h2>&lt;div>DRT is part of Linux and Windows builds of the Dart Editor now (look in the chromium) directory. It will be part of builds for Mac &lt;a href="https://code.google.com/p/dart/source/detail?r=17909">soon&lt;/a>.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>If you want to get DRT that is compatible with the latest integration build of Dart - 0.3.2.0 (r17657) - grab &lt;a href="http://gsdview.appspot.com/dartium-archive/drt-mac-inc/drt-mac-inc-17651.0.zip">this guy&lt;/a>.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Just make sure the DumpRenderTree executable is on your path when running tests.&lt;/div>&lt;h2>Bringing it all together&lt;/h2>&lt;div>&lt;a href="http://drone.io/">drone.io&lt;/a> supports DumpRenderTree for Dart projects. Read about it &lt;a href="http://docs.drone.io/dart.html">here&lt;/a>.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>The trick is creating a script that returns an exit code of zero for success and not zero (1 is pretty standard) for failure.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Check out the &lt;a href="https://github.com/kevmoo/bot.dart/blob/1b9e186f6234cfcf835a8596533eb660e50dbb22/bin/run_browser_test_drt.sh">script I created&lt;/a> for BOT.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>And let me know how it goes for you.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Happy hacking.&lt;/div>&lt;div>&lt;br />&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="dart"/>
    <category term="testing"/>
    <category term="DumpRenderTree"/>
  </entry>
  <entry>
    <title type="html">Dart Widgets Dev Journal 1 - Basic Animations</title>
    <link href="https://kevmoo.com/2013/01/tldr-implementing-features-similar-to.html" rel="alternate" type="text/html" title="Dart Widgets Dev Journal 1 - Basic Animations"/>
    <published>2013-01-11T17:50:00.002Z</published>
    <updated>2013-01-11T17:50:00.002Z</updated>
    <id>https://kevmoo.com/2013/01/tldr-implementing-features-similar-to.html</id>
    <content type="html" xml:base="https://kevmoo.com/2013/01/tldr-implementing-features-similar-to.html">&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://kevmoo.github.com/widget.dart/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://2.bp.blogspot.com/-GziCm1MUz28/UPBNIGEa1KI/AAAAAAAAIFs/L2IPI__Zka4/s1600/Screen+Shot+2013-01-11+at+12.00.54+PM.png" />&lt;/a>&lt;/div>&lt;blockquote class="tr_bq">&lt;a href="http://en.wiktionary.org/wiki/TLDR">tl;dr&lt;/a>: Implementing features similar to &lt;a href="http://twitter.github.com/bootstrap/">Bootstrap&lt;/a> is hard without basic animation support in Dart. Basic animation support is not as easy as you'd think. &lt;a href="https://github.com/kevmoo/widget.dart">I've made a stab&lt;/a>. &lt;a href="http://kevmoo.github.com/widget.dart/">Check out the demo&lt;/a>.&lt;/blockquote>I've started a new Dart project - &lt;a href="https://github.com/kevmoo/widget.dart/">Dart Widgets&lt;/a>. The inspiration is &lt;a href="http://twitter.github.com/bootstrap/">Bootstrap&lt;/a>, but with a focus on features that map cleanly to &lt;a href="https://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html">Web Components&lt;/a>.&lt;br />&lt;br />While digging into Bootstrap, I realized that there was a heavy dependency on &lt;a href="http://jquery.com/">jQuery&lt;/a>--specifically the &lt;a href="http://api.jquery.com/category/effects/basics/">show/hide/toggle&lt;/a> functionality. This is critical for expanders, menus, modals, pretty much everything.&lt;br />&lt;h2>Show, hide, toggle&lt;/h2>It turns out implementing show/hide/toggle is not as easy as one might guess.&lt;br />&lt;br />One could naively toggle &lt;code>display: none;&lt;/code> in an element's style attribute and call it a day, but a lot of edge cases would be missed.&lt;br />&lt;br />Throw in the ability to optionally animate the show/hide behavior and things get a lot more complicated.&lt;br />&lt;br />A short list of the cases to ponder:&lt;br />&lt;br />&lt;ul>&lt;li>Element with a non-standard display value. (e.g. a div inherited a display of inline-block)&lt;/li>&lt;li>Element with a local display of none&amp;nbsp;&lt;/li>&lt;li>Element inherited a display of none&lt;/li>&lt;li>Show is called while an element is hiding and vice versa&lt;/li>&lt;li>Toggle is called 10 times before the first animation finishes&lt;/li>&lt;li>Show is called on an element with effect A while effect B is hiding it.&lt;/li>&lt;/ul>Huge props to the jQuery and jQuery-ui folks for tackling this problem. Their code served a great starting spot. I feel bad that they had to implement this logic in Javascript.&lt;br />&lt;h2>Test&lt;/h2>I can't tell you how valuable test-driven development was in getting this project off the ground. It would have been next to impossible to ensure all of the edge cases were handled cleanly.&lt;br />&lt;br />I need to write another post about how my approach to testing in Dart has evolved. Let's just say I didn't code up 939 tests by hand.&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="https://github.com/kevmoo/widget.dart/" imageanchor="1">&lt;img border="0" height="476" src="http://3.bp.blogspot.com/--JP3TGuagMk/UPBOirhAPII/AAAAAAAAIF8/QiFrC-ZMmtY/s640/Screen+Shot+2013-01-11+at+12.28.41+PM.png" width="640" />&lt;/a>&lt;/div>After a lot of head scratching, I think I ended up with pretty clean, extensible model.&lt;br />&lt;br />As proof, I offer the &lt;a href="https://github.com/kevmoo/widget.dart/blob/b1cec11ff67cafe94a7c954f7e759b1211b1576f/lib/src/effects/css3_transition_effects.dart#L52">code&lt;/a> for doing a open/close door effect:&lt;br />&lt;br />&lt;pre>&lt;b>class&lt;/b> DoorEffect &lt;b>extends&lt;/b> Css3TransitionEffect {&lt;br /> DoorEffect() : &lt;b>super&lt;/b>(&lt;br /> '-webkit-transform',&lt;br /> 'perspective(1000px) rotateY(90deg)',&lt;br /> 'perspective(1000px) rotateY(0deg)',&lt;br /> {'-webkit-transform-origin': '0% 50%'}&lt;br /> );&lt;br />}&lt;/pre>&lt;br />There are still a few things I'd like to get working--&lt;a href="https://github.com/kevmoo/widget.dart/issues/8">get tests working in Firefox&lt;/a>, &lt;a href="https://github.com/kevmoo/widget.dart/issues/7">find a way to handle browser prefixes cleanly&lt;/a>--but generally I'm happy with progress.&lt;br />&lt;br />Check out the &lt;a href="http://kevmoo.github.com/widget.dart/">demo&lt;/a>.&lt;br />&lt;br />Check out the &lt;a href="https://github.com/kevmoo/widget.dart/">code&lt;/a>.&lt;br />&lt;br />Let me know what you think.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="Programming"/>
  </entry>
  <entry>
    <title type="html">Excited to see dart2js minified output getting smaller (real world numbers below)</title>
    <link href="https://kevmoo.com/2012/11/excited-to-see-dart2js-minified-output.html" rel="alternate" type="text/html" title="Excited to see dart2js minified output getting smaller (real world numbers below)"/>
    <published>2012-11-16T14:58:00.003Z</published>
    <updated>2012-11-16T14:58:00.003Z</updated>
    <id>https://kevmoo.com/2012/11/excited-to-see-dart2js-minified-output.html</id>
    <content type="html" xml:base="https://kevmoo.com/2012/11/excited-to-see-dart2js-minified-output.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;/div>&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="https://www.dartlang.org/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://gravatar.com/avatar/a6dba8dde1d2e987545720e40b4a529c?s=200" />&lt;/a>&lt;/div>&lt;br />&lt;br />I noticed &lt;a href="http://code.google.com/p/dart/source/detail?r=15005">r15005&lt;/a> turns on more renaming in dart2js with --minify so I thought I'd see the impact on &lt;a href="http://dart-lang.github.com/pop-pop-win/">Pop, Pop, Win!&lt;/a>&lt;br />&lt;br />The last time I did a build and deploy of PPW was on r14873.&lt;br />&lt;br />Here are the sizes of game.dart.js&lt;br />&lt;br />&lt;table>&lt;tbody>&lt;tr>&lt;td>dart2js&lt;/td>&lt;td>617,201 bytes&lt;/td>&lt;/tr>&lt;tr>&lt;td>closure compiler&lt;/td>&lt;td>621.07KB&lt;/td>&lt;/tr>&lt;tr>&lt;td>gzip (via http)&lt;/td>&lt;td>107.7KB&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>&lt;br />Notes:&lt;br />&lt;ul>&lt;li>dart2js is running with the --minify flag&lt;/li>&lt;li>I'm using the &lt;a href="http://code.google.com/p/closure-compiler/">closure-compiler&lt;/a> with default settings. Build from 17 Sept, 2012&lt;/li>&lt;li>Notice how the output is bigger from closure? This is because output is optimized for gzip. Not intuitive, until you see the network panel in Chrome Dev Tools.&lt;/li>&lt;li>gzip is the size Chrome sees over the wire. Most servers gzip payloads. It's critical to pay attention to this number and not just the size on disk.&lt;/li>&lt;/ul>&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-8-5r9ATUd6o/UKZT8R0UpzI/AAAAAAAAIBE/_5gpcnBdJ9w/s1600/Screen+Shot+2012-11-16+at+8.56.51+AM.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;">&lt;img border="0" height="46" src="http://1.bp.blogspot.com/-8-5r9ATUd6o/UKZT8R0UpzI/AAAAAAAAIBE/_5gpcnBdJ9w/s640/Screen+Shot+2012-11-16+at+8.56.51+AM.jpg" width="640" />&lt;/a>&lt;/div>&lt;br />Now with the bleeding edge build r15005&lt;br />&lt;br />&lt;table>&lt;tbody>&lt;tr>&lt;td>dart2js&lt;/td>&lt;td>451,183 bytes&lt;/td>&lt;td>&lt;b>~33% smaller&lt;/b>&lt;/td>&lt;/tr>&lt;tr>&lt;td>closure compiler&lt;/td>&lt;td>388.71 KB&lt;/td>&lt;td>&lt;b>~37% smaller&lt;/b>&lt;/td>&lt;/tr>&lt;tr>&lt;td>gzip (via http)&lt;/td>&lt;td>90.2KB&lt;/td>&lt;td>&lt;b>~16% smaller&lt;/b>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://1.bp.blogspot.com/-nSFvHp0lbYY/UKZUDNN3tYI/AAAAAAAAIBM/l04l1M31IqY/s1600/Screen+Shot+2012-11-16+at+9.47.56+AM.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;">&lt;img border="0" src="http://1.bp.blogspot.com/-nSFvHp0lbYY/UKZUDNN3tYI/AAAAAAAAIBM/l04l1M31IqY/s1600/Screen+Shot+2012-11-16+at+9.47.56+AM.png" />&lt;/a>&lt;/div>&lt;br />Notes:&lt;br />&lt;ul>&lt;li>The output from dart2js is &lt;b>substantially smaller&lt;/b>. This is just the work from the dart2js guys recently. Amazing.&lt;/li>&lt;li>This time the output from the closure is smaller than the input (~12%). I can only speculate why. Perhaps the new minified output is more optimizable?&lt;/li>&lt;li>The gain with gzip is not as big (~16%). I'm not surprised by this. PPW is a pretty big game. The json that stores the texture data alone is huge.&lt;/li>&lt;/ul>&lt;br />Keep in mind, the Dart source for the game is 1.5 MB as reported by dart2js.&lt;br />&lt;blockquote class="tr_bq">&lt;span style="font-family: Courier New, Courier, monospace;">info: compiled 1576654 bytes Dart -&amp;gt; 451183 bytes JavaScript in web/game.dart.js&lt;/span>&lt;/blockquote>Is it fair to say we're getting ~94% smaller output? It depends on how valid one considers the the Dart code size reported by dart2js.&lt;br />&lt;br />But I certainly don't feel I need to justify the javascript output size for non-trivial apps anymore.&lt;br />&lt;br />Great work folks!</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
  </entry>
  <entry>
    <title type="html">Dartsweeper: Dev Journal 3--Graphics, Animation, Audio</title>
    <link href="https://kevmoo.com/2012/09/dartsweeper-dev-journal-3-graphics.html" rel="alternate" type="text/html" title="Dartsweeper: Dev Journal 3--Graphics, Animation, Audio"/>
    <published>2012-09-19T17:17:00.002Z</published>
    <updated>2012-09-19T17:17:00.002Z</updated>
    <id>https://kevmoo.com/2012/09/dartsweeper-dev-journal-3-graphics.html</id>
    <content type="html" xml:base="https://kevmoo.com/2012/09/dartsweeper-dev-journal-3-graphics.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;/div>&lt;div class="separator" style="clear: both; text-align: center;">&lt;br />&lt;/div>&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://sweeper.j832.com/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" height="640" src="http://3.bp.blogspot.com/-dXHbIXS4qrQ/UFn1-VsqexI/AAAAAAAAHQY/F7N2-fuTsiw/s640/Screen+Shot+2012-09-19+at+12.42.01+PM.png" width="630" />&lt;/a>&lt;/div>I've been busy the last few weeks. I've had to give more time to another gig, so I've slowed my progress on the &lt;strike>Dartsweeper&lt;/strike> Pop, Pop, Win! But I've made some great tractions. Check out the demo at &lt;a href="http://sweeper.j832.com/">sweeper.j832.com&lt;/a>.&lt;br />&lt;a href="http://draft.blogger.com/">&lt;/a>&lt;br />&lt;h2>Graphics and animation with TexturePacker&lt;/h2>&lt;div>Graphics for the Pop, Pop Win! (PPW) are packaged using &lt;a href="http://www.codeandweb.com/texturepacker">TexturePacker&lt;/a>. TexturePacker takes a number of source images and produces an optimized &lt;a href="http://www.altdevblogaday.com/2012/09/17/building-an-html5-game-dont-shrug-off-atlases/" target="_blank">texture atlas&lt;/a>.&lt;br />&lt;br />PPW has two texture files: &lt;a href="http://sweeper.j832.com/dart_opaque_01.jpg" target="_blank">one for square textures&lt;/a> (that don't have transparency) and &lt;a href="http://sweeper.j832.com/dart_transparent_01.png" target="_blank">one for the textures that need transparency&lt;/a>. Using a jpeg for the textures that don't require transparency saves a lot of bandwidth.&lt;br />&lt;br />TexturePacker outputs a map file that provides the location of each source image in the output map. Initially I was given an XML file which I parsed with the&amp;nbsp;&lt;a href="https://github.com/prujohn/dart-xml" target="_blank">dart-xml&lt;/a> library. (Thanks, &lt;a href="https://plus.google.com/115427174005651655317/posts">John&lt;/a>!) I converted the XML to JSON which I stored as a string in code and deserialized with &lt;a href="http://api.dartlang.org/docs/continuous/dart_json.html" target="_blank">dart:json&lt;/a>.&lt;br />&lt;br />Then I realized I was being dumb.&lt;br />&lt;br />First, I learned TexturePacker can output json directly. So long xml parsing.&lt;br />&lt;br />Second, I realized that valid json can be provided as a literal for &lt;a href="http://api.dartlang.org/docs/continuous/dart_core/Map.html" target="_blank">Map&lt;/a> in Dart. Goodbye JSON decoding.&lt;br />&lt;br />Using some simple canvas tricks, I can now easily display graphics and animations representing over one hundred source textures using only two input files.&lt;/div>&lt;h2>Audio&lt;/h2>&lt;div>Supporting audio is super easy with &lt;a href="http://api.dartlang.org/docs/continuous/dart_html/AudioContext.html" target="_blank">AudioContext&lt;/a>. I started with the &lt;a href="http://www.html5rocks.com/en/tutorials/webaudio/intro/js/buffer-loader.js" target="_blank">BufferLoader&lt;/a> sample from an &lt;a href="http://www.html5rocks.com/en/tutorials/webaudio/intro/" target="_blank">HTML5 Rocks tutorial&lt;/a> and converted it to Dart.&lt;br />&lt;br />I went a bit further and generalized all of my resource loading into an abstract ResourceLoader class which is then subclassed by ImageLoader and AudioLoader. I plan to migrate these classes into &lt;a href="https://github.com/kevmoo/dartlib">dartlib&lt;/a> in the near future.&lt;br />&lt;br />Easy.&lt;/div>&lt;h2>Issues&lt;/h2>&lt;div>In my &lt;a href="http://work.j832.com/2012/08/dartsweeper-dev-journal-2-now-with.html" target="_blank">last post&lt;/a>, I mentioned an issue using offsetX and offsetY in MouseEvent in Firefox. The &lt;a href="http://code.google.com/p/dart/issues/detail?id=1087" target="_blank">bug has been fixed&lt;/a> so I removed my work around.&lt;br />&lt;br />The other glaring issue is the lack of audio support on browsers other than Chrome. Chrome is the only browser that supports AudioContext (that I tried). I've dealt with cross-browser game audio before--see Agent8ball--and I'm not super excited to fix it here. In the mean, just use Chrome.&lt;/div>&lt;h2>Next Steps&lt;/h2>&lt;div>&lt;br />&lt;ul>&lt;li>A few more graphics tweaks.&lt;/li>&lt;li>A few more sound effects.&lt;/li>&lt;li>Mobile support.&lt;/li>&lt;li>Some loading UI.&amp;nbsp;&lt;/li>&lt;/ul>&lt;/div>&lt;h2>You can help&lt;/h2>&lt;div>Don't forget all the &lt;a href="https://github.com/kevmoo/sweeper.dart" target="_blank">source is on GitHub&lt;/a>. &lt;a href="https://github.com/kevmoo/sweeper.dart/issues">Open issues&lt;/a>. Fork it.&lt;br />&lt;br />Let me know if you have any questions.&lt;br />&lt;br />Happy hacking...and popping.&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="Programming"/>
    <category term="Dartsweeper"/>
  </entry>
  <entry>
    <title type="html">Dartsweeper: Dev Journal 2--now with Canvas</title>
    <link href="https://kevmoo.com/2012/08/dartsweeper-dev-journal-2-now-with.html" rel="alternate" type="text/html" title="Dartsweeper: Dev Journal 2--now with Canvas"/>
    <published>2012-08-23T18:14:00.000Z</published>
    <updated>2012-08-23T18:14:00.000Z</updated>
    <id>https://kevmoo.com/2012/08/dartsweeper-dev-journal-2-now-with.html</id>
    <content type="html" xml:base="https://kevmoo.com/2012/08/dartsweeper-dev-journal-2-now-with.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://sweeper.j832.com/canvas/" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" height="640" src="http://4.bp.blogspot.com/-S83-1A7djM4/UDPshhm-KMI/AAAAAAAAHIE/gseNb5wzRT8/s640/Screen+Shot+2012-08-21+at+4.15.40+PM.png" width="433" />&lt;/a>&lt;/div>&lt;h2>Looks can be&amp;nbsp;deceiving&lt;/h2>&lt;div>Looks about the same as &lt;a href="http://work.j832.com/2012/08/dartsweeper-dev-journal-1.html">last time&lt;/a>, right? The visuals and interaction were designed to be almost identical, but the plumbing is very different.&lt;br />&lt;br />The original, &lt;a href="http://sweeper.j832.com/">HTML DOM version&lt;/a> used a table to render the game board. It's straight forward to let DOM elements handle layout and mouse interaction. Throw in a little CSS and you have a functional—albeit ugly—game.&lt;br />&lt;br />But if one wants to make something really amazing, without fighting a&amp;nbsp;Matryoshka doll of layout and CSS issues, one should leave the DOM behind.&lt;br />&lt;br />Since I've decided leaving the third&amp;nbsp;dimension for later, HTML canvas is an obvious choice. I also have a bit of of experience building games on canvas. See &lt;a href="http://agent8ball.com/">Agent 8 Ball&lt;/a> and &lt;a href="http://thinkpixellab.com/portfolio/throwingstars/">our work for Ze Frank&lt;/a>.&lt;br />&lt;h2>Darts on Canvas&lt;/h2>The &lt;a href="http://sweeper.j832.com/canvas">working version of Dartsweeper&lt;/a> does all of its drawing and click handeling via canvas.&amp;nbsp;Canvas is an&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Immediate_mode">immediate mode&lt;/a>&amp;nbsp;graphics API. It's simple and straight-forward. It's also easy to have code complexity blow up once you start building anything complex.&lt;br />&lt;br />When I was building out the UI layer for Throwing Stars for Mr. Frank, I wanted an object-oriented way to think about game elements. I wanted a star object and a wall object and a coin object that encapsulated the game physics and element rendering. So I put on my &lt;a href="http://www.joelonsoftware.com/articles/fog0000000018.html">astronaut suit&lt;/a>&amp;nbsp;and built the &lt;a href="http://thinkpixellab.github.com/pl/">PL javascript library&lt;/a>.&amp;nbsp;PL is short for &lt;a href="http://thinkpixellab.com/">Pixel Lab&lt;/a>.&lt;br />&lt;br />A big chunk of PL is under the &lt;a href="https://github.com/thinkpixellab/pl/tree/master/src/retained">retained namespace&lt;/a>. It's a collection of types for &lt;a href="http://en.wikipedia.org/wiki/Retained_mode">retained mode&lt;/a> graphics on canvas. I've &lt;a href="https://github.com/kevmoo/dartlib/tree/master/lib/retained">ported most of the retained libraries&lt;/a> to my dartlib project and they are used heavily in Sweeper.&lt;/div>&lt;h2>Retained mode with Dartlib&lt;/h2>&lt;div>I'll probably do a video at some point about the retained model in dartlib. The short version:&lt;/div>&lt;div>&lt;ul>&lt;li>&lt;a href="https://github.com/kevmoo/dartlib/blob/master/lib/retained/stage.dart">Stage&lt;/a>: The glue between the DOM (a HTML Canvas element) and a root "element" in the retained world.&lt;/li>&lt;li>&lt;a href="https://github.com/kevmoo/dartlib/blob/master/lib/retained/pelement.dart">PElement&lt;/a>: The base class for visual elements in the retained world.&lt;/li>&lt;ul>&lt;li>Drawing is done with CanvasRenderContext2d. Super simple.&lt;/li>&lt;ul>&lt;li>&lt;a href="http://api.dartlang.org/docs/continuous/dart_html/CanvasRenderingContext2D.html">Dart API docs&lt;/a>&lt;/li>&lt;li>&lt;a href="https://developer.mozilla.org/en-US/docs/DOM/CanvasRenderingContext2D">Mozilla docs&lt;/a>&lt;/li>&lt;/ul>&lt;li>Zero or more transforms, which allow layout by the parent and fun effects&lt;/li>&lt;li>Parent and child pointers&lt;/li>&lt;ul>&lt;li>Allow hit testing and mouse interaction&lt;/li>&lt;/ul>&lt;li>The P prefix stands for Pixel Lab. I'm trying to avoid naming conflicts with &lt;a href="http://api.dartlang.org/docs/continuous/dart_html/Element.html">Element&lt;/a>.&lt;/li>&lt;/ul>&lt;/ul>There's a bunch of other magic here, too. Mouse support. An attached property and attached event model. Support for correct Click behavior (mouse down the mouse up on the same element). Check out the samples in dartlib.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>If you're feeling really&amp;nbsp;adventurous, take a look at &lt;a href="https://github.com/kevmoo/vote.dart">vote.dart&lt;/a>. I have a lot of fun with retained graphics.&lt;/div>&lt;h2>Issues&lt;/h2>&lt;h3>Cross-browser confusion&lt;/h3>&lt;div>I've run into a couple of issues when trying to play the JS-compiled version of Dartsweeper on Firefox.&amp;nbsp;&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>In one case, I was using a webkit-specific version of requestAnimationFrame which doesn't exist on FireFox. Thankfully, Seth pointer me to the un-prefixed version of the API that works everywhere. &lt;a href="http://code.google.com/p/dart/issues/detail?id=4585">A bug is open&lt;/a> to removed the webkit prefixes.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>In another case I discovered MouseEvent.offset[X|Y] don't exist in FireFox. There is &lt;a href="http://code.google.com/p/dart/issues/detail?id=1087">a bug on this&lt;/a>, too. I added a &lt;a href="https://github.com/kevmoo/dartlib/commit/b7c9b55f6b39307d1abdbff745e15c1998c8157d">helper to dartlib&lt;/a> provide the same functionality.&lt;/div>&lt;h3>Growing pains with pub&lt;/h3>I'm started tip-toeing into &lt;a href="http://www.dartlang.org/docs/pub-package-manager/">pub&lt;/a> by migrating unit test code away from the copy in dartlib (which has been removed) to the SDK version.&lt;br />&lt;br />Setting up pub has caused me a bit of stress since I use a &lt;a href="https://gist.github.com/2933621">custom homebrew formula&lt;/a> to keep my SDK updated. Pub needs the DART_SDK environment variable to be set and homebrew installs versions in directories based on the version number. This causes a bit of headache as I need to delete the packages directory and rerun &lt;b>pub install&lt;/b> every time I update my copy of Dart.&lt;br />&lt;br />It's a bit of a headache, but it's purely related to how I install Dart. I'm hoping to tweak the homebrew formula to resolve this issue soon.&lt;br />&lt;h2>Next Steps&lt;/h2>All of the work to migrate the game to canvas would be a bit silly if the output still looks like a poorly styled table.&lt;br />&lt;br />After I finish up work storing high scores and created a touch-enabled interaction model, I'm going to jump into custom graphics, animation, and sound.&lt;br />&lt;br />I'm excited. Stay tuned.&lt;br />&lt;h2>Oh, and you can help&lt;/h2>All of the &lt;a href="https://github.com/kevmoo/sweeper.dart">code is on github&lt;/a>. File issues. Fork and add features. I'd love collaborators.&lt;br />&lt;br />If you'd be interested in doing a hangout to discuss my graphics model, let me know.&lt;br />&lt;br />Cheers.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="Programming"/>
    <category term="Dartsweeper"/>
    <category term="internet"/>
  </entry>
  <entry>
    <title type="html">Are you ready to bet on the Web? Let's talk.</title>
    <link href="https://kevmoo.com/2012/08/are-you-ready-to-bet-on-web-lets-talk.html" rel="alternate" type="text/html" title="Are you ready to bet on the Web? Let's talk."/>
    <published>2012-08-20T23:33:00.001Z</published>
    <updated>2012-08-20T23:33:00.001Z</updated>
    <id>https://kevmoo.com/2012/08/are-you-ready-to-bet-on-web-lets-talk.html</id>
    <content type="html" xml:base="https://kevmoo.com/2012/08/are-you-ready-to-bet-on-web-lets-talk.html">&lt;br />&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://3.bp.blogspot.com/-E_6nW7Cm30A/UDLGLEC-EoI/AAAAAAAAHH0/Bdkde5_W-9w/s1600/bet_on_the_web.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://3.bp.blogspot.com/-E_6nW7Cm30A/UDLGLEC-EoI/AAAAAAAAHH0/Bdkde5_W-9w/s1600/bet_on_the_web.png" />&lt;/a>&lt;/div>&lt;br />Are you maintaining a legacy applications written in VB6? Windows Forms? Java?&lt;br />Are you relying on ActiveX and outdated browsers?&lt;br />Are you unsure how to support new devices, new form factors, and new platforms?&lt;br />&lt;br />Do you have a Web&amp;nbsp;presence, but lack a Web mindset?&lt;br />&lt;br />&lt;a href="mailto:talk@kevinmooreconsulting.com">Let's talk.&lt;/a>&lt;br />&lt;br />As a consultant, I have had the opportunity to work on a lot of different projects and platforms.&lt;br />&lt;br />Big enterprise apps with .NET.&lt;br />Fun and engaging apps for iOS.&lt;br />&lt;br />Beautiful games with Javascript and HTML5.&lt;br />&lt;br />&lt;br />I've had pretty good luck having interesting work find me.&lt;br />&lt;br />Now I'm turning the tables.&lt;br />&lt;br />I've learned a lot building frameworks and applications both using enterprise development technologies that target a single platform and open source tools and technologies that target the standards-based Web.&lt;br />&lt;br />I want to help bring tools and methodologies used by leading-edge companies and startups to organizations that feel stuck and left behind.&lt;br />&lt;br />Is that you?&lt;br />&lt;br />Does your an organization want to cross the chasm?&lt;br />&lt;br />&lt;a href="mailto:talk@kevinmooreconsulting.com">Let's talk.&lt;/a>&lt;br /></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="bet on the web"/>
  </entry>
  <entry>
    <title type="html">Dartsweeper: Dev Journal 1</title>
    <link href="https://kevmoo.com/2012/08/dartsweeper-dev-journal-1.html" rel="alternate" type="text/html" title="Dartsweeper: Dev Journal 1"/>
    <published>2012-08-16T18:16:00.001Z</published>
    <updated>2012-08-16T18:16:00.001Z</updated>
    <id>https://kevmoo.com/2012/08/dartsweeper-dev-journal-1.html</id>
    <content type="html" xml:base="https://kevmoo.com/2012/08/dartsweeper-dev-journal-1.html">&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;">&lt;tbody>&lt;tr>&lt;td style="text-align: center;">&lt;a href="http://sweeper.j832.com/" imageanchor="1" style="margin-left: auto; margin-right: auto;">&lt;img border="0" height="508" src="http://4.bp.blogspot.com/-guDQMXuKIRw/UCwIcfruSEI/AAAAAAAAHCk/QXIRrykUkCI/s640/Screen+Shot+2012-08-15+at+4.36.53+PM.png" width="640" />&lt;/a>&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>&lt;a href="http://en.wikipedia.org/wiki/Wikipedia:Too_long;_didn't_read">tl;dr&lt;/a>: I'm building a version of &lt;a href="http://en.wikipedia.org/wiki/Minesweeper_(video_game)">Minesweeper&lt;/a> in &lt;a href="http://www.dartlang.org/">Dart&lt;/a>&amp;nbsp;as an example of&amp;nbsp;something straight-forward and fun. I hope to show how to build Dart apps and demonstrate why Dart is a great tool for building web&amp;nbsp;experiences. Play it &lt;a href="http://sweeper.j832.com/">&lt;span id="goog_107169435">&lt;/span>here&lt;span id="goog_107169436">&lt;/span>&lt;/a>. Check out the &lt;a href="https://github.com/kevmoo/sweeper.dart">code on Github&lt;/a>. Watch my blog for updates in the next few weeks.&lt;br />&lt;h2>Intro&lt;/h2>I'm having a lot of fun with Dart. It's a great intersection of the things I love about other platforms.&lt;br />&lt;ul>&lt;li>The open source goodness of Ruby and Python.&lt;/li>&lt;li>The type goodness of C# and Java--which lights up a productive IDE development experience.&lt;/li>&lt;li>The run everywhere goodness of Javascript.&lt;/li>&lt;/ul>I've built a &lt;a href="https://github.com/kevmoo/dartlib">couple&lt;/a> &lt;a href="https://github.com/kevmoo/vote.dart">projects&lt;/a> in Dart, but I wanted to build something for newbies.&lt;br />&lt;h2>Getting the Code&lt;/h2>&lt;div>Dartsweeper uses my &lt;a href="https://github.com/kevmoo/dartlib">Dartlib&lt;/a> library. I haven't quite migrated Dartlib to &lt;a href="http://www.dartlang.org/docs/pub-package-manager/">pub&lt;/a>. If you want to play with the code, make sure you download (or git clone) both the code for Dartsweeper and Dartlib and put them in adjacent directories.&lt;/div>&lt;div>&lt;ul>&lt;li>source_code&lt;/li>&lt;ul>&lt;li>sweeper.dart&lt;/li>&lt;ul>&lt;li>lib&lt;/li>&lt;li>html&lt;/li>&lt;li>readme.md (for sweeper)&lt;/li>&lt;li>...&lt;/li>&lt;/ul>&lt;li>dartlib&lt;/li>&lt;ul>&lt;li>bin&lt;/li>&lt;li>docs&lt;/li>&lt;li>readme.md (for dartlib)&lt;/li>&lt;li>...&lt;/li>&lt;/ul>&lt;/ul>&lt;/ul>If you're using &lt;a href="http://www.dartlang.org/docs/editor/">Dart Editor&lt;/a>,&amp;nbsp;which I recommend, open both directories to see all of the code.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://3.bp.blogspot.com/-ivuASKIiSd0/UC0zfaMWCeI/AAAAAAAAHDs/njxVgAL-AJE/s1600/Screen+Shot+2012-08-16+at+1.52.32+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;">&lt;img border="0" src="http://3.bp.blogspot.com/-ivuASKIiSd0/UC0zfaMWCeI/AAAAAAAAHDs/njxVgAL-AJE/s1600/Screen+Shot+2012-08-16+at+1.52.32+PM.png" />&lt;/a>&lt;/div>&lt;h2>Approach&lt;/h2>Honestly, I'm a bit confused and tired of the whole MVVMVPMVC discussion.&lt;br />&lt;br />Let me put my approach simply: &lt;a href="http://en.wikipedia.org/wiki/Separation_of_concerns">Separation&amp;nbsp;of Concern (SOC)&lt;/a>. Build small pieces that do a small set of things and connect them in clean ways. It enables easy unit testing. It enables flexible architecture. It avoids &lt;a href="http://en.wiktionary.org/wiki/bikeshedding">bike shedding&lt;/a> about what's the V or the C or the VM or the P.&lt;br />&lt;br />The other acronym I'll hang my hat on: &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD&lt;/a>. Test-driven development is amazing generally, but especially for games. Games often have states that take a while to get to--like winning. Games that have random state--like Dartsweeper--can also suffer from obscure edge casses that one can only find by playing a lot.&lt;br />&lt;br />It ends up being much easier to just point a unit test at a Game object and have it hammer through a large number of game states.&lt;br />&lt;br />But I'm getting ahead of myself. Follow along in the &lt;a href="https://github.com/kevmoo/sweeper.dart/tree/master/lib">lib directory&lt;/a> in the repo.&lt;br />&lt;h3>lib/sweeper directory&lt;/h3>&lt;div>Main logic of the game. Nothing UI-specific.&lt;/div>&lt;br />&lt;ul>&lt;li>&lt;b>Field&lt;/b>: The read-only, 2-D collection of squares. Booleans. True if it's a mine. Also exposes the adjacent count to make rendering numbers easy.&lt;/li>&lt;li>&lt;b>Game&lt;/b>: The core logic. Tracks the state of the game. Allows revealing and flagging. Exposes the duration of the game.&lt;/li>&lt;li>&lt;b>GameState&lt;/b> and &lt;b>SquareState&lt;/b>: enum-like classes for recording the state of the game or individual squares&lt;/li>&lt;/ul>Take a look at the associated &lt;a href="https://github.com/kevmoo/sweeper.dart/tree/master/test/sweeper">unit tests&lt;/a>. Dart advertises itself as "batteries included". An example: the core libraries include a really nice unit test framework.&lt;br />&lt;h3>lib/html&lt;/h3>The HTML version of the game.&lt;br />&lt;ul>&lt;li>&lt;b>GameView&lt;/b>:&amp;nbsp;Populates the provided DOM elements and wires up event handles.&lt;/li>&lt;/ul>&lt;h3>html&lt;/h3>&lt;div>Where you actual application exists.&lt;/div>&lt;div>&lt;ul>&lt;li>&lt;b>sweeper_demo.dart&lt;/b>: A tiny bit of code that imports the game logic and the html logic, finds the target elements in the page, and creates the GameView.&lt;/li>&lt;li>&lt;b>index.html&lt;/b>: Defines the elements for the app. Aside from a couple of special script tags, it's just HTML, which is the point.&lt;/li>&lt;li>&lt;b>style.css&lt;/b>: Just styles. Nothing special.&lt;/li>&lt;/ul>&lt;/div>&lt;h2>Experience&lt;/h2>So far I haven't hit many big issues with the app. It's a joy to work in an IDE with a typed language.&lt;br />&lt;br />I'm much less scared about refactoring code in Dart because I get warnings if I've forgotten to rename a variable or if I'm missing an argument to a method. Not only does the type system make initial development faster (with features like member completion), it makes code maintenance easier. This is a huge win.&lt;br />&lt;br />Being able to debug Dart source directly (instead of generated javascript) also greatly improves productivity.&lt;br />&lt;br />I have hit a couple of bumps, though.&lt;br />&lt;h2>Issues&lt;/h2>&lt;h3>Compiled Javascript size&lt;/h3>&lt;div>It's huge. Far bigger than the source Dart code in my project. It's been the source of mockery on Hacker News, etc.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>While it's a bit annoying now, I'm not worried. At the moment, compiler processes all of the imported libraries (even the code that's not used) and generates output that's not minified. Tools like the &lt;a href="https://developers.google.com/closure/compiler/">Closure Compiler&lt;/a> have shown this a solved problem. The Dart team is worried about stability and correctness now, as they should. I'm patient.&lt;/div>&lt;h3>Minor cross-browser issues&lt;/h3>&lt;div>I was using MouseEvent.toElement, which is not supported in FireFox. I &lt;a href="https://github.com/kevmoo/sweeper.dart/commit/4057d58a84c776c2fc7b6b3205e8e9766238a5da#diff-1">moved to MouseEvent.currentTarget&lt;/a> and everything now works. This is a case where having the uncompressed javascript output was a good thing. It was debug the output to find the problem.&amp;nbsp;&lt;/div>&lt;h2>Future&lt;/h2>&lt;div>Canvas, sound, mobile. I already have a nice set of retained graphics libraries in Dartlib. I going to dive in with animations and the &lt;a href="http://www.html5rocks.com/en/tutorials/webaudio/games/">Web Audio API&lt;/a>. I'll keep the existing HTML app in place, since it's such a straight-forward sample. Once I figure out a clean interaction model, I also hope to make Dartsweeper sing on phones and tables.&lt;br />&lt;br />I'm excited to see how much I can light up this app with Dart.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Stay tuned.&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="Programming"/>
    <category term="Dartsweeper"/>
    <category term="internet"/>
  </entry>
  <entry>
    <title type="html">QR Code Generation in Dart</title>
    <link href="https://kevmoo.com/2012/07/qr-code-generation-in-dart.html" rel="alternate" type="text/html" title="QR Code Generation in Dart"/>
    <published>2012-07-21T04:25:00.000Z</published>
    <updated>2012-07-21T04:25:00.000Z</updated>
    <id>https://kevmoo.com/2012/07/qr-code-generation-in-dart.html</id>
    <content type="html" xml:base="https://kevmoo.com/2012/07/qr-code-generation-in-dart.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;img border="0" height="320" src="http://4.bp.blogspot.com/-MCRz_5fDiYs/UAotnSOwrYI/AAAAAAAAGp8/fsYHZa-TY28/s320/Screen+Shot+2012-07-20+at+9.18.17+PM.png" width="318" />&lt;/div>&lt;div class="separator" style="clear: both; text-align: center;">&lt;br />&lt;/div>&lt;div class="separator">I've ported the QR Code logic from my &lt;a href="https://github.com/thinkpixellab/pl">pl javascript library&lt;/a> into &lt;a href="https://github.com/kevmoo/dartlib">dartlib&lt;/a>. I don't have funky animations yet, but:&lt;/div>&lt;div class="separator">&lt;/div>&lt;ul>&lt;li>The QR Code is generated off-thread using isolates.&lt;/li>&lt;li>It compiles to Javascript. &lt;a href="https://github.com/kevmoo/dartlib/commit/7f95fb2691a5ed97326f11ba28d5ec87ec3e5872#samples/qr/qr_demo.dart.js">~9,000 lines worth.&lt;/a>&lt;/li>&lt;li>The JS version seems to work fine in Chrome, but not Firefox or Safari.&lt;/li>&lt;/ul>&lt;div>The conversion was pretty straight forward. Types in Dart make debugging this type of code so much easier. Isolates make it easy to keep CPU-intensive tasks (like generating QR codes) from slowing down your UI.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Cool.&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="dartlang"/>
    <category term="Programming"/>
  </entry>
  <entry>
    <title type="html">Getting Git - Feb 23 - Buy Tickets Now</title>
    <link href="https://kevmoo.com/2012/02/getting-git-feb-23-buy-tickets-now.html" rel="alternate" type="text/html" title="Getting Git - Feb 23 - Buy Tickets Now"/>
    <published>2012-02-17T22:39:00.000Z</published>
    <updated>2012-02-17T22:39:00.000Z</updated>
    <id>https://kevmoo.com/2012/02/getting-git-feb-23-buy-tickets-now.html</id>
    <content type="html" xml:base="https://kevmoo.com/2012/02/getting-git-feb-23-buy-tickets-now.html">&lt;div class="separator" style="clear: both; text-align: center;">&lt;a href="http://unitedrepublic.org/" imageanchor="1">&lt;img border="0" src="http://2.bp.blogspot.com/-pP25dQCA_YA/TzVjK5K9mDI/AAAAAAAACfs/X-wyP1akzys/s1600/united_republic_logo_horiz.png" />&lt;/a>&lt;/div>&lt;br />&lt;i>&lt;a href="http://en.wiktionary.org/wiki/TL;DR">tl;dr&lt;/a>: Go to&amp;nbsp;&lt;a href="http://www.razoo.com/story/Getting-Git-Feb-23">this form&lt;/a>&amp;nbsp;and donate $20 to an&amp;nbsp;&lt;a href="http://unitedrepublic.org/">amazing cause&lt;/a>.&amp;nbsp;Show up at&amp;nbsp;&lt;a href="http://officenomads.com/">Office Nomads&lt;/a>&amp;nbsp;on Thursday, Feb 23 at 6:30pm. Learn&amp;nbsp;&lt;a href="http://git-scm.com/">Git&lt;/a>.&lt;/i>&lt;br />&lt;i>&lt;br />&lt;/i>&lt;br />&lt;b>What&lt;/b>: a workshop to get people productive with Git.&lt;br />&lt;br />&lt;b>Why:&lt;/b>&lt;br />&lt;ul>&lt;li>Git is an amazing tool to manage and collaborate on text content -- source code, html, javascript, etc.&lt;/li>&lt;li>Giving money to &lt;a href="http://unitedrepublic.org/">United Republic&lt;/a> is a great way to get involved in the political process and fight the influence of money in our democracy.&lt;/li>&lt;/ul>&lt;br />&lt;b>Where&lt;/b>:&lt;br />&lt;br />&lt;ul>&lt;li>&lt;a href="http://officenomads.com/">Office Nomads&lt;/a>&lt;/li>&lt;li>&lt;a href="http://g.co/maps/8fuvy">1617 Boylston Ave&lt;/a>,&amp;nbsp;Seattle, WA 98122&lt;/li>&lt;/ul>&lt;br />&lt;b>When&lt;/b>:&lt;br />&lt;ul>&lt;li>Thursday, Feb 23, 2012.&lt;/li>&lt;li>6:30pm.&lt;/li>&lt;li>Doors open at 6:15.&lt;/li>&lt;li>We'll start right at 6:30. Don't be late.&lt;/li>&lt;/ul>&lt;br />&lt;b>How much&lt;/b>: $20. &lt;a href="http://www.razoo.com/story/Getting-Git-Feb-23">Donate here&lt;/a>.&lt;br />&lt;br />&lt;b>What to bring&lt;/b>:&lt;br />&lt;ul>&lt;li>Your laptop.&lt;/li>&lt;ul>&lt;li>&lt;b>Windows&lt;/b> - install &lt;a href="http://code.google.com/p/gitextensions/downloads/list">Git Extensions&lt;/a>. Use the latest "Setup Complete"&lt;/li>&lt;li>&lt;b>Mac&lt;/b>&lt;/li>&lt;ul>&lt;li>If you &lt;b>don't&lt;/b> already have &lt;a href="http://mxcl.github.com/homebrew/">HomeBrew&lt;/a> or &lt;a href="http://www.macports.org/">MacPorts&lt;/a> installed, &lt;a href="http://code.google.com/p/git-osx-installer/downloads/list?can=3">install Git from here&lt;/a>.&lt;/li>&lt;li>If you &lt;b>do&lt;/b> have HomeBrew or MacPorts, I'll help you get going when you get here.&lt;/li>&lt;/ul>&lt;li>&lt;b>Linux&lt;/b>&lt;/li>&lt;ul>&lt;li>I'm sure you can figure it out.&lt;/li>&lt;/ul>&lt;/ul>&lt;li>A &lt;a href="https://github.com/">GitHub&lt;/a> account. Free. Easy.&lt;/li>&lt;li>Note taking materials. Your favorite text editor or a pen and paper.&lt;/li>&lt;/ul>&lt;div>If you have questions, &lt;a href="mailto:tcpq3b44r8@snkmail.com">email me&lt;/a>.&lt;br />&lt;br />See you on Thursday!&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="git"/>
  </entry>
  <entry>
    <title type="html">Geeking for Democracy</title>
    <link href="https://kevmoo.com/2012/02/geeking-for-democracy.html" rel="alternate" type="text/html" title="Geeking for Democracy"/>
    <published>2012-02-10T19:01:00.000Z</published>
    <updated>2012-02-10T19:01:00.000Z</updated>
    <id>https://kevmoo.com/2012/02/geeking-for-democracy.html</id>
    <content type="html" xml:base="https://kevmoo.com/2012/02/geeking-for-democracy.html">&lt;div style="text-align: center;">&lt;a href="http://unitedrepublic.org/">&lt;img border="0" src="http://2.bp.blogspot.com/-pP25dQCA_YA/TzVjK5K9mDI/AAAAAAAACfs/X-wyP1akzys/s1600/united_republic_logo_horiz.png" />&lt;/a>&lt;/div>&lt;br />&lt;i>&lt;a href="http://en.wikipedia.org/wiki/Wikipedia:Too_long;_didn't_read">tl;dr&lt;/a>: Fill out &lt;a href="https://docs.google.com/a/j832.com/spreadsheet/viewform?formkey=dEdTTFJzM0RMR3hvUWh3Sk1HSWZJc0E6MQ">this form&lt;/a>. Contribute to a &lt;a href="http://unitedrepublic.org/">great cause&lt;/a>. Learn that thing you've been putting off.&lt;/i>&lt;br />&lt;br />A year and change ago I did a &lt;a href="http://work.j832.com/2010/09/getting-git-lunch-workshop-on-cap-hill.html">Getting Git&lt;/a> workshop at my coworker spot in Seattle, &lt;a href="http://officenomads.com/">Office Nomads&lt;/a>.&lt;br />&lt;br />Getting bootstrapped--self-sufficient--on new technologies is tough, especially if you don't have a good relationship with someone&amp;nbsp;experienced. Conferences and user groups can be intimidating and rarely offer opportunities to dig in from the beginning--especially for more than the length of a 50-minute presentation.&lt;br />&lt;br />I've learned a lot of fun technology since I left Microsoft 5 years ago--has it been that long?--in no small part because people in the know were kind enough to show me the way.&lt;br />&lt;br />There are three pieces of tech I love showing people and I feel--at least compared to beginners--I can offer a great starting point:&lt;br />&lt;ul>&lt;li>&lt;a href="http://git-scm.com/">Git&lt;/a>&lt;/li>&lt;li>&lt;a href="http://rubyonrails.org/">Ruby on Rails&lt;/a>&lt;/li>&lt;li>&lt;a href="http://code.google.com/closure/compiler/">Google Closure Compiler and Libraries&lt;/a>&amp;nbsp;- used to build &lt;a href="http://agent8ball.com/">Agent 008 Ball&lt;/a>, among other things at Pixel Lab.&lt;/li>&lt;/ul>Fill out &lt;a href="https://docs.google.com/a/j832.com/spreadsheet/viewform?formkey=dEdTTFJzM0RMR3hvUWh3Sk1HSWZJc0E6MQ">this form&lt;/a>. Once I find a sweet spot of interest, I'm going to schedule a workshop. A weeknight or a weekend morning/afternoon in Capitol Hill (Seattle).&lt;br />&lt;br />The price of admission? A donation to &lt;a href="http://unitedrepublic.org/">United Republic&lt;/a> -- a group dedicated to getting money out of politics.&lt;br />&lt;br />&lt;div style="text-align: left;">You get to learn some great tech and we both get a warm fuzzy helping out a great organization.&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="javascript"/>
    <category term="git"/>
    <category term="ruby on rails"/>
    <category term="Ruby"/>
    <category term="rails"/>
  </entry>
  <entry>
    <title type="html">In case you missed it: Lot's of Bag 'o Tricks fun recently</title>
    <link href="https://kevmoo.com/2011/07/in-case-you-missed-it-lots-of-bag-o.html" rel="alternate" type="text/html" title="In case you missed it: Lot's of Bag 'o Tricks fun recently"/>
    <published>2011-07-21T18:46:00.000Z</published>
    <updated>2011-07-21T18:46:00.000Z</updated>
    <id>https://kevmoo.com/2011/07/in-case-you-missed-it-lots-of-bag-o.html</id>
    <content type="html" xml:base="https://kevmoo.com/2011/07/in-case-you-missed-it-lots-of-bag-o.html">My main gig has been all Silverlight all the time over the last many moons. I've pushed a lot of changes to the &lt;a href="https://github.com/thinkpixellab/bot">Bag 'o Tricks&lt;/a> in response.&lt;br />&lt;br />I've also added the BOT to &lt;a href="http://nuget.org/List/Packages/PixelLab.BOT">NuGet&lt;/a>. &lt;br />&lt;br />Here's a lazy man's update--just a copy-paste from the &lt;a href="https://github.com/thinkpixellab/bot/blob/master/changelog.md">changelog&lt;/a>.&lt;br />&lt;br />Take a look.&lt;br />&lt;br />&lt;h1> Bag of Tricks Change Log&lt;/h1>&lt;h2> V4.1.0 - 2011-07-20&lt;/h2>&lt;em>Lot's of fun now stuff, but no breaking changes! Feels good.&lt;/em>&lt;br />&lt;ul>&lt;li>Added &lt;code>GetStringComparer&lt;/code> extension that takes a CultureInfo&lt;/li>&lt;li>Added &lt;code>SelectAdjacentPairs&lt;/code> to extensions&lt;/li>&lt;li>Added &lt;code>ResourceHelpers&lt;/code> extensions to SL assembly&lt;/li>&lt;li>Added &lt;code>TryGetTypedValue&amp;lt;&amp;gt;&lt;/code> extension&lt;/li>&lt;li>Fixed a gnarly bug in SL version of &lt;code>ColorHelper.HsbToRgb&lt;/code>&lt;/li>&lt;li>Added &lt;code>NextFloat&lt;/code> extension method for &lt;code>Random&lt;/code>&lt;/li>&lt;li>Added &lt;code>ModalControl&lt;/code> &lt;em>Closes #23&lt;/em>&lt;/li>&lt;li>Adjacent pairs methods now take &lt;code>IEnumerable&amp;lt;T&amp;gt;&lt;/code> instead of requiring &lt;code>IList&amp;lt;T&amp;gt;&lt;/code>&lt;/li>&lt;/ul>&lt;h2> v4.0.0 - 2011-07-08&lt;/h2>&lt;ul>&lt;li>&lt;strong>BREAKING&lt;/strong> - Removed &lt;code>DispatcherExtensions&lt;/code>. The implementation was trivial and it brought in all of Reactive Extensions as a dependency, which isn't worth it.&lt;/li>&lt;li>Fix for &lt;em>Issue #3&lt;/em> from Larry.&lt;/li>&lt;/ul>&lt;h2> v3.0.0 - 2011-07-08&lt;/h2>&lt;em>Because this rev contains non-compatible breaking changes, I'm bumping the version number. If this is annoying, let me know and I'll be more careful.&lt;/em>&lt;br />&lt;ul>&lt;li>Added command support to &lt;code>DoubleClickBehavior&lt;/code> - &lt;em>thanks, Larry&lt;/em>&lt;/li>&lt;li>Added demo for &lt;code>DoubleClickBehavior&lt;/code>&lt;/li>&lt;li>Added &lt;code>FilteredObservableEnumerable&lt;/code>&lt;/li>&lt;li>&lt;strong>BREAKING&lt;/strong> - Using &lt;em>Reactive Extensions&lt;/em> for async features&lt;/li>&lt;/ul>&lt;h2> v2.0.0 - 2011-07-05&lt;/h2>&lt;em>In the &lt;code>NuGet&lt;/code> world, BOT is not three projects: Core, Common, BOT. This allows one to minimize dependencies on external assemblies (mostly Prism) when not needed.&lt;/em>&lt;br />&lt;ul>&lt;li>&lt;strong>BREAKING&lt;/strong> - Added a &lt;code>Core&lt;/code> Silverlight assembly to match the same in WPF&lt;/li>&lt;li>&lt;strong>BREAKING&lt;/strong> - Moved &lt;code>DemoCollection&lt;/code> back to WPF demo app. This eliminates the dependency on Prism in Core and Common&lt;/li>&lt;/ul>&lt;h2> v1.1.0 - 2011-06-22&lt;/h2>&lt;em>Moving to &lt;a href="http://semver.org/">Semantic Versioning&lt;/a>. Non-breaking features are added, so we bump minor version number.&lt;/em>&lt;br />&lt;h3> Library changes&lt;/h3>&lt;ul>&lt;li>Added &lt;code>Insert&lt;/code> method to &lt;code>WeakEnumerable&amp;lt;T&amp;gt;&lt;/code>, which puts new items at the beginning of the enumeration. Which makes insertion O(1) instead of O(n)&lt;/li>&lt;li>Added &lt;code>SortedObservableEnumerable&amp;lt;T&amp;gt;&lt;/code>: because sometimes you'd like a sorted view of an &lt;code>INotifyCollectionChange&lt;/code>&lt;/li>&lt;li>Added &lt;code>Synchronize&lt;/code> extension method. For those times you want to update an OCP with a source collection and a factory&lt;/li>&lt;/ul>&lt;h3> Non-library changes&lt;/h3>&lt;ul>&lt;li>Fixed the WPF demo around property watcher&lt;/li>&lt;li>Removed Phone from the main solution (since it remains broken)&lt;/li>&lt;li>Added another layer of directories to builds, so there are no longer collisions between Silverlight and WPF build outputs&lt;/li>&lt;/ul>&lt;h2> v1.0.6&lt;/h2>&lt;ul>&lt;li>Added support for critical inner exceptions to &lt;code>IsCritical&lt;/code>&lt;/li>&lt;li>Moved &lt;code>DispatcherExtensions&lt;/code> methods to use &lt;code>SynchronizationContext&lt;/code>, which is more general &lt;ul>&lt;li>Should likely rename the class to &lt;code>SynchronizationContextExtensions&lt;/code>, huh?&lt;/li>&lt;/ul>&lt;/li>&lt;li>Naming and param order changes to &lt;code>PropertyChangeWatcher&lt;/code> - &lt;strong>Breaking Change&lt;/strong>&lt;/li>&lt;li>Clean-up in the SL test project&lt;/li>&lt;li>Added test for &lt;code>PropertyChangeWatcher&lt;/code>&lt;/li>&lt;/ul>&lt;h2> v1.0.5&lt;/h2>&lt;ul>&lt;li>A mountain of changes to &lt;code>ObservableCollectionPlus&amp;lt;T&amp;gt;&lt;/code> &lt;ul>&lt;li>Added &lt;code>Reset&lt;/code> method - &lt;em>Closes #21&lt;/em>&lt;/li>&lt;li>Made sort methods safe - &lt;em>Closes #22&lt;/em>&lt;/li>&lt;li>Added &lt;code>MultiUpdateActive&lt;/code>&lt;/li>&lt;li>Changed the location of the call to protected &lt;code>AfterMultiUpdate&lt;/code> to before raising reset&lt;/li>&lt;/ul>&lt;/li>&lt;/ul>&lt;h2> v1.0.4&lt;/h2>&lt;ul>&lt;li>A mountain of clean-up in demo and test code&lt;/li>&lt;li>Added &lt;code>WatchProperty&lt;/code> extension method to &lt;code>Extensions&lt;/code>&lt;/li>&lt;li>&lt;strong>NEW&lt;/strong> &lt;code>PropertyChangeWatcher&lt;/code> - &lt;em>Issue #16&lt;/em>&lt;/li>&lt;li>Added some usage details to &lt;code>InstanceFactory&lt;/code>&lt;/li>&lt;li>Added &lt;code>Util.ThrowUnless&lt;/code>&lt;/li>&lt;li>&lt;code>Extensions.GetCustomAttributes&lt;/code> -&amp;gt; change param &lt;code>MemberInfo&lt;/code> to more generic &lt;code>ICustomAttributeProvider&lt;/code> - &lt;em>Issue #19&lt;/em>&lt;/li>&lt;li>Added &lt;code>AddRange&lt;/code> to &lt;code>ObservableCollectionPlus&amp;lt;T&amp;gt;&lt;/code> - &lt;em>Issues # 17&lt;/em>&lt;/li>&lt;li>Some work to get Windows Phone 7 projects to load, although I've hit a snag with sharing generic.xaml between SL4 and Phone - progress towards &lt;em>Issue #18&lt;/em>&lt;/li>&lt;/ul>&lt;h2> v1.0.3&lt;/h2>&lt;ul>&lt;li>Much smarter implementation of &lt;code>Util.GetHashCode&lt;/code>&lt;/li>&lt;li>Added &lt;code>ClearErrors&lt;/code> to &lt;code>DataErrorHelper&lt;/code>&lt;/li>&lt;li>Moved the &lt;code>targets&lt;/code> files&lt;/li>&lt;li>Removed &lt;code>[DataContract]&lt;/code> from &lt;code>Changeable&lt;/code> - and cried that serialization support in Silverlight wasn't more flexible&lt;/li>&lt;li>&lt;code>AsyncValue&lt;/code>: added &lt;code>LoadCommand&lt;/code> property and &lt;code>LoadError&lt;/code> event - &lt;em>Closes #10&lt;/em>&lt;/li>&lt;/ul></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Bag of Tricks"/>
    <category term=".NET"/>
    <category term="NuGet"/>
    <category term="C#"/>
    <category term="thinkpixellab"/>
  </entry>
  <entry>
    <title type="html">Uninstalling Rails beta–with crazy bash tricks</title>
    <link href="https://kevmoo.com/2010/10/uninstalling-rails-betawith-crazy-bash.html" rel="alternate" type="text/html" title="Uninstalling Rails beta–with crazy bash tricks"/>
    <published>2010-10-22T19:46:00.001Z</published>
    <updated>2010-10-22T19:46:00.001Z</updated>
    <id>https://kevmoo.com/2010/10/uninstalling-rails-betawith-crazy-bash.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/10/uninstalling-rails-betawith-crazy-bash.html">&lt;p>I'm know I could have done this by hand way faster than it took me to figure out.&lt;/p> &lt;p>I’m sure there are better ways to do this than I figured out below.&lt;/p> &lt;p>But still enjoyed figuring it out.&lt;/p> &lt;p>Scenario: &lt;br>Uninstall all gems with version 3.0.0.beta4. These map to one of the last Rails 3 betas.&lt;br>…and do it in one bash command.&lt;/p> &lt;p>This is what I ended up with.&lt;/p> &lt;p>&lt;code>gem list | grep beta4 | awk '{print $1}' | xargs gem uninstall -v=3.0.0.beta4&lt;/code>&lt;/p> &lt;ul> &lt;li>&lt;strong>gem list&lt;/strong> – lists all installed gems&lt;/li> &lt;li>&lt;strong>grep beta4&lt;/strong> – filters the output to lines containing ‘beta4’&lt;/li> &lt;li>&lt;strong>awk ‘{print $1'}’&lt;/strong> – takes each line and outputs only the gem name (not the version info)&lt;/li> &lt;li>&lt;strong>xargs&lt;/strong> – takes the last output and appends it to the given command: &lt;strong>gem uninstall -v=3.0.0.beta4&lt;/strong>&lt;/li>&lt;/ul> &lt;p>Cool, huh?&lt;/p> &lt;p>Well, if you know bash, maybe not. I’d love to see a “better” version of this.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="bash"/>
    <category term="rails"/>
  </entry>
  <entry>
    <title type="html">MSBuild and Custom Targets: Almost too much fun</title>
    <link href="https://kevmoo.com/2010/10/msbuild-and-custom-targets-almost-too.html" rel="alternate" type="text/html" title="MSBuild and Custom Targets: Almost too much fun"/>
    <published>2010-10-15T16:47:00.001Z</published>
    <updated>2010-10-15T16:47:00.001Z</updated>
    <id>https://kevmoo.com/2010/10/msbuild-and-custom-targets-almost-too.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/10/msbuild-and-custom-targets-almost-too.html">&lt;script src="http://gist.github.com/628499.js?file=gistfile1.xml">&lt;/script> &lt;p>I’m a big believer in DRY – &lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">Don’t Repeat Yourself&lt;/a> – in software.&lt;/p> &lt;p>While I try hard to practice this in the code for the &lt;a href="http://github.com/thinkpixellab/bot">Bag of Tricks&lt;/a> (BOT), until recently I’ve ignored my project files.&lt;/p> &lt;p>VS handles that, right?&lt;/p> &lt;p>Well, kind.&lt;/p> &lt;p>It turns out there is a lot of duplication in proj files. Every one defines constants and output paths. If you’re using Code Contracts, you get a bunch of contract properties all over – sometimes differing in inexplicable ways between debug and release.&lt;/p> &lt;p>I got sick of it. I cleaned it up.&lt;/p> &lt;ul> &lt;li>&lt;strong>BuildShared.targets&lt;/strong> – Shared state across every project. Warning levels, shared build constants, even output path. &lt;ul> &lt;li>This is great. If I want to change the location of obj and bin, I just change one file now. Super nice.&lt;/li>&lt;/ul> &lt;li>&lt;strong>Contracts.targets&lt;/strong> – This defines all of the Code Contracts build parameters. &lt;li>&lt;strong>WPF4, SL4, WP7.targets&lt;/strong> – Common code for a given platform. Things like target framework, framework profile, etc. (WPF and SL include Contracts, Phone dosen’t.) &lt;li>Now each proj file includes the associated platform proj file and just sets project-specific properties. &lt;ul> &lt;li>Guids, OutputType (library or exe), root namespace, assembly name, etc.&lt;/li>&lt;/ul>&lt;/li>&lt;/ul> &lt;p>The downside: if you go hack specific properties via VS, you’ll add a bunch of one-off changes to individual proj files.&lt;/p> &lt;p>…but this is why we use source control, right? I can look at the diffs and ask: are these changes I want to share across projects or things I can just throw-away?&lt;/p> &lt;p>And having all of the shared noise in another place makes parsing the proj file a lot faster.&lt;/p> &lt;p>Take a look at the code. All of the targets are in &lt;strong>PixelLab.Common\_targets&lt;/strong>. (Yeah, a weird place. I’ll explain later.)&lt;/p> &lt;p>Happy hacking.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="visual studio"/>
    <category term="Bag of Tricks"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="msbuild"/>
    <category term="vs2010"/>
    <category term="thinkpixellab"/>
  </entry>
  <entry>
    <title type="html">Bag of Tricks on Github: How and Why</title>
    <link href="https://kevmoo.com/2010/10/bag-of-tricks-on-github-how-and-why.html" rel="alternate" type="text/html" title="Bag of Tricks on Github: How and Why"/>
    <published>2010-10-14T16:50:00.001Z</published>
    <updated>2010-10-14T16:50:00.001Z</updated>
    <id>https://kevmoo.com/2010/10/bag-of-tricks-on-github-how-and-why.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/10/bag-of-tricks-on-github-how-and-why.html">&lt;p style="text-align: center">&lt;a href="http://github.com/thinkpixellab/bot">&lt;img title="bot2git" border="0" alt="bot2git" src="http://lh4.ggpht.com/_3BkQqJvzLFM/TLc004ltJXI/AAAAAAAAKzM/Xfeh3OQfen4/bot2git%5B5%5D.png?imgmax=800" width="480" height="233">&lt;/a>&lt;/p> &lt;p>On October 7, I updated the &lt;a href="http://bot.codeplex.com/">Bag of Tricks CodePlex site&lt;/a>: &lt;blockquote>Active development for BOT has moved to &lt;a href="http://github.com/thinkpixellab/bot">GitHub&lt;/a>.&lt;/blockquote> &lt;h1>Don’t Panic! (You can still use Subversion)&lt;/h1> &lt;p>I’m super happy folks like using the BOT. I don’t want to stop you.&lt;/p> &lt;p>You can still download the source as a zip. Just click download on the &lt;a href="http://github.com/thinkpixellab/bot">GitHub page&lt;/a>.&lt;/p> &lt;p>And you can still use Subversion (SVN). GitHub has done the wonderful work of enabling SVN via HTTP. Point &lt;a href="http://tortoisesvn.tigris.org/">Tortoise&lt;/a> (or your other favorite client) at &lt;a title="http://svn.github.com/thinkpixellab/bot" href="http://svn.github.com/thinkpixellab/bot">http://svn.github.com/thinkpixellab/bot&lt;/a>. Super easy.&lt;/p> &lt;h1>Reason: Git vs SVN&lt;/h1> &lt;p>I could rant a long time, but I’ll just point you here: &lt;a title="http://whygitisbetterthanx.com/#svn" href="http://whygitisbetterthanx.com/#svn">http://whygitisbetterthanx.com/#svn&lt;/a>&lt;/p> &lt;p>The short version:&lt;/p> &lt;ul> &lt;li>&lt;strong>Easy to work locally.&lt;/strong> Which is something you likely won’t comprehend until you do it. Saving a bunch of small changes locally before a big push to the server is really nice. &lt;li>&lt;strong>Easy to branch.&lt;/strong> On the server. Locally. It’s all easy. It’s all scary fast, too. No copying a bunch of identical files. &lt;li>&lt;strong>Scary fast.&lt;/strong> I can’t emphasize this enough. Wow. It’s just really fast. Everything. Pushing, Pulling, Committing, Branching. Amazing.&lt;/li>&lt;/ul> &lt;h1>Reason: GitHub vs CodePlex&lt;/h1> &lt;ul> &lt;li>&lt;strong>Faster.&lt;/strong> GitHub is just way faster. It probably has a lot to do with the benefits of Git. &lt;li>&lt;strong>Better Tools.&lt;/strong> Better for looking at changes, commenting on commits, etc. &lt;li>&lt;strong>Way less annoying.&lt;/strong> I frequently have crazy issues on CodePlex. Commits fail for weird reasons. Updates don’t update everything. I’m sick of it. Never had such problems on GitHub.&lt;/li>&lt;/ul> &lt;h1>Reason: Logistics&lt;/h1> &lt;ul> &lt;li>&lt;strong>Rails.&lt;/strong> I do a lot of work with &lt;a href="http://rubyonrails.org/">Rails&lt;/a>. The Rails universe is all on Git and GitHub. &lt;li>&lt;strong>I think in Git.&lt;/strong> It’s the tool I love. It’s the tool I use. I want to use it everywhere. &lt;li>&lt;strong>I live on GitHub.&lt;/strong> All of my projects – both open and closed – live on GitHub. I want to have one place to go.&lt;/li>&lt;/ul> &lt;h1>Jump on in. The Git is fine.&lt;/h1> &lt;p>It’s more than fine. It’s awesome.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Bag of Tricks"/>
    <category term="git"/>
    <category term="thinkpixellab"/>
    <category term="SVN"/>
  </entry>
  <entry>
    <title type="html">Auto-discovering demos in the Bag of Tricks with MEF and System.Xaml</title>
    <link href="https://kevmoo.com/2010/09/auto-discovering-demos-in-bag-of-tricks.html" rel="alternate" type="text/html" title="Auto-discovering demos in the Bag of Tricks with MEF and System.Xaml"/>
    <published>2010-09-29T18:22:00.001Z</published>
    <updated>2010-09-29T18:22:00.001Z</updated>
    <id>https://kevmoo.com/2010/09/auto-discovering-demos-in-bag-of-tricks.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/09/auto-discovering-demos-in-bag-of-tricks.html">&lt;p>&lt;/p> &lt;p>&lt;a href="http://bot.codeplex.com" target="_blank">&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://download.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=bot&amp;amp;DownloadId=114209&amp;amp;Build=17184">&lt;/a>&lt;/p> &lt;p>Back in the old days (sometime in 2005) I built out the Bag of Tricks. At the time, the index of the samples was stored in an XML file. I then used data binding to to connect to the XML, show the items and the descriptions, navigate to the page URLs.&lt;/p> &lt;p>It was very cool…kinda…&lt;/p> &lt;p>&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_3BkQqJvzLFM/TKOD75fyK4I/AAAAAAAAKy0/1cIZPHnHhdA/image%5B32%5D.png?imgmax=800" width="512" height="183"> Then &lt;a href="http://msdn.microsoft.com/en-us/library/dd460648.aspx" target="_blank">MEF&lt;/a> came along and I realized that having a secondary list of each demo was a bit broken. Each demo should describe itself, right? So I MEF-ized all of the demos that had custom classes by annotating the classes with custom metadata.&lt;/p> &lt;p>It was very cool…but…&lt;/p> &lt;p>I had a bunch of demos that were Xaml-only. Just pages of Xaml that did their thing.&lt;/p> &lt;p>&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_3BkQqJvzLFM/TKOD8UW2_aI/AAAAAAAAKy4/wlJs5DzbhuQ/image%5B33%5D.png?imgmax=800" width="567" height="174"> I started the process of creating classes for a bunch of them, but that felt broken. Pages are just xaml. I should be able to use attached properties on each page to specify demo metadata.&lt;/p> &lt;p>Thanks to the work of the Xaml team at MS, we got it done. (Thanks for the email support, &lt;a href="http://blogs.windowsclient.net/rob_relyea/" target="_blank">Rob&lt;/a>.)&lt;/p> &lt;p>Now BOT samples for both Silverlight and WPF use the same mechanism to load samples—although the WPF version gets special support for Xaml-only pages.&lt;/p> &lt;p>Download the &lt;a href="http://bot.codeplex.com/SourceControl/list/changesets" target="_blank">latest code on the Source Code page&lt;/a> on BOT’s home on Codeplex.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term="Bag of Tricks"/>
    <category term=".NET"/>
    <category term="xaml"/>
    <category term="C#"/>
    <category term="Silverlight"/>
    <category term="thinkpixellab"/>
  </entry>
  <entry>
    <title type="html">Getting ‘git’: lunch workshop on Cap Hill, Oct 5</title>
    <link href="https://kevmoo.com/2010/09/getting-git-lunch-workshop-on-cap-hill.html" rel="alternate" type="text/html" title="Getting ‘git’: lunch workshop on Cap Hill, Oct 5"/>
    <published>2010-09-23T21:39:00.001Z</published>
    <updated>2010-09-23T21:39:00.001Z</updated>
    <id>https://kevmoo.com/2010/09/getting-git-lunch-workshop-on-cap-hill.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/09/getting-git-lunch-workshop-on-cap-hill.html">&lt;img alt="git-logo" height="176" src="http://images.maketecheasier.com/2010/03/git-logo.png" style="display: block; float: none; margin-left: auto; margin-right: auto;" width="152" />&lt;br />Update: &lt;a href="http://twtvite.com/caphillgit">RSVP here&lt;/a>.&lt;br />&lt;br />I love &lt;a href="http://git-scm.com/">git&lt;/a>. Really, really love &lt;a href="http://git-scm.com/">git&lt;/a>. I’ve used SVN and PerForce. They don’t come close.&lt;br />Some folks here at &lt;a href="http://officenomads.com/">Office Nomads&lt;/a> have asked me to give a talk. I figured I’d open it up to the public.&lt;br />&lt;strong>Details&lt;/strong>:&lt;br />&lt;ul>&lt;li>&lt;strong>Location&lt;/strong>: &lt;a href="http://officenomads.com/">Office Nomads&lt;/a>, 2nd Floor, &lt;a href="http://goo.gl/maps/HNlW">1617 Boylston, Seattle&lt;/a>.&lt;/li>&lt;li>&lt;strong>When&lt;/strong>: Noon to 2pm, October 5, 2010&lt;/li>&lt;li>&lt;strong>Cost&lt;/strong>: Proof of a $25 donation to &lt;a href="http://www.eff.org/">EFF&lt;/a> or &lt;a href="https://donate.change-congress.org/page/contribute/">Fix Congress First&lt;/a>. (If you’re tight on cash, let’s talk.)&lt;/li>&lt;/ul>I’d suggest watching one or both of these videos are prerequisites:&lt;br />&lt;ul>&lt;li>The original &lt;a href="http://vimeo.com/14629850">Getting Git&lt;/a> introduction by Scott Chacon.&lt;/li>&lt;li>From the man himself, &lt;a href="http://www.youtube.com/watch?v=4XpnKHJAok8">Linus being hilarious&lt;/a> talking about the why and how of git.&lt;/li>&lt;/ul>Before you come you should also:&lt;br />&lt;ul>&lt;li>Create a free account on &lt;a href="http://github.com/">github&lt;/a>.&lt;/li>&lt;li>Install software for your machine:&lt;/li> &lt;ul>&lt;li>Windows: go with &lt;a href="http://code.google.com/p/gitextensions/downloads/list">Git Extensions&lt;/a>. Pick the 203 “complete” release. Should integrate nicely into Visual Studio, too.&lt;/li>&lt;li>Mac: &lt;/li> &lt;ul>&lt;li>Command line&lt;/li> &lt;ul>&lt;li>If you use &lt;a href="http://www.macports.org/">Mac Ports&lt;/a> or another package manager, use that to get the latest git (1.7*)&lt;/li>&lt;li>Otherwise, install from &lt;a href="http://code.google.com/p/git-osx-installer/downloads/list?can=3">here&lt;/a>. (I use MacPorts, so I have no clue how this works)&lt;/li>&lt;/ul>&lt;li>GUI&lt;/li> &lt;ul>&lt;li>&lt;a href="http://github.com/brotherbard/gitx/downloads">GitX experimental branch&lt;/a>. See the link to 3.0.3 at the very top of the page.&lt;/li>&lt;/ul>&lt;/ul>&lt;li>Linux&lt;/li> &lt;ul>&lt;li>You don’t need my help…&lt;/li>&lt;/ul>&lt;/ul>&lt;/ul>If you have problems with install, &lt;a href="http://twitter.com/home?status=%40kevmoo%2C%20I%20need%20help%20with%20%23git.%20%5BQuestion%20here.%5D" target="_blank">tweet me a help request&lt;/a>.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="seattle"/>
    <category term="git"/>
  </entry>
  <entry>
    <title type="html">Physics for Agent 8 Ball - box2d</title>
    <link href="https://kevmoo.com/2010/09/physics-for-agent-8-ball-box2d.html" rel="alternate" type="text/html" title="Physics for Agent 8 Ball - box2d"/>
    <published>2010-09-15T18:22:00.000Z</published>
    <updated>2010-09-15T18:22:00.000Z</updated>
    <id>https://kevmoo.com/2010/09/physics-for-agent-8-ball-box2d.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/09/physics-for-agent-8-ball-box2d.html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_3BkQqJvzLFM/TJEPLhseu_I/AAAAAAAAKys/6I5xjQZ8cx4/s1600/Screen+shot+2010-09-15+at+11.23.09+AM.png">&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 172px;" src="http://4.bp.blogspot.com/_3BkQqJvzLFM/TJEPLhseu_I/AAAAAAAAKys/6I5xjQZ8cx4/s320/Screen+shot+2010-09-15+at+11.23.09+AM.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5517207709203479538" />&lt;/a>&lt;br />&lt;div>I don't have a lot of time to write, since I'm actually at the launch event, but I wanted to share a quick note about the plumbing of Agent 8 Ball. Check out &lt;a href="http://box2d.thinkpixellab.com/">http://box2d.thinkpixellab.com/&lt;/a> to see how we made our pool game come alive.&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="thinkpixellab"/>
  </entry>
  <entry>
    <title type="html">bundle_view is now "bundle viz"</title>
    <link href="https://kevmoo.com/2010/05/bundleview-is-now-bundle-viz.html" rel="alternate" type="text/html" title="bundle_view is now &quot;bundle viz&quot;"/>
    <published>2010-05-17T18:19:00.000Z</published>
    <updated>2010-05-17T18:19:00.000Z</updated>
    <id>https://kevmoo.com/2010/05/bundleview-is-now-bundle-viz.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/05/bundleview-is-now-bundle-viz.html">&lt;a href="http://2.bp.blogspot.com/_3BkQqJvzLFM/S_GIwQGpdMI/AAAAAAAAKyQ/qh1ZzgJmRHs/s1600/Gemfile.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}">&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5472305384769811650" src="http://2.bp.blogspot.com/_3BkQqJvzLFM/S_GIwQGpdMI/AAAAAAAAKyQ/qh1ZzgJmRHs/s400/Gemfile.png" style="cursor: hand; cursor: pointer; display: block; height: 182px; margin: 0px auto 10px; text-align: center; width: 400px;" />&lt;/a>&lt;br />Last weekend I tweeted:&lt;br />&lt;blockquote>My weekend #ruby hacking. GraphViz for your #rails Gemfile using @gembundler. http://bit.ly/b1PaXT Suggestions, patches welcome!&lt;/blockquote>What a fun week it's been.&lt;br />&lt;a href="http://twitter.com/wycats">@wycats&lt;/a> hunted me down and asked if I'd roll bundle_view into bundler.&lt;br />&lt;br />Update: Made it into bundler. See the commits &lt;a href="http://github.com/carlhuda/bundler/commits/master?author=kevmoo">here&lt;/a>.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="bundler"/>
    <category term="ruby on rails"/>
    <category term="rails"/>
  </entry>
  <entry>
    <title type="html">CLI on the Web? Sure, but put x86 their first</title>
    <link href="https://kevmoo.com/2010/05/cli-on-web-sure-but-put-x86-their-first.html" rel="alternate" type="text/html" title="CLI on the Web? Sure, but put x86 their first"/>
    <published>2010-05-03T22:08:00.001Z</published>
    <updated>2010-05-03T22:08:00.001Z</updated>
    <id>https://kevmoo.com/2010/05/cli-on-web-sure-but-put-x86-their-first.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/05/cli-on-web-sure-but-put-x86-their-first.html">&lt;p>Miguel &lt;a href="http://tirania.org/blog/archive/2010/May-03.html">blogged a great idea&lt;/a> today, expanding on Joe Hewitt’s simple &lt;a href="http://twitter.com/joehewitt/status/13321942026">statement on Twitter&lt;/a>: &lt;blockquote>If CLI was the ECMA standard baked into browsers instead of ECMAScript we'd have a much more flexible web.&lt;/blockquote> &lt;p>&lt;/p> &lt;p>Agreed. I’d love to be able to run C# instead of Javascript on my web page. I’d also love to be able to run Ruby. Or even &lt;a href="http://www.scala-lang.org/">Scala&lt;/a>. So why not JVM on the Web? What about &lt;a href="http://golang.org/">Go&lt;/a>?&lt;/p> &lt;p>Why not indeed. If there is going to be a push to have broader language support on the web, let’s jump over the problem of picking the right VM and Garbage collector. Let’s skip shared agreement on compatibilities between Microsoft’s implementation and Miguel’s.&lt;/p> &lt;p>Let’s go straight to &lt;a href="http://code.google.com/p/nativeclient/">Native Client&lt;/a>.&lt;/p> &lt;p>I’ve talked about &lt;a href="http://work.j832.com/2010/01/google-native-client-belongs-on-server.html">Native Client before&lt;/a>. Here’s the official summary: &lt;blockquote>Native Client is an open-source technology for running native code in web applications, with the goal of maintaining the browser neutrality, OS portability, and safety that people expect from web apps. We've released this project at an early stage to get feedback from the open-source community. We believe that Native Client technology will help web developers to create richer and more dynamic browser-based applications. &lt;br>&lt;br>Native Client runs on 32-bit x86 systems that use Windows, Vista, Mac OS X, or Linux. Some ARM and x86-64 support is implemented in the source base, and we hope to make it available for application developers later this year.&lt;/blockquote> &lt;p>&lt;/p> &lt;p>Instead of worrying about Mono or Microsoft worrying about getting the sandbox right for the browser, let’s solve it once.&lt;/p> &lt;p>Then I can target the C# with the Mono CLI.&lt;/p> &lt;p>Or IronPython with the Microsoft CLR.&lt;/p> &lt;p>Or Ruby with JRuby. Or just &lt;a href="http://en.wikipedia.org/wiki/Ruby_MRI">MRI&lt;/a>, if I want.&lt;/p> &lt;p>I’m certainly waving my hands over a lot of technical details. I know.&lt;/p> &lt;p>My thought is simply this: CLI as another Javascript is radical idea.&lt;/p> &lt;p>Perhaps just not radical enough.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="Ruby"/>
    <category term="C#"/>
    <category term="google"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">Bag of Tricks Update (two years in the making)</title>
    <link href="https://kevmoo.com/2010/04/bag-of-tricks-update-two-years-in.html" rel="alternate" type="text/html" title="Bag of Tricks Update (two years in the making)"/>
    <published>2010-04-07T05:50:00.001Z</published>
    <updated>2010-04-07T05:50:00.001Z</updated>
    <id>https://kevmoo.com/2010/04/bag-of-tricks-update-two-years-in.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/04/bag-of-tricks-update-two-years-in.html">&lt;a href="http://bot.codeplex.com/">&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" src="http://download.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=bot&amp;amp;DownloadId=114209&amp;amp;Build=16429" />&lt;/a>&lt;p>Has it really been two years since the &lt;a href="http://work.j832.com/2008/03/bag-o-tricks-march-edition.html">last official update&lt;/a> of the &lt;a href="http://bot.codeplex.com/">Bag of Tricks&lt;/a>?&lt;/p> &lt;p>I guess it has. A lot has changed since then. I started my own consulting company. And then joined up with &lt;a href="http://twitter.com/ingebretsen">Robby&lt;/a> to launch &lt;a href="http://thinkpixellab.com/">Pixel Lab&lt;/a>.&lt;/p> &lt;p>With previous releases, I was doing a very good job of breaking out almost all of the changes. This time, there are just too many. I’ll try to highlight the big ones.&lt;/p> &lt;ul> &lt;li>Added Org Tree. This is a pretty straight-forward sample of a vertical tree view.&lt;/li> &lt;li>Added ReorderListBox. This is something Robby’s had for a while. I cleaned it up a bit for reuse.&lt;/li> &lt;li>Added Show&lt;/li> &lt;li>Removed the date controls. There are better versions in the official &lt;a href="http://wpf.codeplex.com/">WPF Codeplex site&lt;/a>.&lt;/li> &lt;li>Created AnimatingPanel abstract class. This is now the base class for AnimatingTilePanel &lt;em>and&lt;/em> TreeMapPanel. All you have to tweak is call the protected virtual ArrangeChild in ArrangeOverride.&lt;/li> &lt;li>A bunch of additions to the Common assembly.&lt;/li> &lt;li>Moved main development over to VS 2010.&lt;/li> &lt;li>Added support for Silverlight 4. You’ll find projects nested in the same folder. You’ll also notice #define #if #else for SILVERLIGHT which handles some special cases where things don’t work in both places.&lt;/li> &lt;li>Added Vector for Silverlight. This allows a bunch of my helper methods and animation methods to work without code changes between the two frameworks.&lt;/li> &lt;li>Added ObservableCollectionPlus&amp;lt;T&amp;gt;. This has a ReadOnly property, along with support for Sort and adds Move to Silverlight OC&amp;lt;T&amp;gt;.&lt;/li> &lt;li>…and a bunch of other stuff I’m likely forgetting.&lt;/li>&lt;/ul> &lt;p>You can get the source (via SVN) at Codeplex: &lt;a href="http://bot.codeplex.com/">http://bot.codeplex.com/&lt;/a>&lt;/p> &lt;p>You can download a sample app that runs against WPF 3.5 &lt;a href="http://bot.codeplex.com/releases/view/43175">here&lt;/a>.&lt;/p> &lt;p>The BOT has been the basis for Silverlight, WPF, and Windows Phone 7 apps I’ve written this year. Robby and I are going to keep tweaking it and updating it as we need new stuff.&lt;/p> &lt;p>You should do the same.&lt;/p> &lt;p>File bugs. Submit patches.&lt;/p> &lt;p>Let’s make this &lt;em>our&lt;/em> Bag of Tricks.&lt;/p> &lt;p> &lt;/p> &lt;p>Happy hacking,&lt;/p> &lt;p>>Kevin&lt;/p>&lt;p>PS -> please make comments on the codeplex project discussion page! It's much easier to reply there. :-)&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="xaml"/>
    <category term="C#"/>
    <category term="Silverlight"/>
  </entry>
  <entry>
    <title type="html">Google's Native Client belongs on the Server, too</title>
    <link href="https://kevmoo.com/2010/01/google-native-client-belongs-on-server.html" rel="alternate" type="text/html" title="Google's Native Client belongs on the Server, too"/>
    <published>2010-01-24T20:14:00.001Z</published>
    <updated>2010-01-24T20:14:00.001Z</updated>
    <id>https://kevmoo.com/2010/01/google-native-client-belongs-on-server.html</id>
    <content type="html" xml:base="https://kevmoo.com/2010/01/google-native-client-belongs-on-server.html">&lt;h1>What is Native Client?&lt;/h1>Have you heard of Native Client (NaCl) from Google? Yet another open-source client software play from our overlords in Mountainview.&lt;br />&lt;br />The write-up on the &lt;a href="http://code.google.com/p/nativeclient/">project site&lt;/a> is pretty good:&lt;blockquote>Native Client is an open-source technology for running native code in web applications, with the goal of maintaining the browser neutrality, OS portability, and safety that people expect from web apps. We've released this project at an early stage to get feedback from the open-source community. We believe that Native Client technology will help web developers to create richer and more dynamic browser-based applications.&lt;/blockquote>Think of it this way:&lt;br />&lt;br />Right now, the only way to play with the HTML DOM is with Javascript--Javascript with a surface area explicitly limited to the DOM.&lt;br />&lt;br />Now imagine you could give &lt;em>any&lt;/em> x86 the same explicit sandbox--with some clever run-type verification.&lt;br />&lt;br />While we should all be worried about claims of safety, the promise of high-performance and language agnosticism is tempting.&lt;br />&lt;br />Forget the CLR and the JVM.&lt;br/>x86 won a long time ago.&lt;h1>Now App Engine, Please&lt;/h1>If Google really buys into the safety of NaCl, they should put their data center where their mouth is.&lt;br />&lt;br />They've done a lot of work to provide Python and Java support on &lt;a href="http://code.google.com/appengine/">App Engine&lt;/a>. Why not allow &lt;em>any language&lt;/em> on App Engine with NaCl?&lt;br />&lt;br />Instead HTML DOM being the "safe" surface area, make it HTTP request/response. Think &lt;a href="http://en.wikipedia.org/wiki/Common_Gateway_Interface">CGI&lt;/a> or (as a Ruby guy) &lt;a href="http://en.wikipedia.org/wiki/Rack_(web_server_interface)">Rack&lt;/a>--expanded, certainly, for background tasks, datastore/memcache access, email, etc.&lt;h1>A revolution in back-end web programming&lt;/h1>There's a painful gap between ease and flexibility on the backend.&lt;h2>Sandbox too Small&lt;/h2>If you want ease, you're stuck with a limited "approved stack" at a host--Java/Python on App Engine, PHP/Rails at Dreamhost, etc.&lt;br />&lt;br />You're stuck with Ruby 1.8.6 at Heroku. You're waiting for Google to support Python 3.0 on App Engine.&lt;h2>Sandbox too Big&lt;/h2>If you want flexibility, you're stuck managing a Linux image on Amazon EC2 or Slicehost.&lt;br />&lt;br />You have to worry about which Linux distro to run...if/when you should patch it.&lt;br />&lt;br />Not to mention giving up all of the smart scaling one gets from App Engine-like solutions.&lt;h2>Sandbox just right&lt;/h2>We need an abstraction layer that fills the gap.&lt;br />&lt;br />NaCl seems like it would fit the bill. &lt;br />&lt;br />Google could re-write their Python and Java sandboxes for App Engine to run within NaCl. At this point I'd wager, any language/framework--Ruby/Rails, PHP, or even old-school Perl/CGI could be tweaked to run there, too.&lt;br />&lt;br />Google could open-source this sandbox, no doubt, providing a de facto, language-agnostic web server model.&lt;br />&lt;br />Which sounds really nice to me.&lt;h1>Shipping Microsoft Singularity&lt;/h1>Our friends in Redmond have been playing with the idea of allowing safe execution of 3rd-party code.&lt;br />&lt;br />A research project called &lt;a href="http://research.microsoft.com/en-us/projects/singularity/">Singularity&lt;/a> aims to allow high-performance and safety...but it feels like the all too common "boil the ocean" play from Microsoft. New tools, new languages, and a new operating system.&lt;br />&lt;br />It's a project that's been public for 5 years, with little more than some &lt;a href="http://channel9.msdn.com/Search/?Term=Singularity">channel9 videos&lt;/a> to show for it. I fear we'll see a lot more research papers before we see any production-approved code.&lt;br />&lt;br />Google's model with NaCl--"let's make x86 safe"--is ambitious, but tightly constrained. It also piggy-backs on a &lt;em>huge&lt;/em> stack of open-source languages, frameworks and tools.&lt;br/>&lt;br/>&lt;br/>Native Client could be huge.&lt;br/>Huge in the browser.&lt;br/>Just as huge on the server.&lt;p>&lt;a href="http://twitter.com/home?status=The+crazy+cool+potential+of+Google%27s+Native+Client...on+the+Server+http%3A%2F%2Fbit.ly%2F6AowzL+via+%40kevmoo" target="_blank">Tweet This!&lt;/a>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="javascript"/>
    <category term="Programming"/>
    <category term="google"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">Thoughts on Google's client software strategy</title>
    <link href="https://kevmoo.com/2009/12/get-me-to-brain-understanding-googles.html" rel="alternate" type="text/html" title="Thoughts on Google's client software strategy"/>
    <published>2009-12-21T06:02:00.000Z</published>
    <updated>2009-12-21T06:02:00.000Z</updated>
    <id>https://kevmoo.com/2009/12/get-me-to-brain-understanding-googles.html</id>
    <content type="html" xml:base="https://kevmoo.com/2009/12/get-me-to-brain-understanding-googles.html">We’d all like a peek inside the mind of &lt;a href="http://twitter.com/ericschmidt">Eric Schmidt&lt;/a>—beyond just understanding what he’s wearing in his twitter &lt;a href="http://twitter.com/account/profile_image/ericschmidt">profile picture&lt;/a>. Search and maps and profiles: these all make sense. But there are a set projects that Google has been putting out lately that don't fit. They're open source and focused on the client machine.&lt;div>&lt;ul>&lt;li>A &lt;a href="http://www.google.com/chrome">browser&lt;/a>.&lt;/li>&lt;li>An &lt;a href="http://www.chromium.org/chromium-os">operating system&lt;/a>.&lt;/li>&lt;li>An extension to HTTP - &lt;a href="http://www.chromium.org/spdy/spdy-whitepaper">SPDY&lt;/a>.&lt;/li>&lt;li>An drastic evolution of AJAX - &lt;a href="http://dev.w3.org/html5/websockets/">Web Sockets&lt;/a>.&lt;/li>&lt;li>A public &lt;a href="http://code.google.com/speed/public-dns/">DNS service&lt;/a>.&lt;/li>&lt;li>A drastic evolution in web programming - &lt;a href="http://code.google.com/p/nativeclient/">Native Client&lt;/a>.&lt;/li>&lt;/ul>&lt;div>Some of these are put under the banner of "making the web faster".&lt;/div>&lt;div>Let me go a step further.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Google makes lots of money when you're clicking. The faster and more efficiently you consume their experiences, the more you click. The more you click, the more money Google makes.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>But there are bumps along the way.&lt;/div>&lt;div>&lt;div>Crappy ISPs&lt;/div>&lt;div>Out-dated operating system.&lt;/div>&lt;div>Outdated and/or bloated browsers, protocols, and programming languages.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Google was silent on these for a long time--pushing existing technologies in novel or extreme ways--AJAX with Google Maps, Java Web Toolkit for Javascript, even shoe-horning &lt;a href="http://code.google.com/chrome/chromeframe/">Chrome into IE&lt;/a>.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>In the end, the've decided to cut out the middle man.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Ponder the stack of technology between you and Google's web offerings. When Eric Schmidt thinks about protocols, operating systems, and browsers--he has the same thoughts as Bill Gates did 20 years ago--about disk drives, CPUs and RAM.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Make them solid. Make them better.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>But keep them out of the competitive picture.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>Commoditize.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>MSFT did it riding a wave of cheap PCs.&lt;/div>&lt;div>GOOG is doing it by riding a wave of free software.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;/div>&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="internet"/>
    <category term="google"/>
  </entry>
  <entry>
    <title type="html">Tomorrow. Seattle. Have a Mac? Wanna learn Rails?</title>
    <link href="https://kevmoo.com/2009/12/tomorrow-seattle-have-mac-wanna-learn.html" rel="alternate" type="text/html" title="Tomorrow. Seattle. Have a Mac? Wanna learn Rails?"/>
    <published>2009-12-17T08:47:00.000Z</published>
    <updated>2009-12-17T08:47:00.000Z</updated>
    <id>https://kevmoo.com/2009/12/tomorrow-seattle-have-mac-wanna-learn.html</id>
    <content type="html" xml:base="https://kevmoo.com/2009/12/tomorrow-seattle-have-mac-wanna-learn.html">&lt;img style="float:left; margin:0 10px 10px 0;width: 87px; height: 111px;border: none;" src="http://rubyonrails.org/images/rails.png" border="0" alt="" />I had a friend ask me if I'd be willing to teach him &lt;a href="http://rubyonrails.org/">Rails&lt;/a>. I said sure. Then I got to thinking: what would it take? Take a code-savvy person and teach them enough &lt;a href="http://git-scm.com/">Git&lt;/a> and &lt;a href="http://www.ruby-lang.org/">Ruby&lt;/a> and &lt;a href="http://api.rubyonrails.org/classes/ActiveRecord/Base.html">ActiveRecord&lt;/a> to get them moving.&lt;br />&lt;br />So I'm going to try it on Friday. Maybe just with Donald, but if anyone else wants to join us on Capitol Hill in Seattle, you're welcome.&lt;br />&lt;br />Requirements:&lt;br />&lt;ol>&lt;li>Have done some coding.&lt;/li>&lt;li>Have some experience with web sites, HTML, etc.&lt;/li>&lt;li>Have a Mac.&lt;/li>&lt;li>Free on Friday, Dec 18, in the afternoon.&lt;/li>&lt;li>The catch: you must bring proof of at least a $50 donation to the &lt;a href="http://www.eff.org/">EFF&lt;/a>, &lt;a href="http://creativecommons.org/">Creative Commons&lt;/a>, or &lt;a href="http://wikimediafoundation.org/wiki/Home">WikiMedia&lt;/a>. (If you're in a tight spot, we can talk.)&lt;/li>&lt;/ol>&lt;div>Drop me an email at &lt;i>ror4aday (at) j832 (dot) com&lt;/i> if you're interested. I might do something slightly more formal in January, too.&lt;/div>&lt;div>&lt;br />&lt;/div>&lt;div>See you on Friday.&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="seattle"/>
    <category term="ruby on rails"/>
    <category term="Ruby"/>
  </entry>
  <entry>
    <title type="html">Goole and reCaptcha: expanding Google's Cloud Brain</title>
    <link href="https://kevmoo.com/2009/09/goole-and-recaptcha-expanding-googles.html" rel="alternate" type="text/html" title="Goole and reCaptcha: expanding Google's Cloud Brain"/>
    <published>2009-09-16T17:27:00.000Z</published>
    <updated>2009-09-16T17:27:00.000Z</updated>
    <id>https://kevmoo.com/2009/09/goole-and-recaptcha-expanding-googles.html</id>
    <content type="html" xml:base="https://kevmoo.com/2009/09/goole-and-recaptcha-expanding-googles.html">&lt;div style="text-align:center;">&lt;img src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Chimp_Brain_in_a_jar.jpg/238px-Chimp_Brain_in_a_jar.jpg"/>&lt;/div>&lt;br />You've heard of &lt;a href="http://translate.google.com/">Google Translate&lt;/a>, right?&lt;br />&lt;br />You know how it works? &lt;a href="http://www.google.com/intl/en/help/faq_translation.html">It learns&lt;/a>:&lt;br />&lt;blockquote>Our system takes a different approach: we feed the computer billions of words of text, both monolingual text in the target language, and aligned text consisting of examples of human translations between the languages. We then apply statistical learning techniques to build a translation model. We've achieved very good results in research evaluations.&lt;br />&lt;/blockquote>Heard of &lt;a href="http://www.google.com/goog411/">Google 411&lt;/a>? Why would Google get into the 411 business? So it can learn. &lt;a href="http://www.infoworld.com/t/data-management/google-wants-your-phonemes-539">Read&lt;/a>:&lt;br />&lt;blockquote>So we need a lot of people talking, saying things so that we can ultimately train off of that. ... So 1-800-GOOG-411 is about that: Getting a bunch of different speech samples so that when you call up or we're trying to get the voice out of video, we can do it with high accuracy.&lt;/blockquote>So &lt;a href="http://googleblog.blogspot.com/2009/09/teaching-computers-to-read-google.html">Google bought reCaptcha&lt;/a>? Why? I'm betting it's the same reason.&lt;br />&lt;br />It's not about finding one translation problem with one blurry word and fixing it. It's about learning how to read any and all blurry words. So it'll need humans to intervene less and less.&lt;br />&lt;br />This is pure brilliance on Google's part: humans providing input--doing valuable work--and getting a valuable service.&lt;br />&lt;br />And Mountain View silently reaps massive amounts of intelligence.&lt;br />&lt;br />Google is throwing a lot of code over the fence--&lt;a href="http://code.google.com/p/google-collections/">Java libraries,&lt;/a> &lt;a href="http://code.google.com/chromium/">Chrome&lt;/a>, &lt;a href="http://code.google.com/android/">Android&lt;/a>--mocking the business model of traditional software companies.&lt;br />&lt;br />And they don't care. Because in the end, they have a world-class, next-to-impossible-to-replicate cloud brain.&lt;br />&lt;br />And it's getting smarter with every search, every new web page, every Goo411 call, and now, every new "You're a human, right?" verification.&lt;br />&lt;br />Cool...and a bit scary.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">RightZoom - Windows Maximize on Mac - Almost</title>
    <link href="https://kevmoo.com/2009/07/rightzoom-windows-maximize-on-mac.html" rel="alternate" type="text/html" title="RightZoom - Windows Maximize on Mac - Almost"/>
    <published>2009-07-09T19:58:00.001Z</published>
    <updated>2009-07-09T19:58:00.001Z</updated>
    <id>https://kevmoo.com/2009/07/rightzoom-windows-maximize-on-mac.html</id>
    <content type="html" xml:base="https://kevmoo.com/2009/07/rightzoom-windows-maximize-on-mac.html">&lt;p>I was looking for a maximize solution on my Mac that felt more like, well, Windows. &lt;a href="http://www.switchingtomac.com/tutorials/make-the-os-x-maximize-button-work-like-windows/">RightZoom&lt;/a> (almost) gets it.&lt;/p>&lt;p>&lt;strong>Best feature&lt;/strong>: keyboard shortcut. I can just mash down on Ctrl+Alt+Command+M and maximize a window. Boom. Awesome. (See below.)&lt;/p>&lt;p>&lt;strong>Worst issue&lt;/strong>: causes weirdness of windows when I'm multi-mon. Only on my smaller window, which is fine.&lt;/p>&lt;div style="text-align: center;">&lt;img src="http://lh6.ggpht.com/_3BkQqJvzLFM/SlZKwWAONzI/AAAAAAAAKnc/UFdbLbkzrgU/RightZoomConfig.png?imgmax=800" alt="RightZoomConfig.png" border="0" height="731" width="551" />&lt;/div>&lt;p>&lt;a href="http://www.switchingtomac.com/tutorials/make-the-os-x-maximize-button-work-like-windows/">Check it out&lt;/a>.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="mac"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">Search keywords in Firefox rock!</title>
    <link href="https://kevmoo.com/2009/07/search-keywords-in-firefox-rock.html" rel="alternate" type="text/html" title="Search keywords in Firefox rock!"/>
    <published>2009-07-03T17:56:00.001Z</published>
    <updated>2009-07-03T17:56:00.001Z</updated>
    <id>https://kevmoo.com/2009/07/search-keywords-in-firefox-rock.html</id>
    <content type="html" xml:base="https://kevmoo.com/2009/07/search-keywords-in-firefox-rock.html">I just found a &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/10279">twitter search plugin&lt;/a> for Firefox. Cool.&lt;br />&lt;br />As many know, your non-default search providers show up by clicking a drop-down by the search box. At the bottom of this drop-down, you'll notice &lt;em>Manage Search Engines...&lt;/em> link.&lt;br />&lt;br />Click it. You'll see this.&lt;br />&lt;br />&lt;img src="http://lh6.ggpht.com/_3BkQqJvzLFM/Sk5EbG7XgSI/AAAAAAAAKnY/KTnJNhXIZk0/Picture%201.png?imgmax=800" alt="Manage Search Engines Dialog" border="0" width="566" height="416" />&lt;br />&lt;br />Notice the keyword column? Notice the &lt;em>Edit Keyword...&lt;/em> button? WTF?&lt;br />&lt;br />This &lt;a href="http://support.mozilla.com/en-US/kb/Search+bar#Keywords">Mozilla KB article&lt;/a> explains it.&lt;br />&lt;br />See the keywords I added above.&lt;br />&lt;br />Typing "w Iowa" searches Wikipedia for Iowa.&lt;br />&lt;br />Typing "t health care" searches twitter for health care.&lt;br />&lt;br />Sweet!</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="internet"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">Parsing JSON with Unicode in Ruby and Rails</title>
    <link href="https://kevmoo.com/2008/12/parsing-json-with-ruby-and-rails.html" rel="alternate" type="text/html" title="Parsing JSON with Unicode in Ruby and Rails"/>
    <published>2008-12-27T23:22:00.001Z</published>
    <updated>2008-12-27T23:22:00.001Z</updated>
    <id>https://kevmoo.com/2008/12/parsing-json-with-ruby-and-rails.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/12/parsing-json-with-ruby-and-rails.html">As I've done &lt;a href="http://work.j832.com/2008/10/ruby-rails-render-and-content-type-http.html">twice&lt;/a> &lt;a href="http://work.j832.com/2008/10/imagemagick-rmagick-kerning-and.html">before&lt;/a>, I'm going to try to save someone else a couple of hours of hair pulling.&lt;br />&lt;br />I'm playing with some &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">RESTful&lt;/a> web services with a rails app as the client. The service returns &lt;a href="http://www.json.org/">JSON&lt;/a>.&lt;br />&lt;br />Cool.&lt;br />&lt;br />As defined in the spec, JSON strings may contain Unicode characters escaped as '\u &lt;span style="font-style: italic;">four-hex-digits&lt;/span>'.&lt;br />&lt;br />Let's say you had a JSON result with xml, like &lt;code>{"value":"&amp;lt;xml/&amp;gt;"}&lt;/code>.&lt;br />&lt;br />The service might return &lt;code>{"value":"\u003cxml/\u003e"}&lt;/code>.&lt;br />&lt;br />That's fine, except the default JSON parser in rails--&lt;a href="http://apidock.com/rails/ActiveSupport/JSON">ActiveSupport::JSON&lt;/a>--doesn't (&lt;a href="http://rails.lighthouseapp.com/projects/8994/tickets/1592-activesupportjsondecode-doesnt-unescape-unicode-characters">yet?&lt;/a>) support unescaping the Unicode characters.&lt;br />&lt;br />Boo!&lt;br />&lt;br />A &lt;a href="http://www.digitalhobbit.com/archives/2008/08/27/rails-and-json-containing-unicode-characters/">blog post&lt;/a> pointed me to the stand-alone &lt;a href="http://json.rubyforge.org/">JSON rails gem&lt;/a>.&lt;br />&lt;br />That solved my problem.&lt;br />&lt;br />Happy hacking, my friends.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="ruby on rails"/>
    <category term="rails"/>
    <category term="unicode"/>
    <category term="json"/>
  </entry>
  <entry>
    <title type="html">20 questions/thoughts around MGrammar</title>
    <link href="https://kevmoo.com/2008/11/20-questionsthoughts-around-mgrammar.html" rel="alternate" type="text/html" title="20 questions/thoughts around MGrammar"/>
    <published>2008-11-25T22:48:00.001Z</published>
    <updated>2008-11-25T22:48:00.001Z</updated>
    <id>https://kevmoo.com/2008/11/20-questionsthoughts-around-mgrammar.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/11/20-questionsthoughts-around-mgrammar.html">&lt;p>I had a great time attending the PDC virtually. Azure, &lt;a href="http://channel9.msdn.com/pdc2008/TL16/">C#&lt;/a>, &lt;a href="http://channel9.msdn.com/pdc2008/TL36/">Xaml&lt;/a>—these all were cool. The tech I was most excited about was Oslo, specifically building custom &lt;a href="http://channel9.msdn.com/pdc2008/TL31/">DSLs with MGrammar&lt;/a>.&lt;/p> &lt;p>Having spent a lot of time in Xaml and C# at Microsoft and migrating to a world of Ruby and JavaScript and HTML/CSS and HAML/SASS, I've had my hands in a lot of tools. And I have lots of questions and thoughts for the community. And, specifically, &lt;a href="http://www.simplegeek.com/">Chris&lt;/a>, &lt;a href="http://www.pluralsight.com/community/blogs/dbox/">Don&lt;/a>, &lt;a href="http://douglaspurdy.com/">Doug&lt;/a>, &lt;a href="http://tinyfinger.blogspot.com/">Pinky&lt;/a>, and the gang.&lt;/p> &lt;p>When I talk about a 'logical', I'm talking about MSchema in Oslo terminology--at least I think so.&lt;/p> &lt;ol> &lt;li>Where&amp;#160; is the MGrammar for C#? &lt;/li> &lt;li>…for VB? &lt;/li> &lt;li>…for CSV? &lt;/li> &lt;li>…for VS Solution files? &lt;/li> &lt;li>…for XML? &lt;/li> &lt;li>Could C#/VB implement their compilers using MGrammar? Should they? Would they? &lt;ul> &lt;li>I’m imagining the tools I could write if I had the grammar…and could insert myself in pre-compile stage. Awesome. &lt;/li> &lt;li>What an amazing better-together with C#'s new compiler-as-service. &lt;/li> &lt;/ul> &lt;/li> &lt;li>There should be standardized or defacto escape mechanisms for existing grammars. &lt;ul> &lt;li>&amp;quot;If you want to inject your own magic into [C#|VB|XML|etc] use this (relatively) safe/constrained notation.&amp;quot; &lt;/li> &lt;li>I'm thinking about a subset of &lt;a href="http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html">SASS&lt;/a> markup for WPF styles that I could in-line in XAML and have processed at build-time. &lt;/li> &lt;/ul> &lt;/li> &lt;li>Could the MGrammar for XAML just party off the MGrammar for XML? &lt;/li> &lt;li>…could it be written without referring to 'physical' XML, and instead just refer to the XML MSchema model? &lt;/li> &lt;li>If I had a MGrammar for &lt;a href="http://haml.hamptoncatlin.com/">HAML&lt;/a> that could generate most of ‘logical’ XML, could I then 'infer' the 'XAML in HAML' using #9? &lt;/li> &lt;li>Will there be tools to go back from a logical model (MSchema) to the input format? I'd like to store data in a logical model, but be able to allow editing via the text format. &lt;/li> &lt;li>How about tools that allow the comparison of two grammars to see if they generate the same MSchema--perhaps with different labels. Perhaps with the ability to convert between them. Perhaps with the ability to identify strict sub- or super-set grammars. &lt;/li> &lt;li>Where is the community site for MGrammar? &lt;ul> &lt;li>User-submitted grammars &lt;/li> &lt;li>User submitted and verified 'tests' against the grammars &lt;/li> &lt;li>Easy tracking of new (and old) versions &lt;/li> &lt;li>Easy tracking of forked/related grammars &lt;/li> &lt;/ul> &lt;/li> &lt;li>Want to have &lt;a href="http://www.mgrammars.com/">MGrammars.com&lt;/a>? I registered it for Microsoft. I'll give it to ya'll for free. Just promise to make a great community site. &lt;/li> &lt;li>I'll even build the site for you. It'll give me an excuse to use &lt;a href="http://azure.com/">Azure&lt;/a>. I'm happy to offer my &lt;a href="http://kevinmooreconsulting.com/">consulting services&lt;/a>. &lt;/li> &lt;li>Any news with Mono? Is Miguel interested? &lt;/li> &lt;li>Are you making a play to make MGrammar a standard? I've heard yes, but just wanted to confirm. &lt;/li> &lt;li>How is the computer science behind MGrammar? Is it as good/better than existing tools? BNF? Lex/Yacc? Others? Is there a write-up? I'd love to see where MGrammar is pushing the state-of-the-art. &lt;/li> &lt;li>Anyone pushing a normalized Wiki grammar? Like &lt;a href="http://www.riehle.org/2008/01/09/an-ebnf-grammar-for-wiki-creole-10/">this&lt;/a>? Yes, a weird point, but think of how much IQ in the world is stored in Wikipedia and it's next to impossible to parse because MediaWiki format has a bunch of random PHP parsing quirks. A great intern project. &lt;/li> &lt;li>As you can tell, super excited about the project, guys. Keep it up. &lt;/li> &lt;/ol></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="mgrammar"/>
    <category term="xaml"/>
    <category term="C#"/>
    <category term="oslo"/>
  </entry>
  <entry>
    <title type="html">Props to Silverlight CLR team: My Common DLL Just Works FTMP</title>
    <link href="https://kevmoo.com/2008/11/props-to-silverlight-clr-team-my-common.html" rel="alternate" type="text/html" title="Props to Silverlight CLR team: My Common DLL Just Works FTMP"/>
    <published>2008-11-21T09:17:00.001Z</published>
    <updated>2008-11-21T09:17:00.001Z</updated>
    <id>https://kevmoo.com/2008/11/props-to-silverlight-clr-team-my-common.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/11/props-to-silverlight-clr-team-my-common.html">&lt;p>FTMP = For the most part&lt;/p> &lt;p>In Visual Web Developer 2008 Express Edition SP1 .NET XP Live.&lt;/p> &lt;ul> &lt;li>I created a new Silverlight control library, under my &lt;a href="http://j832.com/PublicSoftware/">public SVN&lt;/a> location. &lt;/li> &lt;li>I did the right-click ‘Add Existing Item...’ trick. &lt;/li> &lt;li>I navigated to J832.Common and added all of the CS files (except DBUtil and ReaderWriterLockHelper). &lt;/li> &lt;li>And I hit build and watch it compile. &lt;/li> &lt;/ul> &lt;p>The result is a very &lt;a href="http://j832.com/PublicSoftware/J832.SL.Common/">boring looking directory&lt;/a> with great potential: I can now use all of my common tricks in Silverlight, too.&lt;/p> &lt;p>You know, if I happen to be working on something in Silverlight. Hypothetically.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="Silverlight"/>
  </entry>
  <entry>
    <title type="html">First Project Shipped: What A Lovely Name</title>
    <link href="https://kevmoo.com/2008/11/first-project-shipped-what-lovely-name.html" rel="alternate" type="text/html" title="First Project Shipped: What A Lovely Name"/>
    <published>2008-11-17T20:43:00.000Z</published>
    <updated>2008-11-17T20:43:00.000Z</updated>
    <id>https://kevmoo.com/2008/11/first-project-shipped-what-lovely-name.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/11/first-project-shipped-what-lovely-name.html">&lt;a href="http://www.whatalovelyname.com/" style="text-align: center; display: block;">&lt;img style="width: 255px; height: 141px;" src="http://3.bp.blogspot.com/_3BkQqJvzLFM/SSHYa_nwWTI/AAAAAAAAIQ4/teyDWkr8Mzk/s400/logo.png" alt="" id="BLOGGER_PHOTO_ID_5269730997266569522" border="0" />&lt;/a>&lt;br />It's &lt;a href="http://www.jacksonfish.com/blog/2008/11/17/what-a-lovely-name/">official&lt;/a>.&lt;br />&lt;br />After an amazing first collaboration with my friends at &lt;a href="http://www.jacksonfish.com/">Jackson Fish Market&lt;/a>, &lt;a href="http://www.whatalovelyname.com/">What A Lovely Name&lt;/a> has launched.&lt;br />&lt;br />Thanks to...&lt;ul>&lt;li>&lt;a href="http://www.jacksonfish.com/blog/author/jenny/">Jenny&lt;/a> - what an amazing designer. It was an honor just to be able to set her graphics as div backgrounds.&lt;/li>&lt;li>&lt;a href="http://waltersmith.us/">Walter&lt;/a> - in a word, brilliant. Turned hours of hacking into moments of enlightenment. He's made me a better [ruby|javascript|css|*nix] hacker and a better engineer.&lt;/li>&lt;li>&lt;a href="http://www.hillel.com/">Hillel&lt;/a> convinced me to leave a comfortable job at an insurance company and start my own gig--with a story about half-priced pots. I'm not kidding. I'm not sure I would have done it without his encouragement--or prodding. Looking back over what I've done and what I've learned over the last 4+ months, I couldn't be more grateful.&lt;/li>&lt;/ul>Also thanks to...&lt;ul>&lt;li>&lt;a href="http://www.apple.com/macbookpro/">MacBook Pro&lt;/a> for being an amazing piece of hardware, even if it's not the new one.&lt;br />&lt;/li>&lt;li>&lt;a href="http://www.ruby-lang.org/en/">Ruby&lt;/a> and &lt;a href="http://www.rubyonrails.org/">Ruby on Rails&lt;/a> for challenging my sole devotion to statically typed and compiled languages&lt;/li>&lt;li>&lt;a href="http://apidock.com/rails">APIDock&lt;/a> for being a great Rails reference.&lt;br />&lt;/li>&lt;li>&lt;a href="http://haml.hamptoncatlin.com/">Haml and Sass&lt;/a> for making HTML and CSS fun&lt;br />&lt;/li>&lt;li>&lt;a href="http://www.prototypejs.org/">Prototype&lt;/a> and &lt;a href="http://script.aculo.us/">script.aculo.us&lt;/a> for some amazing Javascript tools&lt;/li>&lt;li>&lt;a href="http://www.imagemagick.org/">ImageMagick&lt;/a> for server-side dynamic image generation&lt;/li>&lt;li>&lt;a href="http://en.wikipedia.org/wiki/Secure_Shell">ssh&lt;/a> - I now know how people on Unix get things done&lt;/li>&lt;li>&lt;a href="http://git.or.cz/">git&lt;/a> (and for a while &lt;a href="http://subversion.tigris.org/">Subversion&lt;/a>) for version control.&lt;br />&lt;/li>&lt;li>&lt;a href="http://pmt.sourceforge.net/pngcrush/">pngcrush&lt;/a> for making small pngs&lt;br />&lt;/li>&lt;li>&lt;a href="http://www.capify.org/">Capistrano&lt;/a> for making deployment easy&lt;br />&lt;/li>&lt;li>&lt;a href="http://www.macports.org/">Mac Ports&lt;/a> for making it scary easy to install unix tricks on a mac&lt;br />&lt;/li>&lt;li>&lt;a href="http://getfirebug.com/">Firebug&lt;/a> for debugging everything. Amazing.&lt;/li>&lt;li>&lt;a href="http://www.mozilla.com/en-US/firefox/">Firebox&lt;/a> for having an extensibility story that supports things like Firebug&lt;/li>&lt;li>&lt;a href="http://www.apple.com/safari/">Safari&lt;/a> for being more stable and more standards-compliant than Firefox a lot of the time&lt;br />&lt;/li>&lt;li>&lt;a href="http://www.vmware.com/">VMWare&lt;/a> for letting me test IE7 compat without a Windows box&lt;/li>&lt;li>&lt;a href="http://www.microsoft.com/windows/internet-explorer/">IE8&lt;/a> for emulating IE7 so nicely with something approaching reasonable dev tools&lt;/li>&lt;li>&lt;a href="http://www.slicehost.com/">SliceHost&lt;/a> for, well, hosting&lt;br />&lt;/li>&lt;li>&lt;a href="http://macromates.com/">TextMate&lt;/a> for being an amazing editor&lt;br />&lt;/li>&lt;li>&lt;a href="http://www.skype.com/">Skype&lt;/a> and &lt;a href="http://www.adiumx.com/">Adium&lt;/a> for helping me stay in touch&lt;/li>&lt;li>&lt;a href="http://www.onlinecoffeeco.com/">Online Coffee Company&lt;/a> for keeping me caffeinated&lt;br />&lt;/li>&lt;/ul>It's been a great ride. Can't wait for the next project.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">ImageMagick, RMagick, Kerning, and baseline_shift</title>
    <link href="https://kevmoo.com/2008/10/imagemagick-rmagick-kerning-and.html" rel="alternate" type="text/html" title="ImageMagick, RMagick, Kerning, and baseline_shift"/>
    <published>2008-10-29T19:51:00.000Z</published>
    <updated>2008-10-29T19:51:00.000Z</updated>
    <id>https://kevmoo.com/2008/10/imagemagick-rmagick-kerning-and.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/10/imagemagick-rmagick-kerning-and.html">As I &lt;a href="http://work.j832.com/2008/10/ruby-rails-render-and-content-type-http.html">said on Monday&lt;/a>, at some point there has to be the first person to blog a useful tidbit in the world of software.&lt;br />&lt;br />So, for the second time this week, let me be the first.&lt;br />&lt;br />I've been using &lt;a href="http://www.imagemagick.org/">ImageMagick&lt;/a>--via &lt;a href="http://www.imagemagick.org/RMagick/doc/">RMagick&lt;/a>--to generate dynamic PNGs on the server.&lt;br />&lt;br />In general, it's working great, except in one case.&lt;br />&lt;br />I'm drawing text with custom fonts. The fonts have custom &lt;a href="http://en.wikipedia.org/wiki/Kerning">kerning&lt;/a>.&lt;br />&lt;br />ImageMagick seems to handle this fine &lt;em>except&lt;/em> when one uses &lt;a href="http://www.imagemagick.org/RMagick/doc/rvgtext.html#advanced">baseline_shift&lt;/a>, at which point ImageMagick forgets everything about kerning.&lt;br />&lt;br />You can fake the baseline shift by using &lt;a href="http://www.imagemagick.org/RMagick/doc/draw.html#get_type_metrics">get_type_metrics&lt;/a>.&lt;br />&lt;br />Again, here's hoping this saves someone 20 minutes...or in my case, a few hours.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="ImageMagick"/>
    <category term="ruby on rails"/>
    <category term="rails"/>
    <category term="RMagick"/>
  </entry>
  <entry>
    <title type="html">Ruby, Rails, Render, and the Content-Type HTTP header</title>
    <link href="https://kevmoo.com/2008/10/ruby-rails-render-and-content-type-http.html" rel="alternate" type="text/html" title="Ruby, Rails, Render, and the Content-Type HTTP header"/>
    <published>2008-10-27T18:58:00.000Z</published>
    <updated>2008-10-27T18:58:00.000Z</updated>
    <id>https://kevmoo.com/2008/10/ruby-rails-render-and-content-type-http.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/10/ruby-rails-render-and-content-type-http.html">Don't you hate it when you google for 30 minutes, trying to solve a simple problem, but for some reason the right combination of terms--or at least the combination of terms you think is right--fails.&lt;br />&lt;br />It just happened to me with a simple problem: change the &lt;a href="http://en.wikipedia.org/wiki/List_of_HTTP_headers">Content-Type HTTP Response Header&lt;/a> for using standard Rails templates to be &lt;code>text/xml&lt;/code>.&lt;br />&lt;br />The solution is pretty straight-forward:&lt;blockquote>&lt;code>response.headers["Content-Type"] = 'text/xml'&lt;/code>&lt;/blockquote>...as I eventually found &lt;a href="http://snipplr.com/view/6463/header-content-type-in-rails-2/">here&lt;/a>.&lt;br />&lt;br />Setting this hash value in your &lt;a href="http://apidock.com/rails/ActionController/Base">ActionController&lt;/a> action method does the trick.&lt;br />&lt;br />Here's hoping google picks this up and saves someone 20 minutes.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="ruby on rails"/>
    <category term="rails"/>
  </entry>
  <entry>
    <title type="html">Fun with Google Maps and JavaScript</title>
    <link href="https://kevmoo.com/2008/10/fun-with-google-maps-and-javascript.html" rel="alternate" type="text/html" title="Fun with Google Maps and JavaScript"/>
    <published>2008-10-25T06:49:00.000Z</published>
    <updated>2008-10-25T06:49:00.000Z</updated>
    <id>https://kevmoo.com/2008/10/fun-with-google-maps-and-javascript.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/10/fun-with-google-maps-and-javascript.html">In &lt;a href="http://work.j832.com/2008/09/what-ive-been-up-to.html">my last post&lt;/a>, I mentioned some hacking with &lt;a href="http://en.wikipedia.org/wiki/JavaScript">JavaScript&lt;/a>.&lt;br />&lt;br />While I've been finishing my first 'real' project for &lt;a href="http://www.jacksonfish.com/">Jackson Fish Market&lt;/a>, I've also been using my new knowledge of JS to dig into the &lt;a href="http://code.google.com/apis/maps/">Google Maps APIs&lt;/a>.&lt;br />&lt;br />My &lt;a href="http://j832.com/boxotricks/simplegooglemaps/">first sample&lt;/a> is a simple location list. Type in an address (or just a city, zip, landmark) and hit 'Add location'. If the place can be found, it will be mapped and added to a list of locations. You can click on a location to go back to it or click on the 'X' to remove it.&lt;br />&lt;br />&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://j832.com/boxotricks/simplegooglemaps/">&lt;img style="cursor: pointer; width: 400px; height: 250px;" src="http://2.bp.blogspot.com/_3BkQqJvzLFM/SQLD502CFvI/AAAAAAAAINQ/TtIxkXq1qSs/s400/gmapsimple.png" alt="" id="BLOGGER_PHOTO_ID_5260982712927393522" border="0" />&lt;/a>&lt;br />Pretty simple, but also pretty cool.&lt;br />&lt;br />And since this is the web, I don't have to post a zip file. 'View Source' will get you into see the magic.&lt;br />&lt;br />Enjoy and happy hacking.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="javascript"/>
    <category term="Programming"/>
    <category term="google maps"/>
  </entry>
  <entry>
    <title type="html">What I've been up to...</title>
    <link href="https://kevmoo.com/2008/09/what-ive-been-up-to.html" rel="alternate" type="text/html" title="What I've been up to..."/>
    <published>2008-09-03T05:01:00.000Z</published>
    <updated>2008-09-03T05:01:00.000Z</updated>
    <id>https://kevmoo.com/2008/09/what-ive-been-up-to.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/09/what-ive-been-up-to.html">I just realized that I haven't really posted since June.&lt;br />&lt;br />For all of you still subscribed, I'm glad you're still hopeful I'll be blogging something interesting.&lt;br />&lt;br />Here's a quick run-down of my (work) life the last couple of months.&lt;br />&lt;ul>&lt;li>Hacking a bunch of &lt;a href="http://rubyonrails.org/">Ruby on Rails&lt;/a> for a soon-to-be-released &lt;a href="http://www.jacksonfish.com/">JFM&lt;/a> experience.&lt;/li>&lt;li>Loving &lt;a href="http://haml.hamptoncatlin.com/">HAML and SASS&lt;/a> for generating HTML and CSS in Rails.&lt;/li>&lt;li>Loving &lt;a href="http://www.prototypejs.org/">Prototype&lt;/a> for coding Javascript--completely blown away what one can do with script. Loving blowing off a Flash component because it turns out JS+CSS is perfectly good.&lt;br />&lt;/li>&lt;li>Loving my &lt;a href="http://www.apple.com/">Mac&lt;/a>, mostly because it's &lt;a href="http://www.freebsd.org/">UNIX&lt;/a>.&lt;/li>&lt;li>Loving tweaking my bash shell--although considering moving to &lt;a href="http://en.wikipedia.org/wiki/Zsh">zsh&lt;/a>.&lt;/li>&lt;li>Loving &lt;a href="http://www.macports.org/">MacPorts&lt;/a> for OSS installation.&lt;/li>&lt;li>Finally understanding and tweaking &lt;a href="http://en.wikipedia.org/wiki/Ipfw">ipfw firewall&lt;/a> settings with &lt;a href="http://www.hanynet.com/waterroof/">WaterRoof&lt;/a>.&lt;/li>&lt;li>Loving &lt;a href="http://macromates.com/">TextMate&lt;/a>, although I still need to learn more keyboard shortcuts.&lt;/li>&lt;li>Getting darn good at &lt;a href="http://subversion.tigris.org/">SVN&lt;/a>, but really want to start using &lt;a href="http://git.or.cz/">Git&lt;/a> more often.&lt;/li>&lt;/ul>What I hope to be doing soon.&lt;br />&lt;ul>&lt;li>Coding some &lt;a href="http://silverlight.net/">Silverlight&lt;/a>. Maybe some controls?&lt;br />&lt;/li>&lt;li>Coding some &lt;a href="http://www.python.org/">Python&lt;/a>, hopefully for &lt;a href="http://code.google.com/appengine/">Google App Engine&lt;/a>.&lt;/li>&lt;li>Coding some stuff for &lt;a href="http://www.apple.com/iphone/">iPhone&lt;/a>. Maybe...&lt;br />&lt;/li>&lt;li>Moving my blog to a server I control--maybe &lt;a href="http://wordpress.org/">WordPress&lt;/a>--maybe something that runs on Rails. Who knows.&lt;br />&lt;/li>&lt;li>Working on some cool projects to improve democracy. Yes, random and vague. Hopefully I'll have more in a few months.&lt;/li>&lt;/ul>A lot of that will be on the back burner until I'm back from Europe. If any readers are in London, Oslo, Berlin, Munich, Paris or Cardiff, let me know. I'll be around mid-Sept to mid-October.&lt;br />&lt;br />In the mean time and as always, happy hacking.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Robby is Free, too</title>
    <link href="https://kevmoo.com/2008/09/robby-is-free-too.html" rel="alternate" type="text/html" title="Robby is Free, too"/>
    <published>2008-09-03T04:57:00.000Z</published>
    <updated>2008-09-03T04:57:00.000Z</updated>
    <id>https://kevmoo.com/2008/09/robby-is-free-too.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/09/robby-is-free-too.html">My good friend &lt;a href="http://nerdplusart.com/">Robby&lt;/a>--yes, check out that insanely hot &lt;a href="http://nerdplusart.com/">Silverlight homepage&lt;/a>--just &lt;a href="http://blog.nerdplusart.com/archives/a-fond-farewell">announced he's leaving&lt;/a> &lt;a href="http://identitymine.com/">Identity Mine&lt;/a>&lt;br />&lt;br />Congrats on your freedom, my friend.&lt;br />&lt;br />Yes, we need to get lunch this week.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">I'm Free(lance)</title>
    <link href="https://kevmoo.com/2008/06/i-freelance.html" rel="alternate" type="text/html" title="I'm Free(lance)"/>
    <published>2008-06-04T04:37:00.001Z</published>
    <updated>2008-06-04T04:37:00.001Z</updated>
    <id>https://kevmoo.com/2008/06/i-freelance.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/06/i-freelance.html">&lt;p>It's seems like only 8 month ago that I was &lt;a href="http://work.j832.com/2007/09/i-leaving-microsoft.html">leaving a job&lt;/a>. It's just too much fun to switch around my insurance and investment plans, I guess.&lt;/p> &lt;p>I've had a great time at &lt;a href="http://actman.com/">AMC&lt;/a>. I proved to myself I can be happy being a developer full-time--something that worried me after five years as a program manager at Microsoft.&lt;/p> &lt;p>I'll miss working with &lt;a href="http://www.actman.com/contacts/paul.html">Paul&lt;/a> and &lt;a href="http://dpotter.net/Technical/">David&lt;/a>. Working day-to-day with David has been amazing. One of the hardest working and sweetest guys I know. He's made be a better developer and probably a better person.&lt;/p> &lt;p>What's next?&lt;/p> &lt;p>On June 16 I enter the wonderful, terrifyingly independent world of software consulting and freelancing.&lt;/p> &lt;p>My first gig will be helping out some good friends and former MS co-workers at &lt;a href="http://www.jacksonfish.com/">Jackson Fish Market&lt;/a>.&lt;/p> &lt;p>You'll hear all about the project when it's done. All I can say now: &lt;a href="http://www.rubyonrails.org/">Ruby on Rails&lt;/a> and a little &lt;a href="http://www.adobe.com/products/flash/">Flash&lt;/a>.&lt;/p> &lt;p>I can't wait to hear the comments about either leaving or go to the dark side.&lt;/p> &lt;p>Yes, I've been spending time at the &lt;a href="http://store.apple.com/us">Apple Store&lt;/a>. Scary.&lt;/p> &lt;p>No, I'm not giving up the MS stack. I'm hoping to have the chance to do consulting and freelance work in WPF and Silverlight, too.&lt;/p> &lt;p>While I'm likely booked for over a month, I'll be looking for gig+1, +2, etc. shortly.&lt;/p> &lt;p>If you would like to chat about my services, please drop me an line: edeya9902(at)sneakemail(dot)com.&lt;/p> &lt;p>In the mean time, happy hacking.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">iPhone 2 - Apple's entry into the console market</title>
    <link href="https://kevmoo.com/2008/06/iphone-2-apple-entry-into-console.html" rel="alternate" type="text/html" title="iPhone 2 - Apple's entry into the console market"/>
    <published>2008-06-03T20:33:00.001Z</published>
    <updated>2008-06-03T20:33:00.001Z</updated>
    <id>https://kevmoo.com/2008/06/iphone-2-apple-entry-into-console.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/06/iphone-2-apple-entry-into-console.html">&lt;p>&lt;a href="http://j832.com/workBlogFiles/_images/iPhone2Applesentryintotheconsolemarket_BEB1/image.png">&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="185" alt="image" src="http://j832.com/workBlogFiles/_images/iPhone2Applesentryintotheconsolemarket_BEB1/image_thumb.png" width="244" border="0" />&lt;/a> &lt;/p> &lt;p>Well, maybe not so much the console market as the console business model.&lt;/p> &lt;p>The $200 price tag has been &lt;a href="http://cultofmac.com/hot-tip-iphone-2-features-detailed-3g-gps-2xram-thinner-better-battery-and-only-200/2032">thrown&lt;/a> &lt;a href="http://www.macrumors.com/2008/06/01/200-low-end-iphone/">around&lt;/a> &lt;a href="http://gizmodo.com/385429/atts-3g-iphone-is-199-this-summer">a lot&lt;/a>.&lt;/p> &lt;p>Can the device be this cheap to make? Maybe, but I doubt it matters.&lt;/p> &lt;p>It seems Apple is going for the two-headed revenue model of Xbox.&lt;/p> &lt;p>1) &lt;strong>Get a slice off the service. &lt;/strong>Assuming the existing deal sticks around with AT&amp;amp;T and is copied in other countries, Apple gets a cut of the monthly phone service plan. (&lt;a href="http://www.alleyinsider.com/2007/10/apples-iphone-bounty-432-from-att.html">$18/month currently&lt;/a>.) This is an even better deal for Apple than Xbox Live is for Microsoft. MS has to deal with the infrastructure and up time for their for-profit service. Apple leaves all of that grunt work to the carriers and still walks away with a fat check every month.&lt;/p> &lt;p>2) &lt;strong>Charge app authors.&lt;/strong> There will be a flood of apps for iPhone 2. Apple gets 30% of the sale of all applications--similar to fees changes for XBox and PS. If initial excitement around iPhone apps holds up--even if it's just for games--Apple stands to make a lot of money.&lt;/p> &lt;p>Apples doesn't even have to break even on the hardware to come out ahead. That puts Steve Jobs in an amazing advantage over Blackberry and others who have to make their hardware generate profit from sales alone.&lt;/p> &lt;p>Brilliant.&lt;/p> &lt;p>In the end, I don't care. I'm happy with the money I've thrown down so far.&lt;/p> &lt;p>One request: add over-the-air calendar/contacts sync with Google.&lt;/p> &lt;p>I'll be the happiest man alive.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="iphone"/>
  </entry>
  <entry>
    <title type="html">Rob Relyea doesn't hate my mom; Karsten?</title>
    <link href="https://kevmoo.com/2008/05/rob-relyea-doesn-hate-my-mom-karsten.html" rel="alternate" type="text/html" title="Rob Relyea doesn't hate my mom; Karsten?"/>
    <published>2008-05-30T04:06:00.001Z</published>
    <updated>2008-05-30T04:06:00.001Z</updated>
    <id>https://kevmoo.com/2008/05/rob-relyea-doesn-hate-my-mom-karsten.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/05/rob-relyea-doesn-hate-my-mom-karsten.html">&lt;p>&lt;em>Search for &amp;quot;&lt;/em>&lt;a href="http://www.google.com/search?q=why+does+rob+hate+my+mom">&lt;em>why does rob hate my mom&lt;/em>&lt;/a>&lt;em>&amp;quot;. I love the internet.&lt;/em>&lt;/p> &lt;p>In March, I called out &lt;a href="http://robrelyea.com/">Rob Relyea&lt;/a> about his &lt;a href="http://work.j832.com/2008/03/rob-relyea-hates-my-mom.html">passive aggressive stance&lt;/a> towards a wonderful high school librarian in Iowa.&lt;/p> &lt;p>He was kind enough to &lt;a href="http://windowsclient.net/blogs/rob_relyea/archive/2008/03/17/why-does-karsten-hate-kevin-s-mom.aspx">respond&lt;/a>, but I've been lazy about the follow-up.&lt;/p> &lt;p>So now I redirect my indignation: what's the story, &lt;a href="http://rhizohm.net/irhetoric/">Karsten&lt;/a>?&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">GMail feature request: help me keep track of replies.</title>
    <link href="https://kevmoo.com/2008/05/gmail-feature-request-help-me-keep.html" rel="alternate" type="text/html" title="GMail feature request: help me keep track of replies."/>
    <published>2008-05-24T04:40:00.001Z</published>
    <updated>2008-05-24T04:40:00.001Z</updated>
    <id>https://kevmoo.com/2008/05/gmail-feature-request-help-me-keep.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/05/gmail-feature-request-help-me-keep.html">&lt;p>Scenario:&lt;/p> &lt;ol> &lt;li>I sent out email to many people via BCC. &lt;/li> &lt;li>I get a bunch of replies to this email. &lt;/li> &lt;li>I want to reply in kind to these incoming messages, but GMail doesn't show which received messages I've replied to. &lt;/li> &lt;/ol> &lt;p>Suggestions:&lt;/p> &lt;ol> &lt;li>Give the option of the standard threaded discussion via. While GMail's interface is better in most scenarios, there are cases where a tree is better. &lt;/li> &lt;li>At minimum, give some indication that I've replied to a message. With many messages stacked in a thread, I can't figure out which I've replied to and which I haven't. &lt;/li> &lt;/ol> &lt;p>You have until next Friday, or I'm going back to Hotmail.&lt;/p> &lt;p>I bet if I wait long enough, Microsoft will give me $.05 for every email I send.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="internet"/>
  </entry>
  <entry>
    <title type="html">Why I hate Frameworks: from hammer to "general-purpose tool-building factory factory factory"</title>
    <link href="https://kevmoo.com/2008/05/why-i-hate-frameworks-from-hammer-to.html" rel="alternate" type="text/html" title="Why I hate Frameworks: from hammer to &quot;general-purpose tool-building factory factory factory&quot;"/>
    <published>2008-05-12T23:48:00.001Z</published>
    <updated>2008-05-12T23:48:00.001Z</updated>
    <id>https://kevmoo.com/2008/05/why-i-hate-frameworks-from-hammer-to.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/05/why-i-hate-frameworks-from-hammer-to.html">&lt;p>A recent discussion with a smart guy reminded me of an article I read years ago. I wanted to think I read it on &lt;a href="http://www.joelonsoftware.com/">Joel on Software&lt;/a>. I wanted to think it had something to do with &amp;quot;hammer factories&amp;quot;.&lt;/p> &lt;p>Google &lt;a href="http://www.google.com/search?q=hammer+factory+joel">did the rest&lt;/a>.&lt;/p> &lt;p>The write-up, &lt;em>&lt;a href="http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12">Why I Hate Frameworks&lt;/a>&lt;/em> comes from &lt;a href="http://discuss.joelonsoftware.com/default.asp?joel">Joel's discussion group&lt;/a>. Written by &lt;a href="http://benjismith.net/">Benji Smith&lt;/a>.&lt;/p> &lt;blockquote> &lt;p>&amp;quot;So, instead, we started selling schematic diagrams for hammer factories, enabling our clients to build their own hammer factories, custom engineered to manufacture only the kinds of hammers that they would actually need.&amp;quot;&lt;/p> &lt;p>&amp;quot;Let me guess. You don't sell those anymore.&amp;quot;&lt;/p> &lt;p>&amp;quot;Nope. Sure don't. As it turns out, people don't want to build an entire factory just to manufacture a couple of hammers. Leave the factory-building up to the factory-building experts, that's what I always say!!&amp;quot;&lt;/p> &lt;/blockquote> &lt;p>Like most good content on the internet, brilliant &lt;em>and&lt;/em> hilarious.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">License for the Bag-o-Tricks...uh...</title>
    <link href="https://kevmoo.com/2008/05/license-for-bag-o-trickesuh.html" rel="alternate" type="text/html" title="License for the Bag-o-Tricks...uh..."/>
    <published>2008-05-07T22:39:00.001Z</published>
    <updated>2008-05-07T22:39:00.001Z</updated>
    <id>https://kevmoo.com/2008/05/license-for-bag-o-trickesuh.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/05/license-for-bag-o-trickesuh.html">&lt;p>I might as well handles the two &amp;quot;&lt;a href="http://work.j832.com/2008/05/bag-o-tricks-datepicker-controluh.html">90% issues&lt;/a>&amp;quot; together.&lt;/p> &lt;p>A lot of people ask about the license for the &lt;a href="http://j832.com/bagotricks/">bag-o-tricks&lt;/a>.&lt;/p> &lt;p>Here's the story.&lt;/p> &lt;p>Most of the code in the bag-o-tricks was written while I was at Microsoft. I never took the time to formally license it while at Microsoft.&lt;/p> &lt;p>Given the type of code and how it's been released, I &lt;em>think&lt;/em> it's more than safe to consider it under the &lt;a href="http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx">Microsoft Public License&lt;/a>.&lt;/p> &lt;p>I say &amp;quot;I think&amp;quot; because I'm not a lawyer and I'm not 100% sure how to deal with code that I wrote while at Microsoft--and therefor, technically, &amp;quot;owned&amp;quot; by Microsoft.&lt;/p> &lt;p>I'd bet $10 you won't get sued if you use it any way you see fit. But that's as far as I'll stick my neck out. Being on the other side of the fence from the MSFT legal department is a bit...uh...interesting.&lt;/p> &lt;p>Everything that's new since I left I've put under the &lt;a href="http://www.opensource.org/licenses/mit-license.php">MIT license&lt;/a>, which I find pretty good.&lt;/p> &lt;p>I'm trying to keep a clear firewall between that code, even going so far as to keep the namespaces separate.&lt;/p> &lt;p>I hope this helps a little. I know folks are looking to use individual controls in their commercial applications.&lt;/p> &lt;p>While I can't give you a 100% guarantee about the code, I can say I'm pretty sure you have nothing to worry about.&lt;/p> &lt;p>I'm not sure if that sounds more like lawyer speak or marketing speak.&lt;/p> &lt;p>Happy hacking (except where prohibited)&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Bag-o-Tricks DatePicker control...uh...</title>
    <link href="https://kevmoo.com/2008/05/bag-o-tricks-datepicker-controluh.html" rel="alternate" type="text/html" title="Bag-o-Tricks DatePicker control...uh..."/>
    <published>2008-05-07T22:27:00.001Z</published>
    <updated>2008-05-07T22:27:00.001Z</updated>
    <id>https://kevmoo.com/2008/05/bag-o-tricks-datepicker-controluh.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/05/bag-o-tricks-datepicker-controluh.html">&lt;p>90% of the questions I get on the &lt;a href="http://j832.com/bagotricks/">bag-o-tricks&lt;/a> fall into one of two buckets.&lt;/p> &lt;p>The first bucket is DatePicker.&lt;/p> &lt;p>While I'd love to take credit (or perhaps blame) for it, I didn't build it.&lt;/p> &lt;p>It was done as a demo by some engineers in a Microsoft office in China.&lt;/p> &lt;p>I have the slightest clue how it is built or how it works (other than I'm pretty sure I'd do a total 180 if I were to try to implement the same functionality.)&lt;/p> &lt;p>I've got a number of bug reports and feature requests. I'm sorry for being quiet on them. DatePicker really doesn't line up with anything I'm playing with at the moment...so I haven't spent much (read &amp;quot;any&amp;quot;) time on it.&lt;/p> &lt;p>If anyone has bug fixes or new features, as always, send me me an SVN patch and I'll be happy to get things fixed.&lt;/p> &lt;p>Alternatively, you can always offer to shower me with cash and lavish gifts to dig in on your favorite problem.&lt;/p> &lt;p>I'm not above being bought. :-)&lt;/p> &lt;p>&amp;#160;&lt;/p> &lt;p>Oh, and it's great being back in Seattle. India was great, but there's no place like home.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">India in April</title>
    <link href="https://kevmoo.com/2008/04/india-in-april.html" rel="alternate" type="text/html" title="India in April"/>
    <published>2008-04-01T17:12:00.001Z</published>
    <updated>2008-04-01T17:12:00.001Z</updated>
    <id>https://kevmoo.com/2008/04/india-in-april.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/04/india-in-april.html">&lt;p>This is just a heads-up. I'm going to be pretty quiet for the month of April. I'm getting on a plane in 4 hours for India.&lt;/p> &lt;p>I'm spending the month there--doing a &lt;a href="http://tushita.info/">meditation retreat&lt;/a>, seeing &lt;a href="http://en.wikipedia.org/wiki/Taj_Mahal">some sites&lt;/a>, hopefully &lt;a href="http://lindyhopindia.com/">dancing a bit&lt;/a>.&lt;/p> &lt;p>If you're a regular reader and live in Mumbai, Delhi, or points in between, let me know. We might be able to meet for coffee.&lt;/p> &lt;p>edeya9902(at)sneakemail(dot)com&lt;/p> &lt;p>Watch my &lt;a href="http://blog.j832.com/">personal blog&lt;/a> for updates. If I find a computer, I'll try to make some posts.&lt;/p> &lt;p>Otherwise, see you in May!&lt;/p> &lt;p>&amp;gt;Kevin&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">IE8, Standards, and Joel is Scary Brilliant</title>
    <link href="https://kevmoo.com/2008/03/ie8-standards-and-joel-is-scary.html" rel="alternate" type="text/html" title="IE8, Standards, and Joel is Scary Brilliant"/>
    <published>2008-03-17T23:27:00.001Z</published>
    <updated>2008-03-17T23:27:00.001Z</updated>
    <id>https://kevmoo.com/2008/03/ie8-standards-and-joel-is-scary.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/03/ie8-standards-and-joel-is-scary.html">&lt;p>By Joel, I mean &lt;a href="http://www.joelonsoftware.com/">Joel Spolsky&lt;/a>. Not only does he have great taste in &lt;a href="http://www.barackobama.com/">presidential candidates&lt;/a>, but he's a person everyone in technology should be reading.&lt;/p> &lt;p>It's good to have idols, I think. I dream of having the perspective and wisdom to write like &lt;a href="http://www.joelonsoftware.com/items/2008/03/17.html">this&lt;/a>.&lt;/p> &lt;blockquote> &lt;p>The IE 8 team is in the process of making a decision that lies perfectly, exactly, precisely on the fault line smack in the middle of two different ways of looking at the world. It&amp;#8217;s the difference between conservatives and liberals, it&amp;#8217;s the difference between &amp;quot;idealists&amp;quot; and &amp;quot;realists&amp;quot;, it&amp;#8217;s a huge global jihad dividing members of the same family, engineers against computer scientists, and Lexuses vs. olive trees. &lt;/p> &lt;/blockquote> &lt;p>Of course he's talking about how IE8 will handle web standards when so much of the world expects IE to work the way it has always worked. Is there a solution? According to Joel:&lt;/p> &lt;blockquote> &lt;p>&lt;em>There is no solution&lt;/em>. Each solution is terribly wrong. Eric Bangeman at &lt;em>ars technica&lt;/em> &lt;a href="http://arstechnica.com/news.ars/post/20071219-ie8-goes-on-an-acid2-trip-beta-due-in-first-half-of-2008.html">writes&lt;/a>, &amp;quot;The IE team has to walk a fine line between tight support for W3C standards and making sure sites coded for earlier versions of IE still display correctly.&amp;quot; This is incorrect. It&amp;#8217;s not a fine line. It's a line of negative width. There is no place to walk. They are damned if they do and damned if they don't.&lt;/p> &lt;/blockquote> &lt;p>His Martian headset analogy is just a bit forced, but totally forgiven. The write-up is brilliant and fascinating.&lt;/p> &lt;p>Like Joel, I'm going to sit back with some popcorn.&lt;/p> &lt;blockquote> &lt;p>...it will be really, really entertaining to watch...&lt;/p>&lt;/blockquote></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Internet Explorer"/>
    <category term="IE"/>
    <category term="internet"/>
    <category term="important"/>
    <category term="Microsoft"/>
    <category term="interesting"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">Rob Relyea Hates my Mom</title>
    <link href="https://kevmoo.com/2008/03/rob-relyea-hates-my-mom.html" rel="alternate" type="text/html" title="Rob Relyea Hates my Mom"/>
    <published>2008-03-17T17:37:00.001Z</published>
    <updated>2008-03-17T17:37:00.001Z</updated>
    <id>https://kevmoo.com/2008/03/rob-relyea-hates-my-mom.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/03/rob-relyea-hates-my-mom.html">&lt;p>&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="276" alt="Mom, Dad, Kevin" src="http://j832.com/workBlogFiles/_images/RobRelyeaHatesmyMom_956D/image.png" width="324" border="0" /> &lt;/p> &lt;p>My mother is a lovely woman. So I'm confused as to why &lt;a href="http://blogs.windowsclient.net/rob_relyea/">Rob&lt;/a> dislikes her so much.&lt;/p> &lt;p>Let me back up. Last August (when I was still at my &lt;a href="http://microsoft.com">former employer&lt;/a>) I &lt;a href="http://channel9.msdn.com/showpost.aspx?postid=332987">did some demos&lt;/a> of new features in WPF 3.5 for Channel 9.&lt;/p> &lt;p>I was happy to see Rob reused some of the same demos for &lt;a href="http://sessions.visitmix.com/?selectedSearch=t11">his MIX '08 Talk&lt;/a>.&lt;/p> &lt;p>When I was watching the Add-In demo, I was surprise to see the data had remained the same--for the most part. My dad--Robert, my brothers--Brian and John, and I were still in the data set.&lt;/p> &lt;p>&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="612" alt="image" src="http://j832.com/workBlogFiles/_images/RobRelyeaHatesmyMom_956D/image_3.png" width="656" border="0" /> &lt;/p> &lt;p>But my mother--Wynette--replaced by &amp;quot;Web Service&amp;quot;. I mean, I know WCF is powerful, but it's a poor replacement for the most wonderful woman in the world--even if she has an uncommon name.&lt;/p> &lt;p>I did find it funny that the last name was left unchanged.&lt;/p> &lt;p>&lt;a href="http://j832.com/workBlogFiles/_images/RobRelyeaHatesmyMom_956D/image_4.png">&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="180" alt="image" src="http://j832.com/workBlogFiles/_images/RobRelyeaHatesmyMom_956D/image_thumb.png" width="244" border="0" />&lt;/a> &lt;/p> &lt;p>So come on Relyea. Let's hear it. I think I deserve an explanation. :-)&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term=".NET"/>
    <category term="fun"/>
    <category term="web services"/>
    <category term="Mix08"/>
    <category term="Microsoft"/>
    <category term="mix"/>
  </entry>
  <entry>
    <title type="html">Reader Question: "Why WrapperElement&lt;T> instead of Decorator?"</title>
    <link href="https://kevmoo.com/2008/03/reader-question-wrapperelement-instead.html" rel="alternate" type="text/html" title="Reader Question: &quot;Why WrapperElement&lt;T> instead of Decorator?&quot;"/>
    <published>2008-03-14T21:16:00.001Z</published>
    <updated>2008-03-14T21:16:00.001Z</updated>
    <id>https://kevmoo.com/2008/03/reader-question-wrapperelement-instead.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/03/reader-question-wrapperelement-instead.html">&lt;p>&lt;/p> &lt;p>Yuval, via a &lt;a href="http://work.j832.com/2008/03/bag-o-tricks-march-edition.html#c4679708233397793013">comment&lt;/a>, asks:&lt;/p> &lt;blockquote> &lt;p>Can you explain why you chose to define &lt;i>WrapperElement&amp;lt;T&amp;gt;&lt;/i> instead of simply inheriting from &lt;i>Decorator&lt;/i>? They seem to be doing the same thing.&lt;/p> &lt;/blockquote> &lt;p>Ah, it is good to read my post &lt;a href="http://work.j832.com/2007/06/don-subclass-panel-unless-you-making.html">&amp;quot;Don't subclass a Panel, unless you're making a Panel&amp;quot;&lt;/a>.&lt;/p> &lt;p>First, where do I used WrapperElement&amp;lt;T&amp;gt;? Well, at the moment, it's used in three places: FlipTile3D, Set, and Transition3D. In all cases it simply wraps a Viewport3D.&lt;/p> &lt;p>Now, could I simply use Decorator? Sure. I could subclass Decorator and do basically the same thing. Even easier: I could subclass Viewport3D.&lt;/p> &lt;p>Why don't I?&lt;/p> &lt;p>It's all about API usability and correctness.&lt;/p> &lt;p>When I write a control (especially for the &lt;a href="http://j832.com/bagotricks/">bag-o-tricks&lt;/a>) I try to make it &amp;quot;right&amp;quot;.&lt;/p> &lt;p>If these controls subclassed Viewport3D, they should &lt;em>act&lt;/em> like Viewport3D. Meaning, they should support someone added arbitrary lights, models, etc. They should support messing with and removing elements that are already added.&lt;/p> &lt;p>I don't want this.&lt;/p> &lt;p>Wrapping everything with a Decorator, just exchanges problems.&lt;/p> &lt;p>If I subclass Decorator, it would imply that I mean people to treat the control like a Decorator, which means accessing and changing the Child property.&lt;/p> &lt;p>I don't want this, either.&lt;/p> &lt;p>WrapperElement&amp;lt;T&amp;gt; does some very simple things.&lt;/p> &lt;ul> &lt;li>Stores a Framework element as a child visual.&lt;/li> &lt;li>Adds it to its visual tree (via AddVisualChild)&lt;/li> &lt;li>overrides GetVisualChildCount&lt;/li> &lt;li>overrides VisualChildCount&lt;/li> &lt;li>overrides MeasureOverride&lt;/li> &lt;li>overrides ArrangeOverride&lt;/li> &lt;li>Provides &lt;em>protected&lt;/em> access to the child so the subclass can play with it, but not the end user.&lt;/li> &lt;/ul> &lt;p>One should use WrapperElement&amp;lt;T&amp;gt; when one wants to use the implementation of an existing component--Viewport3D, Grid, etc.--but doesn't want the object model of that component exposed.&lt;/p> &lt;p>Make sense?&lt;/p> &lt;p>Thanks for the question, Yuval.&lt;/p> &lt;p>Happy hacking.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
  </entry>
  <entry>
    <title type="html">Consolas: the Coder's Font</title>
    <link href="https://kevmoo.com/2008/03/consolas-coder-font.html" rel="alternate" type="text/html" title="Consolas: the Coder's Font"/>
    <published>2008-03-13T02:36:00.001Z</published>
    <updated>2008-03-13T02:36:00.001Z</updated>
    <id>https://kevmoo.com/2008/03/consolas-coder-font.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/03/consolas-coder-font.html">&lt;p>&lt;a href="http://en.wikipedia.org/wiki/Consolas">Consolas&lt;/a> is one of a set of new ClearType fonts that shipped as part of Windows Vista and Office 2007.&lt;/p> &lt;p>It's absolutely beautiful. I love to code in it.&lt;/p> &lt;p>The problem: no applications seem to be smart enough to use it by default. In this post, I'll go through all the places I use monospaced fonts&lt;/p> &lt;h3>Visual Studio&lt;/h3> &lt;p>Tools-&amp;gt;Options-&amp;gt;Environment-&amp;gt;Fonts and Colors&lt;/p> &lt;p>Set &amp;quot;Plain Text&amp;quot; under &amp;quot;Display Items&amp;quot; to Consolas.&lt;/p> &lt;p>&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="375" alt="image" src="http://lh3.google.com/BobStange/R9iTIp-477I/AAAAAAAAEHM/lhaA_u5RKvU/image%5B9%5D?imgmax=800" width="644" border="0" /> &lt;/p> &lt;h3>Firefox&lt;/h3> &lt;p>Tools-&amp;gt;Options&lt;/p> &lt;p>Under the Content tab, in the &amp;quot;Fonts &amp;amp; Colors&amp;quot; box, pick &amp;quot;Advanced&amp;quot;. In Monospace, pick Consolas.&lt;/p> &lt;p>&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="491" alt="image" src="http://lh5.google.com/BobStange/R9iTJJ-478I/AAAAAAAAEHU/SmivOfxeKNc/image%5B15%5D?imgmax=800" width="547" border="0" /> &lt;/p> &lt;h3>Internet Explorer&lt;/h3> &lt;p>Tools-&amp;gt;Internet Options&lt;/p> &lt;p>General tab, under Appearance, pick 'Fonts'.&lt;/p> &lt;p>Under &amp;quot;Plain text font:&amp;quot; pick Consolas.&lt;/p> &lt;p>&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="512" alt="image" src="http://lh4.google.com/BobStange/R9iTJ5-479I/AAAAAAAAEHc/YbKSDIj52fU/image%5B21%5D?imgmax=800" width="545" border="0" /> &lt;/p> &lt;h3>.NET Reflector&lt;/h3> &lt;p>View-&amp;gt;Options&lt;/p> &lt;p>Under 'Appearance', 'Code Font': Consolas.&lt;/p> &lt;p>&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="325" alt="image" src="http://lh6.google.com/BobStange/R9iTKZ-47-I/AAAAAAAAEHk/wiZZXkuewj8/image%5B41%5D?imgmax=800" width="406" border="0" /> &lt;/p> &lt;h3>CMD.EXE&lt;/h3> &lt;p>(Thanks to &lt;a href="http://www.jacksonfish.com/blog/author/walter/">Walter&lt;/a> for pointing this out to me.)&lt;/p> &lt;p>Yes, even the command window. If you're running Vista, make sure to run this command 'elevated'. You'll have to restart your machine before the setting takes effect.&lt;/p> &lt;blockquote> &lt;p>reg add &amp;quot;HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont&amp;quot; /v 00 /d Consolas&lt;/p> &lt;/blockquote> &lt;p>&lt;a href="http://lh4.google.com/BobStange/R9iTK5-47_I/AAAAAAAAEHs/g4-aLs5WTUw/image%5B32%5D?imgmax=800">&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="103" alt="image" src="http://lh6.google.com/BobStange/R9iTLZ-48AI/AAAAAAAAEH0/0hF4CSAkJLY/image_thumb%5B10%5D?imgmax=800" width="640" border="0" />&lt;/a> &lt;/p> &lt;p>Next, right click on the command window header and pick 'Properties'. You'll probably want to up the font size, too.&lt;/p> &lt;p>&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="461" alt="image" src="http://lh3.google.com/BobStange/R9iTLp-48BI/AAAAAAAAEH8/CsBZDvpQ54o/image%5B48%5D?imgmax=800" width="376" border="0" /> &lt;/p> &lt;p>And there you go. All your most important applications using the nicest monospaced font.&lt;/p> &lt;p>Happy hacking!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term="general"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">Bag-o-Tricks March '08 Edition</title>
    <link href="https://kevmoo.com/2008/03/bag-o-tricks-march-edition.html" rel="alternate" type="text/html" title="Bag-o-Tricks March '08 Edition"/>
    <published>2008-03-09T04:30:00.001Z</published>
    <updated>2008-03-09T04:30:00.001Z</updated>
    <id>https://kevmoo.com/2008/03/bag-o-tricks-march-edition.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/03/bag-o-tricks-march-edition.html">&lt;p>January 12 was my &lt;a href="http://work.j832.com/2008/01/real-update-to-bag-o-tricks.html">last update&lt;/a> to the bag-o-tricks. I couldn&amp;#8217;t let two months go by without another refresh. There is a lot of stuff here I've already talked about. The code has been available via SVN for a while, but not in the convenient package.&lt;/p> &lt;h3>The Goods&lt;/h3> &lt;p>&lt;a href="http://j832.com/bagotricks/wpfbagotricks.zip">Binaries and Source&lt;/a> [zip, 4.17MB]. &lt;em>Tested with Visual C# Express 2008.&lt;/em>&lt;/p> &lt;h3>The Details&lt;/h3> &lt;ul> &lt;li>&lt;strong>VS Copy-to-HTML - &lt;em>New!&lt;/em>&lt;/strong> &lt;ul> &lt;li>Blogged about it &lt;a href="http://work.j832.com/2008/01/source-code-html-and-exercise-for.html">here&lt;/a>. &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>NotifyWorker - &lt;em>New!&lt;/em>&lt;/strong> &lt;ul> &lt;li>Blogged about it &lt;a href="http://work.j832.com/2008/01/responsive-ui-with-unresponsive-data.html">here&lt;/a>. &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>HueConverter - &lt;em>New!&lt;/em>&lt;/strong> &lt;ul> &lt;li>Makes it easy to create a pretty spectrum of colors for a number of items &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>Animating Tile Panel&lt;/strong> &lt;ul> &lt;li>Renamed AnimateNewItem property to AnimatesNewItem &lt;/li> &lt;li>Made initial load not animate new items &lt;/li> &lt;li>Polished the demo code &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>CompositionTargetRenderingListener&lt;/strong> &lt;ul> &lt;li>Added Dispose and used it where appropriate &lt;/li> &lt;li>Added WireParentLoadedUnloaded helper method &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>DemoCollection&lt;/strong> &lt;ul> &lt;li>Added Reset command &lt;/li> &lt;li>Moved to library assembly &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>Extentions&lt;/strong> &lt;ul> &lt;li>Added SelectResursive (see &lt;a href="http://work.j832.com/2008/01/selectrecursive-if-3rd-times-charm-4th.html">last blog post&lt;/a>), among others &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>FlipTile3D&lt;/strong> &lt;ul> &lt;li>Moved to WrapperElement&amp;lt;Viewport3D&amp;gt; &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>FolderPicker&lt;/strong> &lt;ul> &lt;li>Moved to new SelectRecursive implementation &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>WPFUtil&lt;/strong> &lt;ul> &lt;li>Added HSB-RGB converter &lt;/li> &lt;li>Created &amp;#8216;Animate&amp;#8217; methods to abstract physics model. Moved FileTile3D, AnimatingTilePanel, and ZapDecorator to these. &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>ZapScroller&lt;/strong> &lt;ul> &lt;li>A &lt;strong>lot&lt;/strong> cleaner. Removed a completely unnecessary layer of complexity. &lt;/li> &lt;li>Added the ability to template the buttons. Thanks for the suggestion, Atul. &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>WPF Set&lt;/strong> &lt;ul> &lt;li>New in 3D! See &lt;a href="http://work.j832.com/2008/01/wpf-set-now-in-3d.html">blog post&lt;/a>. &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>General&lt;/strong> &lt;ul> &lt;li>A bunch of renaming of namespaces. Most of the new stuff will exist under J832.Wpf &lt;/li> &lt;/ul> &lt;/li> &lt;/ul> &lt;p>As always, the &lt;a href="http://j832.com/PublicSoftware/">SVN location&lt;/a> has been updated. Patches are always welcome. (I've had one taker on this. Very cool to do an apply patch. Would love to do it again.)&lt;/p> &lt;p>Enjoy and happy hacking!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="xaml"/>
    <category term="C#"/>
  </entry>
  <entry>
    <title type="html">iPhone makes me a better person</title>
    <link href="https://kevmoo.com/2008/03/iphone-makes-me-better-person.html" rel="alternate" type="text/html" title="iPhone makes me a better person"/>
    <published>2008-03-07T23:57:00.001Z</published>
    <updated>2008-03-07T23:57:00.001Z</updated>
    <id>https://kevmoo.com/2008/03/iphone-makes-me-better-person.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/03/iphone-makes-me-better-person.html">&lt;p>...or at least it makes me feel that way.&lt;/p> &lt;p>Let's rewind.&lt;/p> &lt;p>When I moved to Seattle in 2002, I had a simple, &amp;quot;candy bar&amp;quot; Nokia phone. I could barely text message with it, but it worked.&lt;/p> &lt;p>My first Windows Mobile phone was the Audiovox SMT5600--a fancy name for the &lt;a href="http://en.wikipedia.org/wiki/HTC_Typhoon">HTC Typhoon&lt;/a>. I could sync calendar and contacts over the air with Exchange. I could T9 through my address book.&lt;/p> &lt;p>I felt like I jumped 18 months into the future. I got the upgraded version of the Typhoon (with the weird bump on the top). It ran a newer version of Windows Mobile. It had a prettier screen. Let's say I jumped forward another 6 months.&lt;/p> &lt;p>Then I went &lt;a href="http://en.wikipedia.org/wiki/BlackJack_%28phone%29">BlackJack&lt;/a>. Bigger screen. Keyboard. A reasonable browsing experience, at least for GMail. Maybe a jump of a year into the future.&lt;/p> &lt;p>After a brief stint, I managed to loose my BlackJack, and went to &lt;a href="http://en.wikipedia.org/wiki/Blackjack_2">BlackJack 2&lt;/a>. Slicker look. Newer version of Windows Mobile. Maybe a 6 month jump.&lt;/p> &lt;p>Fast-forward to Sunday. I was snowboarding with some friends. My phone was in my pocket. My pocket was open. I was in the terrain park. I lot my phone.&lt;/p> &lt;p>Damn.&lt;/p> &lt;p>So I go back to the AT&amp;amp;T store. And the iPhone stand starts calling to me.&lt;/p> &lt;p>I have many friends with iPhone.&lt;/p> &lt;p>Both of my brothers have one.&lt;/p> &lt;p>I get one.&lt;/p> &lt;p>It's been less than a week.&lt;/p> &lt;p>Easily a 5 year jump. I feel like I'm living in the future. The thing freakin' rocks. It makes the BlackJack2 look like a joke.&lt;/p> &lt;p>Not only have I ditched Windows Mobile, I've ditched Zune. I've gone to buying MP3s from Amazon's store. Instant gratification. No expiration. No DRM.&lt;/p> &lt;p>This is the future.&lt;/p> &lt;p>It flawlessly syncs with Outlook on my desktop. (I have a friend who's been trying to get it to work with her BlackJack for months.) The experience with iTunes is great. Maps, Email, SMS, all clean and beautiful.&lt;/p> &lt;p>With the announcement of the SDK and Enterprise support (over-the air sync with Exchange, etc) I can't imagine a better setup for a phone.&lt;/p> &lt;p>I'm sure Google will have a cool offer with &lt;a href="http://code.google.com/android/">Android&lt;/a>. I'm sure MS is sweating bullets and cranking on some interesting stuff. At least I hope so.&lt;/p> &lt;p>In the end, the bar has been raised--by a lot. All mobile users will benefit in the long-run by the existence of iPhone.&lt;/p> &lt;p>Especially those that have one.&lt;/p> &lt;p>I couldn't imagine going back.&lt;/p> &lt;p>Let me say it again: wow.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="iphone"/>
    <category term="interesting"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">Dump Evite</title>
    <link href="https://kevmoo.com/2008/02/dump-evite.html" rel="alternate" type="text/html" title="Dump Evite"/>
    <published>2008-02-21T08:45:00.001Z</published>
    <updated>2008-02-21T08:45:00.001Z</updated>
    <id>https://kevmoo.com/2008/02/dump-evite.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/02/dump-evite.html">&lt;p>&lt;a href="http://blog.j832.com/2008/02/dump-evite.html">&lt;em>Cross-post&lt;/em>&lt;/a>&lt;em> from my personal blog.&lt;/em>&lt;/p> &lt;p>&lt;a href="http://www.wired.com/culture/culturereviews/magazine/16-02/su_evite">This article&lt;/a> from the &lt;a href="http://www.wired.com/wired/issue/16-02">January Wired&lt;/a> got me started:&lt;/p> &lt;blockquote> &lt;p>An email arrives announcing a fete, but it's short on deets. You're forced to click to an ad-choked Web page, then another to RSVP, and then back to the first to see the info again. That faint sound you hear? It's coins tumbling into the pockets of media conglomerate IAC/InterActiveCorp, which acquired the site in 2003.&lt;/p> &lt;/blockquote> &lt;p>It's been 2 days since I read the article and I've received 4 evites. It's time to put a stop to this.&lt;/p> &lt;p>The article recommends &lt;a href="http://www.socializr.com/">Socializer&lt;/a> as an alternative, but it's way too heavy for my taste. The sign-up experience should be almost invisible.&lt;/p> &lt;p>What I want:&lt;/p> &lt;ul> &lt;li>Painless sign-up &lt;/li> &lt;li>Time and location details in the email &lt;/li> &lt;li>+1 if it includes a link to a map &lt;/li> &lt;li>+1 if the map link is to Google Maps &lt;/li> &lt;li>+1 if a calendar file is attached for us Gmail/Outlook users. &lt;/li> &lt;li>Super-clean user experience. &lt;/li> &lt;/ul> &lt;p>&lt;a href="http://www.invitastic.com/">&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="160" alt="image" src="http://j832.com/workBlogFiles/_images/DumpEvite_A62/image.png" width="244" border="0" />&lt;/a> &lt;/p> &lt;p>&lt;a href="http://www.invitastic.com/">Invitastic&lt;/a> nails it. There are no crazy custom themes or anything and I'm fine with that. Kudos to the &lt;a href="http://www.jacksonfish.com/">Jackson Fish Market&lt;/a> folks.&lt;/p> &lt;p>&lt;a href="http://www.goovite.com/">&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="77" alt="image" src="http://j832.com/workBlogFiles/_images/DumpEvite_A62/image_3.png" width="180" border="0" />&lt;/a> &lt;/p> &lt;p>&lt;a href="http://www.goovite.com/">Goovite&lt;/a> also looks promising. It includes the ability to offer a number of possible meeting times and allow a discussion about when.&lt;/p> &lt;p>Progress rocks!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">Xaml Serialization with WCF</title>
    <link href="https://kevmoo.com/2008/02/xaml-serialization-with-wcf.html" rel="alternate" type="text/html" title="Xaml Serialization with WCF"/>
    <published>2008-02-05T08:06:00.001Z</published>
    <updated>2008-02-05T08:06:00.001Z</updated>
    <id>https://kevmoo.com/2008/02/xaml-serialization-with-wcf.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/02/xaml-serialization-with-wcf.html">&lt;p>So I'm reading &lt;a href="http://www.amazon.com/gp/product/0596529260?ie=UTF8&amp;amp;tag=j832com&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596529260">RESTful Web Services&lt;/a> and I got inspired. Sounds like a great way to expose data on the web.&lt;/p> &lt;p>I've heard great things about WCF support for &lt;a href="http://en.wikipedia.org/wiki/REST">REST&lt;/a>, with their new &lt;a href="http://msdn2.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute.aspx">WebGet attribute&lt;/a> and such.&lt;/p> &lt;p>So I fire up &lt;a href="http://www.microsoft.com/express/vcsharp/">Visual C# Express&lt;/a> and get hacking.&lt;/p> &lt;p>Amazing what one can do in 54 lines of code.&lt;/p> &lt;div style="font-family: monospace"> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System;&lt;/div> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System.ServiceModel;&lt;/div> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System.ServiceModel.Web;&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div>&lt;span style="color: #0000ff">namespace&lt;/span> J832&lt;/div> &lt;div>{&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">class&lt;/span> &lt;span style="color: #2b91af">Program&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">static&lt;/span> &lt;span style="color: #0000ff">void&lt;/span> Main(&lt;span style="color: #0000ff">string&lt;/span>[] args)&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #2b91af">Time&lt;/span> time = &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">Time&lt;/span>();&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #0000ff">using&lt;/span> (&lt;span style="color: #2b91af">WebServiceHost&lt;/span> host = &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">WebServiceHost&lt;/span>(time, &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">Uri&lt;/span>(&lt;span style="color: #a31515">&amp;quot;http://localhost:8080/&amp;quot;&lt;/span>)))&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">host.AddServiceEndpoint(&lt;span style="color: #0000ff">typeof&lt;/span>(&lt;span style="color: #2b91af">ITime&lt;/span>), &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">WebHttpBinding&lt;/span>(), &lt;span style="color: #a31515">&amp;quot;time&amp;quot;&lt;/span>);&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">host.Open();&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">&lt;span style="color: #2b91af">Console&lt;/span>.WriteLine(&lt;span style="color: #a31515">&amp;quot;enter to close...&amp;quot;&lt;/span>);&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">&lt;span style="color: #2b91af">Console&lt;/span>.ReadLine();&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">}&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">[&lt;span style="color: #2b91af">ServiceContract&lt;/span>]&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">interface&lt;/span> &lt;span style="color: #2b91af">ITime&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">[&lt;span style="color: #2b91af">OperationContract&lt;/span>, &lt;span style="color: #2b91af">WebGet&lt;/span>]&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #2b91af">DateTimeCount&lt;/span> GetTime();&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">[&lt;span style="color: #2b91af">ServiceBehavior&lt;/span>(InstanceContextMode = &lt;span style="color: #2b91af">InstanceContextMode&lt;/span>.Single)]&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">class&lt;/span> &lt;span style="color: #2b91af">Time&lt;/span> : &lt;span style="color: #2b91af">ITime&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #2b91af">DateTimeCount&lt;/span> GetTime()&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #0000ff">return&lt;/span> &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">DateTimeCount&lt;/span>(&lt;span style="color: #2b91af">DateTime&lt;/span>.Now, m_count++);&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">private&lt;/span> &lt;span style="color: #0000ff">int&lt;/span> m_count;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">[&lt;span style="color: #2b91af">Serializable&lt;/span>]&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">class&lt;/span> &lt;span style="color: #2b91af">DateTimeCount&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> DateTimeCount(&lt;span style="color: #2b91af">DateTime&lt;/span> now, &lt;span style="color: #0000ff">int&lt;/span> count)&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">Now = now;&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">Count = count;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #2b91af">DateTime&lt;/span> Now { &lt;span style="color: #0000ff">get&lt;/span>; &lt;span style="color: #0000ff">set&lt;/span>; }&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">int&lt;/span> Count { &lt;span style="color: #0000ff">get&lt;/span>; &lt;span style="color: #0000ff">set&lt;/span>; }&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;/div> &lt;p>And we open a browser to &lt;strong>http://localhost:8080/time/GetTime&lt;/strong>:&lt;/p> &lt;div style="font-family: monospace"> &lt;div>&lt;span style="color: #0000ff">&amp;lt;&lt;/span>&lt;span style="color: #a31515">DateTimeCount&lt;/span> &lt;span style="color: #ff0000">xmlns&lt;/span>&lt;span style="color: #0000ff">=&lt;/span>&amp;quot;&lt;span style="color: #0000ff">http://schemas.datacontract.org/2004/07/J832&lt;/span>&amp;quot; &lt;span style="color: #ff0000">xmlns:i&lt;/span>&lt;span style="color: #0000ff">=&lt;/span>&amp;quot;&lt;span style="color: #0000ff">http://www.w3.org/2001/XMLSchema-instance&lt;/span>&amp;quot;&lt;span style="color: #0000ff">&amp;gt;&lt;/span>&lt;/div> &lt;div style="margin-left: 6ex; text-indent: -4ex">&lt;span style="color: #0000ff">&amp;lt;&lt;/span>&lt;span style="color: #a31515">_x003C_Count_x003E_k__BackingField&lt;/span>&lt;span style="color: #0000ff">&amp;gt;&lt;/span>0&lt;span style="color: #0000ff">&amp;lt;/&lt;/span>&lt;span style="color: #a31515">_x003C_Count_x003E_k__BackingField&lt;/span>&lt;span style="color: #0000ff">&amp;gt;&lt;/span>&lt;/div> &lt;div style="margin-left: 6ex; text-indent: -4ex">&lt;span style="color: #0000ff">&amp;lt;&lt;/span>&lt;span style="color: #a31515">_x003C_Now_x003E_k__BackingField&lt;/span>&lt;span style="color: #0000ff">&amp;gt;&lt;/span>2008-02-04T23:28:21.987561-08:00&lt;span style="color: #0000ff">&amp;lt;/&lt;/span>&lt;span style="color: #a31515">_x003C_Now_x003E_k__BackingField&lt;/span>&lt;span style="color: #0000ff">&amp;gt;&lt;/span>&lt;/div> &lt;div>&lt;span style="color: #0000ff">&amp;lt;/&lt;/span>&lt;span style="color: #a31515">DateTimeCount&lt;/span>&lt;span style="color: #0000ff">&amp;gt;&lt;/span>&lt;/div> &lt;/div> &lt;p>Isn't that *cough* *choke* pretty *gag*.&lt;/p> &lt;p>I suddenly had a flash of nostalgia...of longing...for &lt;a href="http://en.wikipedia.org/wiki/Extensible_Application_Markup_Language">Xaml&lt;/a>.&lt;/p> &lt;p>Xaml: that wonderful language where document-object mapping is implicit, trivial, and human-understandable.&lt;/p> &lt;p>(I'd love to link to &lt;strong>Our 7 Goals of Xaml&lt;/strong> introduction but the &lt;a href="http://www.windows-now.com/blogs/rrelyea/archive/2004/11/29/7838.aspx">link is dead&lt;/a>. Help, &lt;a href="http://rrelyea.spaces.live.com">Rob&lt;/a>?)&lt;/p> &lt;p>Thankfully, &lt;a href="http://technet.microsoft.com/en-us/library/system.windows.markup.xamlwriter.aspx">XamlWriter&lt;/a> is publicly available and WCF is insanely, gratuitously, wonderfully extensible.&lt;/p> &lt;ul> &lt;li>WCF services have endpoints. &lt;/li> &lt;li>Endpoints have contracts. &lt;/li> &lt;li>Contracts have operations. &lt;/li> &lt;li>Operations have behaviors. &lt;/li> &lt;li>Behaviors have formatters. &lt;/li> &lt;li>Formatters can have custom messages--for instance, XamlMessage. &lt;/li> &lt;/ul> &lt;p>Thanks to &lt;a href="http://maheshwar.net/Blog">Maheshwar Jayaraman&lt;/a> for &lt;a href="http://blogs.msdn.com/mahjayar/archive/2007/03/14/wcf-extensibility-plugging-in-custom-message-processing-logic.aspx">the post&lt;/a> (and &lt;a href="http://blogs.msdn.com/mahjayar/attachment/1884927.ashx">sample&lt;/a>) on his &lt;a href="http://blogs.msdn.com/mahjayar/">old blog&lt;/a> that got me started.&lt;/p> &lt;p>The code is a bit longer, but it's mostly boiler plate:&lt;/p> &lt;div style="font-family: monospace"> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System;&lt;/div> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System.ServiceModel;&lt;/div> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System.ServiceModel.Channels;&lt;/div> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System.ServiceModel.Description;&lt;/div> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System.ServiceModel.Dispatcher;&lt;/div> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System.ServiceModel.Web;&lt;/div> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System.Windows.Markup;&lt;/div> &lt;div>&lt;span style="color: #0000ff">using&lt;/span> System.Xml;&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div>[&lt;span style="color: #0000ff">assembly&lt;/span>: &lt;span style="color: #2b91af">XmlnsDefinition&lt;/span>(&lt;span style="color: #a31515">&amp;quot;http://schemas.j832.com/demo/2008&amp;quot;&lt;/span>, &lt;span style="color: #a31515">&amp;quot;J832&amp;quot;&lt;/span>)]&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div>&lt;span style="color: #0000ff">namespace&lt;/span> J832&lt;/div> &lt;div>{&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">class&lt;/span> &lt;span style="color: #2b91af">Program&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">static&lt;/span> &lt;span style="color: #0000ff">void&lt;/span> Main(&lt;span style="color: #0000ff">string&lt;/span>[] args)&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #2b91af">Time&lt;/span> time = &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">Time&lt;/span>();&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #0000ff">using&lt;/span> (&lt;span style="color: #2b91af">WebServiceHost&lt;/span> host = &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">WebServiceHost&lt;/span>(time, &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">Uri&lt;/span>(&lt;span style="color: #a31515">&amp;quot;http://localhost:8080/&amp;quot;&lt;/span>)))&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">&lt;span style="color: #2b91af">ServiceEndpoint&lt;/span> endPoint = host.AddServiceEndpoint(&lt;span style="color: #0000ff">typeof&lt;/span>(&lt;span style="color: #2b91af">ITime&lt;/span>), &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">WebHttpBinding&lt;/span>(), &lt;span style="color: #a31515">&amp;quot;time&amp;quot;&lt;/span>);&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">&lt;span style="color: #0000ff">foreach&lt;/span> (&lt;span style="color: #2b91af">OperationDescription&lt;/span> operationDescription &lt;span style="color: #0000ff">in&lt;/span> endPoint.Contract.Operations)&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 24ex; text-indent: -4ex">operationDescription.Behaviors.Add(&lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">MyOperationBehavior&lt;/span>());&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">host.Open();&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">&lt;span style="color: #2b91af">Console&lt;/span>.WriteLine(&lt;span style="color: #a31515">&amp;quot;enter to close...&amp;quot;&lt;/span>);&lt;/div> &lt;div style="margin-left: 20ex; text-indent: -4ex">&lt;span style="color: #2b91af">Console&lt;/span>.ReadLine(); &lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">}&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">[&lt;span style="color: #2b91af">ServiceContract&lt;/span>]&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">interface&lt;/span> &lt;span style="color: #2b91af">ITime&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">[&lt;span style="color: #2b91af">OperationContract&lt;/span>, &lt;span style="color: #2b91af">WebGet&lt;/span>]&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #2b91af">DateTimeCount&lt;/span> GetTime();&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">[&lt;span style="color: #2b91af">ServiceBehavior&lt;/span>(InstanceContextMode = &lt;span style="color: #2b91af">InstanceContextMode&lt;/span>.Single)]&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">class&lt;/span> &lt;span style="color: #2b91af">Time&lt;/span> : &lt;span style="color: #2b91af">ITime&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #2b91af">DateTimeCount&lt;/span> GetTime()&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #0000ff">return&lt;/span> &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">DateTimeCount&lt;/span>(&lt;span style="color: #2b91af">DateTime&lt;/span>.Now, m_count++);&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">private&lt;/span> &lt;span style="color: #0000ff">int&lt;/span> m_count;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">[&lt;span style="color: #2b91af">Serializable&lt;/span>]&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">class&lt;/span> &lt;span style="color: #2b91af">DateTimeCount&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> DateTimeCount(&lt;span style="color: #2b91af">DateTime&lt;/span> now, &lt;span style="color: #0000ff">int&lt;/span> count)&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">Now = now;&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">Count = count;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #2b91af">DateTime&lt;/span> Now { &lt;span style="color: #0000ff">get&lt;/span>; &lt;span style="color: #0000ff">set&lt;/span>; }&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">int&lt;/span> Count { &lt;span style="color: #0000ff">get&lt;/span>; &lt;span style="color: #0000ff">set&lt;/span>; }&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">class&lt;/span> &lt;span style="color: #2b91af">MyOperationBehavior&lt;/span> : &lt;span style="color: #2b91af">IOperationBehavior&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">void&lt;/span> AddBindingParameters(&lt;span style="color: #2b91af">OperationDescription&lt;/span> operationDescription, &lt;span style="color: #2b91af">BindingParameterCollection&lt;/span> bindingParameters) { }&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">void&lt;/span> ApplyClientBehavior(&lt;span style="color: #2b91af">OperationDescription&lt;/span> operationDescription, &lt;span style="color: #2b91af">ClientOperation&lt;/span> clientOperation) { }&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">void&lt;/span> ApplyDispatchBehavior(&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #2b91af">OperationDescription&lt;/span> operationDescription,&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #2b91af">DispatchOperation&lt;/span> dispatchOperation)&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">dispatchOperation.Formatter = &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">MyMessageFormatter&lt;/span>();&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">void&lt;/span> Validate(&lt;span style="color: #2b91af">OperationDescription&lt;/span> operationDescription) { }&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">class&lt;/span> &lt;span style="color: #2b91af">MyMessageFormatter&lt;/span> : &lt;span style="color: #2b91af">IDispatchMessageFormatter&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">void&lt;/span> DeserializeRequest(&lt;span style="color: #2b91af">Message&lt;/span> message, &lt;span style="color: #0000ff">object&lt;/span>[] parameters) { }&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #2b91af">Message&lt;/span> SerializeReply(&lt;span style="color: #2b91af">MessageVersion&lt;/span> messageVersion, &lt;span style="color: #0000ff">object&lt;/span>[] parameters, &lt;span style="color: #0000ff">object&lt;/span> result)&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #0000ff">return&lt;/span> &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">XamlMessage&lt;/span>(result);&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">class&lt;/span> &lt;span style="color: #2b91af">XamlMessage&lt;/span> : &lt;span style="color: #2b91af">Message&lt;/span>&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> XamlMessage(&lt;span style="color: #0000ff">object&lt;/span> value){ Value = value; }&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">override&lt;/span> &lt;span style="color: #2b91af">MessageHeaders&lt;/span> Headers&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #0000ff">get&lt;/span> { &lt;span style="color: #0000ff">return&lt;/span> &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">MessageHeaders&lt;/span>(&lt;span style="color: #2b91af">MessageVersion&lt;/span>.None); }&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">protected&lt;/span> &lt;span style="color: #0000ff">override&lt;/span> &lt;span style="color: #0000ff">void&lt;/span> OnWriteBodyContents(&lt;span style="color: #2b91af">XmlDictionaryWriter&lt;/span> writer)&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">{&lt;/div> &lt;div style="margin-left: 16ex; text-indent: -4ex">&lt;span style="color: #2b91af">XamlWriter&lt;/span>.Save(Value, writer);&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">override&lt;/span> &lt;span style="color: #2b91af">MessageProperties&lt;/span> Properties{ &lt;span style="color: #0000ff">get&lt;/span>{ &lt;span style="color: #0000ff">return&lt;/span> &lt;span style="color: #0000ff">new&lt;/span> &lt;span style="color: #2b91af">MessageProperties&lt;/span>(); } } &lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">override&lt;/span> &lt;span style="color: #2b91af">MessageVersion&lt;/span> Version{ &lt;span style="color: #0000ff">get&lt;/span>{ &lt;span style="color: #0000ff">return&lt;/span> &lt;span style="color: #2b91af">MessageVersion&lt;/span>.None; }}&lt;/div> &lt;div>&amp;#160;&lt;/div> &lt;div style="margin-left: 12ex; text-indent: -4ex">&lt;span style="color: #0000ff">public&lt;/span> &lt;span style="color: #0000ff">object&lt;/span> Value { &lt;span style="color: #0000ff">get&lt;/span>; &lt;span style="color: #0000ff">private&lt;/span> &lt;span style="color: #0000ff">set&lt;/span>; }&lt;/div> &lt;div style="margin-left: 8ex; text-indent: -4ex">}&lt;/div> &lt;div>}&lt;/div> &lt;/div> &lt;p>And (drumroll) the output from &lt;strong>http://localhost:8080/time/GetTime&lt;/strong>:&lt;/p> &lt;div style="font-family: monospace"> &lt;div>&lt;span style="color: #0000ff">&amp;lt;&lt;/span>&lt;span style="color: #a31515">DateTimeCount&lt;/span> &lt;span style="color: #ff0000">Now&lt;/span>&lt;span style="color: #0000ff">=&lt;/span>&amp;quot;&lt;span style="color: #0000ff">2008-02-04T23:53:18.884273-08:00&lt;/span>&amp;quot; &lt;span style="color: #ff0000">Count&lt;/span>&lt;span style="color: #0000ff">=&lt;/span>&amp;quot;&lt;span style="color: #0000ff">14&lt;/span>&amp;quot; &lt;span style="color: #ff0000">xmlns&lt;/span>&lt;span style="color: #0000ff">=&lt;/span>&amp;quot;&lt;span style="color: #0000ff">http://schemas.j832.com/demo/2008&lt;/span>&amp;quot;&lt;span style="color: #0000ff">/&amp;gt;&lt;/span>&lt;/div> &lt;/div> &lt;p>Isn't that pretty? The XmlnsDefinition assembly attribute is the icing that gives you the pretty xmlns.&lt;/p> &lt;p>Do other folks love Xaml? Do you wish it was available outside PresentationFramework.dll?&lt;/p> &lt;p>Let me know. I'm thinking of starting a campaign.&lt;/p> &lt;p>Hear that, &lt;a href="http://rrelyea.spaces.live.com/blog/">Rob&lt;/a>? :-)&lt;/p> &lt;br />&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwork.j832.com%2f2008%2f02%2fxaml-serialization-with-wcf.html">&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwork.j832.com%2f2008%2f02%2fxaml-serialization-with-wcf.html&amp;bgcolor=c9c9c9&amp;cbgcolor=eeeeee" border="0" alt="kick it on DotNetKicks.com" />&lt;/a></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term=".NET"/>
    <category term="REST"/>
    <category term="xaml"/>
    <category term="web services"/>
    <category term="C#"/>
    <category term="wcf"/>
  </entry>
  <entry>
    <title type="html">WPF Set: Now in 3D!</title>
    <link href="https://kevmoo.com/2008/01/wpf-set-now-in-3d.html" rel="alternate" type="text/html" title="WPF Set: Now in 3D!"/>
    <published>2008-01-31T05:50:00.001Z</published>
    <updated>2008-01-31T05:50:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/wpf-set-now-in-3d.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/wpf-set-now-in-3d.html">&lt;p>I last &lt;a href="http://work.j832.com/2008/01/wpf-set-this-is-good-stopping-spot.html">discussed Set&lt;/a> about 3 weeks ago. At the time, my implementation was based on buttons. It worked fine, but when I saw how it looked on a friend's machine running the 'classic' theme I was appalled.&lt;/p> &lt;p>I got thinking: there has to be a way to make this game more interesting.&lt;/p> &lt;p>The answer: 3D and gratuitous animation.&lt;/p> &lt;p>The address for the XBAP hasn't changed: &lt;a title="http://j832.com/workBlogFiles/WpfSet/" href="http://j832.com/workBlogFiles/WpfSet/">http://j832.com/workBlogFiles/WpfSet/&lt;/a>&lt;/p> &lt;div style="text-align: center">&lt;a href="http://j832.com/workBlogFiles/_images/WPFSetNowin3D_13301/image.png">&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="373" alt="WPF Set - 3D!" src="http://j832.com/workBlogFiles/_images/WPFSetNowin3D_13301/image_thumb.png" width="400" border="0" />&lt;/a> &lt;/div> &lt;p>The source code has been checked-in to my &lt;a href="http://j832.com/PublicSoftware/">SVN repository&lt;/a>. The code files actually live under &lt;a title="http://j832.com/PublicSoftware/J832.Wpf.BagOTricksApp/" href="http://j832.com/PublicSoftware/J832.Wpf.BagOTricksApp/">J832.Wpf.BagOTricksApp&lt;/a>, but you can build and play with the stand-alone app by loading the &lt;a href="http://j832.com/PublicSoftware/J832.WpfSet.sln">J832.WpfSet solution file&lt;/a>. (Thank you, CSProj file linking feature.)&lt;/p> &lt;p>&lt;strong>Cool stuff&lt;/strong>:&lt;/p> &lt;ul> &lt;li>The listbox on the right that displays the matched sets now uses AnimatingTilePanel. &lt;/li> &lt;li>First use of the new WPFUtil class, which exposes a set of Animate methods. These basically formalize and abstract my simple attraction-based physics model. I support 1-dimensional (double), 2-dimensional (Point/Vector), and 3-dimensional (Point3D/Vector3D) animation. Check out ZapScroller and AnimatingTilePanel in the source to see the other places these are used. &lt;/li> &lt;li>I've also added some helper extension methods to WPFUtil. Very useful. &lt;/li> &lt;li>Implemented a couple of super-simple 3D components: ButtonBase3D and ToggleButton3D. An interesting exercise. Hoping to move FlipTile3D to these in the future. &lt;/li> &lt;/ul> &lt;p>&lt;strong>Not cool stuff&lt;/strong>:&lt;/p> &lt;ul> &lt;li>Keyboard accessibility has evaporated. With the previous implementation, you could tab around to the buttons and press spacebar to select/unselect a &amp;quot;card&amp;quot;. More work than I signed up for in this iteration, but something to keep in mind. &lt;/li> &lt;li>WPF handles z-order great in 3D unless you have transparency in your textures. Take a look at the corners of raised cards. Very frustrating. The only work-around is to manually re-order the child elements. Lame. &lt;/li> &lt;li>Perf is great...on my super fast workstation. Even on my relatively beefy laptop, I notice some glitching when things are moving around. Ideally, I'd detect machines hardware limitations and degrade the animations. I should probably offer a &amp;quot;turn off the fancy stuff&amp;quot; check box. Eh, V3. &lt;/li> &lt;/ul> &lt;p>This will of course be included in the next drop of the full &lt;a href="http://j832.com/bagotricks/">bag-o-tricks&lt;/a>, but I thought it was cool enough to share out-of-band.&lt;/p> &lt;p>Have fun.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term=".NET"/>
    <category term="fun"/>
    <category term="C#"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">Improving NotifyWorker (and why blogging makes me smarter)</title>
    <link href="https://kevmoo.com/2008/01/improving-notifyworker-and-why-blogging.html" rel="alternate" type="text/html" title="Improving NotifyWorker (and why blogging makes me smarter)"/>
    <published>2008-01-27T22:58:00.001Z</published>
    <updated>2008-01-27T22:58:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/improving-notifyworker-and-why-blogging.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/improving-notifyworker-and-why-blogging.html">&lt;p>My current day job consists of writing middleware and web-based LOB software for an &lt;a href="http://actman.com/">actuarial services company&lt;/a>.&lt;/p> &lt;p>&lt;a href="http://dpotter.net/Technical/">David&lt;/a> is my primary collaborator and a fellow blogger. We get along amazingly well, but every once in a while, we disagree. The amazing thing, though, is how we handle disagreements.&lt;/p> &lt;p>I'm at a point where I look forward to disagreement! For a reason that I hope more people can come to realize.&lt;/p> &lt;p>If we disagree about how something should work, it's almost always an opportunity for improvement. Specifically, &lt;em>at least&lt;/em> one of the following is likely to happen:&lt;/p> &lt;ul> &lt;li>I get smarter&lt;/li> &lt;li>He gets smarter&lt;/li> &lt;li>The code gets better&lt;/li> &lt;/ul> &lt;p>Quite often, it's all three. I know this sounds like motivational speaker talk or corporate training fodder, but it's true. The fact that we often discuss our disagreements with explicit reference to &lt;a href="http://work.j832.com/2007/12/when-you-code-do-you-know-your-masters.html">masters&lt;/a> is also helpful.&lt;/p> &lt;p>I blog for similar reasons. I'm far from a CLR, C# or WPF expert, at least relative to the experts I've had the opportunity to work with.&lt;/p> &lt;p>I'm just a geek trying to figure things out and sharing as I go. Hopefully what I share is helpful. Often, though, blogging has self-serving benefits. Just taking the time to write down explanations for what I'm doing forces me to rationalize edge cases.&lt;/p> &lt;p>If I had never blogged the recursive flattening craziness, I would have never have seen all of the edge cases I had missed the first time out.&lt;/p> &lt;p>Anyway, to my point.&lt;/p> &lt;p>Simon was kind enough to point out a deadlock in my &lt;a href="http://work.j832.com/2008/01/responsive-ui-with-unresponsive-data.html">NotifyWorker&lt;/a> code.&lt;/p> &lt;p>&lt;em>FYI: At this point, looking at &lt;a href="http://j832.com/PublicSoftware/J832.Wpf.BagOTricksLibrary/NotifyWorker.cs">the code&lt;/a> will be quite helpful.&lt;/em>&lt;/p> &lt;p>I was doing a Thread.Join() in the middle of a lock. Of course, if the thread in question is waiting on the lock which is held, the thread will never exit. The result: the Join() call will never return.&lt;/p> &lt;p>Deadlock, indeed.&lt;/p> &lt;p>Props to Simon for pointing out this problem.&lt;/p> &lt;p>I moved the Join() outside of the lock and thought I'd fixed the problem.&lt;/p> &lt;p>Maybe, but I also realized another problem.&lt;/p> &lt;ul> &lt;li>Dispose is likely called from the UI thread.&lt;/li> &lt;li>Dispose calls Join on my worker thread as discussed above.&lt;/li> &lt;li>The worker thread does Dispatcher.Invoke twice.&lt;/li> &lt;/ul> &lt;p>What happens if Dispose is called between my check for m_disposed and when the Invoke actually gets to the UI thread?&lt;/p> &lt;p>Dispose will be tying up the UI thread waiting for Join() to return. The worker thread will never terminate because it's waiting for Invoke to get to the UI thread.&lt;/p> &lt;p>Deadlock again.&lt;/p> &lt;p>Darn.&lt;/p> &lt;p>The solution: Move from Dispatcher.Invoke to Dispatcher.BeginInvoke.&lt;/p> &lt;p>BeginInvoke returns an instance of DispatcherOperation. This class has an Abort method which can be used to abort a pending BeginInvoke.&lt;/p> &lt;p>I now have an instance field containing the pending operation, if one exists, which can be aborted via Dispose before the call to Join. I also now enforce that Dispose must be called on the UI thread (by adding a call to VerifyAccess). This ensures that Abort is not called while the worker is synchronized to the UI thread.&lt;/p> &lt;p>After some careful uses of DisaptcherOperation.Wait and some paranoid null checks, I think I'm okay.&amp;#160; &lt;/p> &lt;p>As an aside, I also noticed that Dispose() will throw in the case where NotifyNewWork() has never been called. I fixed that, too.&lt;/p> &lt;p>*Sigh*&lt;/p> &lt;p>Threading code is tough. I had to stand up and pace around a few times as I mentally worked through possible edge cases.&lt;/p> &lt;p>As I've said before, I think this implementation is better, but it would be a stretch for me to claim it's correct. Hopefully, it's more correct.&lt;/p> &lt;p>Please keep the questions, comments, and feedback coming (after you take a look at &lt;a href="http://work.j832.com/2008/01/oleg-what-your-email-contacting-me-via.html">the post&lt;/a> about contacting me).&lt;/p> &lt;p>The code will get better and we'll all get smarter.&lt;/p> &lt;p>&amp;#160;&lt;/p> &lt;p>Happy hacking.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="threading"/>
  </entry>
  <entry>
    <title type="html">Oleg, what's your email? (Contacting me via my blog.)</title>
    <link href="https://kevmoo.com/2008/01/oleg-what-your-email-contacting-me-via.html" rel="alternate" type="text/html" title="Oleg, what's your email? (Contacting me via my blog.)"/>
    <published>2008-01-26T19:48:00.001Z</published>
    <updated>2008-01-26T19:48:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/oleg-what-your-email-contacting-me-via.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/oleg-what-your-email-contacting-me-via.html">&lt;p>This has happened a few times, so I thought it would be worth mentioning.&lt;/p> &lt;ol> &lt;li>I love comments. I try to blog more than &amp;quot;check out this link&amp;quot; posts. It takes a bit of work. Knowing folks are reading is great. But...&lt;/li> &lt;li>If you're saying more than &amp;quot;interesting post&amp;quot;--if you have comments or questions--please make sure I have a way to contact you.&lt;/li> &lt;/ol> &lt;p>Oleg Mihailik made an interesting comment about my &lt;a href="http://work.j832.com/2008/01/responsive-ui-with-unresponsive-data.html">NotifyWorker post&lt;/a>:&lt;/p> &lt;blockquote> &lt;p>As long as you are already using the delegates, you can use closures (local variables) instead of creating artifical types to hold them.&lt;/p> &lt;p>Then you'd have to provide 2 parameterless delegates: one for work item and another for 'OnCompleted' logic on GUI thread.&lt;/p> &lt;p>That simplifies out the packaged parameters' class, AND eliminates the exception catching work by design.&lt;/p> &lt;p>If they care enough to handle exceptions, they'd do it in conventional and readable way: by enclosing the dangerous part in try/catch. And then, they can reflects it in exactly the same 'OnCompleted' delegate.&lt;/p> &lt;/blockquote> &lt;p>I have questions for him and I have no clue how to drop him a line.&lt;/p> &lt;p>If you'd like to chat (or talk job offers) please send me an email.&lt;/p> &lt;p>My obfuscated address--&lt;em>edeya9902(at)sneakemail(dot)com&lt;/em>--in the left pane, is meant as a test. If you can't figure it out or don't want to go through the effort of doing the manual copy-paste-replace, we probably shouldn't chat.&lt;/p> &lt;p>Or if you post a comment, just make sure you link back to a blog with a contact page. That's more than sufficient.&lt;/p> &lt;p>Thanks.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="general"/>
  </entry>
  <entry>
    <title type="html">Responsive UI with Unresponsive Data: NotifyWorker</title>
    <link href="https://kevmoo.com/2008/01/responsive-ui-with-unresponsive-data.html" rel="alternate" type="text/html" title="Responsive UI with Unresponsive Data: NotifyWorker"/>
    <published>2008-01-22T22:47:00.001Z</published>
    <updated>2008-01-22T22:47:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/responsive-ui-with-unresponsive-data.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/responsive-ui-with-unresponsive-data.html">&lt;p>&lt;/p> &lt;p>&lt;em>Yes, I finally got &lt;a href="http://work.j832.com/2008/01/flattening-recursive-algorithms-is-like.html">off&lt;/a> &lt;a href="http://work.j832.com/2008/01/flattening-recursive-algorithms-with.html">my&lt;/a> &lt;a href="http://work.j832.com/2008/01/recursion-linq-etc-3rd-times-charm.html">SelectRecursive&lt;/a> &lt;a href="http://work.j832.com/2008/01/selectrecursive-if-3rd-times-charm-4th.html">kick&lt;/a>. This is penance.&lt;/em>&lt;/p> &lt;h3>The 3-box Visio Diagram&lt;/h3> &lt;p>How many user interfaces do you design that follow this pattern?&lt;/p> &lt;p>&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="84" alt="image" src="http://j832.com/workBlogFiles/_images/ResponsiveUIwithUnresponsiveDataLayers_CFF3/image.png" width="366" border="0" /> &lt;/p> &lt;p>Okay, almost all of them.&lt;/p> &lt;p>A frequent refrain from users (well, at least me):&lt;/p> &lt;blockquote> &lt;p>Regardless of what you're doing behind-the-scenes, the interface should &lt;em>&lt;strong>never&lt;/strong>&lt;/em> hang, stutter, or lag. &lt;strong>&lt;em>Ever&lt;/em>&lt;/strong>.&lt;/p> &lt;/blockquote> &lt;p>Easily said, right?&lt;/p> &lt;p>Well, while hacking on one of my side projects, I ran into this problem.&lt;/p> &lt;p>I put on my &amp;quot;framework guy&amp;quot; hat and asked, &amp;quot;Can I formalize this into a pattern?&amp;quot;&lt;/p> &lt;p>My answer: NotifyWorker.&lt;/p> &lt;p>Now before I get into NotifyWorker, I should mention &lt;a href="http://msdn2.microsoft.com/en-us/library/8xs8549b.aspx">BackgroundWorker&lt;/a>: a frequently used and well thought-out component supplied by our friends in the Baseclass Library (BCL) for this kind of thing.&lt;/p> &lt;p>The trick performed by BackgroundWorker is simple, but important: allow start/stop/cancel of a task on another thread. It also keeps developers sane who have to deal with strict rules about what can only be done on the UI thread.&lt;/p> &lt;p>The type of tasks for which NotifyWorker was designed fit into a special niche that I think BackgroundWorkre misses:&lt;/p> &lt;ul> &lt;li>Tasks that are long enough to lag the interface (0.1+ seconds) but are too short to require tracking of percent complete (so shorter than, say, 5 seconds). &lt;/li> &lt;li>Tasks that are repeated constantly as the UI updates. Think of recalculating a math/physics model or checking a server-hosted word list for a type-a-head find control. &lt;/li> &lt;li>Tasks where the work to be done is--in relative terms--longer than the work to update the user interface. If the task takes 0.1 seconds, but updating the 1,000 controls in your window takes 2 seconds, you should start by tweaking your architecture before using NotifyWorker. &lt;/li> &lt;/ul> &lt;h3>How does it work?&lt;/h3> &lt;p>&lt;em>(Reflector is how I learn all of my new APIs.)&lt;/em>&lt;/p> &lt;p>&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="292" alt="image" src="http://j832.com/workBlogFiles/_images/ResponsiveUIwithUnresponsiveDataLayers_CFF3/image_3.png" width="426" border="0" /> &lt;/p> &lt;p>The constructor takes three parameters that outline the diagram above and the workings of NotifyWorker:&lt;/p> &lt;ul> &lt;li>&lt;strong>Func&amp;lt;bool&amp;gt; prework&lt;/strong>: this is a delegate that is called on the Dispatcher (UI) thread in a WPF application. Delegate passing is a trick I use a lot, and you should, too. The method does the work to take interesting parameters from the UI (control values, etc.) and puts them in a spot where NotifyWorker can safely play on a non-UI thread. If you decide there is nothing interesting to do, you can return false, telling NotifyWorker &amp;quot;never mind&amp;quot;.&lt;/li> &lt;li>&lt;strong>Action work&lt;/strong>: this is where the magic happens. This function is called on a background thread which will leave your UI nice and responsive. Be super careful that 'work' only touches state (fields, etc) that you've safely set aside during prework.&lt;/li> &lt;li>&lt;strong>Action postWork&lt;/strong>: the last box in our diagram. It takes the work done in 'work' and updates the UI accordingly. This method, as well as 'preWork', synchronizes the UI and background threads, so you don't have to worry about locking.&lt;/li> &lt;/ul> &lt;p>How do you kick things off? Call NotifyNewWork. This method can be called often, if you want. Put it in the 'Changed' handler of your favorite Slider or TextBox. If NotifyWorker is idle, it will wake up and immediately call preWork. If NotifyWorker is busy, it'll loop right around to get new input values as soon as postWork is done.&lt;/p> &lt;h3>A demo&lt;/h3> &lt;p>&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="223" alt="image" src="http://j832.com/workBlogFiles/_images/ResponsiveUIwithUnresponsiveDataLayers_CFF3/image_4.png" width="459" border="0" /> &lt;/p> &lt;p>Sexy, huh?&lt;/p> &lt;p>The scenario is simplistic and contrived, like so many good demos.&lt;/p> &lt;p>Both sets of UI do the same thing: take the values from two sliders and sum them. Not too complicated.&lt;/p> &lt;p>For some strange reason, the sum 'routine' takes 0.25 seconds to return a result.&lt;/p> &lt;p>Maybe it's that new math...&lt;/p> &lt;p>Eh, it's probably the Thread.Sleep(250) I put in the method.&lt;/p> &lt;p>Anyway, use your imagination. You'll notice that the 'slow' UI is, well, slower. It lags a bunch as you drag the sliders since it's calling the expensive sum method on the UI thread.&lt;/p> &lt;p>The NotifyWorker controls do much better because the expensive call is hidden off-thread.&lt;/p> &lt;p>Simple, but useful.&lt;/p> &lt;h3>Odds and ends&lt;/h3> &lt;p>You'll notice a LastClientExceptionEventArgs property and a ClientException event. These are designed to make it a bit easier to handle non-critical exceptions during 'work'. The demo code actually shows this off pretty well.&lt;/p> &lt;p>You'll also notice that NotifyWorker implements IDisposable. Dispose will make sure to end any background work when you're done with NotifyWorker.&lt;/p> &lt;p>Under the covers, NotifyWorker uses &lt;a href="http://work.j832.com/2007/11/going-beyond-monitorenterexit-c-lock.html">LockHelper&lt;/a> and some of the &lt;a href="http://work.j832.com/2007/10/threading-fun-monitorwait-monitorpulse.html">pulse/monitor tricks I wrote about&lt;/a> a few months ago.&lt;/p> &lt;h3>That's about it.&lt;/h3> &lt;p>Since NotifyWorker is hard-wired to the notion the Dispatcher, it lives in J832.Wpf.BackOTricksLib. The demo is in the Bag-o-Tricks app under NotifyWorker.&lt;/p> &lt;p>I'm &lt;strong>&lt;em>not&lt;/em>&lt;/strong> going to do an official release (zip with binaries/source) of the bag for this sample. It's cool, but not cool enough to warrant a whole new drop.&lt;/p> &lt;p>It also gives you an excuse to &lt;a href="http://work.j832.com/2007/12/tortoisesvn-rocks.html">play with SVN&lt;/a>, if you haven't already. You can always just manually download the code from my &lt;a href="http://j832.com/PublicSoftware/">SVN share&lt;/a> using your browser, too.&lt;/p> &lt;p>Let me know if this works well for you.&lt;/p> &lt;p>&amp;#160;&lt;/p> &lt;p>Happy multi-threaded hacking!&lt;/p> &lt;p>&amp;#160;&lt;/p> &lt;p>&lt;em>Note: I've had some funky auth issues with Firefox on the SVN server lately. Let me know if you have any trouble.&lt;/em>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="threading"/>
  </entry>
  <entry>
    <title type="html">SelectRecursive: If 3rd times the charm, 4th times a warning</title>
    <link href="https://kevmoo.com/2008/01/selectrecursive-if-3rd-times-charm-4th.html" rel="alternate" type="text/html" title="SelectRecursive: If 3rd times the charm, 4th times a warning"/>
    <published>2008-01-20T02:49:00.001Z</published>
    <updated>2008-01-20T02:49:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/selectrecursive-if-3rd-times-charm-4th.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/selectrecursive-if-3rd-times-charm-4th.html">&lt;p>I thought I finally nailed &lt;code>SelectRecursive&lt;/code>--my Linq-friendly extension method for navigating homogenous hierarchies. In my infinite cleverness, I figured I could avoid paying the common call stack cost of recursive algorithms by creating my own stack.&lt;/p> &lt;p>The solution I &lt;a href="http://work.j832.com/2008/01/flattening-recursive-algorithms-with.html">posted Wednesday&lt;/a> was an okay start of the philosophy, but I really messed up the implementation.&lt;/p> &lt;p>I thought I got it right &lt;a href="http://work.j832.com/2008/01/recursion-linq-etc-3rd-times-charm.html">yesterday&lt;/a>, but after being bitten once, I was cautious--notice I said &amp;quot;Smart(er)&amp;quot;.&lt;/p> &lt;p>Well, the implementation yesterday was certainly better, but it was missing a critical component: correct clean-up.&lt;/p> &lt;p>&lt;code>IEnumerator&amp;lt;T&amp;gt;&lt;/code> implements &lt;code>IDisposable&lt;/code>.&lt;/p> &lt;p>Why? Well, suppose you're enumerating over a database table. When one is done walking through the items, you might want to close your connection.&lt;/p> &lt;p>We rarely see the use of &lt;code>IDisposable&lt;/code> in this context, because it's hidden behind the 99.999% use of &lt;code>IEnumerable&amp;lt;T&amp;gt;&lt;/code>--&lt;code>foreach&lt;/code>.&lt;/p> &lt;p>Don't forget that this:&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #0000ff">foreach&lt;/span> (&lt;span style="color: #0000ff">object&lt;/span> item &lt;span style="color: #0000ff">in&lt;/span> sourceEnum) &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000">// do something&lt;/span> &lt;br />}&lt;/div> &lt;p>Looks like this to the runtime:&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #0000ff">using&lt;/span> (&lt;span style="color: #2b91af">IEnumerator&lt;/span>&amp;lt;&lt;span style="color: #0000ff">object&lt;/span>&amp;gt; source = sourceEnum.GetEnumerator()) &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">while&lt;/span> (source.MoveNext()) &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000">// do something&lt;/span> &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />} &lt;br />&lt;/div> &lt;p>Well, actually it looks like this:&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #2b91af">IEnumerator&lt;/span>&amp;lt;&lt;span style="color: #0000ff">object&lt;/span>&amp;gt; source = sourceEnum.GetEnumerator(); &lt;br />&lt;span style="color: #0000ff">try&lt;/span> &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">while&lt;/span> (source.MoveNext()) &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #008000">// do something&lt;/span> &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />} &lt;br />&lt;span style="color: #0000ff">finally&lt;/span> &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; source.Dispose(); &lt;br />} &lt;br />&lt;/div> &lt;p>&lt;code>foreach&lt;/code> does the work of calling &lt;code>Dispose()&lt;/code> on the enumerator--both when things go well and if there is an exception thrown in the while loop.&lt;/p> &lt;p>Since the &amp;quot;simple&amp;quot; version of &lt;code>SelectEnumerator&lt;/code> I posted yesterday uses &lt;code>foreach&lt;/code>, everything works great. Even if an exception is thrown deep in the recursion, the unrolling of the stack will go through all of the nested finally blocks.&lt;/p> &lt;p>The &amp;quot;smart(er)&amp;quot; version of &lt;code>SelectEnumerator&lt;/code> will have to be smart to handle disposing every enumerator it creates--both when the stack is popped normally and in the case of an exception.&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #0000ff">public&lt;/span>&amp;#160;&lt;span style="color: #0000ff">static&lt;/span>&amp;#160;&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt; SelectRecursive&amp;lt;TSource&amp;gt;( &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">this&lt;/span>&amp;#160;&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt; source, &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af">Func&lt;/span>&amp;lt;TSource, &lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt;&amp;gt; recursiveSelector) &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af">Stack&lt;/span>&amp;lt;&lt;span style="color: #2b91af">IEnumerator&lt;/span>&amp;lt;TSource&amp;gt;&amp;gt; stack = &lt;span style="color: #0000ff">new&lt;/span>&amp;#160;&lt;span style="color: #2b91af">Stack&lt;/span>&amp;lt;&lt;span style="color: #2b91af">IEnumerator&lt;/span>&amp;lt;TSource&amp;gt;&amp;gt;(); &lt;br />&amp;#160;&amp;#160;&amp;#160; stack.Push(source.GetEnumerator()); &lt;br /> &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">try&lt;/span> &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">while&lt;/span> (stack.Count &amp;gt; 0) &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">if&lt;/span> (stack.Peek().MoveNext()) &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TSource current = stack.Peek().Current; &lt;br /> &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> current; &lt;br /> &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; stack.Push(recursiveSelector(current).GetEnumerator()); &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">else&lt;/span> &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; stack.Pop().Dispose(); &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">finally&lt;/span> &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">while&lt;/span> (stack.Count &amp;gt; 0) &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; stack.Pop().Dispose(); &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />} &lt;/div> &lt;p>Take a look at the &lt;a href="http://work.j832.com/2008/01/recursion-linq-etc-3rd-times-charm.html">code from yesterday&lt;/a> to see the diff. &lt;/p> &lt;p>At this point, I'm pretty nervous about saying I've gotten this &amp;quot;right&amp;quot;. In all honesty, I did the stack flattening to see if I could do it and do it well.&lt;/p> &lt;p>As I've mentioned before, this pattern is only useful if you plan on having prohibitively deep hierarchies where the cost of the churning the runtime stack or the chance of stack overflow is high.&lt;/p> &lt;p>If neither is the case, keep things simple.&lt;/p> &lt;p>Remember what I said about clever.&lt;/p> &lt;p>&amp;#160;&lt;/p> &lt;p>Happy hacking.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Source code, HTML, and an Exercise for the Reader</title>
    <link href="https://kevmoo.com/2008/01/source-code-html-and-exercise-for.html" rel="alternate" type="text/html" title="Source code, HTML, and an Exercise for the Reader"/>
    <published>2008-01-19T03:57:00.001Z</published>
    <updated>2008-01-19T03:57:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/source-code-html-and-exercise-for.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/source-code-html-and-exercise-for.html">&lt;p>No clue why I want to be vague about this. Probably because I'm late for a party, but really wanted to share.&lt;/p> &lt;p>And you're smart. You'll figure it out.&lt;/p> &lt;div style="font-family:monospace;"> &lt;span style="color:#0000FF;">&amp;lt;&lt;/span>&lt;span style="color:#A31515;">Window&lt;/span>&lt;span style="color:#0000FF;">&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">x:Class&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">MainWindow&lt;/span>&amp;quot;&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">xmlns&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span>&amp;quot;&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">xmlns:x&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">http://schemas.microsoft.com/winfx/2006/xaml&lt;/span>&amp;quot;&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">Title&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">VS&amp;nbsp;Copy-Paste&amp;nbsp;to&amp;nbsp;HTML&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">&amp;nbsp;&amp;gt;&lt;/span>&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/span>&lt;span style="color:#A31515;">Grid&lt;/span>&lt;span style="color:#0000FF;">&amp;gt;&lt;/span>&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/span>&lt;span style="color:#A31515;">Grid.ColumnDefinitions&lt;/span>&lt;span style="color:#0000FF;">&amp;gt;&lt;/span>&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/span>&lt;span style="color:#A31515;">ColumnDefinition&lt;/span>&lt;span style="color:#0000FF;">&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">Width&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">*&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">&amp;nbsp;/&amp;gt;&lt;/span>&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/span>&lt;span style="color:#A31515;">ColumnDefinition&lt;/span>&lt;span style="color:#0000FF;">&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">Width&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">*&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">&amp;nbsp;/&amp;gt;&lt;/span>&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/span>&lt;span style="color:#A31515;">Grid.ColumnDefinitions&lt;/span>&lt;span style="color:#0000FF;">&amp;gt;&lt;/span>&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/span>&lt;span style="color:#A31515;">RichTextBox&lt;/span>&lt;span style="color:#0000FF;">&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">Name&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">m_richTextBox&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">TextChanged&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">m_richTextBox_TextChanged&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">&amp;nbsp;/&amp;gt;&lt;/span>&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/span>&lt;span style="color:#A31515;">TextBox&lt;/span>&lt;span style="color:#0000FF;">&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">Grid.Column&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">1&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">&amp;nbsp;&lt;/span>&lt;span style="color:#FF0000;">Name&lt;/span>&lt;span style="color:#0000FF;">=&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">m_textBoxHTML&lt;/span>&amp;quot;&lt;span style="color:#0000FF;">&amp;nbsp;/&amp;gt;&lt;/span>&lt;br/> &lt;span style="color:#0000FF;">&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/span>&lt;span style="color:#A31515;">Grid&lt;/span>&lt;span style="color:#0000FF;">&amp;gt;&lt;/span>&lt;br/> &lt;span style="color:#0000FF;">&amp;lt;/&lt;/span>&lt;span style="color:#A31515;">Window&lt;/span>&lt;span style="color:#0000FF;">&amp;gt;&lt;/span>&lt;br/> &lt;br/> &lt;/div> &lt;div style="font-family:monospace;"> &lt;span style="color:#0000FF;">using&lt;/span>&amp;nbsp;System;&lt;br/> &lt;span style="color:#0000FF;">using&lt;/span>&amp;nbsp;System.Collections.Generic;&lt;br/> &lt;span style="color:#0000FF;">using&lt;/span>&amp;nbsp;System.Diagnostics;&lt;br/> &lt;span style="color:#0000FF;">using&lt;/span>&amp;nbsp;System.Linq;&lt;br/> &lt;span style="color:#0000FF;">using&lt;/span>&amp;nbsp;System.Web;&lt;br/> &lt;span style="color:#0000FF;">using&lt;/span>&amp;nbsp;System.Windows;&lt;br/> &lt;span style="color:#0000FF;">using&lt;/span>&amp;nbsp;System.Windows.Controls;&lt;br/> &lt;span style="color:#0000FF;">using&lt;/span>&amp;nbsp;System.Windows.Documents;&lt;br/> &lt;span style="color:#0000FF;">using&lt;/span>&amp;nbsp;System.Windows.Media;&lt;br/> &lt;br/> &lt;span style="color:#0000FF;">public&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">partial&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">class&lt;/span>&amp;nbsp;&lt;span style="color:#2B91AF;">MainWindow&lt;/span>&amp;nbsp;:&amp;nbsp;&lt;span style="color:#2B91AF;">Window&lt;/span>&lt;br/> {&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">public&lt;/span>&amp;nbsp;MainWindow()&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InitializeComponent();&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">private&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">void&lt;/span>&amp;nbsp;m_richTextBox_TextChanged(&lt;span style="color:#0000FF;">object&lt;/span>&amp;nbsp;sender,&amp;nbsp;&lt;span style="color:#2B91AF;">TextChangedEventArgs&lt;/span>&amp;nbsp;e)&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_textBoxHTML.Clear();&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_textBoxHTML.AppendText(&lt;span style="color:#A31515;">&amp;quot;&amp;lt;div&amp;nbsp;style=\&amp;quot;font-family:monospace;\&amp;quot;&amp;gt;&amp;quot;&lt;/span>&amp;nbsp;+&amp;nbsp;&lt;span style="color:#2B91AF;">Environment&lt;/span>.NewLine);&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">foreach&lt;/span>&amp;nbsp;(&lt;span style="color:#2B91AF;">Paragraph&lt;/span>&amp;nbsp;paragraph&amp;nbsp;&lt;span style="color:#0000FF;">in&lt;/span>&amp;nbsp;m_richTextBox.Document.Blocks.Cast&amp;lt;&lt;span style="color:#2B91AF;">Paragraph&lt;/span>&amp;gt;())&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">foreach&lt;/span>&amp;nbsp;(&lt;span style="color:#2B91AF;">Run&lt;/span>&amp;nbsp;run&amp;nbsp;&lt;span style="color:#0000FF;">in&lt;/span>&amp;nbsp;Decompose(paragraph.Inlines))&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_textBoxHTML.AppendText(toCleanedColoredSpan(run));&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_textBoxHTML.AppendText(&lt;span style="color:#A31515;">&amp;quot;&amp;lt;br/&amp;gt;&amp;quot;&lt;/span>&amp;nbsp;+&amp;nbsp;&lt;span style="color:#2B91AF;">Environment&lt;/span>.NewLine);&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;m_textBoxHTML.AppendText(&lt;span style="color:#A31515;">&amp;quot;&amp;lt;/div&amp;gt;&amp;quot;&lt;/span>);&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">private&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">string&lt;/span>&amp;nbsp;toCleanedColoredSpan(&lt;span style="color:#2B91AF;">Run&lt;/span>&amp;nbsp;run)&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#2B91AF;">SolidColorBrush&lt;/span>&amp;nbsp;solidColorBrush&amp;nbsp;=&amp;nbsp;run.Foreground&amp;nbsp;&lt;span style="color:#0000FF;">as&lt;/span>&amp;nbsp;&lt;span style="color:#2B91AF;">SolidColorBrush&lt;/span>;&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">if&lt;/span>&amp;nbsp;(solidColorBrush&amp;nbsp;==&amp;nbsp;&lt;span style="color:#0000FF;">null&lt;/span>)&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">return&lt;/span>&amp;nbsp;cleanString(run.Text);&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">else&lt;/span>&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">if&lt;/span>&amp;nbsp;(solidColorBrush.Color&amp;nbsp;==&amp;nbsp;&lt;span style="color:#2B91AF;">Colors&lt;/span>.Black)&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">return&lt;/span>&amp;nbsp;cleanString(run.Text);&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">else&lt;/span>&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">string&lt;/span>&amp;nbsp;colorString&amp;nbsp;=&amp;nbsp;solidColorBrush.Color.ToString();&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#2B91AF;">Debug&lt;/span>.Assert(colorString.Length&amp;nbsp;==&amp;nbsp;9);&lt;br/> &lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;colorString&amp;nbsp;=&amp;nbsp;colorString.Substring(3);&lt;br/> &lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">return&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">string&lt;/span>.Format(&lt;span style="color:#A31515;">&amp;quot;&amp;lt;span&amp;nbsp;style=\&amp;quot;color:#{0};\&amp;quot;&amp;gt;{1}&amp;lt;/span&amp;gt;&amp;quot;&lt;/span>,&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;colorString,&amp;nbsp;cleanString(run.Text));&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">private&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">string&lt;/span>&amp;nbsp;cleanString(&lt;span style="color:#0000FF;">string&lt;/span>&amp;nbsp;source)&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source&amp;nbsp;=&amp;nbsp;&lt;span style="color:#2B91AF;">HttpUtility&lt;/span>.HtmlEncode(source);&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;source&amp;nbsp;=&amp;nbsp;source.Replace(&lt;span style="color:#A31515;">&amp;quot;&amp;nbsp;&amp;quot;&lt;/span>,&amp;nbsp;&lt;span style="color:#A31515;">&amp;quot;&amp;amp;nbsp;&amp;quot;&lt;/span>);&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">return&lt;/span>&amp;nbsp;source;&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">private&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">static&lt;/span>&amp;nbsp;&lt;span style="color:#2B91AF;">IEnumerable&lt;/span>&amp;lt;&lt;span style="color:#2B91AF;">Run&lt;/span>&amp;gt;&amp;nbsp;Decompose(&lt;span style="color:#2B91AF;">IEnumerable&lt;/span>&amp;lt;&lt;span style="color:#2B91AF;">Inline&lt;/span>&amp;gt;&amp;nbsp;inlines)&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">foreach&lt;/span>&amp;nbsp;(&lt;span style="color:#2B91AF;">Inline&lt;/span>&amp;nbsp;inline&amp;nbsp;&lt;span style="color:#0000FF;">in&lt;/span>&amp;nbsp;inlines)&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">if&lt;/span>&amp;nbsp;(inline&amp;nbsp;&lt;span style="color:#0000FF;">is&lt;/span>&amp;nbsp;&lt;span style="color:#2B91AF;">Span&lt;/span>)&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">foreach&lt;/span>&amp;nbsp;(&lt;span style="color:#2B91AF;">Run&lt;/span>&amp;nbsp;run&amp;nbsp;&lt;span style="color:#0000FF;">in&lt;/span>&amp;nbsp;Decompose(((&lt;span style="color:#2B91AF;">Span&lt;/span>)inline).Inlines))&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">yield&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">return&lt;/span>&amp;nbsp;run;&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">else&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">if&lt;/span>&amp;nbsp;(inline&amp;nbsp;&lt;span style="color:#0000FF;">is&lt;/span>&amp;nbsp;&lt;span style="color:#2B91AF;">Run&lt;/span>)&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">yield&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">return&lt;/span>&amp;nbsp;(&lt;span style="color:#2B91AF;">Run&lt;/span>)inline;&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">else&lt;/span>&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:#0000FF;">throw&lt;/span>&amp;nbsp;&lt;span style="color:#0000FF;">new&lt;/span>&amp;nbsp;&lt;span style="color:#2B91AF;">NotSupportedException&lt;/span>();&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br/> }&lt;br/> &lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term=".NET"/>
    <category term="fun"/>
    <category term="C#"/>
    <category term="Linq"/>
    <category term="css"/>
  </entry>
  <entry>
    <title type="html">Recursion, Linq, etc. - 3rd Times the Charm</title>
    <link href="https://kevmoo.com/2008/01/recursion-linq-etc-3rd-times-charm.html" rel="alternate" type="text/html" title="Recursion, Linq, etc. - 3rd Times the Charm"/>
    <published>2008-01-18T16:12:00.001Z</published>
    <updated>2008-01-18T16:12:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/recursion-linq-etc-3rd-times-charm.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/recursion-linq-etc-3rd-times-charm.html">&lt;p>The joke about Microsoft is that it always takes them &lt;a href="http://www.google.com/search?q=microsoft+%22three+times+to+get+it+right%22">three times to get it right&lt;/a>.&lt;/p> &lt;p>If you look at my posts on the game Set in WPF, it would seem I follow &lt;a href="http://work.j832.com/2008/01/wpf-set-xbap.html">the&lt;/a> &lt;a href="http://work.j832.com/2008/01/game-in-wpf-redux.html">same&lt;/a> &lt;a href="http://work.j832.com/2008/01/wpf-set-this-is-good-stopping-spot.html">pattern&lt;/a>.&lt;/p> &lt;p>Well, here I go again.&lt;/p> &lt;p>Let's start simple: I have a path to a directory and I want to enumerate over all of it's subdirectories recursively. To be super concrete:&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #0000ff">string&lt;/span>[] startPaths = &lt;span style="color: #0000ff">new&lt;/span>&amp;#160;&lt;span style="color: #0000ff">string&lt;/span>[] { &lt;span style="color: #a31515">@&amp;quot;D:\j832_svn\PublicSoftware\&amp;quot;&lt;/span> };&amp;#160; &lt;br />&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;&lt;span style="color: #0000ff">string&lt;/span>&amp;gt; subPaths = SelectRecursivePaths(startPaths);&lt;/div> &lt;p>Easy enough.&lt;/p> &lt;p>What's the scenario-specific implementation of &lt;code>SelectRecursive&lt;/code>? Well, our friend &lt;code>System.IO.Directory&lt;/code> provides what we need.&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #0000ff">private&lt;/span>&amp;#160;&lt;span style="color: #0000ff">static&lt;/span>&amp;#160;&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;&lt;span style="color: #0000ff">string&lt;/span>&amp;gt; SelectRecursivePaths(&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;&lt;span style="color: #0000ff">string&lt;/span>&amp;gt; paths) &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">foreach&lt;/span> (&lt;span style="color: #0000ff">string&lt;/span> path &lt;span style="color: #0000ff">in&lt;/span> paths) &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> path; &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">foreach&lt;/span> (&lt;span style="color: #0000ff">string&lt;/span> subPath &lt;span style="color: #0000ff">in&lt;/span> SelectRecursivePaths(&lt;span style="color: #2b91af">Directory&lt;/span>.GetDirectories(path))) &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> subPath; &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />} &lt;/div> &lt;p>This code does the job for doing an in-order, recursive traversal of all of all of the directories. But it isn't very Linq-ish, is it?&lt;/p> &lt;h3>Getting Linq-ish: SelectRecursiveSimple&lt;/h3> &lt;p>Could there be a way to extract out the call to &lt;code>Directory.GetDirectories&lt;/code> such that this method could be used over any homogenous, hierarchical structure? Yup.&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #0000ff">public&lt;/span>&amp;#160;&lt;span style="color: #0000ff">static&lt;/span>&amp;#160;&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt; SelectRecursiveSimple&amp;lt;TSource&amp;gt;( &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">this&lt;/span>&amp;#160;&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt; source, &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af">Func&lt;/span>&amp;lt;TSource, &lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt;&amp;gt; recursiveSelector) &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">foreach&lt;/span> (TSource element &lt;span style="color: #0000ff">in&lt;/span> source) &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> element; &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">foreach&lt;/span> (TSource subElement &lt;span style="color: #0000ff">in&lt;/span> recursiveSelector(element).SelectRecursiveSimple(recursiveSelector)) &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> subElement; &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />}&lt;/div> &lt;p>Now we change the call site to embody the call to &lt;code>GetDirectories&lt;/code>:&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;&lt;span style="color: #0000ff">string&lt;/span>&amp;gt; subPaths = startPaths.SelectRecursiveSimple(path =&amp;gt; &lt;span style="color: #2b91af">Directory&lt;/span>.GetDirectories(path));&lt;/div> &lt;p>I love &lt;a href="http://msdn2.microsoft.com/en-us/library/bb397687.aspx">lambda expressions&lt;/a> and &lt;a href="http://msdn2.microsoft.com/en-us/library/bb383977.aspx">extension methods&lt;/a>.&lt;/p> &lt;p>With me so far?&lt;/p> &lt;h3>Getting Clever: SelectRecursiveClever&lt;/h3> &lt;p>Now we go back to my clever idea from &lt;a href="http://work.j832.com/2008/01/flattening-recursive-algorithms-is-like.html">Tuesday&lt;/a> and &lt;a href="http://work.j832.com/2008/01/flattening-recursive-algorithms-with.html">Wednesday&lt;/a> about flattening recursion. The code I ended up with:&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #0000ff">public&lt;/span>&amp;#160;&lt;span style="color: #0000ff">static&lt;/span>&amp;#160;&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt; SelectRecursiveClever&amp;lt;TSource&amp;gt;( &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">this&lt;/span>&amp;#160;&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt; source, &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af">Func&lt;/span>&amp;lt;TSource, &lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt;&amp;gt; recursiveSelector) &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af">Stack&lt;/span>&amp;lt;TSource&amp;gt; stack = &lt;span style="color: #0000ff">new&lt;/span>&amp;#160;&lt;span style="color: #2b91af">Stack&lt;/span>&amp;lt;TSource&amp;gt;(); &lt;br />&amp;#160;&amp;#160;&amp;#160; source.Reverse().ForEach(stack.Push); &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">while&lt;/span> (stack.Count &amp;gt; 0) &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TSource current = stack.Pop(); &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> current; &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; recursiveSelector(current).Reverse().ForEach(stack.Push); &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />}&lt;/div> &lt;p>&lt;em>Note: &lt;code>ForEach&lt;/code> is an extension method I created that does what &lt;code>Array.ForEach&lt;/code> does: calls an &lt;code>Action&amp;lt;T&amp;gt;&lt;/code> delegate on each item. In this case, pushing every item in the sequence into the stack.&lt;/em>&lt;/p> &lt;p>Now the caller-side behavior of this is exactly the same as the &amp;quot;simple&amp;quot; version above. The implementation tries to be &amp;quot;clever&amp;quot; though, by discarding the &amp;quot;naive&amp;quot; use of recursion by replacing the &lt;em>call stack&lt;/em> with a &lt;em>local stack&lt;/em>. I was quite proud of this implementation. As I said on Tuesday:&lt;/p> &lt;blockquote>If you can flatten a recursive implementation, you will have a better understanding of what's really going on under the covers.&lt;/blockquote> &lt;p>Gulp. Perhaps I spoke to soon.&lt;/p> &lt;h3>The Problem with Clever&lt;/h3> &lt;p>I showed a co-worker this code. It took a bit of work to explain the use of &lt;code>.Reverse()&lt;/code>. Stacks are Last-in-first-out, so if you want to get the first item out first, you have to put it in last.&lt;/p> &lt;p>Explaining this hurt my head a bit. In the &amp;quot;simple&amp;quot;--read &amp;quot;naive&amp;quot;--implementation, one didn't have to reverse the enumeration. Why should the flattened version be different?&lt;/p> &lt;p>The answer: it shouldn't.&lt;/p> &lt;p>At some point in the &amp;quot;clever&amp;quot; implementation, every item is on the stack. This means if you have a very wide tree, the stack could grow to be huge.&lt;/p> &lt;p>Imagine your &lt;code>recursiveSelector&lt;/code> is smart about not loading all items at a given level into memory at one time--the benefit of sequences, right? It doesn't matter, because &lt;code>SelectRecursiveClever&lt;/code> &lt;strong>&lt;em>will&lt;/em>&lt;/strong> load everything in one level into a stack. It trades the potential benefit of a smaller call stack with the potential blow-up of your working set when iterate over a folder with 10,000 sub-folders.&lt;/p> &lt;p>Oops.&lt;/p> &lt;p>You &lt;strong>&lt;em>have to&lt;/em>&lt;/strong> keep track of your depth in the recursion somewhere: either the runtime stack or your own stack.&lt;/p> &lt;p>But all you have to keep track of is where you are in each sequence at each level. You don't have to queue up all of the items at a given level. &lt;/p> &lt;p>Turns out the CLR has this obscure feature to handle this: &lt;code>IEnumerator&amp;lt;T&amp;gt;&lt;/code>.&lt;/p> &lt;p>Yeah, not so obscure.&lt;/p> &lt;p>It's actually what the simple version of this code does. When you call down into the nested &lt;code>SelectRecursiveSimle&lt;/code>, an &lt;code>IEnumerator&amp;lt;T&amp;gt;&lt;/code> will be waiting patiently at the the current spot for the call to return.&lt;/p> &lt;h3>Getting Smart(er): SelectRecursive&lt;/h3> &lt;p>The code is more ugly, but it also does a better job of illuminating what is happening in the truly recursive, &amp;quot;simple&amp;quot; version.&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #0000ff">public&lt;/span>&amp;#160;&lt;span style="color: #0000ff">static&lt;/span>&amp;#160;&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt; SelectRecursive&amp;lt;TSource&amp;gt;( &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">this&lt;/span>&amp;#160;&lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt; source, &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af">Func&lt;/span>&amp;lt;TSource, &lt;span style="color: #2b91af">IEnumerable&lt;/span>&amp;lt;TSource&amp;gt;&amp;gt; recursiveSelector) &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af">Stack&lt;/span>&amp;lt;&lt;span style="color: #2b91af">IEnumerator&lt;/span>&amp;lt;TSource&amp;gt;&amp;gt; stack = &lt;span style="color: #0000ff">new&lt;/span>&amp;#160;&lt;span style="color: #2b91af">Stack&lt;/span>&amp;lt;&lt;span style="color: #2b91af">IEnumerator&lt;/span>&amp;lt;TSource&amp;gt;&amp;gt;(); &lt;br />&amp;#160;&amp;#160;&amp;#160; stack.Push(source.GetEnumerator()); &lt;br /> &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">while&lt;/span> (stack.Count &amp;gt; 0) &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">if&lt;/span> (stack.Peek().MoveNext()) &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TSource current = stack.Peek().Current; &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> current; &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; stack.Push(recursiveSelector(current).GetEnumerator()); &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">else&lt;/span> &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; stack.Pop(); &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />}&lt;/div> &lt;p>&lt;strong>&lt;em>&lt;font color="#ff0000">2008-01-19: Turns out &lt;a href="http://work.j832.com/2008/01/selectrecursive-if-3rd-times-charm-4th.html">this code is wrong&lt;/a>, too.&lt;/font>&lt;/em>&lt;/strong>&lt;/p> &lt;p>The stack now holds on to what it should: the &lt;code>IEnumerator&amp;lt;T&amp;gt;&lt;/code> at each level. The while loop runs through &lt;code>IEnumerator&amp;lt;T&amp;gt;.MoveNext()&lt;/code>, going deeper with every &lt;code>stack.Push()&lt;/code> until there are no more items and then &amp;quot;returning&amp;quot; with &lt;code>stack.Pop()&lt;/code>.&lt;/p> &lt;h3>Popping the stack&lt;/h3> &lt;p>It's pretty easy to implement a recursive construct using Linq. The first &amp;quot;simple&amp;quot; implementation works great and it's really useful when partying over the file system or any other hierarchy.&lt;/p> &lt;p>I still claim that flattening recursive code is a good thing to do for reasons I mentioned on Tuesday.&lt;/p> &lt;p>Just make sure you do it correctly.&lt;/p> &lt;p>Put another way: pay attention to your &lt;a href="http://work.j832.com/2007/12/when-you-code-do-you-know-your-masters.html">masters&lt;/a>.&lt;/p> &lt;p>If you can't be smart, be simple.&lt;/p> &lt;p>Don't &lt;em>&lt;strong>ever&lt;/strong>&lt;/em> be clever.&lt;/p> &lt;p>Clever will burn you.&lt;/p> &lt;p>&amp;#160;&lt;/p> &lt;p>Happy hacking.&lt;/p> &lt;p>&amp;#160;&lt;/p> &lt;p>&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwork.j832.com%2f2008%2f01%2frecursion-linq-etc-3rd-times-charm.html">&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwork.j832.com%2f2008%2f01%2frecursion-linq-etc-3rd-times-charm.html&amp;amp;fgcolor=000000&amp;amp;bgcolor=CCCCFF" border="0" />&lt;/a>&lt;/p> &lt;p>&lt;em>PS: &lt;a href="http://j832.com/PublicSoftware/">SVN&lt;/a> has been updated again with the latest code. Hopefully the last time I'll touch &lt;code>RecursiveSelect&lt;/code> for a while.&lt;/em>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="Linq"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">Remembering why I like single-vendor platforms</title>
    <link href="https://kevmoo.com/2008/01/remembering-why-i-like-single-vendor.html" rel="alternate" type="text/html" title="Remembering why I like single-vendor platforms"/>
    <published>2008-01-18T08:44:00.001Z</published>
    <updated>2008-01-18T08:44:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/remembering-why-i-like-single-vendor.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/remembering-why-i-like-single-vendor.html">&lt;p>Now before I start a flame war, remember &lt;a href="http://work.j832.com/2007/09/what-i-install-on-new-machine-free-apps.html">what I wrote&lt;/a> in September:&lt;/p> &lt;blockquote> &lt;p>I believe in open standards. The only way to protect and encourage open standards is to have many prevalent implementations of said standards.&lt;/p> &lt;/blockquote> &lt;p>Having said that, there are still a lot of reasons to love single-vendor, even closed, platforms.&lt;/p> &lt;p>One of those reasons: compatibility.&lt;/p> &lt;p>I had a simple goal: change my blog theme from fixed-width to fluid-width.&lt;/p> &lt;p>Code lines tend to take up a lot more space than 450px. Formatting C# for narrow columns is a pain.&lt;/p> &lt;p>I searched and hacked in vane for over an hour before I found a CSS solution.&lt;/p> &lt;p>The whole time there was a 16-year-old inside of me yelling: &amp;quot;Just use tables! They worked great in 1996!&amp;quot;&lt;/p> &lt;p>I'm going to spare you the gnarly details, but it involves negative margins. (Yes, negative margins. I almost fell off my &lt;a href="http://en.wikipedia.org/wiki/Swiss_ball">Swiss ball&lt;/a>.) Huge props to the folks at &lt;a href="http://www.dynamicdrive.com/">Dynamic Drive&lt;/a> for their straight-forward-as-can-be-expected walk-through of &lt;a href="http://www.dynamicdrive.com/style/layouts/category/C9/">fluid, two-column layouts&lt;/a> in CSS.&lt;/p> &lt;p>After a bunch of tweaking, I got everything looking good in &lt;a href="http://www.mozilla.com/firefox/">Firefox&lt;/a>. I then jumped into &lt;a href="http://windowslivewriter.spaces.live.com/">Live Writer&lt;/a> to start writing. I updated the cached theme for my blog. It looked really broken. Why?&lt;/p> &lt;p>Well, Live Writer uses Trident--the IE rendering engine.&lt;/p> &lt;p>After much hacking, I discovered that IE cares about the order of &amp;lt;div&amp;gt; elements in situations where Firefox doesn't. Also, Firefox respects // to mark comments in CSS. IE doesn't.&lt;/p> &lt;p>After another hour, I got things working in both.&lt;/p> &lt;p>No I haven't tested in IE6 or Safari. Please let me know if you have issues.&lt;/p> &lt;p>I'm guessing I'm one of the few who look at my blog in a browser--most probably use a blog reader.&lt;/p> &lt;p>Good idea.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="css"/>
  </entry>
  <entry>
    <title type="html">Flattening recursive algorithms with Linq</title>
    <link href="https://kevmoo.com/2008/01/flattening-recursive-algorithms-with.html" rel="alternate" type="text/html" title="Flattening recursive algorithms with Linq"/>
    <published>2008-01-16T21:13:00.001Z</published>
    <updated>2008-01-16T21:13:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/flattening-recursive-algorithms-with.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/flattening-recursive-algorithms-with.html">&lt;p>I wake up this morning to find a comment from &lt;a href="http://www.blogger.com/profile/10383237063496383837">Stefan&lt;/a> regarding my &lt;a href="http://work.j832.com/2008/01/flattening-recursive-algorithms-is-like.html">post yesterday&lt;/a> about flattening recursion:&lt;/p> &lt;blockquote> &lt;p>In the future version of C# we may receive a new language construct &lt;b>yield foreach&lt;/b> which will eliminate this problem. Read &lt;a href="http://research.microsoft.com/%7Eschulte/Papers/Iterators%28FTfJP2005%29.pdf">this paper&lt;/a> by Erik Meijer or &lt;a href="http://blogs.msdn.com/wesdyer/archive/2007/03/23/all-about-iterators.aspx">this blog post&lt;/a> by Wes Dyer if you are interested.&lt;/p> &lt;/blockquote> &lt;p>Ironically, I had read the paper and associated blog post last week.&lt;/p> &lt;p>And it got me thinking: could I abstract out my recursive traversal?&lt;/p> &lt;p>Even better: could I abstract it out in a way that was &lt;a href="http://en.wikipedia.org/wiki/Language_Integrated_Query">Linq&lt;/a>-friendly?&lt;/p> &lt;p>The answer to both: oh yeah.&lt;/p> &lt;p>Check out the browser-friendly source &lt;a href="http://j832.com/workBlogFiles/2008-01-16_SelectRecursive.htm">here&lt;/a>.&lt;/p> &lt;p>Now the code to find all of the selected directories becomes&lt;/p> &lt;blockquote> &lt;p>SubDirectories &lt;br />.SelectRecursive(directory =&amp;gt; directory.SubDirectories) &lt;br />.Where(directory =&amp;gt; directory.IsSelected);&lt;/p> &lt;/blockquote> &lt;p>How's that for straight-forward?&lt;/p> &lt;p>Note 1: The savvy reader will notice that the third implementation is now like the original: the target node is not included in SelectedDirectories if it is selected. I like this more.&lt;/p> &lt;p>Note 2: Since I made &lt;strong>SelectRecursive&lt;/strong> more general, I'm not quite as efficient about creating a bunch of enumerable instances. I still (likely) save a lot in call stack space and having a general implementation is pretty cool.&lt;/p> &lt;p>Note 3: &lt;del>You'll notice that &lt;strong>SelectRecursive&lt;/strong> handles the case where there &lt;strong>recursiveSelector&lt;/strong> returns null. This is different than how default extensions like &lt;strong>SelectMany&lt;/strong> work. It made my usage in this scenario cleaner, but it's important to note.&lt;/del> &lt;em>Or not. This bothered me for reasons I'll go into in another post. The code as checked-in now throws if null is returned.&lt;/em> These subtle implementation details can cause headaches later.&lt;/p> &lt;p>As I mentioned yesterday, you can get the full source code from my &lt;a href="http://j832.com/PublicSoftware/" target="_blank">SVN repository&lt;/a>. The new methods extension methods have been added to Extensions.cs in J832.Common.&lt;/p> &lt;p>Happy recursive Linq-ing!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="Linq"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">Flattening recursive algorithms is like taking the stairs...</title>
    <link href="https://kevmoo.com/2008/01/flattening-recursive-algorithms-is-like.html" rel="alternate" type="text/html" title="Flattening recursive algorithms is like taking the stairs..."/>
    <published>2008-01-16T04:05:00.001Z</published>
    <updated>2008-01-16T04:05:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/flattening-recursive-algorithms-is-like.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/flattening-recursive-algorithms-is-like.html">&lt;p>...it's rarely necessary, but you'll be better for it.&lt;/p> &lt;p>Okay, a forced analogy.&lt;/p> &lt;p>&lt;strong>&lt;em>&lt;font color="#ff0000">2008-01-19: I've learned a lot since Tuesday. &lt;/font>&lt;font color="#ff0000">&lt;a href="http://work.j832.com/2008/01/selectrecursive-if-3rd-times-charm-4th.html">Please read!&lt;/a>&lt;/font>&lt;/em>&lt;/strong>&lt;/p> &lt;p>I'm sure many remember their first algorithms class and their first introduction to recursion: the infamous &lt;a href="http://en.wikipedia.org/wiki/Tower_of_Hanoi">Tower of Hanoi&lt;/a> problem. I'd been coding for a while when I was presented with this puzzle and wondered (probably out loud), &amp;quot;Why don't we use a more concrete example, like the file system?&amp;quot;&lt;/p> &lt;p>I guess I've always been more of a software engineer than a computer scientist.&lt;/p> &lt;p>While the idea of recursion is useful in many situations, the costs are rarely discussed. As our friends at Wikipedia &lt;a href="http://en.wikipedia.org/wiki/Recursion_%28computer_science%29">mention&lt;/a>:&lt;/p> &lt;blockquote> &lt;p>...in today's programming languages, the stack space available to a thread is often much less than the space available in the heap, and recursive algorithms tend to require more stack space than iterative algorithms.&lt;/p> &lt;/blockquote> &lt;p>Well said.&lt;/p> &lt;p>I was hacking on some work stuff that required recursion-- specifically flattening a hierarchy. I realized I'd done this before, in the &lt;a href="http://j832.com/bagotricks/">bag-o-tricks&lt;/a>. I also realized how expensive it was.&lt;/p> &lt;p>&lt;a href="http://j832.com/workBlogFiles/_images/Flatteningrecursivealgorithmsisliketaki_11A6D/image.png">&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="306" alt="Call stack for recursive function call" src="http://j832.com/workBlogFiles/_images/Flatteningrecursivealgorithmsisliketaki_11A6D/image_thumb.png" width="404" border="0" />&lt;/a> &lt;/p> &lt;p>Not only was I paying in call stack space for every nested call, but I was also allocating a lot of enumerators. &lt;/p> &lt;p>&lt;em>Code for the SelectedDirectories getter.&lt;/em>&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #0000ff">if&lt;/span> (m_directories != &lt;span style="color: #0000ff">null&lt;/span>) &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">foreach&lt;/span> (&lt;span style="color: #2b91af">SelectableDirectory&lt;/span> sd &lt;span style="color: #0000ff">in&lt;/span> m_directories) &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">if&lt;/span> (sd.IsSelected) &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> sd; &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">foreach&lt;/span> (&lt;span style="color: #2b91af">SelectableDirectory&lt;/span> sd2 &lt;span style="color: #0000ff">in&lt;/span> sd.SelectedDirectories) &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> sd2; &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />} &lt;br />&lt;/div> &lt;p>So how does one improve this? Replace the call stack with your own stack.&lt;/p> &lt;div style="font-family: monospace">&lt;span style="color: #2b91af">Stack&lt;/span>&amp;lt;&lt;span style="color: #2b91af">SelectableDirectory&lt;/span>&amp;gt; directoryStack = &lt;span style="color: #0000ff">new&lt;/span>&amp;#160;&lt;span style="color: #2b91af">Stack&lt;/span>&amp;lt;&lt;span style="color: #2b91af">SelectableDirectory&lt;/span>&amp;gt;(); &lt;br />directoryStack.Push(&lt;span style="color: #0000ff">this&lt;/span>); &lt;br />&lt;span style="color: #0000ff">while&lt;/span> (directoryStack.Count &amp;gt; 0) &lt;br />{ &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #2b91af">SelectableDirectory&lt;/span> currentDir = directoryStack.Pop(); &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">if&lt;/span> (currentDir.m_directories != &lt;span style="color: #0000ff">null&lt;/span>) &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">for&lt;/span> (&lt;span style="color: #0000ff">int&lt;/span> i = (currentDir.m_directories.Count - 1); i &amp;gt;= 0; i--) &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; directoryStack.Push(currentDir.m_directories[i]); &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">if&lt;/span> (currentDir.IsSelected) &lt;br />&amp;#160;&amp;#160;&amp;#160; { &lt;br />&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style="color: #0000ff">yield&lt;/span>&amp;#160;&lt;span style="color: #0000ff">return&lt;/span> currentDir; &lt;br />&amp;#160;&amp;#160;&amp;#160; } &lt;br />}&lt;/div> &lt;p>&lt;em>The savvy reader will notice that the second implementation is slightly different: the target node is included if it is selected. Just a detail.&lt;/em>&lt;/p> &lt;p>So, what has improved? Only one enumerator is created. The call stack space for the recursion is also eliminated. The cost is the creation of the local Stack&amp;lt;&amp;gt; to keep track of the location in the hierarchy, which is likely much smaller than the space required for a call stack frame.&lt;/p> &lt;p>Since we want to keep the original order of items returned, we also have to Push each level of directories into the Stack in reverse order, so that the Stack returns them in the original order.&lt;/p> &lt;p>Now how does this match up with &lt;a href="http://work.j832.com/2007/12/when-you-code-do-you-know-your-masters.html">our masters&lt;/a>?&lt;/p> &lt;p>It's certainly less readable. Since the code's not documented, it would probably take longer for even a savvy dev to figure out what's going on. This means it's less maintainable--certainly a negative.&lt;/p> &lt;p>On the plus size, the scalability of this algorithm is now limited by the size of the heap, which is much larger than the call stack. This only matters if one plans to parse very deep directory structures, though.&lt;/p> &lt;p>Another plus is likely performance, since fewer objects are instantiated and the cost of manipulating a local Stack&amp;lt;&amp;gt; is likely much cheaper than churning the call stack. I say 'likely' because I'm not really sure. I should absolutely measure the performance to be certain. Even then, the perf gain is likely trivial unless this code is called a lot. In that case, it might make sense to cache the result of the method.&lt;/p> &lt;p>In the end (and as always), context really matters. I think this is a good exercise to understand the costs and to challenge one's understanding of recursion. If you can flatten a recursive implementation, you will have a better understanding of what's really going on under the covers--something that is always useful.&lt;/p> &lt;p>Happy hacking!&lt;/p> &lt;p>&lt;em>Note: the updated code for Folder Picker has been committed to the bag-o-tricks directory in &lt;a href="http://j832.com/PublicSoftware/">my SVN repository&lt;/a>. You can take a look at the old implementation using &lt;a href="http://tortoisesvn.tigris.org/">Tortoise&lt;/a>. Right-click on Data.cs in the shell. Pick 'Show log' out of the Tortoise menu. Then right-click on revision 58 and pick 'Update item to revision'.&lt;/em>&lt;/p> &lt;p>&lt;a href="http://j832.com/workBlogFiles/_images/Flatteningrecursivealgorithmsisliketaki_11A6D/image_3.png">&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="342" alt="Update to revision" src="http://j832.com/workBlogFiles/_images/Flatteningrecursivealgorithmsisliketaki_11A6D/image_thumb_3.png" width="404" border="0" />&lt;/a>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">A REAL update to the Bag-o-Tricks</title>
    <link href="https://kevmoo.com/2008/01/real-update-to-bag-o-tricks.html" rel="alternate" type="text/html" title="A REAL update to the Bag-o-Tricks"/>
    <published>2008-01-13T02:30:00.001Z</published>
    <updated>2008-01-13T02:30:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/real-update-to-bag-o-tricks.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/real-update-to-bag-o-tricks.html">&lt;p>The &lt;a href="http://work.j832.com/2007/12/bag-o-tricks-christmas-edition.html">last update&lt;/a> to the &lt;a href="http://j832.com/bagotricks/">bag-o-tricks&lt;/a> was pretty lame, I'll admit.&lt;/p> &lt;p>As I &lt;a href="http://work.j832.com/2007/12/when-you-code-do-you-know-your-masters.html">discussed&lt;/a> a bit ago, a lot of people code to &amp;quot;get it done yesterday&amp;quot;. It's clear, looking through a bunch of the code, that I had this mentality about a lot of the samples. Moreover, it's clear that the masters of code quality, maintainability, and best-practices were often ignored.&lt;/p> &lt;p>Here's an attempt to put my money where my mouth is. &lt;/p> &lt;h3>The Goods&lt;/h3> &lt;p>&lt;a href="http://j832.com/bagotricks/wpfbagotricks.zip">Binaries and Source&lt;/a> [zip, 4.3MB]. &lt;em>Developed with Visual C# Express 2008.&lt;/em>&lt;/p> &lt;h3>The Details&lt;/h3> &lt;ul> &lt;li>&lt;strong>Set - &lt;em>New!&lt;/em>&lt;/strong> &lt;ul> &lt;li>The XBap I &lt;a href="http://work.j832.com/2008/01/wpf-set-xbap.html">posted last week&lt;/a> is now part of the bag-o-tricks. &lt;/li> &lt;li>Did some clever project linking to allow building XBap without duplicating files. &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>Interactive 3D - &lt;em>New!&lt;/em>&lt;/strong> &lt;ul> &lt;li>Added the 3D demos I &lt;a href="http://work.j832.com/2008/01/wpf-35-demo-posted-add-ins-and.html">discussed&lt;/a> a while ago &lt;/li> &lt;li>A lot of clean-up to make the code more suitable for general use &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>AnimatingTilePanel&lt;/strong> &lt;ul> &lt;li>Ability to animate in newly added items &lt;/li> &lt;li>Made dampening make sense: bigger number = more dampening &lt;/li> &lt;li>Add Variation property to make item movement make more organic, if desired &lt;/li> &lt;li>Added validation to the public properties &lt;/li> &lt;li>Moved frame tick register/de-register to new CompositionTargetRenderingListener &lt;/li> &lt;li>Perf: Stopped &amp;#8216;ticking&amp;#8217; when nothing is changing &lt;/li> &lt;li>Stopped using clock time between ticks to affect animation: complexity with little benefit &lt;/li> &lt;li>Made ItemHeight/Width attached properties that can be added to a host ItemsControl. &lt;/li> &lt;li>Demo: moved to DemoCollection -&amp;gt; now you can see how changes to the source collection are reflected &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>Graph&lt;/strong> &lt;ul> &lt;li>Removed a completely silly use a Dictionary. Clever perf optimization that made the code bloated, confusing, and probably slower. &lt;/li> &lt;li>Renamed CoefficientOfDampening -&amp;gt; Dampening &lt;/li> &lt;li>Rename FrameRate -&amp;gt; Attraction &lt;/li> &lt;li>Removed unneeded HideAnimationManager -&amp;gt; thank you anonymous methods. &lt;/li> &lt;li>Demo: A bunch of clean-up in the Node data files. Should never have used DispaterObject. &lt;/li> &lt;li>Demo: Moved to dispatcher timer for churning the graph nodes: a lot cleaner and more efficient than a separate Thread. &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>Zap&lt;/strong> &lt;ul> &lt;li>Removed shameful implementation of IPropertyChanged on top of a DependencyObject &lt;/li> &lt;li>Eliminated gratuitous subclassing of DependencyObject by ZapCommandItem &lt;/li> &lt;li>Removed FirstPreviousNextLastCommand (and associated enum) -&amp;gt; thank you ActionICommand &lt;/li> &lt;li>Fixed some pretty glaring bugs in not-so-edge cases &lt;/li> &lt;li>Demo: moved to DemoCollection &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>ActionICommand - &lt;em>New!&lt;/em>&lt;/strong> &lt;ul> &lt;li>Commands often expose the functionality of existing methods. So why can&amp;#8217;t exposing a command be as simple as wrapping the existing method? Exactly. &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>WrapperElement - &lt;em>New!&lt;/em>&lt;/strong> &lt;ul> &lt;li>A while ago, I &lt;a href="http://work.j832.com/2007/06/don-subclass-panel-unless-you-making.html">discussed&lt;/a> not subclassing Panel unless you&amp;#8217;re making a Panel. Well, sometimes all you want to do is compose a single element without exposing it's state to the world. WrapperElement makes the process of wrapping a child element trivial.&lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>CompositionTargetRenderingListener - &lt;em>New!&lt;/em>&lt;/strong> &lt;ul> &lt;li>A class that can be used to manage listening to the static CompositionTarget.Rendering event. I use this pattern so much, it made sense to make a separate class. &lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>Demo: DemoCollection - &lt;em>New!&lt;/em>&lt;/strong> &lt;ul> &lt;li>Writing controls that handle INotifyCollectionChange can be tough. Wouldn&amp;#8217;t it be nice to have a class that makes testing (and then showing off) your list-bound control easy? I thought so.&lt;/li> &lt;/ul> &lt;/li> &lt;li>&lt;strong>General&lt;/strong> &lt;ul> &lt;li>Removed a lot of unused parameters and privates. Thanks, &lt;a href="http://en.wikipedia.org/wiki/FxCop">FxCop&lt;/a>. &lt;/li> &lt;li>Demo: Moved the introduction page to FlowDocument. Why I didn&amp;#8217;t do this a year ago, I&amp;#8217;ll never know. &lt;/li> &lt;/ul> &lt;/li> &lt;/ul> &lt;p>As always, the &lt;a href="http://j832.com/PublicSoftware/">SVN location&lt;/a> has been updated. Patches are always welcome (No one has taken me up on this yet. Would love to try it out.)&lt;/p> &lt;p>Enjoy and happy hacking!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term=".NET"/>
    <category term="C#"/>
  </entry>
  <entry>
    <title type="html">WPF 3.5 Demo Posted: Add-ins and Interactive 3D</title>
    <link href="https://kevmoo.com/2008/01/wpf-35-demo-posted-add-ins-and.html" rel="alternate" type="text/html" title="WPF 3.5 Demo Posted: Add-ins and Interactive 3D"/>
    <published>2008-01-09T04:10:00.001Z</published>
    <updated>2008-01-09T04:10:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/wpf-35-demo-posted-add-ins-and.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/wpf-35-demo-posted-add-ins-and.html">&lt;p>Way back in August, I &lt;a href="http://work.j832.com/2007/08/video-what-new-in-wpf-for-2008.html">posted&lt;/a> about my &lt;a href="http://channel9.msdn.com/showpost.aspx?postid=332987">last Channel 9 interview&lt;/a> where I discussed new stuff in WPF for 3.5. At the time, I was a slacker about getting the code for the demos out.&lt;/p> &lt;a href="http://rhizohm.net/irhetoric/blog/21/default.aspx">&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="269" alt="WPF 3.5 Demo Code" src="http://j832.com/workBlogFiles/_images/WPF3.5DemoPostedAddinsandInteractive3D_11BC1/image5.png" width="392" border="0" />&lt;/a> &lt;p>Well &lt;a href="http://rhizohm.net/irhetoric">Karsten&lt;/a> has &lt;a href="http://rhizohm.net/irhetoric/blog/21/default.aspx">picked up my slack&lt;/a>.&lt;/p> &lt;p>&lt;em>I only have C# 2008 Express installed and for some reason it doesn't like how complicated I made the solution, so I can't claim to have built/run the code as Karsten has posted it. I'm sure it's fine, though.&lt;/em>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term=".NET"/>
    <category term="C#"/>
  </entry>
  <entry>
    <title type="html">WPF Set - This is a good stopping spot</title>
    <link href="https://kevmoo.com/2008/01/wpf-set-this-is-good-stopping-spot.html" rel="alternate" type="text/html" title="WPF Set - This is a good stopping spot"/>
    <published>2008-01-08T08:55:00.001Z</published>
    <updated>2008-01-08T08:55:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/wpf-set-this-is-good-stopping-spot.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/wpf-set-this-is-good-stopping-spot.html">&lt;p align="center">&lt;a href="http://j832.com/workBlogFiles/WPFSetThisisagoodstoppingspot_CFC/image.png">&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="304" alt="WPF Set - 2008-01-08" src="http://j832.com/workBlogFiles/WPFSetThisisagoodstoppingspot_CFC/image_thumb.png" width="227" border="0" />&lt;/a> &lt;/p> &lt;ul> &lt;li>The graphics pretty much match the actual game now.&lt;/li> &lt;li>Moved the &lt;em>New Game&lt;/em> button to minimize accidental clicking.&lt;/li> &lt;li>Some small tweaks to the game logic.&lt;/li> &lt;/ul> &lt;p>URLs are the &lt;a href="http://work.j832.com/2008/01/wpf-set-xbap.html">same as before&lt;/a>:&lt;/p> &lt;ul> &lt;li>&lt;a href="http://j832.com/workBlogFiles/WpfSet/">XBAP&lt;/a>&lt;/li> &lt;li>&lt;a href="http://j832.com/workBlogFiles/J832.WpfSet.zip">Source and Binaries&lt;/a> [Zip, 54KB]&lt;/li> &lt;/ul> &lt;p>Bleh! The third night this darn game has kept me up past midnight. I need another hobby.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="fun"/>
    <category term="C#"/>
  </entry>
  <entry>
    <title type="html">The Game "Set" in WPF (Redux)</title>
    <link href="https://kevmoo.com/2008/01/game-in-wpf-redux.html" rel="alternate" type="text/html" title="The Game &quot;Set&quot; in WPF (Redux)"/>
    <published>2008-01-07T05:41:00.001Z</published>
    <updated>2008-01-07T05:41:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/game-in-wpf-redux.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/game-in-wpf-redux.html">&lt;p>Yesterday (well, early this morning) I &lt;a href="http://work.j832.com/2008/01/wpf-set-xbap.html">posted my first stab&lt;/a> at the game Set implemented in WPF.&lt;/p> &lt;p>Amazing what 20 hours of bake time can do.&lt;/p> &lt;ul> &lt;li>Removed insanely complex and unnecessary optimization that made the code for SetGame.TryPlay almost un-readable.&lt;/li> &lt;li>Cleaned up the 'test' mode by removing it. If you build/run DEBUG, you'll get a Test button. If you build/run RELEASE, you won't.&lt;/li> &lt;li>Used binding in the WPF app where it makes sense.&lt;/li> &lt;li>Added a bunch of caching to the card generation on the WPF side. Re-creating a bunch of brushes and pens is silly.&lt;/li> &lt;li>Added a test project: &lt;strong>WpfSet_Test&lt;/strong> to run the data model through its paces.&lt;/li> &lt;li>Fixed deployment to actually use Visual Studio Deploy functionality. (Yesterday, I just uploaded the files from the build directory.) If you accessed &lt;a href="http://j832.com/workBlogFiles/WpfSet/">the XBAP&lt;/a> yesterday, please refresh and make sure the title says at least &amp;quot;WPF Set - 2008-01-&lt;strong>06&lt;/strong>&amp;quot; and not &amp;quot;WPF Set - 2008-01-&lt;strong>05&lt;/strong>.&amp;quot; If refreshing doesn't move you beyond 2008-01-&lt;strong>05&lt;/strong>, there is something fishy with your application cache. Drop me a line and I'll try to fix it. &lt;/li> &lt;/ul> &lt;p>The &lt;a href="http://j832.com/workBlogFiles/WpfSet/">XBAP URL&lt;/a> hasn't changed.&lt;/p> &lt;p>I've combined the source and binaries into &lt;a href="http://j832.com/workBlogFiles/J832.WpfSet.zip">one zip file&lt;/a> [53KB]. I've always thought having dated copies of files was goodness, but then I realized if someone links to the old version, they'll never get updates. I'm going to try to keep an updated read-me in the zip file so folks know what version they've downloaded.&lt;/p> &lt;p>As always, send me an email or a comment if you have questions.&lt;/p> &lt;p>Happy Setting.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="fun"/>
    <category term="C#"/>
  </entry>
  <entry>
    <title type="html">The Game "Set" in WPF</title>
    <link href="https://kevmoo.com/2008/01/wpf-set-xbap.html" rel="alternate" type="text/html" title="The Game &quot;Set&quot; in WPF"/>
    <published>2008-01-06T09:10:00.001Z</published>
    <updated>2008-01-06T09:10:00.001Z</updated>
    <id>https://kevmoo.com/2008/01/wpf-set-xbap.html</id>
    <content type="html" xml:base="https://kevmoo.com/2008/01/wpf-set-xbap.html">&lt;p>&lt;em>&lt;font color="#ff0000">Update - 2008-01-06: See &lt;a href="http://work.j832.com/2008/01/game-in-wpf-redux.html">this post&lt;/a> for new details. Links below have been changed.&lt;/font>&lt;/em>&lt;/p> &lt;p>&lt;em>In theory, I have so many more important projects to work on. This was one of those ideas that got legs faster than I realized I should be working on something else.&lt;/em>&lt;/p> &lt;p>If you haven't heard of Set, check it out &lt;a href="http://www.setgame.com/set/index.html">company site&lt;/a> or &lt;a href="http://en.wikipedia.org/wiki/Set_(game)">the Wikipedia entry&lt;/a>.&lt;/p> &lt;p align="center">&lt;a href="http://j832.com/workBlogFiles/WPFSetXBAP_109C/image_3.png">&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="304" alt="WPF Set - 2008-01-08" src="http://j832.com/workBlogFiles/WPFSetXBAP_109C/image_thumb.png" width="226" border="0" />&lt;/a> &lt;/p> &lt;p>Building the data model was half the fun. This is some of my first code that uses &lt;a href="http://en.wikipedia.org/wiki/Language_Integrated_Query">Linq&lt;/a> features from .NET 3.5. I'm blown away. Without a doubt as big as generics. Wow!&lt;/p> &lt;p>The UI is super minimal and that was the goal. Get it all working and ponder prettier/sexier things later.&lt;/p> &lt;p>So, if you want to play:&lt;/p> &lt;ul> &lt;li>&lt;a href="http://j832.com/workBlogFiles/WpfSet/">XBAP&lt;/a> - Requires &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=333325fd-ae52-4e35-b531-508d977d32a6&amp;amp;displaylang=en">Microsoft .NET Framework 3.5&lt;/a>. (Works in IE and Firefox.) &lt;/li> &lt;li>&lt;a href="http://j832.com/workBlogFiles/J832.WpfSet.zip">Source and Binaries&lt;/a> [53KB zip] &lt;/li> &lt;/ul> &lt;p>As I've &lt;a href="http://work.j832.com/2007/12/bag-o-tricks-christmas-edition.html">discussed before&lt;/a>, you can also take a look at the source on my &lt;a href="http://j832.com/PublicSoftware/">SVN share&lt;/a> using you &lt;a href="http://work.j832.com/2007/12/tortoisesvn-rocks.html">favorite SVN client&lt;/a>.&lt;/p> &lt;p>Future ideas:&lt;/p> &lt;ul> &lt;li>Add a timer and a notion of players. I think I'd layer this on top of the existing game model to keep things simple and clean. &lt;/li> &lt;li>It would be cool to layer a 3D UI on top of the game model, too. I have some crazy ideas based on the Flip3D stuff from the &lt;a href="http://j832.com/bagotricks/">bag-o-tricks&lt;/a>. &lt;/li> &lt;/ul> &lt;p>Hope you enjoy it! &lt;/p> &lt;p>&lt;em>Note 1: Thanks to &lt;/em>&lt;a href="http://scorbs.com/">&lt;em>Karen&lt;/em>&lt;/a>&lt;em> for the &lt;/em>&lt;a href="http://scorbs.com/2006/06/04/vs-template-flexible-application/">&lt;em>details on making an XBAP project&lt;/em>&lt;/a>&lt;em>.&lt;/em>&lt;/p> &lt;p>&lt;em>&lt;del>Note 2: I'll give a cookie to anyone who sends me an SVN patch that fixes the shapes so they match what's really in the game. (Drop me an email via the link on the right.)&lt;/del>&lt;/em> &lt;em>2008-01-08: &lt;a href="http://work.j832.com/2008/01/wpf-set-this-is-good-stopping-spot.html">No cookie for you&lt;/a>.&lt;/em>&lt;/p> &lt;p>&lt;em>Other bug fixes are always appreciated. &lt;/em>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="fun"/>
    <category term="C#"/>
    <category term="SVN"/>
  </entry>
  <entry>
    <title type="html">When you code, do you know your Master(s)?</title>
    <link href="https://kevmoo.com/2007/12/when-you-code-do-you-know-your-masters.html" rel="alternate" type="text/html" title="When you code, do you know your Master(s)?"/>
    <published>2007-12-29T18:32:00.001Z</published>
    <updated>2007-12-29T18:32:00.001Z</updated>
    <id>https://kevmoo.com/2007/12/when-you-code-do-you-know-your-masters.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/12/when-you-code-do-you-know-your-masters.html">&lt;p>&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="105" alt="Master Chief - Everyone&amp;#39;s Master" src="http://j832.com/workBlogFiles/WhenyoucodedoyouknowyourMasters_9445/halo3masterchief_thumb.png" width="150" align="right" border="0" />&lt;em>There are a whole set of blog posts floating around my head. Discussions of immutability, pre-condition checking, etc. I realized I needed to cover a meta-topic first: the notion of &amp;quot;masters&amp;quot; while programming.&lt;/em>&lt;/p> &lt;p>This is a concept I think everyone has, but for most, it remains fuzzy, undefined and un-discussed--which is fine, if you work by yourself.&lt;/p> &lt;p>As I've dived into the software engineering role in the last few months, I've been required to justify my implementation decisions and opinions with co-workers. Given the seemingly limitless ways in which one could solve a given problem with a file full of curly braces and semi-colons, why did I choose the approach I did? Why do I want to change a bunch of existing code? Why am I asking my colleagues to change how they write software?&lt;/p> &lt;p>When it's a simple matter of &amp;quot;does it work or not&amp;quot; there isn't much of a problem, but as many know, writing solid code goes well beyond getting things to build and run.&lt;/p> &lt;p>So, what drives how you write software? When you are at a cross roads (with a co-worker or even with yourself) about how to approach implementation, what guides your discussion? These are your masters.&lt;/p> &lt;p>Examples:&lt;/p> &lt;ul> &lt;li>Minimize code size&lt;/li> &lt;li>Minimize code complexity&lt;/li> &lt;li>Minimize unnecessary code churn&lt;/li> &lt;li>Maximize code readability&lt;/li> &lt;li>Maximize correctness&lt;/li> &lt;li>Maximize robustness&lt;/li> &lt;li>Maximize flexibility&lt;/li> &lt;li>Maximize code maintainability &lt;/li> &lt;li>Maximize CPU performance characteristics&lt;/li> &lt;li>Maximize Memory performance characteristics&lt;/li> &lt;li>Maximize API ease-of-use&lt;/li> &lt;li>Maximize the chance another dev will use an API correctly (see &lt;a href="http://blogs.msdn.com/brada/archive/2003/10/02/50420.aspx">Pit of Success&lt;/a>)&lt;/li> &lt;li>Opt for immutable data structures&lt;/li> &lt;li>Opt for thread-safe data structures and APIs&lt;/li> &lt;li>Verify pre-conditions&lt;/li> &lt;li>Follow design guidelines&lt;/li> &lt;li>Get it done yesterday!&lt;/li> &lt;/ul> &lt;p>And none of these have anything to do with solving the problem at hand. They are, for lack of a better term, taxes. Well, except for &lt;em>get it done yesterday&lt;/em>.&lt;/p> &lt;p>Some observations:&lt;/p> &lt;p>1) Many (Most? All?) of the&lt;em> &lt;/em>masters conflict with at least one other master. CPU vs Memory performance is a trade off for many algorithms. Performance optimizations often hurt code readability. API ease-of-use often bumps up against immutability and thread safety. Therefor...&lt;/p> &lt;p>2) Context really matters. This is an important point to bring up when discussing with co-workers. &lt;em>In this situation&lt;/em>, which master is most important?&lt;/p> &lt;p>3) When making your case in a disagreement, make it in terms of the masters you are prioritizing in a given situation. If someone doesn't understand the importance of--say--immutability, you'd better be able to articulate it.&lt;/p> &lt;p>4) Speaking in terms of masters makes everyone a lot more sane. How often have implementation discussions turned into irrational arguments? Using a master-focused format, I've found disagreements turn into pretty simple cases of a disagreement about the relative importance of two masters. Other times, it's a matter of agreeing on an exception to general rule. &amp;quot;While in general, Master A is more important than Master B, in this situation, we should prioritize B because of X, Y, Z...&amp;quot;&lt;/p> &lt;p>5) &amp;quot;Fake&amp;quot; masters get exposed--vices wearing the mask of a real master. This is amazingly important, too. Lazy often wears the mask of &lt;em>code size&lt;/em> or &lt;em>get it done yesterday&lt;/em>. &lt;em>Clever&lt;/em> often wears the guise of unnecessary flexibility or performance improvements, while increasing code complexity and decreasing code readability. (I'm often guilty of this.)&lt;/p> &lt;p>So...&lt;/p> &lt;p>Next time you are struggling with several valid ways to implement something, make the mental check-list: what masters am I serving with each implementation? What masters are really important in this situation?&lt;/p> &lt;p>Next time you disagree with a co-worker about an implementation, ask yourself: what masters is she arguing for? What masters am I arguing for? What masters really matter? Maybe step back a bit and talk through your respective masters and make sure you both understand before you dig in.&lt;/p> &lt;p>Next time you are trying to &lt;em>get it done yesterday&lt;/em>, ask yourself: am I just being lazy? :-)&lt;/p> &lt;p>Happy hacking...&lt;/p> &lt;p>&lt;em>Note 1: Huge props to my co-worker, &lt;/em>&lt;a href="http://dpotter.net/Technical/">&lt;em>David Potter&lt;/em>&lt;/a>&lt;em>. A more brilliant, friendly, and fun colleagues I could not ask for. We've been using this master-focused mind set for weeks now and it makes collaborating a blast.&lt;/em>&lt;/p> &lt;p>&lt;em>Note 2: I always get a little nervous posting these long, pseudo-philosophical rants with no source code. As always, if you write a comment saying you read this far (and you don't think I'm crazy) you'll make my day.&lt;/em>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term="important"/>
    <category term="interesting"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">Bag-o-Tricks Christmas Edition</title>
    <link href="https://kevmoo.com/2007/12/bag-o-tricks-christmas-edition.html" rel="alternate" type="text/html" title="Bag-o-Tricks Christmas Edition"/>
    <published>2007-12-20T21:19:00.001Z</published>
    <updated>2007-12-20T21:19:00.001Z</updated>
    <id>https://kevmoo.com/2007/12/bag-o-tricks-christmas-edition.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/12/bag-o-tricks-christmas-edition.html">&lt;p>Here's a token gift from me to you. An update to the &lt;a href="http://j832.com/bagotricks/">bag-o-tricks&lt;/a>. No earth-shattering features, but a bunch of clean-up. I've made everything work under VS 2008 and rolled up a bunch of common files under a 'common' assembly.&lt;/p> &lt;p>I've renamed the assemblies so it's easy to keep track of what comes from me--everything starts with J832.&lt;/p> &lt;p>I've also done some tweaking so that, by default, images are picked up from the users image folder on XP. You can still override this with a command line parameter.&lt;/p> &lt;p>As I hinted to with my &lt;a href="http://work.j832.com/2007/12/tortoisesvn-rocks.html">post about TortoiseSVN&lt;/a>, I've also put all of my code up on an SVN share: &lt;a href="http://j832.com/PublicSoftware/">j832.com/PublicSoftware&lt;/a>.&lt;/p> &lt;p>I'll try to make sure that the bits I check-in are at least building, but no promises. If you want to fix any bugs and send me the patch, I'd love to try it out. Promise that it's your own code and that you're willing to license your work under the MIT License. You can find my email address on my blog.&lt;/p> &lt;p>Happy hacking and happy holidays!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="SVN"/>
    <category term="interesting"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">TortoiseSVN Rocks!</title>
    <link href="https://kevmoo.com/2007/12/tortoisesvn-rocks.html" rel="alternate" type="text/html" title="TortoiseSVN Rocks!"/>
    <published>2007-12-11T05:36:00.001Z</published>
    <updated>2007-12-11T05:36:00.001Z</updated>
    <id>https://kevmoo.com/2007/12/tortoisesvn-rocks.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/12/tortoisesvn-rocks.html">&lt;p>&lt;em>Yes, I'm considering writing a book: &amp;quot;Kevin Explores Things That Rock&amp;quot;.&lt;/em>&lt;/p> &lt;p>My company uses &lt;a href="http://www.perforce.com/">Perforce&lt;/a> for source control. It works pretty well (although there is no shell integration and the Visual Studio integration is a bit flaky.)&lt;/p> &lt;p>I have my own projects on the side that I'd like to managed with source control. These are both code projects and non-code (poetry, screen plays, other writing) projects. Like &lt;a href="http://work.j832.com/2007/12/dreamhost-rocks.html">I said&lt;/a>, anything that I want backed-up, synced and versioned.&lt;/p> &lt;p>If you're like me, you share a set of conflicting tendencies.&lt;/p> &lt;ul> &lt;li>First, a tendency to have many machines that you work on.&lt;/li> &lt;li>Second, a tendency to be paranoid about keeping important data backed-up and protected with good redundancy.&lt;/li> &lt;li>Third, a tendency to hate redundancy! This goes along with &lt;a href="http://work.j832.com/2007/12/in-search-of-dry-spot.html">SPOT&lt;/a>. I hate when things get out of sync. I hate having things spread all over a bunch of machines.&lt;/li> &lt;/ul> &lt;p>Using a source control system helps a lot with this (especially if you're dealing with text-based data formats).&lt;/p> &lt;p>In the world of OSS, &lt;a href="http://en.wikipedia.org/wiki/Subversion_(software)">Subversion&lt;/a> (SVN) is a big player in source management. It's supported by &lt;a href="http://sourceforge.net/">SourceForge&lt;/a>. It's used by &lt;a href="http://subversion.tigris.org/testimonials.html#open-source-projects-using-svn">a mountain&lt;/a> of OSS projects. And (drum roll) it has an amazing Windows shell extension: &lt;a href="http://tortoisesvn.tigris.org/">Tortoise&lt;/a>.&lt;/p> &lt;ul> &lt;li>Step one: &lt;a href="http://tortoisesvn.net/downloads">install&lt;/a>.&lt;/li> &lt;li>Step two: make directory somewhere on your machine.&lt;/li> &lt;li>Step three: right-click and pick &amp;quot;SVN Checkout...&amp;quot;&lt;/li> &lt;li>Step four: type in the URL of a &lt;a href="http://j832.com/PublicSoftware/">public SVN repository&lt;/a>. There are many out there. Check the list above.&lt;/li> &lt;li>Step five: laugh at how easy it all is.&lt;/li> &lt;/ul> &lt;p>Tortoise supports the creation of patches. Renaming and branching. It even has great shell indicators so you know what's checked-in and what's pending check-in. (It works great on XP. So-so on Vista.)&lt;/p> &lt;p>Take a look at &lt;a href="http://tortoisesvn.tigris.org/">TortoiseSVN&lt;/a>.&lt;/p> &lt;p>If you're looking for hosting for your SVN repository, check out &lt;a href="http://work.j832.com/2007/12/dreamhost-rocks.html">DreamHost&lt;/a>.&lt;/p> &lt;p>Happy Hacking...and don't forget to build an test before you check-in. :-)&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term="SVN"/>
    <category term="interesting"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">DreamHost Rocks!</title>
    <link href="https://kevmoo.com/2007/12/dreamhost-rocks.html" rel="alternate" type="text/html" title="DreamHost Rocks!"/>
    <published>2007-12-09T00:05:00.001Z</published>
    <updated>2007-12-09T00:05:00.001Z</updated>
    <id>https://kevmoo.com/2007/12/dreamhost-rocks.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/12/dreamhost-rocks.html">&lt;p align="center">&lt;a href="http://www.dreamhost.com/r.cgi?368099">&lt;img src="http://j832.com/workBlogFiles/2007-12-08_DreamHostLogo.png" />&lt;/a> &lt;/p> &lt;p>I've been all over the map with hosting services. Each has it's own cool features and things that are annoying.&lt;/p> &lt;p>I've finally found one that (almost) has it all: &lt;a href="http://www.dreamhost.com/r.cgi?368099">DreamHost&lt;/a>.&lt;/p> &lt;p>For $10 a month (paid yearly):&lt;/p> &lt;ul> &lt;li>5120 &lt;strong>GB &lt;/strong>per month bandwidth. No, that is not a miss-type. Put another way: 5.120 &lt;strong>TB&lt;/strong> a month. (Now, being realistic, the box it's hosted on would probably melt before you hit that mark. It's almost like offering 50,000 minutes on a cell phone plan when there's only 44,640 minutes in a month. But at least you won't get charged for a &lt;a href="http://digg.com">Digg&lt;/a> hit or something.) &lt;/li> &lt;li>500 &lt;strong>GB&lt;/strong> of storage. Again, not a typo. 0.5 &lt;strong>TB&lt;/strong>. &lt;/li> &lt;li>As many domains as you want. You have to buy the domain names, but you can host 'em all on one account. &lt;/li> &lt;li>As many MySQL databases as you want. Size comes out of your 500 GB of storage so make 'em as big as you want. &lt;/li> &lt;li>Shell access. We're talkin' SSH. (Well, if I could figure out the damn certificate thingy.) I'm using 'ln -s' to create symbolic links for the first time in 6 years. Reminds me of &lt;a href="http://www.iastate.edu/">college&lt;/a>... &lt;/li> &lt;li>The deal-maker: &lt;a href="http://subversion.tigris.org/">SVN&lt;/a>. For those that don't mind (or prefer) OSS source control, this is it. I use it for all of my code and personal writing--all things I want to backup, sync reliably across machines, and keep version history on. I'll post later on my love of &lt;a href="http://tortoisesvn.tigris.org/">Tortoise&lt;/a>. &lt;/li> &lt;li>Oh, and they're &lt;a href="http://www.dreamhost.com/r.cgi?368099/green.cgi?j832.com">carbon neutral&lt;/a>. It's almost silly.&lt;/li> &lt;/ul> &lt;p>I said almost above. What's the catch?&lt;/p> &lt;p>Well, there's not a huge number of easy-to-install software packages. They don't use &lt;a href="http://www.cpanel.net/index.html">cPanel&lt;/a>/&lt;a href="http://netenberg.com/fantastico.php">Fantastico&lt;/a> like a lot of Linux hosting shops. The interface they do provide is very clean and one can manually install most things, but it's kinda nice to do a click-and-install for &lt;a href="http://drupal.org/">Drupal&lt;/a>.&lt;/p> &lt;p>That's my only nit, actually. Everything is super fast. I'm super happy.&lt;/p> &lt;p>&lt;a href="http://www.dreamhost.com/r.cgi?368099">Check 'em out&lt;/a>.&lt;/p> &lt;p>&lt;em>But Kevin, this is a Linux hosting package. Where's the Windows Server 2008 package?&lt;/em>&lt;/p> &lt;p>Sigh. The world is so much larger than the Microsoft stack of technologies. I love VS as much as anyone, but getting a broad skill set is important, right? Plus the OSS web community is insanely strong. The content, energy and enthusiasm are amazing.&lt;/p> &lt;p>&lt;em>Full disclosure: Yes, the links provided are for a referral program. Yes, I get a kick-back if you sign-up. No, I would never pitch anything just for the kick-back.&lt;/em>&lt;/p> &lt;p>&lt;em>I've had plenty of services offer kick-backs that I blinked at--that I never felt strongly about. This is proof I have no subtext. These guys are that good.&lt;/em>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term="internet"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">In search of DRY SPOT</title>
    <link href="https://kevmoo.com/2007/12/in-search-of-dry-spot.html" rel="alternate" type="text/html" title="In search of DRY SPOT"/>
    <published>2007-12-04T10:06:00.001Z</published>
    <updated>2007-12-04T10:06:00.001Z</updated>
    <id>https://kevmoo.com/2007/12/in-search-of-dry-spot.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/12/in-search-of-dry-spot.html">&lt;p>I realized there is a concept I come back to often in a lot of my software implementation and in a lot of my discussions. It goes by two common acronyms that are pretty much interchangeable.&lt;/p> &lt;p>&lt;strong>DRY&lt;/strong>: Don't Repeat Yourself. &lt;br />&lt;strong>SPOT&lt;/strong>: Single Point of Truth.&lt;/p> &lt;p>&lt;a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY&lt;/a> is articulated in the book &lt;a href="http://www.pragprog.com/">&lt;em>The Pragmatic Programmer&lt;/em>&lt;/a>, although &lt;a href="http://www.catb.org/~esr/">Eric Raymond&lt;/a> likes to &lt;a href="http://www.faqs.org/docs/artu/ch04s02.html">call it SPOT&lt;/a>.&lt;/p> &lt;p>How does this exist in our world of C# and .NET? Well, every time you define a &lt;strong>private const string&lt;/strong> or &lt;strong>private const int&lt;/strong> instead of sprinkling magic values all over your code, every time you generate documentation from your source files, every time you develop a clever data structure to represent both the execution and the description of a process, you are practicing &lt;strong>SPOT&lt;/strong>.&lt;/p> &lt;p>Quite often, my SPOT will live in a static class Util that I create for almost all of my software projects. If I have one way to handle errors, one pay to deal with collection, one way to handle user input, centralizing it makes bug fixing so much easier. It actually minimizes bugs in a lot of cases, which minimizes the need to fix them.&lt;/p> &lt;p>If you haven't heard of these concepts, they are great to add to your software vocabulary.&lt;/p> &lt;p>For many, I'm sure the idea has always been floating around, just without a good name.&lt;/p> &lt;p>Now you have a good shorthand when you are mocking someone else's code.&lt;/p> &lt;p>Happy hacking!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="interesting"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">Reasons to subclass: Great, Good, Okay</title>
    <link href="https://kevmoo.com/2007/11/reasons-to-subclass-great-good-okay.html" rel="alternate" type="text/html" title="Reasons to subclass: Great, Good, Okay"/>
    <published>2007-11-22T02:11:00.001Z</published>
    <updated>2007-11-22T02:11:00.001Z</updated>
    <id>https://kevmoo.com/2007/11/reasons-to-subclass-great-good-okay.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/11/reasons-to-subclass-great-good-okay.html">&lt;p>&lt;em>Shout-out to brilliant developer (and my co-worker) &lt;/em>&lt;a href="http://dpotter.net/Technical/">&lt;em>David Potter&lt;/em>&lt;/a>&lt;em>, who--through hours of discussion--helped me arrive at this 'thought'.&lt;/em>&lt;/p> &lt;p>&lt;em>FYI: I use a lot of WPF examples in here. Apologies to the non-WPF devs.&lt;/em>&lt;/p> &lt;p>Back in June, I wrote a post titled: &lt;a href="http://work.j832.com/2007/06/don-subclass-panel-unless-you-making.html">Don't subclass a Panel, unless you're making a Panel&lt;/a>.&lt;/p> &lt;p>In that post, I outlined the 'great' reason to use subclassing (read, inheritance):&lt;/p> &lt;blockquote> &lt;p>I read a great internal paper at MS once--written by one of those brilliant old-guard devs with decades of perspective. The point the author pushed: use inheritance only for polymorphism. Translated: when making MyGrid, only subclass Grid if you mean for people to treat your new MyGrid just like another Grid. Code (and a user, for the most part) that deals with Grid should be able to &amp;quot;deal&amp;quot; with MyGrid without any issues.&lt;/p> &lt;/blockquote> &lt;p>I use a strong word there: only.&lt;/p> &lt;p>Now with time and experience comes perspective.&lt;/p> &lt;p>I'm going to make this philosophy a bit more nuanced by introducing categories of subclassing: great, good, and okay.&lt;/p> &lt;p>My argument: there are times to use each, but the further you get away from 'great', the more trouble you can get in and the more careful and thoughtful you should be.&lt;/p> &lt;h3>Great subclassing: for polymorphism.&lt;/h3> &lt;p>Examples here: Stream (from mscorlib) and UIElement (from WPF).&lt;/p> &lt;p>Stream is worthless by itself. It's meant to be the base class for something else. But there are innumerable features of the CLR that deal with Stream generically, without much concern for any subclass.&lt;/p> &lt;p>UIElement is similar. Basically worthless by itself. Designed to be a baseclass. But things like WPF layout (Measure/Arrange) deal explicitly with UIElement, ignoring any details of any subclass.&lt;/p> &lt;p>If you create a Foo class and have other classes that take a Foo in a constructor or method argument, even though Foo is abstract or rarely used by itself you are playing in the 'great' end of the subclassing spectrum.&lt;/p> &lt;h3>Good subclassing: cognitive simplicity&lt;/h3> &lt;p>If 'great' subclassing is for software components, 'good' subclassing is for humans.&lt;/p> &lt;p>ContentControl (WPF) is a pretty good example. I can't think of any constructor or method that takes ContentControl as a parameter. &lt;/p> &lt;p>We could imagine Button and Label and ScrollViewer all re-exposing the common properties (Content, ContentTemplate, ContentTemplateSelector) without any changes in functionality.&lt;/p> &lt;p>But! It's really nice that users can look at Label and say &amp;quot;oh, that's a ContentControl&amp;quot; and immediately have a valid mental model of how to use it.&lt;/p> &lt;p>The baseclass, in this respect, provides a grouping paradigm for a user to understand classes of types.&lt;/p> &lt;p>While this is a nice feature, it has its issues.&lt;/p> &lt;p>ButtonBase is a good example.&lt;/p> &lt;p>ButtonBase is the 'clickable' widget in WPF.&lt;/p> &lt;p>Almost everything that is clickable subclasses ButtonBase.&lt;/p> &lt;p>ButtonBase subclasses ContentControl.&lt;/p> &lt;p>ContentControl is the 'content' widget in WPF.&lt;/p> &lt;p>Almost everything in WPF that has content is a content control. Well, almost. ContentPresenter has the same properties that ContentControl has regarding content (Content, ContentTemplate, ContentTemplateSelector).&lt;/p> &lt;p>But they don't share a baseclass. Why?&lt;/p> &lt;p>Well, because ContentControl is a Control.&lt;/p> &lt;p>Control is the 'template-able' widget in WPF. It lets you swap out the chrome.&lt;/p> &lt;p>ContentPresenter doesn't let you swap out the chrome, just the template for the data.&lt;/p> &lt;p>So, we could really imagine three separate classes, all of which derive from FrameworkElement.&lt;/p> &lt;ul> &lt;li>ClickElement: exposes the click properties/methods/events. &lt;/li> &lt;li>ContentElement: exposes the content properties/methods/events (Yes, this class name already exists for text stuff. Play along...) &lt;/li> &lt;li>TemplateElement: exposes the template properties/methods/events (this is what Control is now). &lt;/li> &lt;/ul> &lt;p>The fact that ButtonBase subclasses in a specific order is kinda arbitrary.&lt;/p> &lt;p>One could imagine wanting a template-able, click-able element that doesn't have content.&lt;/p> &lt;p>One could imagine wanting a click-able, element that holds content that isn't template-able.&lt;/p> &lt;p>Single inheritance forces framework authors to choose. This can be annoying if you want a re-mix of the available features.&lt;/p> &lt;p>A great example of this: TransitionPresenter (from the &lt;a href="http://j832.com/BagOTricks/">bag-o-tricks&lt;/a>).&lt;/p> &lt;p>It has all of the content properties, but it's not a ContentPresenter or a ContentControl. (The way it does its visual tree is different than both of those controls.)&lt;/p> &lt;p>It turns out to be impossible to subclass ContentPresenter and it's confusing to subclass ContentControl (because TransitionPresenter doesn't use a ControlTemplate).&lt;/p> &lt;p>A really smart dev who was doing code clean-up actually changed the baseclass from FrameworkElement to ContentControl, thinking he was making things simpler.&lt;/p> &lt;p>This is bad! A user will then expect to be able to use the Template property to change the chrome. This is the same problem with making MyGrid from Grid unless you want people treating it like any other Grid.&lt;/p> &lt;p>This trap is usually because of the third type...&lt;/p> &lt;h3>Okay subclassing: tactical code reuse&lt;/h3> &lt;p>If you have 15 classes that all have a Foo, Bar, and Baz property, having a common baseclass just saves code. Less to document. Less to test. Less to mess up.&lt;/p> &lt;p>Fine.&lt;/p> &lt;p>But if sharing some common state is your only goal, just make sure you acknowledge (along with the rest of your team) that is why you're doing it. Put it in the code comments of the class.&lt;/p> &lt;p>In some respects this is less dangerous than the 'good' reason to subclass because the FooBarBaz class probably doesn't have much meaning or use beyond your tactical reasons. As soon as it does, though, you can fall into the MyGrid trap.&lt;/p> &lt;h3>In closing&lt;/h3> &lt;p>This was a really long write-up.&lt;/p> &lt;p>I guess my final advice is be careful.&lt;/p> &lt;p>As with anything in life, if you try to be clever for clever's sake, you'll get burned.&lt;/p> &lt;p>If you try to use every feature of a language or a framework just to add spice to your afternoon of coding, you'll get burned.&lt;/p> &lt;p>As I discussed in my &lt;a href="http://work.j832.com/2007/11/importance-of-patterns-and-guidelines.html">post about patters and guidelines&lt;/a>, always try to understand the implications of the tools/tricks you use when coding.&lt;/p> &lt;p>And that's all I have to say about that.&lt;/p> &lt;p>Happy hacking.&lt;/p> &lt;p>&lt;em>Did you find this interesting? Let me know. I'd hate to think I was riffing all this out just to make my tendinitis worse.&lt;/em>&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
  </entry>
  <entry>
    <title type="html">.NET 3.5 is here; IDataErrorInfo support in WPF seems to be popular</title>
    <link href="https://kevmoo.com/2007/11/net-35-is-here-idataerrorinfo-support.html" rel="alternate" type="text/html" title=".NET 3.5 is here; IDataErrorInfo support in WPF seems to be popular"/>
    <published>2007-11-21T07:41:00.001Z</published>
    <updated>2007-11-21T07:41:00.001Z</updated>
    <id>https://kevmoo.com/2007/11/net-35-is-here-idataerrorinfo-support.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/11/net-35-is-here-idataerrorinfo-support.html">&lt;p>One of the things that sucks about being on the outside is the surprises.&lt;/p> &lt;p>I was blown off my chair when I heard &lt;a href="http://blogs.msdn.com/somasegar/archive/2007/11/19/visual-studio-2008-and-net-framework-3-5-shipped.aspx">.NET 3.5 released yesterday&lt;/a>.&lt;/p> &lt;p>I talked about some of the &lt;a href="http://work.j832.com/2007/08/video-what-new-in-wpf-for-2008.html">new stuff in August&lt;/a>.&lt;/p> &lt;p>My favorite feature (that I designed, at least) was &lt;a href="http://blogs.msdn.com/wpfsdk/archive/2007/10/02/data-validation-in-3-5.aspx">IDataErrorInfo support&lt;/a> in WPF data binding.&lt;/p> &lt;p>&lt;a href="http://www.lhotka.net/weblog/CSLANET35NoMoreWPFValidatorControl.aspx">Rocky likes it&lt;/a>.&lt;/p> &lt;p>&lt;a href="http://wpfwonderland.wordpress.com/2007/10/10/better-wpf-binding-in-net-35/">Walk likes it&lt;/a>.&lt;/p> &lt;p>&lt;a href="http://www.codegod.de/WebAppCodeGod/wpf-idataerrorinfo-and-databinding-AID416.aspx">Even God likes it&lt;/a>. ;-)&lt;/p> &lt;p>You really should be thanking &lt;a href="http://forums.microsoft.com/MSDN/User/Profile.aspx?UserID=75710&amp;amp;SiteID=1">Dr. Bent&lt;/a>, who made it.&lt;/p> &lt;p>And &lt;a href="http://www.beacosta.com/blog/">Bea&lt;/a>, who made sure it worked.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="Microsoft"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">Going beyond Monitor.Enter/Exit (C# lock) with LockHelper</title>
    <link href="https://kevmoo.com/2007/11/going-beyond-monitorenterexit-c-lock.html" rel="alternate" type="text/html" title="Going beyond Monitor.Enter/Exit (C# lock) with LockHelper"/>
    <published>2007-11-14T05:13:00.001Z</published>
    <updated>2007-11-14T05:13:00.001Z</updated>
    <id>https://kevmoo.com/2007/11/going-beyond-monitorenterexit-c-lock.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/11/going-beyond-monitorenterexit-c-lock.html">&lt;p>&lt;em>Sample code: &lt;/em>&lt;a href="http://j832.com/workBlogFiles/LockHelper.cs">&lt;strong>&lt;em>LockHelper.cs&lt;/em>&lt;/strong>&lt;/a>&lt;strong>&lt;em> [6KB]&lt;/em>&lt;/strong>&lt;/p> &lt;p>Debugging threading issues is painful.&lt;/p> &lt;p>Really painful.&lt;/p> &lt;p>One of the most painful problems: dealing with deadlocks--waiting forever on a Monitor.Enter (C# lock) and not knowing which thread already has the lock.&lt;/p> &lt;p>I tried to &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2235119&amp;amp;SiteID=1">dig in on this&lt;/a> on the &lt;a href="http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=39&amp;amp;SiteID=1">CLR Base Class Library Forum&lt;/a>. I was hopeful, since Java has a method [Thread.holdsLock(obj)] that returns the holder of the current lock&lt;/p> &lt;p>Sadly, .NET lacks this functionality.&lt;/p> &lt;p>Enter a can-do attitude: why not build it myself.&lt;/p> &lt;p>Enter LockHelper.&lt;/p> &lt;p>Goals:&lt;/p> &lt;ul> &lt;li>Identical semantics to Monitor.Enter/Exit &lt;/li> &lt;li>Enable other Monitor features (Pulse, Wait) &lt;/li> &lt;li>Close to identical syntax to C# lock &lt;/li> &lt;li>Ability to know, given an instance of LockHelper, the current owning thread &lt;/li> &lt;li>Other conveniences (CheckAccess and VerifyAccess) &lt;/li> &lt;/ul> &lt;p>Wrapping Monitor.Enter/Exit isn't that hard. As you see with the implementation, it's pretty easy to leverage IDisposable + the C# &lt;strong>using&lt;/strong> statement to get syntax that is close to &lt;strong>lock&lt;/strong>.&lt;/p> &lt;p>Instead of:&lt;/p> &lt;blockquote> &lt;p>public void Foo() &lt;br />{ &lt;br />&amp;#xA0;&amp;#xA0;&amp;#xA0; lock(m_lockObject) &lt;br />&amp;#xA0;&amp;#xA0;&amp;#xA0; { &lt;br />&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; //do stuff &lt;br />&amp;#xA0;&amp;#xA0;&amp;#xA0; } &lt;br />} &lt;br /> &lt;br />private readonly object m_lockObject = new object();&lt;/p> &lt;/blockquote> &lt;p>Do this:&lt;/p> &lt;blockquote> &lt;p>public void Foo() &lt;br />{ &lt;br />&amp;#xA0;&amp;#xA0;&amp;#xA0; using(m_lockObject.GetLock()) &lt;br />&amp;#xA0;&amp;#xA0;&amp;#xA0; { &lt;br />&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; //do stuff &lt;br />&amp;#xA0;&amp;#xA0;&amp;#xA0; } &lt;br />} &lt;br /> &lt;br />private readonly LockHelper m_lockObject = new LockHelper(&amp;quot;foo&amp;quot;);&lt;/p> &lt;/blockquote> &lt;p>&lt;strong>GetLock()&lt;/strong> returns a private class that implements &lt;strong>IDisposable&lt;/strong>. The &lt;strong>using&lt;/strong> block has identical try/finally semantics to the &lt;strong>lock&lt;/strong> keyword. (See &lt;a href="http://msdn2.microsoft.com/en-us/library/ms173179(VS.80).aspx">this article&lt;/a> in the C# Programming Guide for details.)&lt;/p> &lt;p>I had to be religious about storing away &lt;strong>Thread.Name&lt;/strong> for the current thread at all times. While debugging, I found that VS was often unable to evaluate the property of the owning thread.&lt;/p> &lt;p>So now I have enough plumbing to figure out which thread has a lock on my lock object. Cool.&lt;/p> &lt;p>What else?&lt;/p> &lt;p>Exposing &lt;strong>Pulse&lt;/strong> and &lt;strong>Wait&lt;/strong> was pretty easy. Beyond these basics, I stole the CheckAccess/VerifyAccess ideas from WPF.&lt;/p> &lt;p>Often times one will have private helpers in a class that access/modify the state of a class. Often times these methods (should) run under the assumption that they were called in the context of a lock.&lt;/p> &lt;p>The simple way around this is to re-lock the object inside the helper method, but this can be a source of deadlocks and really doesn't help maintain the implementation contract.&lt;/p> &lt;p>What one wants: a way to assert that the calling thread owns a lock.&lt;/p> &lt;p>Done!&lt;/p> &lt;p>&lt;strong>CheckAccess&lt;/strong> returns &lt;strong>true&lt;/strong> if the current thread has the lock. Otherwise, &lt;strong>false&lt;/strong>.&lt;/p> &lt;p>&lt;strong>VerifyAccess&lt;/strong> goes a step further and throws an exception if the calling thread doesn't own the lock.&lt;/p> &lt;p>Pretty cool, huh?&lt;/p> &lt;p>&lt;em>Note: I was not on the CLR team at Microsoft. I was not a developer at Microsoft, just a lowly PM. I'm pretty confident this works. At least I haven't hit any issues with it. Please be careful throwing this in your own projects. This is certainly out of the realm of advertised best-practices from MS.&lt;/em>&lt;/p> &lt;p>It works for me, though.&lt;/p> &lt;p>Let me know what you think.&lt;/p> &lt;p>Happy hacking!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="threading"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">The event pattern in C# and funny coincidence</title>
    <link href="https://kevmoo.com/2007/11/event-pattern-in-c-and-funny.html" rel="alternate" type="text/html" title="The event pattern in C# and funny coincidence"/>
    <published>2007-11-03T19:59:00.001Z</published>
    <updated>2007-11-03T19:59:00.001Z</updated>
    <id>https://kevmoo.com/2007/11/event-pattern-in-c-and-funny.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/11/event-pattern-in-c-and-funny.html">&lt;p>On Thursday, I wrote about &lt;a href="http://work.j832.com/2007/11/importance-of-patterns-and-guidelines.html">the importance of software patterns&lt;/a>, specifically the event pattern in C#.&lt;/p> &lt;p>That very afternoon I was going through some code written by a co-worker that leveraged this pattern.&lt;/p> &lt;p>To keep things simple, let's imagine it was like this.&lt;/p>&lt;pre>public event EventHandler&lt;messageeventargs> NewMessage;&lt;br />&lt;br />protected virtual void OnNewMessage(MessageEventArgs args)&lt;br />{&lt;br /> EventHandler&lt;messageeventargs> handler = NewMessage;&lt;br /> if(handler != null)&lt;br /> {&lt;br /> handler(this,args);&lt;br /> }&lt;br />}&lt;br />&lt;br />protected virtual void OnNewMessage(string message)&lt;br />{&lt;br /> EventHandler&lt;messageeventargs> handler = NewMessage;&lt;br /> if(handler != null)&lt;br /> {&lt;br /> handler(this,new MessageEventArgs(message));&lt;br /> }&lt;br />}&lt;/pre>&lt;p>Pretty straight forward, right? See the problem?&lt;/p>&lt;p>This gets to the core of why understanding a pattern deeply is important. The pattern of having a protected virtual &lt;em>OnFoo&lt;/em> method for your &lt;em>Foo&lt;/em> event is to ensure that a subclass can peek at the event before it's fired. The implementation above will require the subclass to not only override both methods, but to understand that she &lt;strong>must&lt;/strong> override both methods to make sure all raised events are captured.&lt;/p>&lt;p>This is making the job of the subclass writer much harder and likely more error prone.&lt;/p>&lt;p>I'm not saying one should get rid of the helper method. It's fine. It just needs to be tweaked.&lt;/p>&lt;pre>protected void OnNewMessage(string message)&lt;br />{&lt;br /> OnNewMessage(new MessageEventArgs(message));&lt;br />}&lt;/pre>&lt;p>First, get rid of the virtual flag. This should be callable from a subclass, but there should only be one method to override.&lt;/p>&lt;p>Second, call the 'real' virtual method from the helper. This ensures that anyone who overrides OnNewMessage will get the desired result.&lt;/p>&lt;p>A clever developer might not like this, because she wants to avoid allocating the EventArgs unless there actually are handlers to call. Clever optimization, but it breaks the pattern.&lt;/p>&lt;p>Make sense?&lt;/p>&lt;p>Happy hacking.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">Former MS co-workers done well: Amar &amp; Robby [Videos]</title>
    <link href="https://kevmoo.com/2007/11/former-ms-co-workers-done-well-amar.html" rel="alternate" type="text/html" title="Former MS co-workers done well: Amar &amp; Robby [Videos]"/>
    <published>2007-11-03T02:55:00.001Z</published>
    <updated>2007-11-03T02:55:00.001Z</updated>
    <id>https://kevmoo.com/2007/11/former-ms-co-workers-done-well-amar.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/11/former-ms-co-workers-done-well-amar.html">&lt;p>Amar was my GPM (manager's manager) in the Longhorn days. (Yes, back when Vista had a lot more managed code and was going to change the world.)&lt;/p> &lt;p>He's one of the stars in the &lt;a href="http://www.youtube.com/watch?v=9KOEbAZJTTk">intro video&lt;/a> for Google's &lt;a href="http://code.google.com/apis/opensocial/">openSocial&lt;/a>. (Look for the Indian guy in the Brazilian soccer jersey.)&lt;/p> &lt;p>I can't wait to start hacking on this stuff.&lt;/p> &lt;p>The last time you may have &lt;a href="http://channel9.msdn.com/Showpost.aspx?postid=80533">seen him on video&lt;/a> was when he was GPM of the RSS team at Microsoft. (Interviewed by &lt;a href="http://scobleizer.com/">Scoble&lt;/a>, none the less. A lot can change in three years, huh?)&lt;/p> &lt;p>&lt;a href="http://notstatic.com/">Robby&lt;/a> is &lt;a href="http://channel9.msdn.com/Showpost.aspx?postid=353035">on channel9 again&lt;/a>, chatting the goodness of the 'integrator' role in WPF/Silverlight development. He's a main guy at &lt;a href="http://www.identitymine.com/">identity mine&lt;/a> these days.&lt;/p> &lt;p>Robby and I worked together on the WPF team in the v1 days. The last time you may have &lt;a href="http://channel9.msdn.com/Showpost.aspx?postid=222817">seen him on channel9&lt;/a> was with yours truly. Although I'd rather forget the topic. :-)&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="Microsoft"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">The importance of patterns and guidelines in software development</title>
    <link href="https://kevmoo.com/2007/11/importance-of-patterns-and-guidelines.html" rel="alternate" type="text/html" title="The importance of patterns and guidelines in software development"/>
    <published>2007-11-01T16:39:00.001Z</published>
    <updated>2007-11-01T16:39:00.001Z</updated>
    <id>https://kevmoo.com/2007/11/importance-of-patterns-and-guidelines.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/11/importance-of-patterns-and-guidelines.html">&lt;em>I've been pulling my hair out on IDisposable, Dispose() and protected virtual Dispose(bool disposing) the last 24 hours.&lt;/em>&lt;/p> &lt;p>&lt;em>I think I've figured it out. Finally!&lt;/em>&lt;br />&lt;br />&lt;em>I started writing a whole entry on it, but then I realized there is a whole prequel that needs to be written first. So...&lt;/em>&lt;br />&lt;br />We're talking about patterns and guidelines for software here, my friends. They exist to ensure consistent behavior and therefor consistent expectations. This is for direct users of your classes and also those who subclass your classes. The problem with patterns, though, is that they become customs. We do them without asking why we do them. Then we start questioning why we do them if we don't fully understand. We might even start tweaking them if they get cumbersome, which can cause unexpected consequences later on.&lt;br />&lt;br />So it's always good to understand why (at least at some level) we implement a pattern.&lt;br />&lt;br />My favorite example: events.&lt;br />&lt;br />So you add a public event to your class:&lt;br />&lt;pre>public event EventHandler Updated;&lt;/pre>&lt;br />And because you were told to, you implement:&lt;br />&lt;pre>protected virtual void OnUpdated(EventArgs args)&lt;br />{&lt;br /> EventHandler handler = Updated;&lt;br /> if(handler != null)&lt;br /> {&lt;br /> handler(this, args);&lt;br /> }&lt;br />}&lt;/pre>&lt;br />Like a robot. Do yo know why? Really?&lt;br />&lt;br />&lt;strong>Q: &lt;/strong>Why protected?&lt;br />&lt;strong>A: &lt;/strong>So a subclass can raise your event. The C# compiler is doing work behind the scenes. You don't see that the event really has both public and private surface area. Only the class that defines the event can raise it directly.&lt;br />&lt;br />&lt;strong>Q: &lt;/strong>Why virtual?&lt;br />&lt;strong>A: &lt;/strong>Because a subclass might want to intercept the event and take some action on it. It's cumbersome for a subclass to register an event listener on itself.&lt;br />&lt;br />&lt;strong>Q: &lt;/strong>Why create the 'handler' field in the method? Seems like a waste of a variable.&lt;br />&lt;strong>A: &lt;/strong>Threading. To ensure that between the check for null and the call, the event hasn't been unregistered. (But I don't have multithreaded stuff in my library, you say. Right. But might you tomorrow? Might a subclass? Might a direct user of your library?)&lt;br />&lt;br />&lt;strong>Q: &lt;/strong>Why not simplify the method signature to take no parameters? EventArgs is empty, right?. I should just handle that in the method, right?&lt;br />&lt;strong>A: &lt;/strong>No. Some subclasses might want to pass a different EventArgs to the method. They might want to pass more information via FooEventArgs. If you lock down the method signature, you are locking them out of extensibility. (Working on WPF, we actually got a bug about this with OnCollectionChanged in ObservableCollection).&lt;br />&lt;br />See! Such a simple pattern, yet so many nuances!&lt;br />&lt;br />You might do this work even if you haven't imagined any subclasses. You are doing it just in case.&lt;br />&lt;br />In fact, the only good reason not to do this work is if you seal your class. Even then, what if the class gets unsealed in the future? Will you remember re-implement the pattern the right way?&lt;br />&lt;br />Better to do it correctly from the start.&lt;br />&lt;br />I need to get some work done now. In the next day or two, I'll post my discoveries on IDisposable.&lt;br />&lt;br />In the mean time, ask yourself: am I cutting corners with patterns? Am I implementing patters which I don't fully understand?&lt;br />&lt;br />Hmm...&lt;br />&lt;br />Happy hacking.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term=".NET"/>
    <category term="C#"/>
  </entry>
  <entry>
    <title type="html">Threading fun: Monitor.Wait, Monitor.Pulse</title>
    <link href="https://kevmoo.com/2007/10/threading-fun-monitorwait-monitorpulse.html" rel="alternate" type="text/html" title="Threading fun: Monitor.Wait, Monitor.Pulse"/>
    <published>2007-10-26T21:02:00.001Z</published>
    <updated>2007-10-26T21:02:00.001Z</updated>
    <id>https://kevmoo.com/2007/10/threading-fun-monitorwait-monitorpulse.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/10/threading-fun-monitorwait-monitorpulse.html">&lt;p>Threading is pretty scary. An solid grasp of threading, as a brilliant dev lead at Microsoft once told me, was one thing that consistently separated the &amp;quot;men/women from the boys/girls&amp;quot; in the engineering discipline.&lt;/p> &lt;p>Here's my attempt to sound adult. (Forgive me if my voice cracks.)&lt;/p> &lt;p>&lt;em>The Scenario&lt;/em>: You have a bunch of threads running around doing work--in this case, adding random numbers to a collection. You have another thread with the aggregation job: take all of the numbers in the collection, add them to a running total, and clear out the collection.&lt;/p> &lt;p>This is a simplification of a problem I was faced with on my current gig: handle multiple &amp;quot;users&amp;quot; via separate WCF connections (coming in on separate threads). Aggregate their work requests and process them on a 'worker' thread. All while staying super responsive.&lt;/p> &lt;p>So you always have the one thread that's waiting around for work. How does it wait? The simple answer would be a while-true loop that's always polling.&lt;/p> &lt;p>That'll peg a thread pretty quick while doing a bunch of unneeded locking of your synchronization object. One could add some sleep statements to the loop to minimize the impact, but that feels like a bandage.&lt;/p> &lt;p>What one wants: a way to have the processing thread &amp;quot;wait&amp;quot; to until there actually is work to do.&lt;/p> &lt;p>Enter &lt;strong>Monitor.Wait&lt;/strong> and &lt;strong>Monitor.Pulse&lt;/strong>.&lt;/p> &lt;p>Mike Woodring &lt;a href="http://www.pluralsight.com/blogs/mike/archive/2004/12/13/3905.aspx">does a pretty good job of explaining this&lt;/a> (with a very funny title/analogy), but I really wanted a fully baked and un-contrived code sample.&lt;/p> &lt;p>So here it is. In exactly 100 lines of code.&lt;/p> &lt;p>&lt;a href="http://j832.com/workBlogFiles/MonitorWaitPulseFun.cs">&lt;strong>MonitorWaitPulseFun.cs&lt;/strong>&lt;/a>&lt;strong> [3KB]&lt;/strong>&lt;/p> &lt;p>&lt;strong>Wait&lt;/strong> and &lt;strong>Pulse&lt;/strong> both must be called in the context of a &lt;strong>lock&lt;/strong> (&lt;strong>Monitor.Enter/Exit&lt;/strong>) for the provided object.&lt;/p> &lt;p>&lt;strong>Wait&lt;/strong> [Line 58] basically gives up the &lt;strong>lock&lt;/strong> (and allows other code blocked by the lock to run) and waits until &lt;strong>Pulse&lt;/strong> [Line 43] is called on another thread. The 'wait' thread then gets back in line for the lock and continues execution from where it left off.&lt;/p> &lt;p>It's a bit weird to accept that a lock for a given object is temporarily given up between the curly braces, but that's what happens.&lt;/p> &lt;p>The only hiccup I ran into was realizing that one really needs to be careful to make sure pulse is called enough, especially when shutting down. 'Wait' will wait forever if it doesn't get kicked.&lt;/p> &lt;p>&lt;em>A note&lt;/em>: I go this all working with a &lt;strong>WaitHandle&lt;/strong> initially (specifically, &lt;strong>AutoResetEvent&lt;/strong>), but I realized it was a lot more involved and (after some research) a lot heavier than I needed. WaitHandle actually wraps some Win32 stuff that goes way beyond what I need for this scenario.&lt;/p> &lt;p>Anyway, here's my foray into non-WPF technical blogging.&lt;/p> &lt;p>Interesting? Helpful?&lt;/p> &lt;p>Happy hacking...&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term="threading"/>
  </entry>
  <entry>
    <title type="html">Hello MSDN Mag Readers</title>
    <link href="https://kevmoo.com/2007/10/hello-msdn-mag-readers.html" rel="alternate" type="text/html" title="Hello MSDN Mag Readers"/>
    <published>2007-10-17T20:20:00.001Z</published>
    <updated>2007-10-17T20:20:00.001Z</updated>
    <id>https://kevmoo.com/2007/10/hello-msdn-mag-readers.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/10/hello-msdn-mag-readers.html">&lt;p>I kinda forgot I &lt;a href="http://msdn.microsoft.com/msdnmag/issues/07/11/EndBracket/default.aspx">wrote this article&lt;/a> in August.&lt;/p> &lt;p>I guess the sudden increase in emails makes sense.&lt;/p> &lt;p>In case it got buried, &lt;a href="http://work.j832.com/2007/09/i-leaving-microsoft.html">I am no longer at Microsoft&lt;/a>, but you can still find the &lt;a href="http://j832.com/BagOTricks/">bag-o-tricks here&lt;/a>.&lt;/p> &lt;p>I've taken a pretty big break from most things WPF. If you have questions, you're best bet is the &lt;a href="http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=119&amp;amp;SiteID=1">WPF MSDN forum&lt;/a>.&lt;/p> &lt;p>Hope you enjoyed my attempt at wit and wisdom.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="Programming"/>
    <category term="MIX07"/>
    <category term="Microsoft"/>
  </entry>
  <entry>
    <title type="html">I'll avoid any reference to rats and ships</title>
    <link href="https://kevmoo.com/2007/10/i-any-reference-to-rats-and-ships.html" rel="alternate" type="text/html" title="I'll avoid any reference to rats and ships"/>
    <published>2007-10-06T01:28:00.001Z</published>
    <updated>2007-10-06T01:28:00.001Z</updated>
    <id>https://kevmoo.com/2007/10/i-any-reference-to-rats-and-ships.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/10/i-any-reference-to-rats-and-ships.html">&lt;p>On Monday, &lt;a href="http://fortes.com/">Fil&lt;/a> made a note on Facebook listing the ~10 people he knew who had left MS this year. After a couple days and a few additions from friends, it was up to 16.&lt;/p> &lt;p>Earlier today I stumbled upon &lt;a href="http://www.neopoleon.com/home/blogs/neo/archive/2007/09/30/27359.aspx">Rory's announcement&lt;/a>.&lt;/p> &lt;p>Then I discovered &lt;a href="http://blogs.msdn.com/dthorpe/archive/2007/10/05/leaving-microsoft.aspx">Danny's post&lt;/a>.&lt;/p> &lt;p>Wow.&lt;/p> &lt;p>Maybe it's just that time of year.&lt;/p> &lt;p>Maybe it's that departures are more visible these days.&lt;/p> &lt;p>To use Microsoft's favorite overloaded statement: interesting.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Microsoft"/>
    <category term="interesting"/>
  </entry>
  <entry>
    <title type="html">What I install on a new machine: Free apps</title>
    <link href="https://kevmoo.com/2007/09/what-i-install-on-new-machine-free-apps.html" rel="alternate" type="text/html" title="What I install on a new machine: Free apps"/>
    <published>2007-09-22T21:41:00.001Z</published>
    <updated>2007-09-22T21:41:00.001Z</updated>
    <id>https://kevmoo.com/2007/09/what-i-install-on-new-machine-free-apps.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/09/what-i-install-on-new-machine-free-apps.html">&lt;p>Starting the new job, you start with a new machine. I thought it would be interesting to go through my 'bag-o-tricks' as far as what I install.&lt;/p> &lt;p>These apps are free. Some are free as in beer; some are free as in speech (or as Stallman says, free as in freedom).&lt;/p> &lt;p>I'd love to know what other people have in their must-install list for a new machine. I might be missing something awesome.&lt;/p> &lt;p>&lt;strong>Windows Live Messenger &amp;amp; Writer&lt;/strong>: &lt;a title="http://get.live.com/wl/all" href="http://get.live.com/wl/all">http://get.live.com/wl/all&lt;/a>&lt;/p> &lt;p>Still going strong with two great apps. My humble requests:&lt;/p> &lt;ul> &lt;li>Messenger guys: please save my preferences on the server. I hate re-configuring tabs, welcome screen, contact grouping, sounds, etc. &lt;/li> &lt;li>Writer guys: please fix your support for images in &lt;a href="http://blogger.com">Blogger&lt;/a>. This is my only complaint. &lt;/li> &lt;/ul> &lt;p>&lt;strong>Paint .NET&lt;/strong>: &lt;a title="http://www.getpaint.net/" href="http://www.getpaint.net/">http://www.getpaint.net/&lt;/a>&lt;/p> &lt;p>I will admit to frequently lusting after a licence to Adobe Photoshop. No longer. An amazing app that just keeps getting better and keeps staying free. Awesome.&lt;/p> &lt;p>&lt;strong>.NET Reflector&lt;/strong>: &lt;a title="http://www.aisto.com/roeder/dotnet/" href="http://www.aisto.com/roeder/dotnet/">http://www.aisto.com/roeder/dotnet/&lt;/a>&lt;/p> &lt;p>If you code .NET, this gets installed before VS. Amazing. Also keeps getting better.&lt;/p> &lt;p>&lt;strong>Firefox&lt;/strong>: &lt;a title="http://www.mozilla.com/en-US/firefox/" href="http://www.mozilla.com/en-US/firefox/">http://www.mozilla.com/en-US/firefox/&lt;/a>&lt;/p> &lt;p>Yes, I'm one of those guys. &lt;br />Yes, I have friends that work on IE. &lt;br />Yes, I wish them well.&lt;/p> &lt;p>But...&lt;/p> &lt;p>I believe in open standards. The only way to protect and encourage open standards is to have many prevalent implementations of said standards.&lt;/p> &lt;p>Firefox is just better. Even when it crashes, it remembers where I was flawlessly...something IE never does. It scales web sites in a (more) rational way. The extensibility is also amazing, as I share below.&lt;/p> &lt;p>&lt;strong>Greasemonkey: &lt;/strong>&lt;a title="https://addons.mozilla.org/en-US/firefox/addon/748" href="https://addons.mozilla.org/en-US/firefox/addon/748">https://addons.mozilla.org/en-US/firefox/addon/748&lt;/a>&lt;/p> &lt;p>What a clever concept. I really only use it for one script, though. Would love to know more good ones.&lt;/p> &lt;p>&lt;strong>Google Secure Pro Greasemonkey Script:&lt;/strong> &lt;a title="http://userscripts.org/scripts/show/5951" href="http://userscripts.org/scripts/show/5951">http://userscripts.org/scripts/show/5951&lt;/a>&lt;/p> &lt;p>Later, I will go through all of the web apps and services I use, but here's a hit: I use a lot of Google stuff.&lt;/p> &lt;p>Google supports HTTPS (SSL) on most of it's properties, but not by default. You have to put http&lt;strong>s&lt;/strong>:// manually in the URL.&lt;/p> &lt;p>This script does that automatically for a whole host of Google properties. It's also extensible for any web site. (Like &lt;a href="http://sneakemail.com/">sneakemail&lt;/a>, which I'll go into in another post.)&lt;/p> &lt;p>&lt;strong>Flash Blocker&lt;/strong>: &lt;a title="http://flashblock.mozdev.org/" href="http://flashblock.mozdev.org/">http://flashblock.mozdev.org/&lt;/a>&lt;/p> &lt;p>Another great Firefox add-on. This one replaces all flash content with a little arrow. When you press it, the flash loads but not before.&lt;/p> &lt;p>Great for seeing only the content you want to see and nothing else.&lt;/p> &lt;p>&lt;strong>Sumartra PDF&lt;/strong>: &lt;a title="http://blog.kowalczyk.info/software/sumatrapdf/" href="http://blog.kowalczyk.info/software/sumatrapdf/">http://blog.kowalczyk.info/software/sumatrapdf/&lt;/a>&amp;#xA0;&lt;/p> &lt;p>See my comment about many implementations of open standards. This is a solid client. It doesn't support all of the bells and whistles of Adobe Acrobat, but it's super small and doesn't install any tray icons or run any background services. Kudos.&lt;/p> &lt;p>&lt;strong>Skype&lt;/strong>: &lt;a title="http://www.skype.com/" href="http://www.skype.com/">http://www.skype.com/&lt;/a>&lt;/p> &lt;p>Great for chatting with the folks and the brothers.&lt;/p> &lt;p>My parents are doing video conferencing.&lt;/p> &lt;p>Scary.&lt;/p> &lt;p>&lt;strong>Notepad++&lt;/strong>: &lt;a title="http://notepad-plus.sourceforge.net/uk/site.htm" href="http://notepad-plus.sourceforge.net/uk/site.htm">http://notepad-plus.sourceforge.net/uk/site.htm&lt;/a>&lt;/p> &lt;p>You can guess: a better version of notepad. Much better.&lt;/p> &lt;p>Support for syntax highlighting for multiple formats (C#, Xml, Ruby, etc.), a convenient shell context menu, tabs, the whole sha-bang.&lt;/p> &lt;p>I discovered this years ago. It keeps getting better.&lt;/p> &lt;p>For those times when you don't want to wait for VS to load.&lt;/p> &lt;p>&lt;strong>Process Explorer&lt;/strong>: &lt;a title="http://www.microsoft.com/technet/sysinternals/Utilities/ProcessExplorer.mspx" href="http://www.microsoft.com/technet/sysinternals/Utilities/ProcessExplorer.mspx">http://www.microsoft.com/technet/sysinternals/Utilities/ProcessExplorer.mspx&lt;/a>&lt;/p> &lt;p>Last, but not least.&lt;/p> &lt;p>Ever want to delete a file and not know which process was keeping it open? This is the tool.&lt;/p> &lt;p>From our friends at SysInternals (that are now our friends in the Windows Kernel team).&lt;/p> &lt;p>&lt;strong>What did I miss?&lt;/strong>&lt;/p> &lt;p>I'd love to know about *your* bag-o-tricks. I'll re-post anything I find useful.&lt;/p> &lt;p>Share the love and have a great Saturday.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term="computing"/>
  </entry>
  <entry>
    <title type="html">I'm leaving Microsoft</title>
    <link href="https://kevmoo.com/2007/09/i-leaving-microsoft.html" rel="alternate" type="text/html" title="I'm leaving Microsoft"/>
    <published>2007-09-14T07:15:00.001Z</published>
    <updated>2007-09-14T07:15:00.001Z</updated>
    <id>https://kevmoo.com/2007/09/i-leaving-microsoft.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/09/i-leaving-microsoft.html">&lt;p>You read that correctly. September 14 is my last day at Building 10 on the Redmond Campus (well, at least as an employee).&lt;/p> &lt;p>Here is (most of) the goodbye email I sent to colleagues and friends last week.&lt;/p> &lt;blockquote> &lt;p>Where to start. Iowa State. Fall of 1998. A career fair. I was a freshman looking for free stuff. The MS recruiter wanted to see a resume. I didn’t have one. (I didn’t think I would need one.) I ran back to my dorm, wrote enough to fill a single page, and brought it back to him.&lt;/p> &lt;p>Early that spring I flew to Sea-Tac and had an on-campus interview. (I was warned that that winter had 100 sunshine-less days.)&lt;/p> &lt;p>In May 1999 I showed up in Redmond for an internship. Building 25. I shared an office with a woman who’s a great friend to this day.&lt;/p> &lt;p>After 3 internships, a stint as a Microsoft Student Consultant at ISU, and 5 great years as an stock &lt;strike>option&lt;/strike> award earning employee, I’m going to try something drastically different.&lt;/p> &lt;p>Friday, September 14 will be my last day in the office.&lt;/p> &lt;p>Monday, September 17 I’m going to work at a small, actuarial company building internal, web-based LOB apps. &lt;/p> &lt;ul> &lt;li>No, I’m not crazy. (At least I don’t think so.) It’s been almost a decade since I’ve built anything substantial end-to-end. I’ve got pretty good at designing the tiny pieces of something XXXL. I’d like to try my hand at implementing a huge pieces of something M. &lt;li>Yes, I’ll be staying in the area. Actually, working from home most days. &lt;li>Yes, it’s all .NET still. I’m actually looking forward to cranking on SQL, ASPX, WCF, Workflow, Linq, ADO Entities, etc. &lt;li>Yes, it’s hard to leave. I’ve been plugged into Microsoft since just after high school. It’s been a great ride. I’ve learned an amazing amount and met some amazing people. Recently though, I’ve realized that if I was ever going to unplug, it was never going to get easier than it is now. &lt;/li>&lt;/ul> &lt;p>&lt;a href="http://j832.com">http://j832.com&lt;/a> is my web site. It mostly just links to my blogs. I plan to keep &lt;a href="http://work.j832.com">work.j832.com&lt;/a> going for any WPF stuff I hack on. The other blog will be everything else. :-)&lt;/p> &lt;p>(If you want the j832 thing explained some time, just ask.)&lt;/p> &lt;p>I have two closing thoughts.&lt;/p> &lt;p>First, &lt;a href="http://www.douglasp.com/blog/">Doug Purdy&lt;/a> shared a tag line that &lt;a href="http://www.pluralsight.com/blogs/dbox/">Don Box&lt;/a> and he used on a presentation once: “There is only one program…and it’s still being written.” Microsoft was a gig. My new company is a gig. There will be gigs after. The gig is not the important thing. It’s the stuff you’re building. I love software because in the end it’s all about helping people record, explorer, and communicate thoughts, memories, and ideas. If we keep making that faster, easier and just better we will all still be working together...and making the world just a bit better.&lt;/p> &lt;p>Second, a video I discovered a couple months ago. While it was after I’d made most of my decisions, it does a good job of representing the stuff in my head right now…the stuff I’m trying to figure out. It’s absolutely worth sharing: &lt;a href="http://blog.j832.com/2007/07/music-and-life.html">http://blog.j832.com/2007/07/music-and-life.html&lt;/a>&lt;/p> &lt;p>I will close out the way my good friend &lt;a href="http://www.pluralsight.com/blogs/dbox/">Robby&lt;/a> did. A master of great design: simple and to-the-point.&lt;/p> &lt;p>Goodbye and thanks again,&lt;/p> &lt;p>&amp;gt;Kevin&lt;/p>&lt;/blockquote> &lt;p>&lt;strong>Q&lt;/strong>: What does this mean for me, loyal reader of &lt;a title="http://work.j832.com/" href="http://work.j832.com/">work.j832.com&lt;/a>?&lt;br>&lt;strong>A&lt;/strong>: Hopefully not much. I plan to keep working with and blogging about WPF. I have some clever project ideas that I still want to hack on. A cool upside: I can actually collaborate in substantial ways with community members. I may blog a wider variety of stuff, but given the new job I'm sure it'll be mostly .NET-related. I'll keep my non-geek stuff on my personal blog: &lt;a href="http://blog.j832.com">blog.j832.com&lt;/a>.&lt;/p> &lt;p>&lt;strong>Q&lt;/strong>: What about the &lt;a href="http://j832.com/BagOTricks/">bag-o-tricks&lt;/a>?&lt;br>&lt;strong>A&lt;/strong>: The current URL (&lt;a href="http://blogs.msdn.com/okoboji/pages/BagOTricks.aspx">blogs.msdn.com/okoboji/pages/BagOTricks.aspx&lt;/a>) is going to die when my MSDN blog dies. (I'm not sure about when that'll happen, actually.) So I'm introducing a new, even more stable home for the latest-and-greatest: &lt;a title="http://j832.com/BagOTricks/" href="http://j832.com/BagOTricks/">j832.com/BagOTricks&lt;/a>. I hope this will be valid as long as I remember anything about WPF and I pay my ISP bill.&lt;/p> &lt;p>&lt;strong>Q&lt;/strong>: Are you planning any updates the bag?&lt;br>&lt;strong>A&lt;/strong>: Great question! I can't say much, but...um...expect great things from a lot of what's in the bag. (This is my subtle and evil way of leaning on &lt;a href="http://blogs.msdn.com/larryolson/">Larry&lt;/a>. Sorry dude.)&lt;/p> &lt;p>&lt;strong>Q&lt;/strong>: What about the &lt;a href="http://work.j832.com/2007/07/making-netfx-framework-application.html">NetFX install stuff&lt;/a>?&lt;br>&lt;strong>A&lt;/strong>: I'm going to hand this off and make sure that those who've emailed me are taken care of--hopefully by making the code generally available.&lt;/p> &lt;p>As I've said to many folks, I'm looking forward to the transition from a Microsoft High Priest for WPF to just another geek in the big city.&lt;/p> &lt;p>See you on the other side, my friends.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
  </entry>
  <entry>
    <title type="html">Video: What's new in WPF for "Orcas"/3.5/VS 2008</title>
    <link href="https://kevmoo.com/2007/08/video-what-new-in-wpf-for-2008.html" rel="alternate" type="text/html" title="Video: What's new in WPF for &quot;Orcas&quot;/3.5/VS 2008"/>
    <published>2007-08-09T18:43:00.001Z</published>
    <updated>2007-08-09T18:43:00.001Z</updated>
    <id>https://kevmoo.com/2007/08/video-what-new-in-wpf-for-2008.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/08/video-what-new-in-wpf-for-2008.html">&lt;p>While it's not &lt;a href="http://channel9.msdn.com/showpost.aspx?postid=222817">KevinButton&lt;/a>, I do spend some time walking through what's new and what's better in our next release.&lt;/p> &lt;p>Thanks to Charles and &lt;a href="http://blogs.msdn.com/tims/">Tim&lt;/a> for coming over.&lt;/p>&lt;p>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://channel9.msdn.com/showpost.aspx?postid=332987">&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_3BkQqJvzLFM/RrthdlIKQII/AAAAAAAABXs/Ao4nj0NIi6E/s400/Channel9WhatsNewPic.jpg" alt="" id="BLOGGER_PHOTO_ID_5096774564110286978" border="0" />&lt;/a>&lt;/p> &lt;p>&lt;span style="font-size:78%;">Not the best picture of me. Maybe I should have shaved. You can see the fireworks from Lake Okoboji in the background, though.&lt;/span>&lt;/p>&lt;p>Enjoy &lt;a href="http://channel9.msdn.com/showpost.aspx?postid=332987">the video&lt;/a>!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
  </entry>
  <entry>
    <title type="html">Gnomedex 7.0: I'm going</title>
    <link href="https://kevmoo.com/2007/07/gnomedex-70-i-going.html" rel="alternate" type="text/html" title="Gnomedex 7.0: I'm going"/>
    <published>2007-07-19T07:22:00.001Z</published>
    <updated>2007-07-19T07:22:00.001Z</updated>
    <id>https://kevmoo.com/2007/07/gnomedex-70-i-going.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/07/gnomedex-70-i-going.html">&lt;p>5 tickets left when I signed-up.&lt;/p>&lt;a href="http://www.gnomedex.com/"> &lt;p align="center">&lt;img height="120" alt="I'm Going to Gnomedex!" src="http://www.gnomedex.com/images/gnomedex/gnomedexer.jpg" width="120" border="0">&lt;/a>&lt;/p> &lt;p>See ya'll there.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="gnomedex"/>
  </entry>
  <entry>
    <title type="html">Making NetFX Framework + Application install easier</title>
    <link href="https://kevmoo.com/2007/07/making-netfx-framework-application.html" rel="alternate" type="text/html" title="Making NetFX Framework + Application install easier"/>
    <published>2007-07-16T22:41:00.001Z</published>
    <updated>2007-07-16T22:41:00.001Z</updated>
    <id>https://kevmoo.com/2007/07/making-netfx-framework-application.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/07/making-netfx-framework-application.html">&lt;p>Do you deploy the .NET Framework 3.0 with your application installation? Would you like a better experience for your users with framework + application installation?&lt;/p> &lt;p>The WPF team has done some work to make this process easier for both application authors and end-users.&lt;/p> &lt;p>Before we make the code generally available, we'd love to have some folks give it a dry run.&lt;/p> &lt;p>Drop me an &lt;a href="mailto:il3obom02@sneakemail.com">email&lt;/a> if you'd like to give our code a test drive or if you have questions.&lt;/p> &lt;p>We're hoping to make the install part of your app experience more enjoyable for everyone.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
  </entry>
  <entry>
    <title type="html">WPF and CSLA (and subclassing Panel)</title>
    <link href="https://kevmoo.com/2007/06/wpf-and-csla-and-subclassing-panel.html" rel="alternate" type="text/html" title="WPF and CSLA (and subclassing Panel)"/>
    <published>2007-06-26T17:06:00.001Z</published>
    <updated>2007-06-26T17:06:00.001Z</updated>
    <id>https://kevmoo.com/2007/06/wpf-and-csla-and-subclassing-panel.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/06/wpf-and-csla-and-subclassing-panel.html">&lt;p>From &lt;a href="http://rrelyea.spaces.live.com/Blog/cns!167AD7A5AB58D5FE!2133.entry">Rob's blog&lt;/a>, I found &lt;a href="http://forums.lhotka.net/forums/thread/15577.aspx">a discussion&lt;/a> about WPF support in CSLA.NET, specifically what to subclass for the containers.&lt;/p> &lt;p>I haven't played w/ the DataPanelBase, as it's discussed, but I'd be curious what Rockford would say about my &lt;a href="http://work.j832.com/2007/06/don-subclass-panel-unless-you-making.html">discussion on subclassing panel&lt;/a>.&lt;/p> &lt;p>If he's building a container to host arbitrary UI, but the user may want an arbitrary layout, I would push for Decorator. This would allow the user to specify any panel she wants.&lt;/p> &lt;p>A bit more Xaml is an okay trade-off to ensure a clean object model and straight-forward usage semantics.&lt;/p> &lt;p>As Rob mentions, Window and Page are great examples of generic containers that only support a single child.&lt;/p> &lt;p>StackPanel is particularly bad since it will give it's child an infinite measure/arrange in the vertical direction. This is really bad if you put in an ItemsControl because it will take up as much space as needed to render all of its items. This could both mess up the UI and slow things way down--virtualization doesn't help much if all of the items are visible.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
  </entry>
  <entry>
    <title type="html">Rob and I hang out too much (RE: a good URL for the bag-o-tricks)</title>
    <link href="https://kevmoo.com/2007/06/rob-and-i-hang-out-too-much-re-good-url.html" rel="alternate" type="text/html" title="Rob and I hang out too much (RE: a good URL for the bag-o-tricks)"/>
    <published>2007-06-26T01:35:00.001Z</published>
    <updated>2007-06-26T01:35:00.001Z</updated>
    <id>https://kevmoo.com/2007/06/rob-and-i-hang-out-too-much-re-good-url.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/06/rob-and-i-hang-out-too-much-re-good-url.html">&lt;p>All of an hour ago, I &lt;a href="http://work.j832.com/2007/06/keeping-track-of-bag-o-tricks.html">made a post&lt;/a> trying to bring sanity to the problem of finding the latest bag-o-tricks.&lt;/p> &lt;p>Looks like Rob &lt;a href="http://rrelyea.spaces.live.com/Blog/cns!167AD7A5AB58D5FE!2127.entry">thought of this 4 days ago&lt;/a>.&lt;/p> &lt;p>Great minds, right?&lt;/p> &lt;p>Or maybe I should just keep up on my blog reading.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">RE: CompositionTarget.Rendering</title>
    <link href="https://kevmoo.com/2007/06/re-compositiontargetrendering.html" rel="alternate" type="text/html" title="RE: CompositionTarget.Rendering"/>
    <published>2007-06-26T01:07:00.001Z</published>
    <updated>2007-06-26T01:07:00.001Z</updated>
    <id>https://kevmoo.com/2007/06/re-compositiontargetrendering.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/06/re-compositiontargetrendering.html">&lt;p>I use &lt;em>&lt;a href="http://msdn.microsoft.com/en-us/library//system.windows.media.compositiontarget.rendering.aspx">CompositionTarget.Rendering&lt;/a>&lt;/em> &lt;strong>a lot&lt;/strong> in the &lt;a href="http://blogs.msdn.com/okoboji/pages/BagOTricks.aspx">bag-o-tricks&lt;/a>. (Last count: AnimatingTilePanel, Graph, ZapDecorator, and FlipTile3D.)&lt;/p> &lt;p>Rob &lt;a href="http://rrelyea.spaces.live.com/Blog/cns!167AD7A5AB58D5FE!2137.entry">posted to an internal discussion&lt;/a> about how to use (and how not to use) the event. (I saw a &lt;a href="http://www.wiredprairie.us/journal/2007/06/compositiontarget_performance.html">link on WiredPrairie&lt;/a> as well.)&lt;/p> &lt;p>Specifically, it's important to remember this is a timer that ticks &lt;strong>all of the time&lt;/strong>--every frame--potentially 60 times a second or more.&lt;/p> &lt;p>Since it's a static event, it will keep firing even if control you use it in isn't on the screen any more.&lt;/p> &lt;p>Hence, it's critically important that you manage the use of this event appropriately.&lt;/p> &lt;ul> &lt;li>&lt;strong>Un-register the event when your control is unloaded.&lt;/strong> I actually add a handler for the Unloaded event in my controls to do this. If you don't do this, events will still be fired to your delegate, even if the control is removed from the visual tree! This is not only a perf hit, but could introduce crazy behavior, crashes, data loss, mass hysteria, etc.&lt;/li> &lt;li>&lt;strong>Potentially un-register the event when the UI isn't visible.&lt;/strong> Like when the window is minimized. Be careful, though. Finding window state from a control could be ugly. You also may want to let your animation run its course even if it's not visible, which leads me to the final bullet...&lt;/li> &lt;li>&lt;strong>Un-register when your animation "settles".&lt;/strong> Since I used the &lt;em>Rendering&lt;/em> event for my physics models, I do this when I reach equilibrium. Once all of the forces have balanced out and stuff stops moving, I un-register the event (and make sure to re-register once something changes that will start things moving again).&lt;/li>&lt;/ul> &lt;p>Users don't like their CPU pegged (unless something really cool is happening). A user with a dead laptop battery is not a happy user.&lt;/p> &lt;p>Happy hacking!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
  </entry>
  <entry>
    <title type="html">Keeping track of the Bag-o-Tricks</title>
    <link href="https://kevmoo.com/2007/06/keeping-track-of-bag-o-tricks.html" rel="alternate" type="text/html" title="Keeping track of the Bag-o-Tricks"/>
    <published>2007-06-26T00:26:00.001Z</published>
    <updated>2007-06-26T00:26:00.001Z</updated>
    <id>https://kevmoo.com/2007/06/keeping-track-of-bag-o-tricks.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/06/keeping-track-of-bag-o-tricks.html">&lt;p>As I update the Bag-o-Tricks, I wanted to keep one URL for people to check to make sure they have the latest hotness.&lt;/p> &lt;p>(This is a nod to Rob's &lt;a href="http://robrelyea.com/UrlManifesto/">Url Manifesto&lt;/a>. While I pick on him a lot about this, I think it's a great way to think about the user model for the web.)&lt;/p> &lt;p>Anyway, I'll keep &lt;a href="http://j832.com/bagotricks">this page&lt;/a> updated with the latest info on the bag-o-tricks. (And, hopefully, a description of each demo/sample when I get some free time).&lt;/p> &lt;p>I'll have some updates soon, I promise.&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
  </entry>
  <entry>
    <title type="html">A great way to learn a programming language</title>
    <link href="https://kevmoo.com/2007/06/great-way-to-learn-programming-language.html" rel="alternate" type="text/html" title="A great way to learn a programming language"/>
    <published>2007-06-19T18:27:00.001Z</published>
    <updated>2007-06-19T18:27:00.001Z</updated>
    <id>https://kevmoo.com/2007/06/great-way-to-learn-programming-language.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/06/great-way-to-learn-programming-language.html">&lt;p>I'm sure many have heard discussions about the &lt;a href="http://en.wikipedia.org/wiki/Dynamic_Language_Runtime">DLR&lt;/a> and &lt;a href="http://en.wikipedia.org/wiki/IronRuby">IronRuby&lt;/a>&amp;nbsp;coming out of MIX07.&lt;/p> &lt;p>As a guy who cares about great developer experiences and great user experiences, I've also paid some attention to &lt;a href="http://www.rubyonrails.org/">Ruby on Rails&lt;/a>.&lt;/p> &lt;p>So last night, I thought I'd dig in.&lt;/p> &lt;p>&lt;a href="http://instantrails.rubyforge.org/wiki/wiki.pl">Instant Rails&lt;/a> seems to be a popular place to start. A one-stop-shop for Ruby + Rails + Apache + MySQL. All runs on Windows by just extracting a zip file. (The only hiccup I encountered was making sure that port 80 was available.)&lt;/p> &lt;p>After I got things running and clicked around a bit, I realized I was trying to learn Japanese by picking up a book and trying to cross reference concepts to a Japanese-English dictionary.&lt;/p> &lt;p>Not very effective.&lt;/p> &lt;p>What I needed was a "vocabulary" and "grammar" introduction. (In quotes, because I'm referring to my Japanese analogy and not programming language constructs.)&amp;nbsp;&lt;/p> &lt;p>After the obvious search term--"&lt;a href="http://www.google.com/search?q=ruby+tutorial">ruby tutorial&lt;/a>"--I stumbled upon an amazing tool: &lt;a href="http://tryruby.hobix.com/">Try Ruby&lt;/a>.&lt;/p> &lt;p>Holy cow! A ruby interpreter in-browser. A great way to understand the language. I had a bit of trouble dealing with mistyped lines, but otherwise, it's an amazing tool.&lt;/p> &lt;p>More programming languages should be presented this way.&lt;/p> &lt;p>This is certainly worth a few hours on a Tuesday night.&lt;/p> &lt;p>Kudos to the developers.&amp;nbsp;&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="Programming"/>
    <category term="Ruby"/>
  </entry>
  <entry>
    <title type="html">Ya'll reading the WPF SDK blog, right?</title>
    <link href="https://kevmoo.com/2007/06/ya-reading-wpf-sdk-blog-right.html" rel="alternate" type="text/html" title="Ya'll reading the WPF SDK blog, right?"/>
    <published>2007-06-18T22:10:00.001Z</published>
    <updated>2007-06-18T22:10:00.001Z</updated>
    <id>https://kevmoo.com/2007/06/ya-reading-wpf-sdk-blog-right.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/06/ya-reading-wpf-sdk-blog-right.html">&lt;p>People are always looking for deep content on WPF. This is a great source: &lt;a title="http://blogs.msdn.com/wpfsdk/" href="http://blogs.msdn.com/wpfsdk/">http://blogs.msdn.com/wpfsdk/&lt;/a>&lt;/p> &lt;p>Carole is an SDK writer that frequently digs in with those of us on the engineering side to make sure the SDK blog is speaking the truth.&lt;/p> &lt;p>Check it out!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Don't subclass a Panel, unless you're making a Panel</title>
    <link href="https://kevmoo.com/2007/06/don-subclass-panel-unless-you-making.html" rel="alternate" type="text/html" title="Don't subclass a Panel, unless you're making a Panel"/>
    <published>2007-06-10T21:02:00.001Z</published>
    <updated>2007-06-10T21:02:00.001Z</updated>
    <id>https://kevmoo.com/2007/06/don-subclass-panel-unless-you-making.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/06/don-subclass-panel-unless-you-making.html">&lt;p>I have a tongue-in-cheek thing I say a lot about WPF compared to Windows Forms:&lt;/p> &lt;blockquote> &lt;p>In Windows Forms, there are two ways to do everything: a good way and a bad way.&lt;/p> &lt;p>In WPF, there are ten ways to do everything: two that are amazing, 3 that are good, 1 that is bad, and 4 that suck.&lt;/p>&lt;/blockquote> &lt;p>My goal in this post is to help move people upstream towards amazing, specifically how and when to use Panel (and its subclasses).&lt;/p> &lt;p>&lt;strong>Markup subclassing&lt;/strong>&lt;/p> &lt;p>Everytime you go into VS and create a new WPF project, you see markup subclassing. This is the &lt;font face="Consolas">Window x:Class="WPFApplication1.Window1"&lt;/font> stuff. It allows you to associate a piece of XAML to a subclass you define in Code. There are four approved places you'll see this in WPF: Application, Window, Page, and UserControl.&lt;/p> &lt;p>More than once, though, I've seen clever people (both outside and inside Microsoft) take this approach one step further. They want to reuse a piece of UI several times. Maybe they have a Grid defined with a set of columns, rows, and controls defined. It's pretty easy to take that Xaml-defined Grid (with all of its XML child elements), put it in it's own Xaml file, slap on an x:Class statement and start rolling. Things work great.&lt;/p> &lt;p>Rock-n-roll, right?&lt;/p> &lt;p>Well, not really.&lt;/p> &lt;p>&lt;strong>Inheritance for polymorphism&lt;/strong>&lt;/p> &lt;p>I read a great internal paper at MS once--written by one of those brilliant old-guard devs with decades of perspective. The point the author pushed: use inheritance only for polymorphism. Translated: when making MyGrid, only subclass Grid if you mean for people to treat your new MyGrid just like another Grid. Code (and a user, for the most part) that deals with Grid should be able to "deal" with MyGrid without any issues.&lt;/p> &lt;p>&lt;strong>Where things break down&lt;/strong>&lt;/p> &lt;p>So let's say you define your BadGrid Xaml like this (with an associated BadGrid.xaml.cs file with properties, events, etc):&lt;/p>&lt;pre class="code">&lt;span style="color: rgb(0,0,255)">&amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Grid&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">x:Class&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">PanelFun.BadGrid&lt;/span>"&lt;br>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">xmlns&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span>"&lt;br>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">xmlns:x&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">http://schemas.microsoft.com/winfx/2006/xaml&lt;/span>"&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br> &lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Grid.RowDefinitions&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">RowDefinition&lt;/span>&lt;span style="color: rgb(0,0,255)">/&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">RowDefinition&lt;/span>&lt;span style="color: rgb(0,0,255)">/&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">RowDefinition&lt;/span>&lt;span style="color: rgb(0,0,255)">/&amp;gt;&lt;br> &amp;lt;/&lt;/span>&lt;span style="color: rgb(163,21,21)">Grid.RowDefinitions&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Grid.ColumnDefinitions&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">ColumnDefinition&lt;/span>&lt;span style="color: rgb(0,0,255)">/&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">ColumnDefinition&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Width&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">100&lt;/span>"&lt;span style="color: rgb(0,0,255)">/&amp;gt;&lt;br> &amp;lt;/&lt;/span>&lt;span style="color: rgb(163,21,21)">Grid.ColumnDefinitions&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br>&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Label&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Row&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">0&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Column&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">0&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Content&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">_First Name&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Target&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">{Binding ElementName=FirstName}&lt;/span>"&lt;span style="color: rgb(0,0,255)"> /&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">TextBox&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Row&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">0&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Column&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">1&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Name&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">FirstName&lt;/span>"&lt;span style="color: rgb(0,0,255)"> /&amp;gt;&lt;br>&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Label&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Row&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">1&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Column&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">0&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Content&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">_Middle Name&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Target&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">{Binding ElementName=MiddleName}&lt;/span>"&lt;span style="color: rgb(0,0,255)"> /&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">TextBox&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Row&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">1&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Column&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">1&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Name&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">MiddleName&lt;/span>"&lt;span style="color: rgb(0,0,255)"> /&amp;gt;&lt;br>&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Label&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Row&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">2&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Column&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">0&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Content&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">_Last Name&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Target&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">{Binding ElementName=LastName}&lt;/span>"&lt;span style="color: rgb(0,0,255)"> /&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">TextBox&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Row&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">2&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Column&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">1&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Name&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">LastName&lt;/span>"&lt;span style="color: rgb(0,0,255)"> /&amp;gt;&lt;br>&lt;br>&amp;lt;/&lt;/span>&lt;span style="color: rgb(163,21,21)">Grid&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br>&lt;/span>&lt;/pre>&lt;a href="http://11011.net/software/vspaste">&lt;/a>&lt;br />&lt;p>Looks okay, right?&lt;/p>&lt;br />&lt;p>Let's use it.&lt;/p>&lt;pre class="code">&lt;span style="color: rgb(0,0,255)">&amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Window&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">xmlns&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span>"&lt;br>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">xmlns:x&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">http://schemas.microsoft.com/winfx/2006/xaml&lt;/span>"&lt;br>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">xmlns:local&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">clr-namespace:PanelFun&lt;/span>"&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br>&lt;/span>&lt;span style="color: rgb(0,0,255)">&lt;/span>&lt;/pre>&lt;pre class="code">&lt;span style="color: rgb(0,0,255)"> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">local:BadGrid&lt;/span>&lt;span style="color: rgb(0,0,255)">/&amp;gt; &lt;br>&lt;/span>&lt;span style="color: rgb(0,0,255)">&lt;/span>&lt;/pre>&lt;pre class="code">&lt;span style="color: rgb(0,0,255)">&amp;lt;/&lt;/span>&lt;span style="color: rgb(163,21,21)">Window&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br>&lt;/span>&lt;/pre>&lt;a href="http://11011.net/software/vspaste">&lt;/a>&lt;br />&lt;p>Run the app. No problem!&lt;/p>&lt;br />&lt;p>Now let's say a naive user (maybe someone in your company or a customer) takes your control and sees that it's a Grid. They write this Xaml:&lt;/p>&lt;pre class="code">&lt;span style="color: rgb(0,0,255)">&amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Window&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">xmlns&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span>"&lt;br>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">xmlns:x&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">&lt;a href="http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;">http://schemas.microsoft.com/winfx/2006/xaml&lt;/span>"&lt;br>&lt;span style="color: rgb(255,0,0)">&lt;/a> xmlns:local&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">clr-namespace:PanelFun&lt;/span>"&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;/span>&lt;/pre>&lt;pre class="code">&lt;span style="color: rgb(0,0,255)">&lt;br>&lt;/span>&lt;span style="color: rgb(0,0,255)"> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">local:BadGrid&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Grid.RowDefinitions&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">RowDefinition&lt;/span>&lt;span style="color: rgb(0,0,255)">/&amp;gt;&lt;br> &amp;lt;/&lt;/span>&lt;span style="color: rgb(163,21,21)">Grid.RowDefinitions&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br>&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">Label&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Row&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">3&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Column&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">0&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Content&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">_Favorite Color&lt;/span>"&lt;span style="color: rgb(0,0,255)">/&amp;gt;&lt;br> &amp;lt;&lt;/span>&lt;span style="color: rgb(163,21,21)">TextBox&lt;/span>&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Row&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">3&lt;/span>"&lt;span style="color: rgb(0,0,255)"> &lt;/span>&lt;span style="color: rgb(255,0,0)">Grid.Column&lt;/span>&lt;span style="color: rgb(0,0,255)">=&lt;/span>"&lt;span style="color: rgb(0,0,255)">1&lt;/span>"&lt;span style="color: rgb(0,0,255)"> /&amp;gt;&lt;br> &amp;lt;/&lt;/span>&lt;span style="color: rgb(163,21,21)">local:BadGrid&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;/span>&lt;/pre>&lt;pre class="code">&lt;span style="color: rgb(0,0,255)">&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;lt;/&lt;/span>&lt;span style="color: rgb(163,21,21)">Window&lt;/span>&lt;span style="color: rgb(0,0,255)">&amp;gt;&lt;br>&lt;/span>&lt;/pre>&lt;a href="http://11011.net/software/vspaste">&lt;/a>&lt;br />&lt;p>Things compile fine. They are using BadGrid just like a Grid. No problem, right?&lt;/p>&lt;br />&lt;p>The problem, of course, is that you didn't mean people to use BadGrid like a Grid. You wanted them to use it like a simple Control. Weird things happen, dogs and cats living together, mass hysteria.&lt;/p>&lt;br />&lt;p>In this case, you get the user-created row inserted into your grid. If the user tries to put a name on the TextBlock, the compiler blows-up because of naming conflicts between the definition scope (in BadGrid.Xaml) and the usage scope (in the Window). The user has no clue why things blew up. (I'm not all that sure myself, actually.)&lt;/p>&lt;br />&lt;p>&lt;strong>If you want to use markup subclassing, stay inside the fences&lt;/strong>&lt;/p>&lt;br />&lt;p>Application, Window, Panel, UserControl. It's pretty simple to paste your desired Xaml into a UserControl, with no unplanned weirdness.&lt;/p>&lt;br />&lt;p>If you want to extend markup subclassing further, we should talk to &lt;a href="http://rrelyea.spaces.live.com/">Rob&lt;/a>. He's the Xaml guy. :-)&lt;/p>&lt;br />&lt;p>&lt;strong>If you want to do any subclassing, pick the right base class&lt;/strong>&lt;/p>&lt;br />&lt;p>In general (even if you're not using Markup subclassing), make sure you "mean it" when you use inheritance in WPF (or any object orientated framework, for that matter). If you subclass a ContentControl, do you mean people to treat it like a ContentControl all the time? Same thing for ItemsControl, Decorator, and Panel.&lt;/p>&lt;br />&lt;p>&lt;strong>When would I subclass a Panel?&lt;/strong>&lt;/p>&lt;br />&lt;p>Well, if you want to make your own panel, start with Panel. AniTilePanel from my bag-o-tricks is a good example.&lt;/p>&lt;br />&lt;p>You might want to subclass a bit deeper, but only in special cases.You could make OrderedStackPanel, where you introduce your own AttachedProperty: OrderedStackPanel.Order. This can be applied to items and your panel will order the items in the stack based on the property. The cool thing: without the property set, your panel should act just like StackPanel. This holds to the theory about inheritance and polymorphism.&lt;/p>&lt;br />&lt;p>Make Sense? Sound good? Hack on!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
  </entry>
  <entry>
    <title type="html">What are you doing to protect the Internet?</title>
    <link href="https://kevmoo.com/2007/06/what-are-you-doing-to-protect-internet.html" rel="alternate" type="text/html" title="What are you doing to protect the Internet?"/>
    <published>2007-06-10T19:30:00.001Z</published>
    <updated>2007-06-10T19:30:00.001Z</updated>
    <id>https://kevmoo.com/2007/06/what-are-you-doing-to-protect-internet.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/06/what-are-you-doing-to-protect-internet.html">&lt;div xmlns="http://www.w3.org/1999/xhtml"> &lt;p>&lt;embed src="http://youtube.com/v/cWt0XUocViE" width="425" height="350" type="application/x-shockwave-flash">&lt;/embed>&lt;/p> &lt;p>For more information: &lt;a title="http://www.savetheinternet.com/" href="http://www.savetheinternet.com/">http://www.savetheinternet.com/&lt;/a>&lt;/p> &lt;p>To promote the cause yourself: &lt;a title="http://www.savetheinternet.com/=promote" href="http://www.savetheinternet.com/=promote">http://www.savetheinternet.com/=promote&lt;/a>&lt;/p>&lt;/div></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Jobs &amp; Gates</title>
    <link href="https://kevmoo.com/2007/06/jobs-gates.html" rel="alternate" type="text/html" title="Jobs &amp; Gates"/>
    <published>2007-06-03T22:02:00.001Z</published>
    <updated>2007-06-03T22:02:00.001Z</updated>
    <id>https://kevmoo.com/2007/06/jobs-gates.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/06/jobs-gates.html">&lt;p>We've &lt;a href="http://www.usatoday.com/tech/techinvestor/industry/2007-05-30-jobs-gates_N.htm">heard a lot&lt;/a> about the meeting of Steve Jobs and Bill Gates.&lt;/p> &lt;p>9 Parts, I'm through part 3...cool stuff, via &lt;a href="http://www.youtube.com/">YouTube&lt;/a>.&lt;/p> &lt;ul> &lt;li>&lt;a href="http://www.youtube.com/watch?v=9HMO0zVYUw8">Part 1&lt;/a>&lt;/li> &lt;li>&lt;a href="http://www.youtube.com/watch?v=M9zN9Hd724A">Part 2&lt;/a>&lt;/li> &lt;li>&lt;a href="http://www.youtube.com/watch?v=UVrFeqdOEbc">Part 3&lt;/a>&lt;/li> &lt;li>&lt;a href="http://www.youtube.com/watch?v=OS9o7ZtBVNk">Part 4&lt;/a>&lt;/li> &lt;li>&lt;a href="http://www.youtube.com/watch?v=zM6o15_-sKk">Part 5&lt;/a>&lt;/li> &lt;li>&lt;a href="http://www.youtube.com/watch?v=8DGluW5x3mo">Part 6&lt;/a>&lt;/li> &lt;li>&lt;a href="http://www.youtube.com/watch?v=U80WAL-w_eM">Part 7&lt;/a>&lt;/li> &lt;li>&lt;a href="http://www.youtube.com/watch?v=dy47mB9XOyU">Part 8&lt;/a>&lt;/li> &lt;li>&lt;a href="http://www.youtube.com/watch?v=p9vDInBgMLM">Part 9&lt;/a>&lt;/li>&lt;/ul></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Caution: Surface is very hot</title>
    <link href="https://kevmoo.com/2007/05/caution-surface-is-very-hot.html" rel="alternate" type="text/html" title="Caution: Surface is very hot"/>
    <published>2007-05-30T06:27:00.001Z</published>
    <updated>2007-05-30T06:27:00.001Z</updated>
    <id>https://kevmoo.com/2007/05/caution-surface-is-very-hot.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/05/caution-surface-is-very-hot.html">&lt;p>&lt;a title="http://www.microsoft.com/surface/" href="http://www.microsoft.com/surface/">http://www.microsoft.com/surface/&lt;/a>&lt;/p> &lt;p>Let us talk about hotness. Holy hotness.&lt;/p> &lt;p>I've never jumped up and down and laughed out loud more than when when I got to play with Surface.&lt;/p> &lt;p>Scary-beyond-words cool stuff.&lt;/p> &lt;p>I've been delighted to help the team with a few tweaks to WPF core controls to ensure they play nicely on Surface. It's a great showcase of the power of our platform (and a number of other MS graphics technologies.)&lt;/p> &lt;p>Actually, very few tweaks were needed to WPF to support their scenarios. &lt;a href="http://blogs.msdn.com/dwayneneed/">Dwayne&lt;/a> and friends did an amazing job designing an extensible input system. Mouse, keyboard and stylus were on the initial list of possible devices. Finger and drink glass just happened to plug in nicely.&lt;/p> &lt;p>Here's to brilliant layering, huh?&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">20 Steps to happiness</title>
    <link href="https://kevmoo.com/2007/05/20-steps-to-happiness.html" rel="alternate" type="text/html" title="20 Steps to happiness"/>
    <published>2007-05-30T05:59:00.001Z</published>
    <updated>2007-05-30T05:59:00.001Z</updated>
    <id>https://kevmoo.com/2007/05/20-steps-to-happiness.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/05/20-steps-to-happiness.html">&lt;p>(This silliness assumes you haven't jumped into the beauty that is WPF development. It also assumes you're running Vista. If you aren't, why not? If you have a good reason, I'm betting you'll get help installing .NET Framework 3.0. on XPSP2)&lt;/p> &lt;ol> &lt;li>Go &lt;a href="http://msdn.microsoft.com/vstudio/express/future/downloads/">here&lt;/a> &lt;li>Click on Visual C# &lt;li>Login with your &lt;a href="http://get.live.com/getlive/overview">Windows Live ID&lt;/a> &lt;li>Download and click on all of the nessesary buttons &lt;li>Marvel at the small (~30 MB) download (if you don't get the data stuff). &lt;li>Type "Visual" in Vista's start menu. &lt;li>Marvel at the cool search feature &lt;li>Pick &lt;em>Microsoft Visual C# 9.0 Express Edition&lt;/em> &lt;li>Marvel at our crazy long product names &lt;li>Pick "New Project..." from the start menu. (Ctrl+Shift+N to be super fast) &lt;li>Pick &lt;em>WPF Application&lt;/em>. &lt;li>Marvel at the visual designer for WPF. (Thanks Cider team.) &lt;li>Open up the Toolbox and find the ListBox under &lt;em>Common Controls&lt;/em>. &lt;li>Draw out a ListBox on the Window. &lt;li>Marvel at the XAML updating right away. &lt;li>Notice the auto-generated name for your ListBox: listBox1. &lt;li>Open up Window1.xaml.cs &lt;li>Paste the following below InitializeCompontent();&lt;br>&lt;br>var foo = from a in Directory.GetDirectories(@"C:\") select new{a, a.Length};&lt;br>listBox1.ItemsSource = foo.ToList();&lt;br> &lt;li>Marvel at:&lt;br>-the use of "var" -- mmm...implicit types&lt;br>-from/select in C# -- mmm...Linq goodness&lt;br>-new {a, a.Length} -- mmm...anonymous types&lt;br>.ToList() -- mmm...extension methods &lt;li>Hit F5&lt;/li>&lt;/ol> &lt;p>WPF Goodness + VS "Orcas" design-time Goodness + Linq goodness = happiness&lt;/p> &lt;p>mmm...&lt;/p> &lt;ol> &lt;p>&amp;nbsp; &lt;p>&amp;nbsp;&lt;/p>&lt;/ol></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">My Mix Session is finally live</title>
    <link href="https://kevmoo.com/2007/05/my-mix-session-is-finally-live.html" rel="alternate" type="text/html" title="My Mix Session is finally live"/>
    <published>2007-05-25T18:48:00.001Z</published>
    <updated>2007-05-25T18:48:00.001Z</updated>
    <id>https://kevmoo.com/2007/05/my-mix-session-is-finally-live.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/05/my-mix-session-is-finally-live.html">&lt;p>Well, it's been live for a while, but I was in Iowa last week.&lt;/p> &lt;p>&lt;a href="http://sessions.visitmix.com/default.asp?event=1011&amp;amp;session=2011&amp;amp;pid=XD009&amp;amp;disc=&amp;amp;id=1598&amp;amp;year=2007&amp;amp;search=XD009">XD009 - WPF For Developers&lt;/a>&lt;/p> &lt;p>As I &lt;a href="http://work.j832.com/2007/05/kevins-bag-o-tricks-mix07-edition.html">said before&lt;/a>, the code for all of the demos is in the &lt;a href="http://wpf.netfx3.com/files/folders/controls/entry10297.aspx">bag-o-tricks&lt;/a>.&lt;/p> &lt;p>Happy hacking!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">Kevin's Bag-O-Tricks - MIX07 Edition</title>
    <link href="https://kevmoo.com/2007/05/kevins-bag-o-tricks-mix07-edition.html" rel="alternate" type="text/html" title="Kevin's Bag-O-Tricks - MIX07 Edition"/>
    <published>2007-05-02T16:52:00.000Z</published>
    <updated>2007-05-02T16:52:00.000Z</updated>
    <id>https://kevmoo.com/2007/05/kevins-bag-o-tricks-mix07-edition.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/05/kevins-bag-o-tricks-mix07-edition.html">For those that came to my talk, thanks! Please fill out an &lt;a href="https://content.visitmix.com/evals/selecteval.aspx?eval=session">evaluation&lt;/a> so I know what you liked.&lt;br />&lt;br />For everyone, as promised, here's the &lt;a href="http://wpf.netfx3.com/files/folders/controls/entry10297.aspx">updated bag-o-tricks&lt;/a>.&lt;br />&lt;br />Drop me an email if you have questions/comments/bugs/suggestions.</content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
  <entry>
    <title type="html">MIX07, here I come!</title>
    <link href="https://kevmoo.com/2007/04/mix07-here-i-come.html" rel="alternate" type="text/html" title="MIX07, here I come!"/>
    <published>2007-04-29T01:32:00.001Z</published>
    <updated>2007-04-29T01:32:00.001Z</updated>
    <id>https://kevmoo.com/2007/04/mix07-here-i-come.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/04/mix07-here-i-come.html">&lt;p>I fly out tomorrow morning for Mix07. I've been cranking for a week on my slides and demos. They feel pretty good.&lt;/p> &lt;p>The public list of sessions is &lt;a href="https://content.visitmix.com/public/sessions.aspx">here&lt;/a>. We've done a bit of churn in our talk format. Rob and I are both riding solo. This is mine.&lt;/p> &lt;p>XD009, &lt;strong>Windows Presentation Foundation for Developers – (Part 2 of 2)&lt;/strong>, Wednesday 11:30-12:45, Lando 4204&lt;/p> &lt;p>Be the first to get your hands on the update to the bag-o-tricks. For those not coming, just watch this space. I'll get them posted publicly shortly after my talk!&lt;/p> &lt;p>I have some good friends giving talks you should check out.&lt;/p> &lt;ul> &lt;li>&lt;a href="http://rrelyea.spaces.live.com/">Rob Relyea&lt;/a>, XD011, &lt;strong>Windows Presentation Foundation for Developers – (Part 1 of 2)&lt;/strong>, Wednesday 10-11:15, Lando 4204 &lt;em>(Right before mine, come to both.)&lt;/em> &lt;li>Kevin Gjerstad, BDM03, &lt;strong>The Art, Science, and Business of Killer Content Experiences&lt;/strong>, Tuesday 8:30-9:45AM, Delfino 4101A &lt;li>&lt;a href="http://blogs.msdn.com/mharsh/">Mike Harsh&lt;/a>, XD001, &lt;strong>Deep Dive on Silverlight Media Integration&lt;/strong>, Tuesday 2:15-3:30, Lando 4201 &lt;li>&lt;a href="http://notstatic.com/">Robby Ingebretsen&lt;/a>, XB003, &lt;strong>"ZAP!, WHAM!, KAPOW!": Windows Presentation Foundation and the Next Generation of Online Comic Book Reading&lt;/strong>, Monday 3-4:15 PM, Delfino 4005&amp;nbsp;&lt;/li>&lt;/ul> &lt;p>For those attending MIX, my Sandbox page is &lt;a title="mixer1029.mixsandbox.com" href="http://mixer1029.mixsandbox.com/">mixer1029.mixsandbox.com&lt;/a>. &lt;/p> &lt;p>See ya'll in Vegas!&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
    <category term="WPF"/>
    <category term="MIX07"/>
  </entry>
  <entry>
    <title type="html">New URL, Same Great Taste!</title>
    <link href="https://kevmoo.com/2007/04/new-url-same-great-taste.html" rel="alternate" type="text/html" title="New URL, Same Great Taste!"/>
    <published>2007-04-08T16:30:00.001Z</published>
    <updated>2007-04-08T16:30:00.001Z</updated>
    <id>https://kevmoo.com/2007/04/new-url-same-great-taste.html</id>
    <content type="html" xml:base="https://kevmoo.com/2007/04/new-url-same-great-taste.html">&lt;p>Hello WPF fans, glad you found your way to my new blog.&lt;/p> &lt;p>I'm trying to consolidate all of my web-based shenanigans.&lt;/p> &lt;p>&lt;a href="http://blogs.msdn.com/">MSDN blogs&lt;/a> has treated me well for 4 years. Check out the &lt;a href="http://blogs.msdn.com/okoboji">old URL&lt;/a> for my previous wit-and-wisdom. It should stick around for a while.&lt;/p> &lt;p>Here's to new beginnings!&lt;/p> &lt;p>(I'm sure I'll get fewer questions about &lt;a href="http://en.wikipedia.org/wiki/University_of_Okoboji">Okoboji&lt;/a>.&amp;nbsp;Never be afraid to ask, though.)&lt;/p></content>
    <author>
      <name>Kevin Moore</name>
    </author>
  </entry>
</feed>