<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Eric Lee</title><link>http://blogs.msdn.com/b/elee/</link><description>Thoughts on Agile development, Scrum, ALT.NET, and whatever else comes to mind.</description><dc:language>en-US</dc:language><generator>Telligent Community 5.6.583.17018 (Build: 5.6.583.17018)</generator><item><title>The Most Important Question</title><link>http://blogs.msdn.com/b/elee/archive/2011/09/06/the-most-important-question.aspx</link><pubDate>Wed, 07 Sep 2011 00:16:32 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10206988</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10206988</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2011/09/06/the-most-important-question.aspx#comments</comments><description>&lt;p&gt;New post up on my new blog: &lt;a href="http://saintgimp.org/2011/09/06/the-most-important-question/"&gt;The Most Important Question&lt;/a&gt;.&amp;nbsp; Why are you still reading these posts on MSDN?&amp;nbsp; &lt;a href="http://saintgimp.org/feed/"&gt;Subscribe to my new blog&lt;/a&gt;!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10206988" width="1" height="1"&gt;</description></item><item><title>Configuration Scripts for Lazy Developers</title><link>http://blogs.msdn.com/b/elee/archive/2011/09/06/configuration-scripts-for-lazy-developers.aspx</link><pubDate>Tue, 06 Sep 2011 19:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10206906</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10206906</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2011/09/06/configuration-scripts-for-lazy-developers.aspx#comments</comments><description>&lt;p&gt;There's a new post up on my new blog: &lt;a href="http://saintgimp.org/2011/09/05/configuration-scripts-for-lazy-developers/"&gt;Configuration Scripts for Lazy Developers&lt;/a&gt;.&amp;nbsp; If you're still reading posts here then you might want to update your RSS feed or saved links because these "redirects" will stop soon.&amp;nbsp; Thanks!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10206906" width="1" height="1"&gt;</description></item><item><title>Why The Standup Meeting Is Important</title><link>http://blogs.msdn.com/b/elee/archive/2011/09/01/why-the-standup-meeting-is-important.aspx</link><pubDate>Thu, 01 Sep 2011 22:47:28 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10204738</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10204738</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2011/09/01/why-the-standup-meeting-is-important.aspx#comments</comments><description>&lt;p&gt;There's a new post up on my new blog: &lt;a href="http://saintgimp.org/2011/09/01/why-the-standup-meeting-is-important/"&gt;Why The Standup Meeting Is Important&lt;/a&gt;.&amp;nbsp; Read it there!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10204738" width="1" height="1"&gt;</description></item><item><title>A New Adventure</title><link>http://blogs.msdn.com/b/elee/archive/2011/09/01/a-new-adventure.aspx</link><pubDate>Thu, 01 Sep 2011 20:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10204673</guid><dc:creator>SaintGimp</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10204673</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2011/09/01/a-new-adventure.aspx#comments</comments><description>&lt;p&gt;Wow.&amp;#160; After almost eighteen years at Microsoft, it’s time to try something different.&amp;#160; I’m moving to Blade Games World to work as a senior developer on &lt;a href="http://www.jumala.com/"&gt;Jumala&lt;/a&gt;!&amp;#160; I’m ridiculously excited about this opportunity, but I’m sure it’s going to be quite a ride moving from a ~90,000 employee behemoth of a corporation to a 14 person startup (well, 15 now, with me.)&amp;#160; Joy and terror in equal measure.&amp;#160; I’ve been told to expect quite a lot of “detox time”, and I’m looking forward to experiencing and blogging about some of the differences.&amp;#160; Oh yeah, this is going to be awesome!&lt;/p&gt;  &lt;p&gt;As part of this move, I’m transitioning my blog from MSDN to &lt;a href="http://saintgimp.org/"&gt;SaintGimp.org&lt;/a&gt;.&amp;#160; I expect that my old posts will remain up on MSDN indefinitely but all new posts will be on my new personal site.&amp;#160; If you’re subscribed to my MSDN blog via RSS, now would be a good time to &lt;a href="http://saintgimp.org/feed/"&gt;update your subscription&lt;/a&gt;.&amp;#160; I have a few new posts that will go up soon on the new site and I’ll post links to them here for as long as I can, but that’ll stop in a couple of weeks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10204673" width="1" height="1"&gt;</description></item><item><title>GenesisEngine: Coordinate Systems</title><link>http://blogs.msdn.com/b/elee/archive/2010/11/27/genesisengine-coordinate-systems.aspx</link><pubDate>Sat, 27 Nov 2010 11:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10097349</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10097349</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/11/27/genesisengine-coordinate-systems.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is not going to be a general-interest post so if you&amp;rsquo;re not interested in my &lt;a href="https://github.com/SaintGimp/GenesisEngine"&gt;GenesisEngine&lt;/a&gt; project or planetary terrain rendering, feel free to move along.&lt;/p&gt;
&lt;p&gt;Ok, so someone recently sent me an email and asked me to write about the various coordinate systems in GenesisEngine.&amp;nbsp; I defined them all briefly with comments in the source code (&lt;a href="https://github.com/SaintGimp/GenesisEngine/blob/master/GenesisEngine/Domain/QuadMesh.cs"&gt;QuadMesh.cs&lt;/a&gt;) but there&amp;rsquo;s a lot more that could be said on the subject.&lt;/p&gt;
&lt;p&gt;As I&amp;rsquo;ve said before, I&amp;rsquo;m not doing any original research here &amp;ndash; I&amp;rsquo;m just borrowing ideas from other places and re-implementing them for my own amusement.&amp;nbsp; For original material you might start with &lt;a href="http://i31www.ira.uka.de/publikationen/files/4_Studproject_JWinzen.pdf"&gt;Jochen Winzen&amp;rsquo;s Interactive Visualization of a Planetary System&lt;/a&gt; paper and then move on to blogs such as the one for the &lt;a href="http://britonia-game.com/"&gt;Britonia&lt;/a&gt; project.&amp;nbsp; This is a pretty complicated topic and I just barely understand it myself.&lt;/p&gt;
&lt;h1&gt;The problem&lt;/h1&gt;
&lt;p&gt;The biggest challenge one faces when building a real-time planetary terrain rendering system is that of numerical precision.&amp;nbsp; First you want to be able to move around on the surface of the planet about six feet off the ground.&amp;nbsp; For that we&amp;rsquo;d like to have terrain mesh resolution of about two meters or so, which requires at least centimeter-level precision in the vertices so we can get smooth elevation changes and have everything fit together nicely.&lt;/p&gt;
&lt;p&gt;An earth-sized planet has a radius of 6,378,100 meters or 637,810,000 centimeters.&amp;nbsp; That number contains nine significant digits, but unfortunately the 32-bit floating point data type only stores approximately seven significant digits.&amp;nbsp; Of course you can use a float to store very large (and very small) numbers, far larger than 637,810,000, but you can only express those very large numbers with seven digits of precision which means you&amp;rsquo;re forced to round off the least significant digits when you go above the single millions.&amp;nbsp; Rounding is fine when you&amp;rsquo;re observing the entire planet at once from far out in space but it&amp;rsquo;s completely unacceptable when you&amp;rsquo;re walking around on the surface.&lt;/p&gt;
&lt;p&gt;To be absolutely clear, the issue here is the number of significant digits, not the order of magnitude of the values.&amp;nbsp; Someone might say, &amp;ldquo;Oh, just use a coordinate system calibrated in kilometers so then your vertices only have to go out to 6378 or so.&amp;nbsp; Problem solved!&amp;rdquo;&amp;nbsp; Actually, no, because in order to let users walk around on a realistic surface your elevation heights are going to have to be specified as something like 6378.17473 km here and 6378.17485 km there, but a float can only store 6378.174 km.&amp;nbsp; The last two digits just disappear.&lt;/p&gt;
&lt;p&gt;We also have a 64-bit double-precision floating point data type available to us.&amp;nbsp; A double can represent about 16 digits of precision, which turns out to be enough to model the entire solar system out to Neptune and beyond at millimeter-level precision.&amp;nbsp; Yeah, there&amp;rsquo;s a big difference between 7 digits and 16 digits, isn&amp;rsquo;t there?&amp;nbsp; So doubles solve our problem.&amp;nbsp; Great!&lt;/p&gt;
&lt;p&gt;Well, there&amp;rsquo;s one catch.&amp;nbsp; XNA, and DirectX underneath it, and the graphics hardware underneath that, deals only with 32-bit floats.&amp;nbsp; We can&amp;rsquo;t build a mesh with double-precision vertices and just tell XNA to render that mesh.&amp;nbsp; We have to build a mesh using floats.&amp;nbsp; We&amp;rsquo;re free to calculate the vertex positions and elevations using doubles but when we go to create an XNA VertexBuffer with that data we have to convert all of the numbers to floats which chops off digits that we really need to keep.&amp;nbsp; Hmmm, what to do?&lt;/p&gt;
&lt;p&gt;On top of that, we also need to wrestle with the fact that curves and spherical objects are hard to work with in a discrete format.&amp;nbsp; Planes and grids we can easily do.&amp;nbsp; Spheres, not so much.&amp;nbsp; It would be great to do the heavy lifting in &amp;ldquo;flat plane&amp;rdquo; mode and only switch over to a spherical shape when we absolutely have to.&lt;/p&gt;
&lt;p&gt;The solution to both problems is to work with several different coordinate systems, each of which are appropriate at a different stage of the mesh-generation pipeline.&amp;nbsp; Whenever you look at spatial data you always have to keep in mind which coordinate system is being used so that you can understand it in context.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s walk through the entire pipeline of a vertex in GenesisEngine from start to finish.&amp;nbsp; This discussion would be helped a lot with some cool diagrams but I&amp;rsquo;m lazy so you&amp;rsquo;ll have to make do with a whole lot of words.&amp;nbsp; Bear with me.&lt;/p&gt;
&lt;p&gt;The planet in GenesisEngine is fundamentally represented by six square, flat quad-trees.&amp;nbsp; Well, they start out as flat then become spherical somewhere along the way.&amp;nbsp; If the camera gets too close and we need more detail than we have, we can split the quad into four equal pieces and repeat the following process for each one of the sub-quads.&amp;nbsp; I&amp;rsquo;m not talking about the quad-tree subdivision in this post so all you really need to understand is that the planet starts out as a box, like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-16-85-metablogapi/8080.image_5F00_3090A80E.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-16-85-metablogapi/5661.image_5F00_thumb_5F00_5AFC1784.png" width="820" height="522" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If we get a little closer each of the quads get split into four sub-quads, like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-16-85-metablogapi/6724.image_5F00_7F012679.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-16-85-metablogapi/3582.image_5F00_thumb_5F00_5444FA02.png" width="820" height="522" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The green border lines indicate the area of the original quad and the red border lines indicate boundaries between sub-quads, which helps us keep track of where we are when things go spherical-shaped later on.&lt;/p&gt;
&lt;h1&gt;Quad grid space&lt;/h1&gt;
&lt;p&gt;The first coordinate system we have to deal with is what I named &amp;ldquo;quad grid&amp;rdquo; coordinates, which is simply the integer column and row of the vertex on the quad.&amp;nbsp; This is a column-major system so the first number gives you the horizontal location and the second number gives you the vertical location.&amp;nbsp; See the next screenshot below which makes the triangles and the vertices that define the triangles a little clearer.&amp;nbsp; (I disabled updates for this shot in order to get in closer without having the quad split.)&amp;nbsp; Each quad has a square grid of 65 by 65 vertices and the triangles are simply lines drawn between them.&amp;nbsp; So a vertex starts life with an identity that says, &amp;ldquo;I&amp;rsquo;m the vertex on the 23rd column and the 37th row of this quad.&amp;rdquo;&amp;nbsp; It doesn&amp;rsquo;t matter how big or small or how many levels deep the quad is because it&amp;rsquo;s all relative to the quad itself.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-16-85-metablogapi/1524.image_5F00_72FB2246.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-16-85-metablogapi/8053.image_5F00_thumb_5F00_1332669F.png" width="820" height="522" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Unit plane space&lt;/h1&gt;
&lt;p&gt;However, the quad doesn&amp;rsquo;t exist in total isolation.&amp;nbsp; It is a member of a group of 1..N quads that make up one of the six faces of the planet, so the next step is to describe this vertex in terms of where it is relative to the face.&amp;nbsp; I called this coordinate system the &amp;ldquo;unit plane&amp;rdquo; system.&amp;nbsp; Let&amp;rsquo;s define the face to have a extent from &amp;ndash;1 to 1 in both directions, so 0,0 is exactly in the center of the face.&amp;nbsp; (I guess that&amp;rsquo;s technically not a unit plane because it&amp;rsquo;s two units wide and long, but oh well.)&amp;nbsp; Each quad has a certain position on that face and so does each of its vertices.&lt;/p&gt;
&lt;p&gt;In the case where we haven&amp;rsquo;t split the original quad then the extents of the quad are the same as the extents of the face, from &amp;ndash;1 to 1 in both directions.&amp;nbsp; So the coordinates of the upper left vertex on this quad are -1, 1 and the lower right is 1, -1, and the rest of the vertices are evenly distributed in 64 equal steps between those extremes in both directions.&lt;/p&gt;
&lt;p&gt;In the case where we have split the quad into four sub-quads, each of them covers one quarter of the face.&amp;nbsp; (Refer to the sub-divided picture above.)&amp;nbsp; So if we examine the upper left quad and consider its upper left vertex, it&amp;rsquo;s &amp;ldquo;unit plane&amp;rdquo; coordinates would be -1, 1 as with the parent quad but its lower right vertex would be 0, 0, which also happens to be the coordinates of the upper left vertex of the lower right quad.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s actually slightly more complicated in practice because we have six faces each facing a different direction in 3D space.&amp;nbsp; The vertices in &amp;ldquo;unit plane&amp;rdquo; space are actually 3D vertices that describe a cube two units wide, long, and deep.&amp;nbsp; For each face, two of the three x-y-z components vary to describe the locations on the face and the other is fixed at 1 or &amp;ndash;1 as appropriate.&amp;nbsp; 0,0,0 is the center of the cube (i.e. the center of the planet).&amp;nbsp; These numbers are unitless so far and would be the same for planets of any real-world size.&lt;/p&gt;
&lt;h1&gt;Unit sphere space&lt;/h1&gt;
&lt;p&gt;Now that we have our vertices laid out in nice, evenly spaced rows and columns across our faces, it&amp;rsquo;s time to get spherical.&amp;nbsp; Conceptually it&amp;rsquo;s not difficult to transform our vertices from box-like to sphere-like; we just bulge out the middles of each face and/or pull in the edges and presto, we have a sphere.&lt;/p&gt;
&lt;p&gt;There are a couple of ways you can do the math here.&amp;nbsp; The most straightforward way is to to take each vertex in &amp;ldquo;unit plane&amp;rdquo; space, treat it vector, and convert it to a unit length vector.&amp;nbsp; Tada, instant sphere.&amp;nbsp; This works ok but results in triangles of uneven sizes over the extents of the face.&amp;nbsp; There is a &lt;a href="http://mathproofs.blogspot.com/2005/07/mapping-cube-to-sphere.html"&gt;better conversion algorithm&lt;/a&gt; that requires a bit more math but gives a nicer result and doesn&amp;rsquo;t cost that much more relative to everything else that&amp;rsquo;s going on.&amp;nbsp; Follow the link to learn more about that.&lt;/p&gt;
&lt;p&gt;Ok, so now we have our vertices transformed to &amp;ldquo;unit sphere&amp;rdquo; space, as in the picture below:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-16-85-metablogapi/0412.image_5F00_002D718E.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-16-85-metablogapi/4212.image_5F00_thumb_5F00_7D73CE68.png" width="820" height="522" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Planet space&lt;/h1&gt;
&lt;p&gt;Now it&amp;rsquo;s time to start thinking about real-world sizes.&amp;nbsp; How big do you want this planet to be?&amp;nbsp; In GenesisEngine the convention is that one unit in &amp;ldquo;planet space&amp;rdquo; coordinates represents one meter of length.&amp;nbsp; To convert from &amp;ldquo;unit sphere&amp;rdquo; coordinates to &amp;ldquo;planet space&amp;rdquo; coordinates we simply multiply the vertex vector by the desired radius of the planet in meters.&amp;nbsp; If we want to do varied terrain heights, which we do because that&amp;rsquo;s kind of the point of this project, we would add the terrain height at this location to the planet radius before multiplying with vertex vector.&amp;nbsp; Now we have a lovely full-sized planet.&lt;/p&gt;
&lt;h1&gt;Mesh space&lt;/h1&gt;
&lt;p&gt;Up to this point all of the math has been done using doubles.&amp;nbsp; Now it&amp;rsquo;s getting close to the time when we have to convert all of these numbers into a mesh we can render, but this is where we run into our issue with significant digits.&amp;nbsp; We&amp;rsquo;ve done all of this work to get beautifully precise numbers that describe every elegant rise and fall of our terrain.&amp;nbsp; We don&amp;rsquo;t really want to dump them into the meat grinder of 32-bit floats.&lt;/p&gt;
&lt;p&gt;The trick here is to temporarily change the origin point of the vertex data so that the origin is exactly in the center of each mesh, or to say it another way, we&amp;rsquo;re going to translate the geometry of each quad down to the planetary origin so that the overall range of numbers isn&amp;rsquo;t so large.&amp;nbsp; This puts us into &amp;ldquo;mesh space&amp;rdquo; which is the same as &amp;ldquo;planet space&amp;rdquo; except that the planet is now disassembled and all of its individual quads are jumbled up on top of each other at the center of the planet.&amp;nbsp; We also remember where each quad mesh is &lt;span style="text-decoration: underline;"&gt;supposed&lt;/span&gt; to be located on the planet&amp;rsquo;s surface so we can reconstruct it in its proper location later.&lt;/p&gt;
&lt;p&gt;What good does that do us?&amp;nbsp; I said above that merely changing the order of magnitude of our coordinate system doesn&amp;rsquo;t help us with the significant digit problem, which is still true.&amp;nbsp; What we&amp;rsquo;re doing here is something different; we&amp;rsquo;re keeping the order of magnitude of the coordinate system the same but we&amp;rsquo;re collapsing the range of values we need to express into just a small part of that range, which reduces the number of significant digits we need to express them.&lt;/p&gt;
&lt;p&gt;Think of it this way: how many significant digits do we need to express the number 12,464,297?&amp;nbsp; Eight digits, too many for a float.&amp;nbsp; But what if we subtract out the 12,000,000 part and hold it somewhere off to the side?&amp;nbsp; How many significant digits do we need to represent 464,297?&amp;nbsp; Only six digits, which does fit in a float.&amp;nbsp; That doesn&amp;rsquo;t solve anything if you&amp;rsquo;re talking only one big number but if you have 65 x 65 = 4,225 big numbers, all of which are relatively close to the same size, then you can subtract some appropriate big number from all of them and be left with 4,225 small numbers to deal with.&lt;/p&gt;
&lt;h1&gt;Rendering big numbers without big numbers&lt;/h1&gt;
&lt;p&gt;Ok, once the vertices are translated into &amp;ldquo;mesh space&amp;rdquo; we finally have numbers that both (indirectly) represent the real world and are suitable for storage in floats.&amp;nbsp; We can build our vertex buffers from these vertices and send them to the graphics card.&lt;/p&gt;
&lt;p&gt;But the mesh data we send to the graphics card is all jumbled up in the same small area.&amp;nbsp; It&amp;rsquo;s not planet-like, so how do we reconstruct the planet?&amp;nbsp; We could set our world matrix to translate each XNA mesh back to where it&amp;rsquo;s supposed to be but that kills our precision.&amp;nbsp; Well, this is where we play a coordinate-system trick with the camera.&amp;nbsp; Instead of moving the view frustum around in our real-world coordinate space, we keep the view frustum fixed at the origin point and we rotate and translate every piece of geometry in the world around the view point.&amp;nbsp; It&amp;rsquo;s kind of like driving down the freeway and imaging that your car is fixed in space while the earth spins beneath it.&lt;/p&gt;
&lt;p&gt;How does that solve our problem?&amp;nbsp; Well, any geometry that&amp;rsquo;s close to the camera is going to be rendered close to the origin (i.e. using small numbers) on the graphics card, so those vertices won&amp;rsquo;t blow the float digit budget.&amp;nbsp; Any geometry that&amp;rsquo;s far away from the camera will be rendered far away from the origin (i.e. using big precision-losing numbers) on the graphics card but that doesn&amp;rsquo;t matter because they&amp;rsquo;re far away and small.&amp;nbsp; Rounding is ok if the viewer isn&amp;rsquo;t close enough to see the damage.&lt;/p&gt;
&lt;p&gt;Specifically, we take a mesh that&amp;rsquo;s encoded to be centered around the origin, and we get its original location relative to the center of the planet (which is still stored in doubles).&amp;nbsp; We also get the location of the camera in real-world space (also stored in doubles).&amp;nbsp; We subtract the camera location from the original location of the mesh which gives us the location of the mesh relative to the camera (in &amp;ldquo;camera space&amp;rdquo;, I guess), and that tells us how much we need to translate the encoded mesh away from the real-world origin in order to appear in the view frustum exactly the same way it would appear if both the mesh and the view frustum were where they were supposed to be in real-world space (which they&amp;rsquo;re not).&lt;/p&gt;
&lt;p&gt;The end result is that all of the numbers stored in 32-bit floats never represent full coordinate values in the world.&amp;nbsp; They only represent differences from some reference value.&amp;nbsp; We can manipulate the reference value to tell us where we need to tell the graphics card to draw the geometry such that everything &lt;span style="text-decoration: underline;"&gt;appears&lt;/span&gt; to be in its proper place, even though to the graphics card itself the perspective is quite different.&amp;nbsp; The important numbers (the ones we see up close and personal) always stay relatively small while in float form and everybody&amp;rsquo;s happy.&lt;/p&gt;
&lt;p&gt;As I said, it&amp;rsquo;s complicated.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10097349" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>Agile Makes Problems Visible</title><link>http://blogs.msdn.com/b/elee/archive/2010/11/25/agile-makes-problems-visible.aspx</link><pubDate>Thu, 25 Nov 2010 19:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10096761</guid><dc:creator>SaintGimp</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10096761</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/11/25/agile-makes-problems-visible.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s often been said that agile project management techniques aren&amp;rsquo;t a silver bullet that will magically solve all of your problems.&amp;nbsp; In fact, their biggest strength lies is not in solving problems, per se, but rather in exposing your buried problems and making them visible so you can deal with them.&amp;nbsp; For a team switching to Agile it can feel like things are getting worse, not better, but that&amp;rsquo;s often because they&amp;rsquo;re being made aware of pre-existing problems they didn&amp;rsquo;t know they had.&amp;nbsp; It may not seem like it but this is actually a good thing.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a real-world example.&amp;nbsp; My &lt;a href="http://blogs.msdn.com/b/elee/archive/2010/11/19/break-time-s-over.aspx"&gt;current team&lt;/a&gt; of six people was recently assembled to build tools for an internal customer.&amp;nbsp; I and one other member have a decent amount of experience with agile approaches but the rest of the team does not.&amp;nbsp; I suggested that everyone read the free ebook &lt;a href="http://www.infoq.com/minibooks/scrum-xp-from-the-trenches"&gt;Scrum and XP from the Trenches&lt;/a&gt; and think about whether they wanted to try that approach.&amp;nbsp; Everyone readily agreed that our situation seems tailor-made for Scrum so we decided to go with it.&lt;/p&gt;
&lt;p&gt;Our team manager did everything right to prepare for our first sprint planning meeting a few weeks ago.&amp;nbsp; He made sure we had a clearly identified product owner, a product backlog of user stories, and he even printed out each story on a separate sheet of paper and taped them up all over a long whiteboard so we could discuss each one and write notes around them and on them as we made our plans.&amp;nbsp; I was quite impressed.&lt;/p&gt;
&lt;p&gt;We started the meeting and after getting through the preliminaries we turned our attention to the first user story on the backlog.&amp;nbsp; The idea was that we were going to talk through about 20 stories to get a feel for the overall strategic direction of the project but within a few minutes we went off the rails.&amp;nbsp; The conversation between the team and our product owner went something like this (not exact quotes, obviously):&lt;/p&gt;
&lt;p&gt;&amp;ldquo;So the first story says the users want to enter information about avails into the system.&amp;nbsp; That information includes these six fields . . .&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Wait, why those six fields?&amp;nbsp; That doesn&amp;rsquo;t make any sense.&amp;nbsp; I thought three of them were part of rights, not avails.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;No, that&amp;rsquo;s part of avails.&amp;nbsp; An avail means [these things].&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Dude, that&amp;rsquo;s not what avail is.&amp;nbsp; You&amp;rsquo;re mixing it up with rights, and maybe pricing rules, too.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;What?!?!?&amp;nbsp; Then what the hell is an avail?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;We spent most of our three-hour meeting getting bogged down in the definition of terms and concepts, not getting anywhere near the original goal of walking through all of the stories.&amp;nbsp; At some point during a painful, aggravated silence our team manager gave me a look that said, &amp;ldquo;Ok, now what, Mr. Agile Genius?&amp;nbsp; You said this was supposed to work.&amp;nbsp; We were supposed to finish this meeting with a&amp;nbsp; sprint plan and that ain&amp;rsquo;t happening.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I raised my hand and said to the room, &amp;ldquo;Ok, point of clarification here.&amp;nbsp; Right now it feels like this process isn&amp;rsquo;t working, right?&amp;nbsp; We&amp;rsquo;ve been going around in circles for two hours because we&amp;rsquo;re not all using the same language.&amp;nbsp; There are several deep misunderstandings that are preventing us from making progress.&amp;nbsp; However, the sprint planning process is doing exactly what it&amp;rsquo;s supposed to be doing.&amp;nbsp; It made us get together in the same room, talk to each other, and discover that we still have some groundwork to do before we can can even have this planning conversation.&amp;nbsp; The Scrum process didn&amp;rsquo;t cause this problem, just just exposed the problem.&amp;nbsp; Not having a shared understanding of the domain concepts is a problem &lt;span style="text-decoration: underline;"&gt;no matter what process you use&lt;/span&gt;.&amp;nbsp; It&amp;rsquo;s far better that we discover this problem right here, right now, rather than write a 50-page spec and do three months of dev work around broken concepts before we realize we&amp;rsquo;re going in the wrong direction.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Fortunately we were able to work through that particular problem and come to agreement on a shared vocabulary by the end of the meeting.&amp;nbsp; We&amp;rsquo;ve had a couple more rough spots crop up since then but in each case we&amp;rsquo;ve identified the source of the problem, solved the problem, and moved on.&amp;nbsp; Progress has not been as quick or as smooth as we imagined it would be but that&amp;rsquo;s not because Scrum isn&amp;rsquo;t working for us; it&amp;rsquo;s because we had a lot of problems to work through and those problems were being made visible quickly so we could identify them and solve them.&lt;/p&gt;
&lt;p&gt;Software development is hard work.&amp;nbsp; I doubt we&amp;rsquo;ll ever find anything that&amp;rsquo;ll change that.&amp;nbsp; &lt;a href="http://en.wikipedia.org/wiki/No_Silver_Bullet"&gt;There are no silver bullets&lt;/a&gt;.&amp;nbsp; But some processes are better than others for pointing you in the right direction and letting you know what problems you need to solve.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10096761" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/project+management/">project management</category><category domain="http://blogs.msdn.com/b/elee/archive/tags/Agile/">Agile</category></item><item><title>ASP.NET MVC 3, IDependencyResolver, and StructureMap</title><link>http://blogs.msdn.com/b/elee/archive/2010/11/19/asp-net-mvc-3-idependencyresolver-and-structuremap.aspx</link><pubDate>Sat, 20 Nov 2010 01:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10094080</guid><dc:creator>SaintGimp</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10094080</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/11/19/asp-net-mvc-3-idependencyresolver-and-structuremap.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;ASP.NET MVC 3 offers new facilities for easy dependency injection in various parts of the application that you might want to implement yourself.&amp;nbsp; Brad Wilson discusses the new features in an &lt;a href="http://bradwilson.typepad.com/blog/2010/07/service-location-pt1-introduction.html"&gt;extensive series of posts&lt;/a&gt;.&amp;nbsp; In the Beta version and beyond, the way you do this is by creating a class that implements IDependencyResolver and serves as an adapter to the IoC container of your choice.&lt;/p&gt;
&lt;p&gt;I happen to like StructureMap as an IoC container so I thought I &amp;lsquo;d wire it up for use in ASP.NET MVC 3.&amp;nbsp; IDependencyResolver isn&amp;rsquo;t exactly a complex interface to implement but being the properly &lt;a href="http://c2.com/cgi/wiki?LazinessImpatienceHubris"&gt;lazy developer&lt;/a&gt; that I am I thought I&amp;rsquo;d look around on the web to see if anyone had already offered up an implementation for StructureMap.&amp;nbsp; I found a few different blog posts that all had pretty much the same code (such as &lt;a href="http://www.userinexperience.com/post/Upgrading-Your-MVC3-Application-from-Preview-1-to-Beta.aspx"&gt;Brandon Satrom&amp;rsquo;s&lt;/a&gt;) so I grabbed it and dropped it into my application.&amp;nbsp; I then tried to have one of my controllers pulled from the container and . . . met with utter failure.&lt;/p&gt;
&lt;p&gt;Specifically, StructureMap kept insisting that it had no idea what I was talking about when my IDependencyResolver adapter asked for an instance of my TitlesController (i.e. container.TryGetInstance(serviceType) was returning null).&amp;nbsp; The framework would then fall back to trying to create an instance on its own which would throw an exception because this controller was designed for dependency injection and didn&amp;rsquo;t have a parameter-less constructor.&lt;/p&gt;
&lt;p&gt;This was particularly aggravating because all the implementations I found on the web seemed to be the same and apparently they were working for other people.&amp;nbsp; I beat my head against this problem for, um, longer than I should have, I guess, until I finally found a &lt;a href="http://groups.google.com/group/structuremap-users/browse_thread/thread/7232b1d3c8bdf3b9"&gt;email thread started by Jimmy Bogard&lt;/a&gt; on the StructureMap users list that clarified the problem for me.&amp;nbsp; The issue is that while StructureMap&amp;rsquo;s Container.GetInstance() will create an instance of a concrete type without it being explicitly registered, Container.TryGetInstance() doesn&amp;rsquo;t do that.&amp;nbsp; Container.TryGetInstance() will give up and return null if the type you&amp;rsquo;re asking for isn&amp;rsquo;t explicitly registered as a plugin type.&amp;nbsp; Coincidentally, the very first thing I was trying to pull out of the container was a concrete type (my controller class).&amp;nbsp; The existing implementations will work for registered interfaces but not for controllers which are requested by concrete type.&lt;/p&gt;
&lt;p&gt;By the way, while researching all of this I ran across &lt;a href="http://groups.google.com/group/structuremap-users/browse_thread/thread/1ef2c8cbb05b6ed8"&gt;this thread&lt;/a&gt; in which Jeremy Miller points out that the original implementation of of IDependencyResolver.GetServices was wrong, too.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s my IDependencyResolver implementation for StructureMap which takes StructureMap&amp;rsquo;s non-intuitive behavior into account and also tries to minimize the number of exceptions that have to be thrown and handled:&lt;/p&gt;
&lt;p&gt;(&lt;span style="color: #ff0000;"&gt;UPDATE&lt;/span&gt;: I removed some registration code from the constructor that was causing confusion and probably wasn't necessary (at least not for resolving concrete controller types, anyway.)&amp;nbsp; If you need to resolve interface types, you'll need to register them with StructureMap in your app's registration code or maybe do it below in the constructor.)&lt;/p&gt;
&lt;div style="background: white;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: 9pt;"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 9pt;"&gt; &lt;span style="color: #0000ff;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;StructureMapDependencyResolver&lt;/span&gt; : &lt;/span&gt;&lt;span style="color: #2b91af; font-size: 9pt;"&gt;IDependencyResolver&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IContainer&lt;/span&gt; _container;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; StructureMapDependencyResolver(&lt;span style="color: #2b91af;"&gt;IContainer&lt;/span&gt; container)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _container = container;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="color: #008000; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // TODO: if you haven't registered necessary interfaces somewhere else, you'll need to do so here.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; GetService(&lt;span style="color: #2b91af;"&gt;Type&lt;/span&gt; serviceType)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;if&lt;/span&gt; (serviceType.IsClass)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&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;"&gt;return&lt;/span&gt; GetConcreteService(serviceType);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff; font-size: 9pt;"&gt;else&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&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;"&gt;return&lt;/span&gt; GetInterfaceService(serviceType);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; GetConcreteService(&lt;span style="color: #2b91af;"&gt;Type&lt;/span&gt; serviceType)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #0000ff; font-size: 9pt;"&gt;try&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #008000; font-size: 9pt;"&gt;// Can't use TryGetInstance here because it won&amp;rsquo;t create concrete types&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&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;"&gt;return&lt;/span&gt; _container.GetInstance(serviceType);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;catch&lt;/span&gt; (&lt;span style="color: #2b91af;"&gt;StructureMapException&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&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;"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff;"&gt;object&lt;/span&gt; GetInterfaceService(&lt;span style="color: #2b91af;"&gt;Type&lt;/span&gt; serviceType)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; _container.TryGetInstance(serviceType);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&amp;gt; GetServices(&lt;span style="color: #2b91af;"&gt;Type&lt;/span&gt; serviceType)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #0000ff;"&gt;return&lt;/span&gt; _container.GetAllInstances(serviceType).Cast&amp;lt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-size: 9pt;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10094080" width="1" height="1"&gt;</description></item><item><title>Break Time’s Over!</title><link>http://blogs.msdn.com/b/elee/archive/2010/11/19/break-time-s-over.aspx</link><pubDate>Sat, 20 Nov 2010 00:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10094073</guid><dc:creator>SaintGimp</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10094073</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/11/19/break-time-s-over.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Winter weather has set in here in Seattle which means much less outdoor playtime for me.&amp;nbsp; I guess that means it&amp;rsquo;s time to get back to blogging!&amp;nbsp; I have a few topics in mind that I&amp;rsquo;m going to try to crank out over the next few days.&amp;nbsp; We&amp;rsquo;ll see how that goes.&lt;/p&gt;
&lt;p&gt;By the way, I recently transferred to a new position within Microsoft working on tools for the content pipeline that feeds the Zune video marketplace.&amp;nbsp; It&amp;rsquo;s pretty cool so far; we have a small, newly formed dev team that&amp;rsquo;s interested in agile processes, lots of interesting challenges, a huge business need to fill, and our customers are right down the hall.&amp;nbsp; Should be a good time.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10094073" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/personal/">personal</category></item><item><title>GenesisEngine: The Task Parallel Library Is Great But Threading Can Still Bite You</title><link>http://blogs.msdn.com/b/elee/archive/2010/07/13/genesisengine-the-task-parallel-library-is-great-but-threading-can-still-bite-you.aspx</link><pubDate>Tue, 13 Jul 2010 08:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10037541</guid><dc:creator>SaintGimp</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10037541</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/07/13/genesisengine-the-task-parallel-library-is-great-but-threading-can-still-bite-you.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The new &lt;a href="http://msdn.microsoft.com/en-us/library/dd460717.aspx"&gt;Task Parallel Library&lt;/a&gt; in the .Net Framework 4.0 is intended to simplify the process of adding concurrency to your application and it does a great job of it.&amp;nbsp; I&amp;rsquo;m really impressed by how well it hides the mechanics of threading and lets you reason declaratively about what you want to do, not how it needs to be done.&lt;/p&gt;
&lt;h1&gt;My real-time engine, um . . . wasn&amp;rsquo;t&lt;/h1&gt;
&lt;p&gt;In &lt;a href="http://github.com/SaintGimp/GenesisEngine"&gt;GenesisEngine&lt;/a&gt;, I had a serious need to do some background processing.&amp;nbsp; As you move around in the world the engine dynamically generates appropriately-detailed quad nodes based on where you are, and generating the terrain meshes for those nodes takes a lot of CPU work.&amp;nbsp; Previously I was splitting nodes into more detailed ones on the main game loop thread during the Update pass and it caused a lot of stuttering in the frame rate.&amp;nbsp; In fact, if you were close the surface you basically couldn&amp;rsquo;t move in real time; you had to turn updates off, move the camera, turn updates back on, and wait for the detail nodes to be generated for your new location.&amp;nbsp; Yeah, it pretty much sucked.&lt;/p&gt;
&lt;p&gt;Clearly it would be desirable to have all of that expensive node splitting and mesh generation happen on a separate thread.&amp;nbsp; First, my laptop has two CPU cores and one of them was just sitting there idle.&amp;nbsp; My desktop machine at work has four cores so three of them were twiddling their thumbs.&amp;nbsp; The future is multi-core so let&amp;rsquo;s get on that train; ok, we need concurrency.&lt;/p&gt;
&lt;p&gt;Second, I&amp;rsquo;d like the the game engine to continue to draw smoothly with whatever quad nodes it has at the moment and then later pick up more detailed nodes as they become available.&amp;nbsp; I don&amp;rsquo;t want the draw loop to be delayed at all by waiting for nodes to be split.&amp;nbsp; That means that not only does the node splitting need to be concurrent but it also needs to be asynchronous.&lt;/p&gt;
&lt;h1&gt;The Task Parallel Library to the rescue&lt;/h1&gt;
&lt;p&gt;Ok, so that didn&amp;rsquo;t sound like fun.&amp;nbsp; I&amp;rsquo;ve written a decent amount of threading code from scratch in my time and while the principles are fairly straightforward the details can be an absolute killer.&amp;nbsp; I wasn&amp;rsquo;t looking forward to doing it again in GenesisEngine so, being a properly lazy developer, I decided to wait until I could use the Task Parallel Library to do it for me.&amp;nbsp; Once Visual Studio 2010 was out and the XNA 4.0 CTP was released, I had all the pieces in place to fix my problem.&amp;nbsp; Many excellent articles have already been written on how to use the TPL so I won&amp;rsquo;t bother with a general tutorial; I&amp;rsquo;ll just present a walkthrough of how I used it to solve a specific problem.&lt;/p&gt;
&lt;p&gt;First, let&amp;rsquo;s look at the code I was trying to make concurrent and asynchronous:&lt;/p&gt;
&lt;div style="font-family: consolas; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Split()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; subextents = _extents.Split();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; subextent &lt;span style="color: blue;"&gt;in&lt;/span&gt; subextents)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; node = _quadNodeFactory.Create();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; node.Initialize(_planetRadius, _planeNormalVector, _uVector, _vVector,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; subextent, Level + 1);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _subnodes.Add(node);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _hasSubnodes = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The Split() method is pretty straightforward:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Divide the extents of the node into four smaller extents.&lt;/li&gt;
&lt;li&gt;Creates new child nodes for each sub-extent.&lt;/li&gt;
&lt;li&gt;Add the new nodes to the list of children.&lt;/li&gt;
&lt;li&gt;Set a flag indicating that it now has children.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The strategy for the new implementation using the Task Parallel Library is pretty similar:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Divide the extents of the node into four smaller extents.&lt;/li&gt;
&lt;li&gt;Create four tasks to run asynchronously and in parallel.&amp;nbsp; Each task will create one child node.&lt;/li&gt;
&lt;li&gt;Create another task that will run when all of the first four tasks have completed.&amp;nbsp; This task will add the new nodes to the list of children and set flags indicating that that split is finished and the node now has children.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Split(&lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; cameraLocation, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; planetLocation)&lt;/p&gt;
&lt;div style="font-family: consolas; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; tasks = CreateBackgroundSplitTasks(cameraLocation, planetLocation);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CreateSplitCompletionTask(tasks);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;Task&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IQuadNode&lt;/span&gt;&amp;gt;&amp;gt; CreateBackgroundSplitTasks(&lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; cameraLocation, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; planetLocation)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _splitInProgress = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; subextents = _extents.Split();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; tasks = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;Task&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IQuadNode&lt;/span&gt;&amp;gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; subextent &lt;span style="color: blue;"&gt;in&lt;/span&gt; subextents)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; capturedExtent = subextent;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; task = &lt;span style="color: #2b91af;"&gt;Task&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IQuadNode&lt;/span&gt;&amp;gt;.Factory.StartNew(() =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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: blue;"&gt;var&lt;/span&gt; node = _quadNodeFactory.Create();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; node.Initialize(_planetRadius, _planeNormalVector, _uVector, _vVector,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; capturedExtent, Level + 1);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; node.Update(cameraLocation, planetLocation);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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: blue;"&gt;return&lt;/span&gt; node;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tasks.Add(task);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; tasks;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;void&lt;/span&gt; CreateSplitCompletionTask(&lt;span style="color: #2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;Task&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IQuadNode&lt;/span&gt;&amp;gt;&amp;gt; tasks)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _splitCompletionTask = &lt;span style="color: #2b91af;"&gt;Task&lt;/span&gt;.Factory.ContinueWhenAll(tasks.ToArray(),&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&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;&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; finishedTasks =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; task &lt;span style="color: blue;"&gt;in&lt;/span&gt; finishedTasks)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _subnodes.Add(task.Result);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _hasSubnodes = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _splitInProgress = &lt;span style="color: blue;"&gt;false&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The second implementation clearly has more code but considering what&amp;rsquo;s being accomplished here, it&amp;rsquo;s remarkably compact and elegant.&amp;nbsp; In CreateBackgroundSplitTasks(), we first set a flag indicating that a split is in progress.&amp;nbsp; This is so that when the main game thread does the next Update pass it won&amp;rsquo;t try to split the node again.&amp;nbsp; Next, we use the StartNew() method of the TPL task factory to create and run tasks that create new nodes.&amp;nbsp; The work that the task performs is defined in a lambda expression.&amp;nbsp; Each task starts running immediately and independently in the background and will return a reference to the newly-created node when it&amp;rsquo;s done.&amp;nbsp; Finally, CreateBackgroundSplitTasks() returns a list of all of the tasks it started.&lt;/p&gt;
&lt;p&gt;How does the node know when all of its children are created and it&amp;rsquo;s safe to draw them?&amp;nbsp; For that we create a fifth task that is dependent on all of the previous four.&amp;nbsp; In CreateSplitCompletionTask() we use the very handy ContinueWhenAll() method of the TPL task factory to create another task that will only run after all of our node-creation tasks have completed.&amp;nbsp; This task puts all of the created nodes into the child list and sets some flags indicating that the split is finished and that the node now has children.&lt;/p&gt;
&lt;p&gt;The great thing about the TPL is that nowhere in this code did I need to think about which threads are going to run which blocks of code, or how many threads I should start up, or even the mechanics of how the different threads should signal to each other.&amp;nbsp; How many cores do I have on this machine?&amp;nbsp; Don&amp;rsquo;t know, don&amp;rsquo;t care.&amp;nbsp; It&amp;rsquo;s all very declarative in nature.&amp;nbsp; It&amp;rsquo;s just, &amp;ldquo;Go away and do these four things in parallel as fast as you can, and when they&amp;rsquo;re all done, do this fifth thing.&amp;rdquo;&amp;nbsp; That&amp;rsquo;s it.&lt;/p&gt;
&lt;p&gt;But!&lt;/p&gt;
&lt;h1&gt;You still have to think about the consequences&lt;/h1&gt;
&lt;p&gt;Using the TPL does &lt;span style="text-decoration: underline;"&gt;NOT&lt;/span&gt; give you a get-out-of-jail-free card.&amp;nbsp; The TPL lets you elegantly express your good concurrency intentions but, as they say, the road to hell is paved with just such.&lt;/p&gt;
&lt;p&gt;If you read both versions of Split() above you&amp;rsquo;ll notice that the TPL version does something that the single-threaded, synchronous version did not: after a node is created, we immediately call Update() on the node.&amp;nbsp; It took me quite a while to infer the need for that.&lt;/p&gt;
&lt;p&gt;When I first wrote the concurrent implementation it seemed to run and generate child nodes ok but there was occasionally a strange artifact where a recently split node wouldn&amp;rsquo;t be drawn correctly at first, leaving a black hole where it was supposed to be.&amp;nbsp; The artifact didn&amp;rsquo;t happen for all new nodes, only a few, and it only lasted for one frame so it was difficult to see exactly what was going on.&amp;nbsp; I eventually deduced the problem by carefully reasoning about the possible interleaving of operations in the parallel implementation.&lt;/p&gt;
&lt;p&gt;Due to the way the synchronous implementation was written, newly-created nodes were guaranteed to be updated before they were drawn.&amp;nbsp; This didn&amp;rsquo;t happen in Split() but happened later in the update pass so it was kind of an implicit contract.&amp;nbsp; In the parallel implementation, on the other hand, there was no particular guarantee that a new node would be updated before being drawn the first time.&amp;nbsp; It turned out that due to timing the background split operation would &lt;span style="text-decoration: underline;"&gt;usually&lt;/span&gt; complete between the draw and update passes so it would get updated in the next pass and then drawn, and everything was fine.&amp;nbsp; Sometimes, however, the background split would complete after an update pass but before a draw pass, and thus would be drawn without ever having been updated.&amp;nbsp; The code didn&amp;rsquo;t crash in this case (it would have been easier to debug if it had), but it didn&amp;rsquo;t draw as expected either.&lt;/p&gt;
&lt;p&gt;The fix was to ensure that each node gets both initialized and updated in the background task before declaring the split operation complete.&amp;nbsp; The new nodes are updated with information that is slightly out of date but that doesn&amp;rsquo;t seem to matter in practice.&lt;/p&gt;
&lt;p&gt;This was one of those tricky concurrency bugs that seems pretty trivial when I describe it in hindsight but it was pretty baffling when I first saw it.&amp;nbsp; The lesson: the TPL lets you easily implement concurrency but it doesn&amp;rsquo;t (and can&amp;rsquo;t) free you from the responsibility of understanding all the myriad of potential race conditions, deadlocks, and other assorted multi-threading nastiness.&amp;nbsp; Sorry, even if you have a nifty library to do the heavy lifting, you still need to understand what it&amp;rsquo;s doing under the covers and how it will impact your code.&lt;/p&gt;
&lt;h1&gt;Concurrency changes contracts&lt;/h1&gt;
&lt;p&gt;The asynchronous implementation created another problem I had to solve.&amp;nbsp; Some of my unit tests started failing.&amp;nbsp; It turned out this was because the tests were causing a node to split and then testing that the correct things happened (child nodes created, etc).&amp;nbsp; The tests were originally written with the assumption that once the call to Split() returned, the post-conditions could be immediately asserted, but with the async implementation that was no longer true.&lt;/p&gt;
&lt;p&gt;The fix here was to capture a reference to the split completion task and make it available to the unit tests so that they could initiate a Split then explicitly wait for the completion task to finish.&amp;nbsp; This necessitated a bit of code in the QuadNode class that serves no other purpose than to aid unit testing but I don&amp;rsquo;t see any way around it.&amp;nbsp; The contract of Split() changed when I changed its implementation.&amp;nbsp; This aspect of the contract wasn&amp;rsquo;t expressed in the method signature but it changed all the same and required a corresponding change in the tests.&amp;nbsp; This just emphasizes the point that you have to think about the consequences every time you pull out the TPL.&lt;/p&gt;
&lt;h1&gt;The TPL is goodness&lt;/h1&gt;
&lt;p&gt;The TPL is a very fine piece of work and it makes implementing concurrency and parallelism dramatically easier.&amp;nbsp; Sure, I still ran into a few hiccups but that&amp;rsquo;s just the nature of the problem space.&amp;nbsp; I was very pleased with the result after I was finished; I can now move around in GenesisEngine and the frame rate stays pretty smooth at all times.&amp;nbsp; The splitting and merging of nodes happens in the background and will eventually catch up with my movements.&amp;nbsp; The engine scales very well with additional cores; on a quad-core processor it&amp;rsquo;s about three times as fast at generating new terrain as it is on a dual-core.&amp;nbsp; (The main game thread runs as fast as possible right now and takes up most of one core, leaving one core available for terrain generation on a dual-core processor and three cores available on a quad-core.)&amp;nbsp; The right thing just happens magically.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s still a lot of work to do to make my implementation less naive.&amp;nbsp; For instance, if a node split is scheduled in the background but the camera moves out of range before it happens, the split request should be discarded without actually doing it.&amp;nbsp; Also, priority should be given to nodes that are currently in the viewing frustum so the user sees the maximum amount of detail at all times.&amp;nbsp; The TPL isn&amp;rsquo;t quite magical enough to do all that for me but I expect it&amp;rsquo;ll give me the tools to do it in a compact and elegant way.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10037541" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>You Get What You Measure</title><link>http://blogs.msdn.com/b/elee/archive/2010/06/13/you-get-what-you-measure.aspx</link><pubDate>Mon, 14 Jun 2010 02:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10024218</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10024218</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/06/13/you-get-what-you-measure.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been participating in more conversations internally about promoting a team-oriented culture at Microsoft.&amp;nbsp; Microsoft has a strong individual-oriented culture which works well for many things but doesn&amp;rsquo;t work so well for agile software development.&amp;nbsp; The question of paying (at least partly) based on team results rather than individual results came up, and it&amp;rsquo;s an interesting thing to think about.&lt;/p&gt;
&lt;p&gt;Many groups at Microsoft strongly focus individual-contributor evaluations on individual results, not team or product results.&amp;nbsp; For instance, a developer might be evaluated on the number of product features he delivered and the number of bugs found in his code.&amp;nbsp; That&amp;rsquo;s understandable in the sense that that individual results are easy to define and easy to measure, but a huge problem in that there&amp;rsquo;s no guarantee that successful execution on a random collection of individual commitments will result in working software.&lt;/p&gt;
&lt;p&gt;That is to say, all of the PMs can successfully write specs, all of the devs can successfully write code, and all of the testers can successfully find bugs, and yet the business fails to make money because the parts didn&amp;rsquo;t synthesize together into a cohesive whole.&amp;nbsp; Of course when you get to the senior manager level you start to see commitments that explicitly say, &amp;ldquo;Ship a successful product,&amp;rdquo; but ICs don&amp;rsquo;t usually have that in their goals and aren&amp;rsquo;t incentivized to make decisions that might promote the &amp;ldquo;ship a successful product&amp;rdquo; goal at the expense of their own individual goals.&lt;/p&gt;
&lt;p&gt;The root issue here is the general failure mode of all metrics.&amp;nbsp; If you define a metric and evaluate people on it, then people will optimize for delivering on that metric.&amp;nbsp; When your metrics represent only secondary attributes rather than your true core goal, then you&amp;rsquo;re at high risk of people optimizing in ways that actually hurt your core goal rather than help it.&amp;nbsp; Metrics are useful in direct proportion to how closely they represent the core goal.&amp;nbsp; At Microsoft, our core goal is to deliver successful software products.&amp;nbsp; Our evaluation and compensation system ought to be tied as closely to that core goal as we can possibly get it.&lt;/p&gt;
&lt;p&gt;Unfortunately our core goal is rather fuzzy.&amp;nbsp; Well, I guess measuring achievement of the core goal is pretty straightforward but mapping the ultimate end result back to the individual contributions that people made to get you there is really, really hard to do in an objective, measurable fashion.&amp;nbsp; When we try to solve that problem we inevitably end up measuring indirect effects rather than primary causes, which makes people optimize on the wrong things, and we&amp;rsquo;re right back where we started.&lt;/p&gt;
&lt;p&gt;It would be great if we could come up with an evaluation and compensation system that would explicitly encourage people to stop and ask themselves, &amp;ldquo;What is the one thing I could do today that would have the greatest impact on shipping a successful product,&amp;rdquo; rather than asking themselves, &amp;ldquo;What did I write down in my commitments last summer that I haven&amp;rsquo;t done yet?&amp;rdquo;&amp;nbsp; That difference in mentality may be subtle but it has far-reaching implications in behaviors and the choices we make.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10024218" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/project+management/">project management</category><category domain="http://blogs.msdn.com/b/elee/archive/tags/Agile/">Agile</category></item><item><title>Learn The Why, Not Just The How</title><link>http://blogs.msdn.com/b/elee/archive/2010/05/25/learn-the-why-not-just-the-how.aspx</link><pubDate>Wed, 26 May 2010 05:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10015356</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10015356</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/05/25/learn-the-why-not-just-the-how.aspx#comments</comments><description>&lt;h1&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In another conversation on an internal email thread, someone asked some newbie questions about Scrum daily standup meetings, like do they have to be every day or could they be done every three days or so?&amp;nbsp; There were some good replies that encouraged the standard practice of daily meetings, then someone else mentioned that since his team sits together in one common team room, they communicate all day long and they&amp;rsquo;ve found the daily standup meeting to be not really necessary at all.&lt;/p&gt;
&lt;p&gt;I thought that was a interesting point and replied:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That&amp;rsquo;s a good example of why it&amp;rsquo;s important to understand the &lt;span style="text-decoration: underline;"&gt;goals&lt;/span&gt; that any given methodology is trying to achieve, not just the ceremonies that it uses to achieve them.&amp;nbsp; The goal in this case is a short feedback cycle, shared understanding of what all team members are doing, and identification of the most important things to be working on right at this moment.&amp;nbsp; The mechanism you use to achieve that is really beside the point if you&amp;rsquo;re able to effectively drive the goal.&amp;nbsp; Scrum&amp;rsquo;s mechanism of the daily standup meeting is very effective for the vast majority of Microsoft teams who have individual offices.&amp;nbsp; If you&amp;rsquo;re fortunately enough to have extremely high communication going on all day long, then sure, I can see how a daily standup would not be as important.&lt;/p&gt;
&lt;p&gt;Anyone who tries to implement Scrum (or any other new methodology) without understanding the end goals and how the individual practices are intended to express those goals is pretty much doomed to failure.&amp;nbsp; I suppose you can start out that way (I guess I did, come to think of it) but you can&amp;rsquo;t continue for very long that way.&amp;nbsp; You have to understand the &amp;ldquo;why&amp;rdquo;, not just the &amp;ldquo;how&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Time and time again when I see a person or a team who is fumbling along with agile practices (whether that&amp;rsquo;s Scrum, XP, TDD, design patterns, or anything else) and it&amp;rsquo;s not really working for them, it&amp;rsquo;s usually because people are just going through the motions they&amp;rsquo;ve read about without any real understanding of the principles, the philosophy, and the goals involved.&amp;nbsp; There&amp;rsquo;s usually some &lt;a href="http://en.wikipedia.org/wiki/Cargo_cult_programming"&gt;cargo cult engineering&lt;/a&gt; going on.&amp;nbsp; This causes at least two types of serious problems:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Either they slavishly follow every detail of the methodology without considering the unique circumstances of their project and adapting certain aspects of the process to best fit what they need,&lt;/li&gt;
&lt;li&gt;Or they start slicing and dicing the methodology, throwing out whatever they don&amp;rsquo;t immediately like or whatever seems difficult to implement without having any sort of plan to accomplish the same goals by other means.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;a href="http://agilemanifesto.org/"&gt;Agile Manifesto&lt;/a&gt; calls for favoring individuals and interactions over processes and tools.&amp;nbsp; No methodology should be followed to the letter without thought, but most methodologies have important, specific reasons for every practice they prescribe.&amp;nbsp; The only way we can favor people over processes and still deliver working software is if we understand the &amp;ldquo;why&amp;rdquo; of our processes so we can intelligently mold them to fit our people.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10015356" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/project+management/">project management</category><category domain="http://blogs.msdn.com/b/elee/archive/tags/Agile/">Agile</category></item><item><title>I’m Speaking 5/13/10 At The South Sound .Net User’s Group</title><link>http://blogs.msdn.com/b/elee/archive/2010/05/12/i-m-speaking-5-13-10-at-the-south-sound-net-user-s-group.aspx</link><pubDate>Thu, 13 May 2010 05:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10012276</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10012276</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/05/12/i-m-speaking-5-13-10-at-the-south-sound-net-user-s-group.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When reading other people&amp;rsquo;s blogs I usually skip over the posts where they announce where they&amp;rsquo;re speaking next, or where they&amp;rsquo;re traveling to, or what they&amp;rsquo;re having for lunch, blah, blah, blah.&amp;nbsp; But now I&amp;rsquo;m going to join the dark side and do it too!&lt;/p&gt;
&lt;p&gt;Tomorrow, 5/13/10, I&amp;rsquo;m doing a talk titled &amp;ldquo;Introduction to Agile Philosophy and Techniques&amp;rdquo; at the &lt;a href="http://www.ssdotnet.org/"&gt;South Sound .Net User&amp;rsquo;s Group&lt;/a&gt; in Olympia, Washington.&amp;nbsp; We&amp;rsquo;re going to talk about the alphabet soup of ideas that make agile development work; DRY, YAGNI, SRP, OCP, DIP, LoD and all the rest.&amp;nbsp; If you&amp;rsquo;re in the area, feel free to join us.&amp;nbsp; If you want to do &amp;ldquo;agile development&amp;rdquo; but don&amp;rsquo;t quite understand what that means, this talk should give you a pretty good overview of the fundamentals and give you hooks for further exploration.&amp;nbsp; If you already understand what all those acronyms stand for and what they mean, then come add your voice to the conversation!&amp;nbsp; Time and place can be found on the web site.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10012276" width="1" height="1"&gt;</description></item><item><title>Multi-task At The Team Level, Not The Individual Level</title><link>http://blogs.msdn.com/b/elee/archive/2010/05/12/multi-task-at-the-team-level-not-the-individual-level.aspx</link><pubDate>Thu, 13 May 2010 04:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10012260</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10012260</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/05/12/multi-task-at-the-team-level-not-the-individual-level.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My current work environment is pretty typical of a lot of tools teams, IT shops, and similar groups; we have lots of relatively small projects to build and maintain.&amp;nbsp; In fact, we have far more projects than we have people in each discipline (Dev, Test, PM).&amp;nbsp; This obviously means that we don&amp;rsquo;t have the luxury of assigning individuals to one and only one project for long periods of time; we have to slice up our time and devote attention to multiple projects in turn.&amp;nbsp; Given that&amp;rsquo;s the reality of our situation, though, there are still different ways we can go about doing that, some healthier than others.&amp;nbsp; We can multi-task at either an individual level or at a team level.&lt;/p&gt;
&lt;h4&gt;Individuals&lt;/h4&gt;
&lt;p&gt;Multi-tasking at an individual level means that Joe is splitting his time between the Widget project and the Froberg project, while Sally is splitting her time between the Froberg project and the Walleye project.&amp;nbsp; Every individual has a different portfolio of projects that they&amp;rsquo;re responsible for.&amp;nbsp; The benefit of this strategy is that it gives us maximum flexibility to allocate scarce engineers in a way that seems to cover all the holes on paper.&amp;nbsp; There are several very expensive costs, however:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;People rapidly shift from project to project which means that no one develops a deep and strategic understanding of any one project.&lt;/li&gt;
&lt;li&gt;Because people are always coming and going on a given project, it&amp;rsquo;s hard to develop a sense of team identity or to develop productive working relationships with colleagues.&lt;/li&gt;
&lt;li&gt;Individuals are often left to make their own choices from day to day about which project is most in need of their attention at the moment.&amp;nbsp; There&amp;rsquo;s no strategic thinking about priorities or about how to spend the overall time budget of the group.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we multi-task at an individual level, we often end up building plans for our projects that assume 100% allocation when that&amp;rsquo;s not really the case.&amp;nbsp; For instance, say that we have work happening on the Widget project and the Froberg project at the same time.&amp;nbsp; From a group planning and budgeting perspective, it might look like we have one team devoted 100% to Widget and another team devoted 100% to Froberg and that the work should be able to proceed in parallel.&amp;nbsp; But in reality that&amp;rsquo;s not the case because Joe is double-booked for both projects.&amp;nbsp; That puts him in an awkward position because now he has to decide on a day-to-day basis which is more urgent: Widget or Froberg.&amp;nbsp; That decision isn&amp;rsquo;t being made by the project owners and it&amp;rsquo;s not being made strategically; it&amp;rsquo;s being made individually and tactically.&amp;nbsp; Despite people&amp;rsquo;s best intentions, that kind of system usually devolves into a last-in-first out work queue, i.e. we work on whatever was most recently brought to our attention.&lt;/p&gt;
&lt;h4&gt;Teams&lt;/h4&gt;
&lt;p&gt;On the other hand, we could multi-task at a team level.&amp;nbsp; In other words, we could build a stable, consistent Dev/Test/PM team that has explicit responsibility for both the Widget and Froberg projects, while another stable team has responsibility for Walleye and something else.&amp;nbsp; We still have multiple projects that need to be worked on, and we still need to make priority decisions between them, but now the trade-offs are visible in the budgeting, planning, and strategic thinking realms.&amp;nbsp; Say the team is working on a new Widget feature.&amp;nbsp; Oops, we have an urgent Froberg bug that needs to be fixed!&amp;nbsp; What&amp;rsquo;s the cost of handling that?&amp;nbsp; Well, the cost is that we postpone the Widget project while the whole team shifts its attention to Froberg.&amp;nbsp; Is it worth it?&amp;nbsp; Maybe, maybe not, but now we can have a proper discussion about it.&amp;nbsp; It&amp;rsquo;s very clear and obvious.&amp;nbsp; You can&amp;rsquo;t just sneak it in under the radar.&lt;/p&gt;
&lt;p&gt;The costs were there in the individual model, too &amp;ndash; if Joe is working on Froberg today then by definition he&amp;rsquo;s not helping Widget make progress &amp;ndash; but the costs were hidden.&amp;nbsp; The individual model seems like it&amp;rsquo;s easier to work with in the short term because it avoids the&amp;nbsp; hard priority choices but those choices still need to be made and it&amp;rsquo;s best if they&amp;rsquo;re made explicitly rather than on an ad hoc basis.&lt;/p&gt;
&lt;h4&gt;Agile Means Teams&lt;/h4&gt;
&lt;p&gt;Of course there are multiple agile project management methodologies that emphasize the team as the unit of work.&amp;nbsp; Scrum prescribes a team, a backlog, and a sprint full of work that is locked.&amp;nbsp; If something urgent comes up, it gets prioritized into the product backlog for the next sprint and everything else necessarily shifts down in the stack.&amp;nbsp; The benefit and the cost are clear to everyone.&lt;/p&gt;
&lt;p&gt;Kanban describes a similar system but emphasizes continuous single-piece workflow which is probably a better fit than Scrum if you&amp;rsquo;re juggling lots of small, unpredictable jobs across multiple projects.&amp;nbsp; If something new comes up, slot it into the backlog and everything else gets bumped down.&amp;nbsp; The team continually pulls from the top of the list and you can forecast a pretty accurate time to delivery for any point in the backlog.&lt;/p&gt;
&lt;p&gt;Even groups who like agile methods and are trying to practice them sometimes have a hard time breaking the habit of treating the individual as the unit of work.&amp;nbsp; Every time they slip back into that old habit everything gets much more unpredictable and velocity falls dramatically.&amp;nbsp; It&amp;rsquo;s inevitable.&amp;nbsp; The way to make agile methods work is to keep the team together as a cohesive unit and feed them the work you want the most.&amp;nbsp; Don&amp;rsquo;t steal individuals for side projects.&amp;nbsp; Multi-task at the team level, not the individual level.&lt;/p&gt;
&lt;p&gt;(Whew, I wrote that whole post without once using the word &amp;ldquo;resource&amp;rdquo;.&amp;nbsp; It was harder than it sounds!&amp;nbsp; :-) )&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10012260" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/project+management/">project management</category><category domain="http://blogs.msdn.com/b/elee/archive/tags/Agile/">Agile</category></item><item><title>When Is A Sprint A Failure?</title><link>http://blogs.msdn.com/b/elee/archive/2010/05/07/when-is-a-sprint-a-failure.aspx</link><pubDate>Sat, 08 May 2010 04:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10009485</guid><dc:creator>SaintGimp</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=10009485</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/05/07/when-is-a-sprint-a-failure.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s another question that was asked on one of our internal distribution lists:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When do we consider a sprint to be a failure?&amp;nbsp; I don&amp;rsquo;t know the answer and have no clue about it.&amp;nbsp; We delivered 7 out of 9 stories we committed with all the release criteria, but we failed to deliver two stories due to under-estimation of the stories we picked.&amp;nbsp; Is this a failed sprint?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This stirred an interesting discussion about sprint commitments, continuous improvement, estimation, retrospectives, and numerous other things.&amp;nbsp; This was my contribution to the thread:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The phrase &amp;ldquo;sprint failure&amp;rdquo; in Scrum has a pretty specific meaning to a lot of people.&amp;nbsp; It means that at some point before the end of the sprint, you realize that your sprint plan has gone so far off the rails that the best thing you can do is to abort the sprint before it&amp;rsquo;s completed and build a new plan.&lt;/p&gt;
&lt;p&gt;What if halfway through your sprint you realize that you&amp;rsquo;re probably going to be able to deliver only 7 of your 9 stories?&amp;nbsp; Should you abort the sprint at that point and plan a new one?&amp;nbsp; I guess it depends on the specifics of the stories but almost always I&amp;rsquo;d say no.&amp;nbsp; You&amp;rsquo;re a little off the plan but not drastically so.&amp;nbsp; That&amp;rsquo;s not uncommon.&amp;nbsp; Keep going, deliver value, and afterwards figure out if there are improvements you can make for next time.&lt;/p&gt;
&lt;p&gt;The original poster is apparently not talking about aborting a sprint halfway through.&amp;nbsp; He&amp;rsquo;s talking about working until the end of the sprint then labeling the results.&amp;nbsp; I think he needs to define what he means by &amp;ldquo;failure&amp;rdquo; here.&amp;nbsp; Does he mean, &amp;ldquo;we should reflect on what happened and look for opportunities to improve?&amp;rdquo;&amp;nbsp; Sure, I agree with that, though I&amp;rsquo;d probably stay away from the term &amp;ldquo;failure&amp;rdquo; because it can be easily misunderstood.&amp;nbsp; Does he mean, &amp;ldquo;there are negative consequences imposed on the team?&amp;rdquo;&amp;nbsp; I emphatically disagree with that.&amp;nbsp; Not delivering 2 of 9 stories is not an outcome that should be punished.&lt;/p&gt;
&lt;p&gt;If it&amp;rsquo;s treated as something to be punished then I guarantee that the team will adopt counter-productive behaviors.&amp;nbsp; In this case, they&amp;rsquo;ll probably just low-ball all of their commitments so that there&amp;rsquo;s very little possibility of failing to deliver.&amp;nbsp; This doesn&amp;rsquo;t help increase efficiency and reduce waste, though, because there&amp;rsquo;s no learning and improvement going on, just self-defense strategies.&lt;/p&gt;
&lt;p&gt;One of the potential weaknesses of Scrum is that it&amp;rsquo;s easy to get too fixated on the concept of a sprint commitment and whether you fulfilled or failed to fulfill that commitment.&amp;nbsp; Some measure of predictability is important, sure.&amp;nbsp; But no &lt;span style="text-decoration: underline;"&gt;estimation technique is foolproof&lt;/span&gt; and you can waste an awful lot of time trying to perfect something that is inherently imperfect.&amp;nbsp; Always remember that the goal is simply &amp;ldquo;good enough&amp;rdquo; estimation because estimation isn&amp;rsquo;t value, it&amp;rsquo;s just a means to an end.&lt;/p&gt;
&lt;p&gt;I think this is one of the reasons why there&amp;rsquo;s been a lot of attention paid to &lt;a href="http://www.infoq.com/articles/hiranabe-lean-agile-kanban"&gt;Kanban&lt;/a&gt; and single-piece flow systems lately; because Kanban gets rid of the sprint timebox and all of the potential distractions that go along with it.&amp;nbsp; I personally feel that Scrum and Kanban aren&amp;rsquo;t mutually exclusive and if you merge the best of both systems you&amp;rsquo;ll knock the rough edges off of both.&amp;nbsp; (Some people use the term &amp;ldquo;&lt;a href="http://leansoftwareengineering.com/ksse/scrum-ban/"&gt;Scrum-ban&lt;/a&gt;&amp;rdquo;.)&amp;nbsp; One of the best influences Kanban can have on Scrum is to put the concept of a sprint commitment into its proper perspective, that is, it&amp;rsquo;s a device for short-term planning, nothing more.&amp;nbsp; Relax!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The sprint retrospective is a powerful tool for change and improvement but it only works if you approach it from a positive perspective of &amp;ldquo;how can we become better?&amp;rdquo; rather than a negative perspective of &amp;ldquo;how badly did we fail?&amp;rdquo;.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Always beware the Law of Unintended Consequences.&amp;nbsp; Whenever you&amp;rsquo;re working with a system that contains humans you&amp;rsquo;ll find that some things you implement for positive reasons end up having negative results because they reinforce the wrong behaviors.&amp;nbsp; I think an over-emphasis on sprint commitments, and and insistence on labeling each sprint as a success or failure, is one of those things.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10009485" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/project+management/">project management</category><category domain="http://blogs.msdn.com/b/elee/archive/tags/Agile/">Agile</category></item><item><title>GenesisEngine: Listen To The Tests!</title><link>http://blogs.msdn.com/b/elee/archive/2010/04/20/genesisengine-listen-to-the-tests.aspx</link><pubDate>Wed, 21 Apr 2010 04:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9999744</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9999744</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/04/20/genesisengine-listen-to-the-tests.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As I wrote last time, I made &lt;a href="http://blogs.msdn.com/elee/archive/2010/04/18/genesisengine-yes-srp-violations-hurt.aspx"&gt;a bit of a mess&lt;/a&gt; in my &lt;a href="http://github.com/SaintGimp/GenesisEngine/"&gt;GenesisEngine&lt;/a&gt; project by jamming too many responsibilities into one class.&amp;nbsp; I&amp;rsquo;m working on straightening that out and ran across some interesting observations already.&amp;nbsp; I&amp;rsquo;m not finished yet but I&amp;rsquo;ll share what I&amp;rsquo;ve discovered so far.&lt;/p&gt;
&lt;h4&gt;Performing the surgery&lt;/h4&gt;
&lt;p&gt;I decided to first separate the quad tree node responsibilities from the mesh generation responsibilities since there didn&amp;rsquo;t seem to be a lot of entangling between them and it appeared to be a straightforward exercise.&amp;nbsp; It turned out that there actually was a fair bit of entanglement in the split/merge logic and the tests helped me identify that and sort it out.&amp;nbsp; I&amp;rsquo;m a big believer in TDD and I&amp;rsquo;m still often surprised at how much clear feedback my unit tests give me about the quality of my design . . . if I take the time to listen!&lt;/p&gt;
&lt;p&gt;Side note: as I&amp;rsquo;ve said before, I&amp;rsquo;m working on the GenesisEngine project and blogging about it in part because I wanted to provide some real-world examples that are a bit more complex and interesting than the typical toy problems you see in &amp;ldquo;intro to &amp;lt;foo&amp;gt;&amp;rdquo; materials.&amp;nbsp; The downside of real-world examples is that it&amp;rsquo;s a lot harder to paste in a bit of code that adequately illustrates what I&amp;rsquo;m talking about, since, well, it&amp;rsquo;s complex.&amp;nbsp; I&amp;rsquo;ll do my best but if you&amp;rsquo;re really interested in understanding what&amp;rsquo;s going on you should probably inspect the diffs on GitHub or grab the code and study it.&lt;/p&gt;
&lt;p&gt;So what happened?&amp;nbsp; The first step in breaking up my SRP problem was to create a new QuadMesh class to handle the generation and management of the terrain mesh data.&amp;nbsp; I moved the mesh code from QuadNode to QuadMesh and also created new QuadMeshRenderer and QuadMeshSpecs classes plus several other ancillary files.&amp;nbsp; Once that was done I had to resolve several compiler errors because it turned out that QuadNode.Update() relied on the presence of the mesh data which was no longer there.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the original version of QuadNode.Update():&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Update(&lt;span style="color: #2b91af;"&gt;TimeSpan&lt;/span&gt; elapsedTime, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; cameraLocation, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; planetLocation, &lt;span style="color: #2b91af;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&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; ClippingPlanes&lt;/span&gt; clippingPlanes)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; cameraRelationship = GetRelationshipToCamera(cameraLocation);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DetermineVisibility(cameraLocation, planetLocation, cameraRelationship.ClosestVertex);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (_isVisible)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (clippingPlanes.Near &amp;gt; cameraRelationship.ClosestDistance)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; clippingPlanes.Near = cameraRelationship.ClosestDistance;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (clippingPlanes.Far &amp;lt; cameraRelationship.FurthestDistance)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; clippingPlanes.Far = cameraRelationship.FurthestDistance;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; distanceFromCamera = cameraRelationship.ClosestDistance;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (_isVisible &amp;amp;&amp;amp; distanceFromCamera &amp;lt; RealWidth() * 1 &amp;amp;&amp;amp; !_hasSubnodes&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;&amp;amp; Level &amp;lt; _settings.MaximumQuadNodeLevel)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Split();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;else&lt;/span&gt; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (distanceFromCamera &amp;gt;= RealWidth() * 1.2 &amp;amp;&amp;amp; _hasSubnodes)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Merge();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (_hasSubnodes)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; subnode &lt;span style="color: blue;"&gt;in&lt;/span&gt; _subnodes)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; subnode.Update(elapsedTime, cameraLocation, planetLocation, clippingPlanes);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The GetRelationshipToCamera() method returned a private CameraRelationship DTO, which looked like this:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;CameraRelationship&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; ClosestVertex { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; FurthestVertex { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;double&lt;/span&gt; ClosestDistance { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;double&lt;/span&gt; FurthestDistance { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The compiler errors were in QuadNode.GetRelationshipToCamera().&amp;nbsp; The basic idea here is that QuadNode used to be looking at the mesh data and figuring out the distance from the camera to the closest vertex and the furthest vertex, and then was using that data to do several things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Figure out whether the node is visible&lt;/li&gt;
&lt;li&gt;Set the clipping planes appropriately if this node is closer or father than the clipping planes already are&lt;/li&gt;
&lt;li&gt;Decide whether to split or merge the node based on the ratio of camera distance to the real-space width of the node.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Complications set in&lt;/h4&gt;
&lt;p&gt;Ok, so obviously the GetRelationshipToCamera method needs to move to QuadMesh because it&amp;rsquo;s inspecting the mesh data, and the CameraRelationship class needs to be promoted to public so it can be shared between QuadNode and QuadMesh.&amp;nbsp; QuadNode.Update() would call QuadMesh.GetRelationshipToCamera() and use the returned CameraRelationship DTO as it has been before.&amp;nbsp; Simple.&amp;nbsp; I made those changes (among others) and got everything to compile.&amp;nbsp; There was only one change to QuadNode.Update(), which now looked like this:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Update(&lt;span style="color: #2b91af;"&gt;TimeSpan&lt;/span&gt; elapsedTime, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; cameraLocation, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; planetLocation, &lt;span style="color: #2b91af;"&gt;ClippingPlanes&lt;/span&gt; clippingPlanes)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; cameraRelationship = _mesh.GetRelationshipToCamera(cameraLocation);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// Other stuff is the same . . .&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I then looked at my failing tests.&amp;nbsp; Hmmm.&amp;nbsp; All of my specs related to splitting and merging were failing because the stubbed-out QuadMesh object was returning null from GetRelationshipToCamera().&amp;nbsp; That&amp;rsquo;s not going to work.&amp;nbsp; To solve that, I would need to create a CameraRelationship object in the spec context, populate it with specific numbers that would cause QuadNode to make the correct decision, and configure GetRelationshipToCamera() on the QuadMesh stub to return it.&amp;nbsp; That means I&amp;rsquo;d have to think really hard about what the numbers ought to be in order to provoke the desired behavior in each spec context.&amp;nbsp; Yuck.&lt;/p&gt;
&lt;p&gt;The good news is that I&amp;rsquo;m lazy and that sounded like a lot of work.&amp;nbsp; Way too much work, in fact.&amp;nbsp; I thought about it for a couple of seconds and remembered the golden rule of TDD: &amp;ldquo;If you have to work hard to write your tests, you&amp;rsquo;re doing it wrong.&amp;rdquo;&lt;/p&gt;
&lt;h4&gt;Laziness FTW!&lt;/h4&gt;
&lt;p&gt;Ok, what am I doing wrong here?&amp;nbsp; I have QuadNode going out to QuadMesh, retrieving a bunch of data, and making decisions based on that data.&amp;nbsp; What kind of decisions?&amp;nbsp; The same ones I listed above:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Is the node visible to the camera?&lt;/li&gt;
&lt;li&gt;Do the clipping planes need to be adjusted to include this node?&lt;/li&gt;
&lt;li&gt;What is the ratio of camera distance to the real-space width of the node?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These decisions all have something to do with the mesh data:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The visibility of the node is determined by the mesh because while a quad node has a 2D area, a mesh has a 3D volume.&amp;nbsp; A large mountain may stick up over the horizon and be visible.&lt;/li&gt;
&lt;li&gt;The clipping plane adjustments are determined by the mesh for the same reason: the mesh is 3D.&lt;/li&gt;
&lt;li&gt;The camera distance part of the ratio is determined by the closest part of the node, which again is determined by the 3D mesh.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It&amp;rsquo;s at about this point that I got a mental image in my head of my unit test suite as a grizzled old sensei glowering at me, saying, &amp;ldquo;Have you learned nothing!&amp;nbsp; Leave me and meditate upon the design principles!&amp;nbsp; Perhaps you will find wisdom.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I was trying to violate at least two principles with my stupid approach.&amp;nbsp; First, the &lt;a href="http://en.wikipedia.org/wiki/Law_of_Demeter"&gt;Law of Demeter&lt;/a&gt;, or &amp;ldquo;only talk to your immediate neighbors.&amp;rdquo;&amp;nbsp; QuadNode was reaching through QuadMesh into the CameraRelationship object to get data.&lt;/p&gt;
&lt;p&gt;Second, the &lt;a href="http://www.pragprog.com/articles/tell-dont-ask"&gt;Tell, Don&amp;rsquo;t Ask&lt;/a&gt; principle, or &amp;ldquo;don&amp;rsquo;t ask for information you need to do something, ask the object holding the data to do it for you.&amp;rdquo;&amp;nbsp; Rather than telling QuadMesh to make decisions based on its private data and inform QuadNode of the results as I should have done, I was grabbing data from QuadMesh, moving it to QuadNode, and making the decision there.&lt;/p&gt;
&lt;h4&gt;Mind your own business&lt;/h4&gt;
&lt;p&gt;Ok, so how to fix it?&amp;nbsp; The fixes were pretty simple once I had the principles firmly in my mind:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ask the QuadMesh whether it is visible to the camera.&amp;nbsp; It has all the information needed to make that decision.&lt;/li&gt;
&lt;li&gt;Forward the clipping planes to the QuadMesh and have it modify them if necessary.&lt;/li&gt;
&lt;li&gt;Have QuadMesh calculate the ratio of of camera distance to the real-space width of the node and return that number.&amp;nbsp; (This is technically still getting data from QuadMesh but it&amp;rsquo;s data that&amp;rsquo;s easily stubbed out and I&amp;rsquo;m ok with this until I find something wrong with it.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;rsquo;s the new QuadNode.Update() method which properly tells QuadMesh to do work and make decisions on its behalf:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Update(&lt;span style="color: #2b91af;"&gt;TimeSpan&lt;/span&gt; elapsedTime, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; cameraLocation, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; planetLocation, &lt;span style="color: #2b91af;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: #2b91af;"&gt;&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; ClippingPlanes&lt;/span&gt; clippingPlanes)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mesh.Update(elapsedTime, cameraLocation, planetLocation, clippingPlanes);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (_mesh.IsVisibleToCamera &amp;amp;&amp;amp; _mesh.WidthToCameraDistanceRatio &amp;lt; 1 &amp;amp;&amp;amp; !_hasSubnodes&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;&amp;amp; Level &amp;lt; _settings.MaximumQuadNodeLevel)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Split();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;else&lt;/span&gt; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (_mesh.WidthToCameraDistanceRatio &amp;gt; 1.2 &amp;amp;&amp;amp; _hasSubnodes)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Merge();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (_hasSubnodes)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; subnode &lt;span style="color: blue;"&gt;in&lt;/span&gt; _subnodes)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; subnode.Update(elapsedTime, cameraLocation, planetLocation, clippingPlanes);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;There&amp;rsquo;s another interesting lesson here as well, derived from Tell, Don&amp;rsquo;t Ask: it&amp;rsquo;s ok to create public members on the class that are highly specific to questions that other classes need to ask, as long as doing so helps you to hide private information.&amp;nbsp; The QuadMesh.WidthToCameraDistanceRatio is a very specific sort of property.&amp;nbsp; If I were designing this class as part of a generalized public framework this wouldn&amp;rsquo;t be something it would occur to me to implement.&amp;nbsp; But I&amp;rsquo;m not designing a public framework; I&amp;rsquo;m designing a highly specific set of application classes that work with each other to solve a problem.&amp;nbsp; In this case my goal should be to keep as much information hidden as possible (in this case, like the distance from the camera to the mesh) and only expose answers to questions or processed information that answers a specific question.&amp;nbsp; This reduces coupling, increases cohesion, and makes the code more flexible and maintainable in the long run.&lt;/p&gt;
&lt;p&gt;Side node: I&amp;rsquo;m maybe still not getting to the heart of Tell, Don&amp;rsquo;t Ask, since I&amp;rsquo;m still querying properties on QuadMesh rather than sending commands to QuadMesh, but it&amp;rsquo;s the best that I understand how to do right now.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s just magical how good unit tests will guide you to quality designs and warn you away from bad designs if you take the time to listen.&amp;nbsp; You&amp;rsquo;d think I&amp;rsquo;d get used to it after awhile but the novelty hasn&amp;rsquo;t worn off for me yet.&amp;nbsp; It&amp;rsquo;s ridiculously awesome.&amp;nbsp; I giggle like a kid every time I see it.&lt;/p&gt;
&lt;p&gt;If you want to examine the diff or download the source as it is after this fix, you can find it &lt;a href="http://github.com/SaintGimp/GenesisEngine/commit/df6a007a0d0a1990eaffef942124f692d5f49cde"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9999744" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/TDD/">TDD</category><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>GenesisEngine: Yes, SRP Violations Hurt</title><link>http://blogs.msdn.com/b/elee/archive/2010/04/18/genesisengine-yes-srp-violations-hurt.aspx</link><pubDate>Sun, 18 Apr 2010 08:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9997972</guid><dc:creator>SaintGimp</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9997972</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/04/18/genesisengine-yes-srp-violations-hurt.aspx#comments</comments><description>&lt;h4&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the process of my continuous learning about agile development, one of my biggest problems is that it&amp;rsquo;s easy to find materials that say, &amp;ldquo;Do this, don&amp;rsquo;t do that,&amp;rdquo; but offer only trivial examples at best.&amp;nbsp; I&amp;rsquo;m always wishing for some non-trivial examples of what the principles, or the violation of the principles, look like in the real world.&amp;nbsp; Part of the reason why I put &lt;a href="http://github.com/SaintGimp/GenesisEngine/"&gt;GenesisEngine&lt;/a&gt; up on GitHub and am blogging about it here is to provide some slightly-less-than-trivial examples of good techniques, but just as importantly, examples of mistakes and how to fix them.&lt;/p&gt;
&lt;h4&gt;True confessions&lt;/h4&gt;
&lt;p&gt;So, I have a confession to make.&lt;/p&gt;
&lt;p&gt;I work on &lt;a href="http://github.com/SaintGimp/GenesisEngine/"&gt;GenesisEngine&lt;/a&gt; in my spare (ha!) time and progress has been kind of slow.&amp;nbsp; I spent a fair amount of time up front on infrastructure and was careful to build it all with TDD and &lt;a href="http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod"&gt;SOLID principles&lt;/a&gt;.&amp;nbsp; I had a good time building that stuff but really, all of the interesting parts have to do with the generation and rendering of the terrain itself.&amp;nbsp; Everything else is just plumbing.&lt;/p&gt;
&lt;p&gt;So after spending quite a number of weeks telling my friends that I was working on this nifty terrain engine project but having only a featureless white ball to show them, I really, really wanted to get something working that resembled actual planetary terrain.&amp;nbsp; The problem was moderately complex and I was growing impatient.&amp;nbsp; I started cutting corners.&amp;nbsp; My QuadNode class started out fairly small but it quickly accumulated a lot of responsibilities and started to sprawl all over the place.&amp;nbsp; I was violating the &lt;a href="http://www.objectmentor.com/resources/articles/srp.pdf"&gt;Single Responsibility Principle&lt;/a&gt;, and frankly, I made a mess.&lt;/p&gt;
&lt;h4&gt;Warning signs&lt;/h4&gt;
&lt;p&gt;One of the early warning signs that you have a fat class that does too many thing is that it&amp;rsquo;s not fun to write tests for it.&amp;nbsp; Rather than just having simple inputs and outputs to manage in your tests, you have to construct elaborate chains of actions just to get your object into the state that you want to test.&amp;nbsp; The tests aren&amp;rsquo;t elegant statements of intent; they&amp;rsquo;re full of confusing noise.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll also see a lot of combinatorial explosion going on where you get a ridiculous number of different contexts that say, &amp;ldquo;when A is true and B is true and C is true&amp;rdquo;, then &amp;ldquo;when A is true and B is true and C is false&amp;rdquo;, and so on through all the combinations of states.&amp;nbsp; It&amp;rsquo;s tedious to write tests for each combination, especially when they&amp;rsquo;re messy tests anyway.&lt;/p&gt;
&lt;p&gt;As I got deeper into the functionality of my quad tree terrain generation and rendering system, I started to clearly see those warning signs in my code.&amp;nbsp; But . . . I just wanted to get something working.&amp;nbsp; Like, now, darn it!&amp;nbsp; I was tired of waiting, and I resisted the obvious need to refactor the QuadNode class because it would take more time than I was willing to spend.&amp;nbsp; Rather than stopping to figure out how many responsibilities I had running around in QuadNode and then figuring out how to tease them apart into separate classes, I simply stopped writing tests for that class.&amp;nbsp; Once I did that then it was easy to not build the Perlin noise generation system test-first either.&lt;/p&gt;
&lt;h4&gt;Stampede!&lt;/h4&gt;
&lt;p&gt;In my non-technical life I&amp;rsquo;m into &lt;a href="http://www.pcta.org/"&gt;long-distance backpacking&lt;/a&gt; and in that world we have a term for when you&amp;rsquo;re about half a day out from town after four or five days and 100+ miles on the trail, and someone says the magic word.&amp;nbsp; &amp;ldquo;Pizza.&amp;rdquo;&amp;nbsp; Or maybe &amp;ldquo;hamburgers&amp;rdquo;.&amp;nbsp; The technical term for what happens then is &amp;ldquo;stampede&amp;rdquo;.&amp;nbsp; All common sense and self-preservation go right out the window and everyone hurtles down the trail at breakneck speed in an effort to get to town.&amp;nbsp; Sometimes people punish their bodies in ways they end up regretting later.&lt;/p&gt;
&lt;p&gt;We stampede in software development, too.&amp;nbsp; We spend a lot of time being careful, doing thing right, making steady progress, but at some point close to the end we sometimes say, &amp;ldquo;Ah, screw it, let&amp;rsquo;s just hack it together and make it work!&amp;rdquo;&amp;nbsp; The result is usually something we call technical debt.&amp;nbsp; You build up a pile of messy stuff that you&amp;rsquo;ve got to go back and fix later.&lt;/p&gt;
&lt;p&gt;I guess that&amp;rsquo;s not always a bad thing.&amp;nbsp; If you&amp;rsquo;re trying to hit an aggressive deadline and you need to just throw yourself forward right at the end, building up some technical debt is a valid way to do that.&amp;nbsp; Or if, like me, you just want to see something working and you&amp;rsquo;re not willing to wait, you can hack something together to scratch that itch.&lt;/p&gt;
&lt;p&gt;The really evil thing about technical debt is not the short-term impact of creating it.&amp;nbsp; You can sometimes derive a lot of benefit from technical debt in the short term.&amp;nbsp; No, the evil thing about technical debt is when you don&amp;rsquo;t immediately go back and clean it up once your short-term goal is realized.&lt;/p&gt;
&lt;h4&gt;Anatomy of an SRP violation&lt;/h4&gt;
&lt;p&gt;Right now the QuadNode class is 472 text lines long.&amp;nbsp; Visual Studio code analysis reports that it has one of the worst maintainability indexes of any class in the project.&amp;nbsp; It has at least three big responsibilities jammed into it right now:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;As the name implies, it acts as a node in the quad tree.&lt;/li&gt;
&lt;li&gt;It also owns the job of generating heightfield data, vertex buffers, and index buffers.&amp;nbsp; This clearly has nothing to do with #1.&lt;/li&gt;
&lt;li&gt;It also has to decide when it&amp;rsquo;s appropriate to split itself into four node children or to merge and delete its children.&amp;nbsp; I first thought that was a trivial aspect of #1 but it turns out to be a huge deal in its own right.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;rsquo;s one of the QuadNode spec contexts.&amp;nbsp; When a node is updated, it may decide to do certain things based on the state of the world.&amp;nbsp; In this case, when a non-leaf node (that is, a node that has children) is far enough away from the camera, the children nodes should be removed and disposed because we don&amp;rsquo;t need that level of detail any more.&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;[&lt;span style="color: #2b91af;"&gt;Subject&lt;/span&gt;(&lt;span style="color: blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af;"&gt;QuadNode&lt;/span&gt;))]&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;when_a_nonleaf_node_is_updated_and_the_camera_is_far&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;QuadNodeContext&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; _nearCameraLocation;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; _farCameraLocation;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Establish&lt;/span&gt; context = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _nearCameraLocation = &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;.Up * 11;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _farCameraLocation = &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;.Up * 15 * 10 * 2;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _node.InitializeMesh(10, &lt;span style="color: #2b91af;"&gt;Vector3&lt;/span&gt;.Up, &lt;span style="color: #2b91af;"&gt;Vector3&lt;/span&gt;.Backward, &lt;span style="color: #2b91af;"&gt;Vector3&lt;/span&gt;.Right, _extents, 0);&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _node.Update(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TimeSpan&lt;/span&gt;(), _nearCameraLocation, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;.Zero, _clippingPlanes);&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Because&lt;/span&gt; of = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _node.Update(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;TimeSpan&lt;/span&gt;(), _farCameraLocation, &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;.Zero, _clippingPlanes);&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_remove_subnodes = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _node.Subnodes.Count.ShouldEqual(0);&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_dispose_subnodes = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; subnode &lt;span style="color: blue;"&gt;in&lt;/span&gt; _node.Subnodes)&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&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;"&gt;IDisposable&lt;/span&gt;)subnode).AssertWasCalled(x =&amp;gt; x.Dispose());&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/p&gt;
&lt;p style="margin: 0px; font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;}&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This is not a &lt;span style="text-decoration: underline;"&gt;horrible&lt;/span&gt; test set.&amp;nbsp; Believe me, I&amp;rsquo;ve seen (and written!) worse.&amp;nbsp; But let&amp;rsquo;s look at a couple of things that it&amp;rsquo;s trying to tell me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The process of setting up a non-leaf node in the context is built on indirect side-effects.&amp;nbsp; Instead of just telling my class under test, &amp;ldquo;Hey, assume you&amp;rsquo;re a non-leaf node&amp;rdquo;, I have to initialize the node&amp;rsquo;s mesh, then call .Update() with camera coordinates that are near enough to cause the node to split itself and generate children, then call .Update() again with different camera coordinates that are far enough to cause the node to merge its children.&amp;nbsp; The spec isn&amp;rsquo;t able to say what it means explicitly; it&amp;rsquo;s very roundabout.&amp;nbsp; Someone unfamiliar with the code base would probably have to put in significant effort to understand how the spec works.&lt;/li&gt;
&lt;li&gt;There&amp;rsquo;s no way to determine whether the QuadNode we&amp;rsquo;re testing decided to merge its children except by inspecting its children.&amp;nbsp; Again, this is relying on indirect side-effects.&amp;nbsp; There&amp;rsquo;s no way to get a clear statement from the class that says, &amp;ldquo;Yes, I&amp;rsquo;ve decided to merge!&amp;rdquo;, which is really what I&amp;rsquo;m interested in testing here.&lt;/li&gt;
&lt;li&gt;This spec context is one of four that test a combinatorial set of conditions:
&lt;ul&gt;
&lt;li&gt;When a non-leaf node is far away from the camera&lt;/li&gt;
&lt;li&gt;When a non-leaf node is close to the camera&lt;/li&gt;
&lt;li&gt;When a leaf node is far away from the camera&lt;/li&gt;
&lt;li&gt;when a leaf node is close to the camera&lt;/li&gt;
&lt;li&gt;when a leaf node is at the maximum allowable tree depth and is close to the camera&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;There is another factor that isn&amp;rsquo;t even mentioned in these specs because I didn&amp;rsquo;t want to deal with a doubling of the condition set.&amp;nbsp; A node should only be split if it&amp;rsquo;s not over the horizon and out of sight, and it should be merged if it does get too far over the horizon even if the camera isn&amp;rsquo;t far enough to cause a merge on its own.&amp;nbsp; That would turn my five contexts into nine.&amp;nbsp; Yuck.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The implementation of .Update() in QuadNode is about as circuitous as these specs would lead you to believe.&amp;nbsp; There&amp;rsquo;s a lot of stuff going on in Update but it&amp;rsquo;s not clearly explained.&amp;nbsp; There are quite a few tests and branches and it&amp;rsquo;s not very maintainable.&lt;/p&gt;
&lt;p&gt;So what&amp;rsquo;s the root problem here?&amp;nbsp; The root problem is that I violated the Single Responsibility Principle.&amp;nbsp; The decision of whether to split or merge a quad node is a good-sized responsibility all on its own.&amp;nbsp; There are different ways to make that decision and it&amp;rsquo;s probably something I&amp;rsquo;ll want to fiddle with a lot over time since it heavily impacts performance and memory footprint.&amp;nbsp; I probably need a SplitMergeStrategy class for the QuadNode to depend on, or maybe even separate SplitStrategy and MergeStrategy classes.&lt;/p&gt;
&lt;p&gt;What would that buy me?&amp;nbsp; First, it would help break apart the combinatorial set.&amp;nbsp; The QuadNode wouldn&amp;rsquo;t have to care anything about the position of the camera or whether it&amp;rsquo;s below the horizon.&amp;nbsp; All it would have to know is that if it&amp;rsquo;s a leaf node, make a call to SplitStrategy, otherwise make a call to MergeStrategy.&amp;nbsp; If the return value is true, do the appropriate thing.&lt;/p&gt;
&lt;p&gt;SplitStrategy and MergeStrategy, for their part, wouldn&amp;rsquo;t have to know whether they&amp;rsquo;re being called by a leaf or non-leaf node.&amp;nbsp; They trust the QuadNode to take care of that question.&amp;nbsp; They just need to think about the camera distance and the horizon and respond with yes or no.&amp;nbsp; Not only does that reduce the combinatorial set but it also makes the inputs and outputs very explicit.&amp;nbsp; Inputs are numbers, output is a boolean.&amp;nbsp; No mysterious multiple calls to QuadNode.Update to set up the context and no mysterious poking at child nodes to determine the results.&lt;/p&gt;
&lt;h4&gt;Cleaning up my mess&lt;/h4&gt;
&lt;p&gt;The technical debt I incurred certainly accomplished my short-term goal.&amp;nbsp; I&amp;rsquo;ve got a working proof of concept of a planetary terrain engine and I feel satisfied at reaching that milestone.&amp;nbsp; However, now I have a problem.&amp;nbsp; The implementation of my terrain generation is very naive and does all of its work on the main thread.&amp;nbsp; At low altitudes this causes so much stuttering as to render the program virtually unusable unless you first turn off updates, move somewhere, then turn updates back on and wait awhile.&amp;nbsp; The fix for that is obviously to a) enlist my other cores for terrain generation and b) do the generation asynchronously so that camera movement and frame rate aren&amp;rsquo;t impacted, even if I have to wait a bit for higher levels of detail to show up.&lt;/p&gt;
&lt;p&gt;Well, yes, that&amp;rsquo;s a great plan except that my QuadNode class is a mess.&amp;nbsp; The code that I need to make more complex with threading and async logic is exactly the code that&amp;rsquo;s already overly-complex and obtuse and isn&amp;rsquo;t fully covered by tests.&amp;nbsp; Ah, ok, now we see the downside of technical debt.&amp;nbsp; You get a quick spike of progress and then a long, slow, painful slide into hell.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve promised myself that before I do any more significant work on this project, I&amp;rsquo;m going to clean up my mess and break QuadNode into multiple classes with single responsibilities.&amp;nbsp; I&amp;rsquo;m curious to see how it turns out.&amp;nbsp; If you want to take a closer look at the code as it is at the time of this writing, the permalink to the current tree is &lt;a href="http://github.com/SaintGimp/GenesisEngine/tree/2e279766c8193eeeda78a63b0c355937056c91d2"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9997972" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>GenesisEngine: Behavior-oriented Language</title><link>http://blogs.msdn.com/b/elee/archive/2010/04/11/genesisengine-behavior-oriented-language.aspx</link><pubDate>Mon, 12 Apr 2010 06:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9994080</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9994080</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/04/11/genesisengine-behavior-oriented-language.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As I wrote in my &lt;a href="http://blogs.msdn.com/elee/archive/2010/04/11/bdd-unit-testing-is-not-that-complicated.aspx"&gt;previous post&lt;/a&gt;, BDD is largely about preserving the flow of intent from your user stories to your unit tests (specifications, in BDD parlance) to your product code.&amp;nbsp; As developers, we&amp;rsquo;re in the habit of switching over from user intent (features that solve problems) to developer intent (mechanics of the code) when we write tests, but preserving as much user intent as possible all the way through is a lot better for maintainability and it helps drive better initial designs, too.&amp;nbsp; It&amp;rsquo;s the same as the ubiquitous language in DDD.&amp;nbsp; Don&amp;rsquo;t abandon the ubiquitous language; stick with it as long as possible.&lt;/p&gt;
&lt;p&gt;In other words, don&amp;rsquo;t focus on how the code works, think about how the system behaves.&amp;nbsp; The code will follow naturally.&lt;/p&gt;
&lt;p&gt;It turns out, though, that it&amp;rsquo;s surprisingly hard to do this well.&amp;nbsp; At least, I find that I often have to remind myself to leave implementation language out of my context and specification names and to focus on how a user would describe the behavior in domain language.&lt;/p&gt;
&lt;p&gt;I recently prepared a presentation on &lt;a href="http://github.com/machine/machine.specifications"&gt;MSpec&lt;/a&gt; for my group at work and I used the Camera specs in the &lt;a href="http://github.com/SaintGimp/GenesisEngine"&gt;GenesisEngine&lt;/a&gt; project as an example of specs written in the behavior-focused style.&amp;nbsp; There&amp;rsquo;s nothing like putting your work in front of other people to make you take a fresh look at it with a critical eye!&amp;nbsp; As I read over my Camera specs, I realized that I had let some implementation language sneak in when I wasn&amp;rsquo;t looking.&amp;nbsp; In other places I had been pretty vague about the behavior that was actually expected.&lt;/p&gt;
&lt;p&gt;For instance, consider this context:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;[&lt;span style="color: #2b91af;"&gt;Subject&lt;/span&gt;(&lt;span style="color: blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af;"&gt;Camera&lt;/span&gt;))]&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;when_view_parameters_are_set_by_look_at&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;CameraContext&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Because&lt;/span&gt; of = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.SetViewParameters(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;(0, 1, 1), &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;.Zero);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_set_the_camera_location_correctly = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.Location.ShouldEqual(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;(0, 1, 1));&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_set_the_camera_yaw_correctly = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.Yaw.ShouldEqual(0f);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_set_the_camera_pitch_correctly = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.Pitch.ShouldEqual((&lt;span style="color: blue;"&gt;float&lt;/span&gt;)(-&lt;span style="color: #2b91af;"&gt;Math&lt;/span&gt;.PI / 4));&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_set_the_camera_roll_correctly = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.Roll.ShouldEqual(0f);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_set_the_camera_view_transformation_correctly = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.OriginBasedViewTransformation.ShouldEqual(&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GenerateOriginBasedViewMatrix(_camera.Location, _camera.Yaw,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&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;&amp;nbsp; _camera.Pitch, _camera.Roll));&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;It should set location/yaw/pitch/roll/transformation &lt;em&gt;correctly&lt;/em&gt;?&amp;nbsp; What the heck does that mean?&amp;nbsp; That tells very little about what my intent actually was.&amp;nbsp; I was just being lazy and didn&amp;rsquo;t want to bother with trying to carefully describe the intent.&lt;/p&gt;
&lt;p&gt;Actually, I bet what I was thinking was something like, &amp;ldquo;Hmm, my expectation here is that these properties should be set to specifc numbers.&amp;nbsp; I don&amp;rsquo;t want to state those numbers in the spec names, though, because that&amp;rsquo;s a test detail.&amp;nbsp; I&amp;rsquo;ll just say it should set the properties &amp;lsquo;correctly&amp;rsquo; because that sounds more generalized.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;But what was my &lt;span style="text-decoration: underline;"&gt;real&lt;/span&gt; intent for the behavior of the camera when the view parameters are set via a look-at point?&amp;nbsp; Well, the real intent is that the camera should go to the requested location and set its orientation to whatever values are needed to face toward the look-at point from that location, and finally generate a new view transformation based on the new camera state.&amp;nbsp; Ok, now that&amp;rsquo;s a description that&amp;rsquo;s phrased in terms of the problem domain, not the implementation domain.&amp;nbsp; Let&amp;rsquo;s see if we can improve those specs:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;[&lt;span style="color: #2b91af;"&gt;Subject&lt;/span&gt;(&lt;span style="color: blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af;"&gt;Camera&lt;/span&gt;))]&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;when_view_parameters_are_set_by_look_at&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;CameraContext&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Because&lt;/span&gt; of = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.SetViewParameters(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;(0, 1, 1), &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;.Zero);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_go_to_the_requested_location = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.Location.ShouldEqual(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;(0, 1, 1));&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_set_the_yaw_to_face_toward_the_look_at_point = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.Yaw.ShouldEqual(0f);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_set_the_pitch_to_face_toward_the_look_at_point = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.Pitch.ShouldEqual(-&lt;span style="color: #2b91af;"&gt;MathHelper&lt;/span&gt;.Pi / 4);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_set_the_roll_to_face_toward_the_look_at_point = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.Roll.ShouldEqual(0f);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;It&lt;/span&gt; should_generate_a_view_transformation_for_the_current_state = () =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera.OriginBasedViewTransformation.ShouldEqual(&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GenerateOriginBasedViewMatrix(_camera.Location, _camera.Yaw,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&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;&amp;nbsp; _camera.Pitch, _camera.Roll));&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;rsquo;s better.&lt;/p&gt;
&lt;p&gt;In the location spec, I got away from the implementation language of &amp;ldquo;setting the location (property)&amp;rdquo; and used the domain language of &amp;ldquo;going to a location (in the world)&amp;rdquo;.&amp;nbsp; Very similar, but different perspectives.&amp;nbsp; For the orientation components, I described the intent of facing in a particular direction.&amp;nbsp; And for the view transformation, I called out the fact that the transformation is dependent on the new state.&lt;/p&gt;
&lt;p&gt;Now, a lot of you may be looking askance at me right now.&amp;nbsp; Isn&amp;rsquo;t this nitpicking pretty silly?&amp;nbsp; Well, sure, it&amp;rsquo;s not earthshattering or anything.&amp;nbsp; I didn&amp;rsquo;t fix a bug or implement a new feature with these changes.&amp;nbsp; But I think I made the code a little bit cleaner, and that&amp;rsquo;s the real reason why I started this project in the first place.&amp;nbsp; It&amp;rsquo;s not about terrain rendering, it&amp;rsquo;s about fine-tuning my techniques.&amp;nbsp; Lesson learned: avoid writing specs that say something should be done &amp;ldquo;correctly&amp;rdquo;.&amp;nbsp; Describe what the correct behavior actually is.&lt;/p&gt;
&lt;p&gt;The diff of the improvements I made to the Camera specs can be found in two parts &lt;a href="http://github.com/SaintGimp/GenesisEngine/commit/6260c745b45cda67a51e1882158324109fddba1c"&gt;here&lt;/a&gt; and &lt;a href="http://github.com/SaintGimp/GenesisEngine/commit/a0c02cef9917e30c55747149ffb5ef274e4a5822"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9994080" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/BDD/">BDD</category><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>BDD Unit Testing is Not That Complicated</title><link>http://blogs.msdn.com/b/elee/archive/2010/04/11/bdd-unit-testing-is-not-that-complicated.aspx</link><pubDate>Sun, 11 Apr 2010 22:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9993992</guid><dc:creator>SaintGimp</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9993992</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/04/11/bdd-unit-testing-is-not-that-complicated.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;One of the first &lt;a href="http://altnetseattle.pbworks.com/FrontPage-2010"&gt;sessions&lt;/a&gt; at the &lt;a href="http://2010conf.altnetseattle.org/home"&gt;Alt.Net Seattle conference&lt;/a&gt; was one on Behavior-Driven Development, or BDD.&amp;nbsp; Actually, we had three suggested sessions all related to BDD that we combined into one session, which was probably a bit of a mistake in hindsight because we had a couple different groups of people looking for different things (BDD at the unit test level vs. BDD at the acceptance test level), which caused a bit of controversy.&lt;/p&gt;
&lt;p&gt;I think that at the unit test level, BDD really isn&amp;rsquo;t that different than normal TDD that we all know and love.&amp;nbsp; All it really brings to the table is a strong emphasis on the arrange-act-assert structure and an even stronger emphasis on the behaviors you&amp;rsquo;re trying to build in your code rather than the mechanics of the code itself.&amp;nbsp; In other words, BDD asks that you think in terms of what the user wants to do and how you&amp;rsquo;re going to enable them to do it.&amp;nbsp; You give clear, explicit names to each scenario that you need to implement and you also give clear names to each expectation that you have for the scenario.&amp;nbsp; The overall point is simply to &lt;a href="http://blogs.msdn.com/elee/archive/2009/01/19/writing-unit-tests-that-people-can-read.aspx"&gt;write tests that people can actually read&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Anyway, &lt;a href="http://www.charliepoole.org/"&gt;Charlie Poole&lt;/a&gt; (one of the developers of NUnit) made a comment to the effect of, &amp;ldquo;Well, I&amp;rsquo;ve been doing that sort of thing in my unit tests for years already.&amp;nbsp; Why do we even have to have a special name for this?&amp;rdquo;&amp;nbsp; I also noticed a lot of other people asking things like, &amp;ldquo;Well, what about SOLID principles?&amp;nbsp; Do they still apply?&amp;nbsp; How about mocking frameworks or IoC containers?&amp;nbsp; Can I still use those?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This confusion is really unnecessary, and Charlie&amp;rsquo;s right: it&amp;rsquo;s unfortunate that we even have a name for it that makes it sound like it&amp;rsquo;s something different than TDD.&amp;nbsp; At least at the unit test level, BDD is not a brand new way of writing tests.&amp;nbsp; It&amp;rsquo;s just the same old red-green-refactor workflow that we&amp;rsquo;ve always used; just with a stronger emphasis on expressing customer-oriented intentions so that when other developers have to pick up your code and maintain it later, they&amp;rsquo;ll know why your tests exist, what user value they map to, and when they break, it&amp;rsquo;ll be obvious what needs to be fixed.&amp;nbsp; You still use all the same state-based and interaction-based testing techniques in your tests and the same SOLID principles in your product code.&amp;nbsp; Nothing changes.&lt;/p&gt;
&lt;p&gt;Relax &amp;ndash; it&amp;rsquo;s not that complicated.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9993992" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/BDD/">BDD</category></item><item><title>GenesisEngine: Using WPF in XNA and other non-WPF applications</title><link>http://blogs.msdn.com/b/elee/archive/2010/04/03/genesisengine-xna-and-wpf.aspx</link><pubDate>Sun, 04 Apr 2010 06:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9990224</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9990224</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/04/03/genesisengine-xna-and-wpf.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There are a &lt;a href="http://bittermanandy.wordpress.com/2008/07/26/efficient-development-part-one/" mce_href="http://bittermanandy.wordpress.com/2008/07/26/efficient-development-part-one/"&gt;couple&lt;/a&gt; &lt;a href="http://bittermanandy.wordpress.com/2008/07/28/efficient-development-part-two/" mce_href="http://bittermanandy.wordpress.com/2008/07/28/efficient-development-part-two/"&gt;of&lt;/a&gt; &lt;a href="http://bittermanandy.wordpress.com/2008/07/28/efficient-development-part-three/" mce_href="http://bittermanandy.wordpress.com/2008/07/28/efficient-development-part-three/"&gt;posts&lt;/a&gt; on the excellent &lt;a href="http://bittermanandy.wordpress.com/" mce_href="http://bittermanandy.wordpress.com/"&gt;Pandemonium&lt;/a&gt; game development blog (which sadly seems to have not been updated recently) that talk about the importance of making your game engine easily configurable and and diagnosable.&amp;nbsp; That&amp;rsquo;s important for any application, of course, but it&amp;rsquo;s particularly critical for graphics engine where things happen in real-time and a lot of what you see on the screen is not easily interpreted to root causes.&amp;nbsp; Diagnostic and configuration tools help you figure out what&amp;rsquo;s going on with your engine.&lt;/p&gt;
&lt;p&gt;For &lt;a href="http://github.com/SaintGimp/GenesisEngine" mce_href="http://github.com/SaintGimp/GenesisEngine"&gt;GenesisEngine&lt;/a&gt;, I knew I wanted to have two debugging features:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The ability to easily view the current configuration options and change them at runtime.&lt;/li&gt;
&lt;li&gt;The ability to view statistics and diagnostic information that would help me understand what the app is doing.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As I noted before, XNA doesn&amp;rsquo;t give you much help out of the box when it comes to building a UI with buttons, checkboxes, textboxes, and all those other things that we take for granted in standard Windows apps.&amp;nbsp; Development tools are important but I didn&amp;rsquo;t want to spend a lot of time building them.&amp;nbsp; Because I&amp;rsquo;m ok with my app being Windows-only right now, it made sense to try to use a Windows-based presentation system, like, say WPF.&lt;/p&gt;
&lt;p&gt;The problem was that the XNA and WPF systems are very, very different and there wasn&amp;rsquo;t a whole lot of material that explained how to glue them together in one app.&amp;nbsp; Fortunately, the answer is pretty simple even if it was a little hard to find so I&amp;rsquo;ll share it here to help out anyone else who may be wondering the same thing.&lt;/p&gt;
&lt;p&gt;To be clear, my approach here is to display WPF windows from an XNA application.&amp;nbsp; Embedding an XNA surface inside a WPF application is a whole different subject!&amp;nbsp; And actually this has nothing to do with XNA: the approach found below will work for any kind of application where you want to control the main app thread yourself and run WPF on a secondary thread.&lt;/p&gt;
&lt;p&gt;In order for WPF to work correctly, it needs a few things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A separate STA thread&lt;/li&gt;
&lt;li&gt;A thread dispatcher object for that thread&lt;/li&gt;
&lt;li&gt;A message pump&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;rsquo;s my WindowManager that makes those things happen:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;WindowManager&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;IWindowManager&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;IDisposable&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IContainer&lt;/span&gt; _container;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IScreenCustodian&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;SettingsView&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;SettingsViewModel&lt;/span&gt;&amp;gt; _settingsCustodian;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IScreenCustodian&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;StatisticsView&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;StatisticsViewModel&lt;/span&gt;&amp;gt; _statisticsCustodian;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Dispatcher&lt;/span&gt; _windowDispatcher;&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; WindowManager(&lt;span style="color: #2b91af;"&gt;IContainer&lt;/span&gt; container)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _container = container;&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StartUIThread();&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _windowDispatcher.Invoke((&lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt;)(() =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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: green;"&gt;// We pull these out of the container here instead of doing normal&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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: green;"&gt;// constructor injection because we need them to be created on this thread.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _settingsCustodian =&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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; _container.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;IScreenCustodian&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;SettingsView&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;SettingsViewModel&lt;/span&gt;&amp;gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _statisticsCustodian =&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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; _container.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;IScreenCustodian&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;StatisticsView&lt;/span&gt;, &lt;span style="color: #2b91af;"&gt;StatisticsViewModel&lt;/span&gt;&amp;gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }));&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; ShowAllWindows()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _windowDispatcher.Invoke((&lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt;)(() =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _settingsCustodian.ShowInactive();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _statisticsCustodian.ShowInactive();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }));&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; StartUIThread()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; dispatcherCreatedEvent = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ManualResetEvent&lt;/span&gt;(&lt;span style="color: blue;"&gt;false&lt;/span&gt;);&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; thread = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Thread&lt;/span&gt;(() =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _windowDispatcher = &lt;span style="color: #2b91af;"&gt;Dispatcher&lt;/span&gt;.CurrentDispatcher;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dispatcherCreatedEvent.Set();&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;"&gt;Dispatcher&lt;/span&gt;.Run();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; thread.SetApartmentState(&lt;span style="color: #2b91af;"&gt;ApartmentState&lt;/span&gt;.STA);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; thread.IsBackground = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; thread.Start();&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dispatcherCreatedEvent.WaitOne();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;" mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Dispose()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (_windowDispatcher != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _windowDispatcher.InvokeShutdown();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;There are a few notable things here.&amp;nbsp; First, all of the WPF-related objects need to be created on the WPF thread.&amp;nbsp; I&amp;rsquo;m pulling them all out of my IoC container which means that they have to be pulled from the container on the WPF thread, not on the main app thread, which means that my WindowManager has to retrieve them from the container itself rather than having them injected.&amp;nbsp; Side node: I may be &lt;a href="http://blogs.msdn.com/elee/archive/2010/03/23/genesisengine-don-t-get-domain-objects-from-the-container.aspx" mce_href="http://blogs.msdn.com/elee/archive/2010/03/23/genesisengine-don-t-get-domain-objects-from-the-container.aspx"&gt;over-relying on the container&lt;/a&gt; again here but I have a very simple UI system at the moment so I haven&amp;rsquo;t run into major problems.&lt;/p&gt;
&lt;p&gt;Second, when the WindowManager creates the UI thread it sets it to use the STA threading model which WPF requires.&amp;nbsp; It also makes it a background thread so that it won&amp;rsquo;t keep the application alive if the main thread quits.&amp;nbsp; That&amp;rsquo;s appropriate for GenesisEngine but maybe not for other apps.&amp;nbsp; The Event object is used to verify that the UI thread is indeed created and running before we continue.&lt;/p&gt;
&lt;p&gt;Third, we call Dispatcher.Run to start the message pump on the UI thread.&amp;nbsp; If this isn&amp;rsquo;t done then WPF won&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;Fourth, all interaction between the main app thread and the WPF elements has to go through Dispatch.Invoke to marshal the calls onto the UI thread.&amp;nbsp; You can see that in the ShowAllWindows method.&lt;/p&gt;
&lt;p&gt;Lastly, the WindowManager is disposable so that it can cleanly shut down the dispatcher&amp;rsquo;s message pump when appropriate.&amp;nbsp; Actually, I suspect I still have an issue with clean shutdown somewhere because occasionally the MSpec runner will complain about mysterious errors when cleaning up my unit tests but I haven&amp;rsquo;t yet invested a lot of time in chasing down the root cause.&lt;/p&gt;
&lt;p&gt;This code seems to work pretty well to create and display WPF windows for my XNA app.&amp;nbsp; I&amp;rsquo;m not doing a whole lot with them yet; the statistics window updates itself once per second and shows a few interesting numbers but the settings window isn&amp;rsquo;t hooked up to anything yet.&amp;nbsp; I&amp;rsquo;ll make more use of them shortly but the infrastructure appears to be working.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9990224" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>GenesisEngine: Input</title><link>http://blogs.msdn.com/b/elee/archive/2010/03/27/genesisengine-input.aspx</link><pubDate>Sat, 27 Mar 2010 07:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9986095</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9986095</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/03/27/genesisengine-input.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once I had the &lt;a href="http://blogs.msdn.com/elee/archive/2010/03/25/genesisengine-the-event-aggregator.aspx"&gt;event aggregator&lt;/a&gt; set up in &lt;a href="http://github.com/SaintGimp/GenesisEngine"&gt;GenesisEngine&lt;/a&gt; I could think about how to turn keyboard and mouse input into events that other parts of the app could respond to.&lt;/p&gt;
&lt;p&gt;The XNA framework doesn&amp;rsquo;t offer as much help in this area as you might be used to in Windows Forms or WPF.&amp;nbsp; There isn&amp;rsquo;t any built-in windowing, or UI controls, or a commanding system so you pretty much have to build your own from scratch.&amp;nbsp; This isn&amp;rsquo;t a terribly difficult task, I suppose, but I like the way mine turned out.&lt;/p&gt;
&lt;h4&gt;XnaInputState&lt;/h4&gt;
&lt;p&gt;All XNA offers for input is a KeyboardState and MouseState struct every update cycle that contain the current state of the keyboard (the current up or down state of every key) and the current state of the mouse cursor (where it currently is and whether each button is currently up or down).&lt;/p&gt;
&lt;p&gt;In order to figure out interesting things like did was a certain key just now pressed this update or has it been held down for awhile, or how far did the mouse move between the last update and this one, you&amp;rsquo;ve got to track both the last state and the current one and check the differences yourself.&amp;nbsp; The XnaInputState class handles this responsibility but it&amp;rsquo;s pretty trivial so I won&amp;rsquo;t list it here.&lt;/p&gt;
&lt;h4&gt;InputMapper&lt;/h4&gt;
&lt;p&gt;The InputMapper class is a bit more interesting.&amp;nbsp; It stores mappings between states and event messages that should be sent when those states occur, where states in this case mean a key was pressed, or a key is being held down, or the mouse cursor moved.&amp;nbsp; The mappings are set up in code right now but could be loaded from a config file in the future.&amp;nbsp; This is from the main Genesis program class:&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;void&lt;/span&gt; SetInputBindings()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyDownMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;MoveForward&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.W);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyDownMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;MoveBackward&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.S);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyDownMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;MoveLeft&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.A);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyDownMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;MoveRight&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.D);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyDownMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;MoveUp&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.E);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyDownMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;MoveDown&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.C);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyDownMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;GoToGround&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.Z);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyPressMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;ToggleDrawWireframeSetting&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.F);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyPressMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;ToggleUpdateSetting&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.U);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyPressMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;ToggleSingleStepSetting&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.P);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyPressMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;IncreaseCameraSpeed&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.OemPlus);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyPressMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;DecreaseCameraSpeed&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.OemMinus);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyPressMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;GarbageCollect&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.G);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddKeyPressMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;ExitApplication&lt;/span&gt;&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt;.Escape);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// TODO: we don't specify which mouse button must be down &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: green;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // (hardcoded to right button ATM),&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// this can be extended when we need to.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper.AddMouseMoveMessage&amp;lt;&lt;span style="color: #2b91af;"&gt;MouseLook&lt;/span&gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p&gt;When a message and an input state are mapped together, InputMapper stores them in lists for later use.&amp;nbsp; Specifically, it stores a set of delegates that will be executed when the correct input conditions are detected and these delegates send the proper messages to the event aggregator to be forwarded to whomever is interested in them.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m creating and storing a delegate that sends an event message rather than simply storing the type of the message because that was the only way I could figure out how to call EventAggregator.SendMessage with a strongly-typed message object.&amp;nbsp; Essentially I have to capture a generic type parameter, save it away, and later pass it to another generic method without losing its type information.&amp;nbsp; Creating a delegate at save time accomplishes that.&amp;nbsp; I&amp;rsquo;m not thrilled with how obtuse it makes the code but it&amp;rsquo;s livable for now.&amp;nbsp; I wouldn&amp;rsquo;t mind finding a better solution, though.&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddKeyPressMessage&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt; key) &lt;span style="color: blue;"&gt;where&lt;/span&gt; T : &lt;span style="color: #2b91af;"&gt;InputMessage&lt;/span&gt;, &lt;span style="color: blue;"&gt;new&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _keyPressEvents.Add(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;KeyEvent&lt;/span&gt; { Key = key, Send = x =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _eventAggregator.SendMessage(&lt;span style="color: blue;"&gt;new&lt;/span&gt; T { InputState = x}) });&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddKeyDownMessage&amp;lt;T&amp;gt;(&lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt; key) &lt;span style="color: blue;"&gt;where&lt;/span&gt; T : &lt;span style="color: #2b91af;"&gt;InputMessage&lt;/span&gt;, &lt;span style="color: blue;"&gt;new&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _keyDownEvents.Add(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;KeyEvent&lt;/span&gt; { Key = key, Send = x =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _eventAggregator.SendMessage(&lt;span style="color: blue;"&gt;new&lt;/span&gt; T { InputState = x }) });&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddMouseMoveMessage&amp;lt;T&amp;gt;() &lt;span style="color: blue;"&gt;where&lt;/span&gt; T : &lt;span style="color: #2b91af;"&gt;InputMessage&lt;/span&gt;, &lt;span style="color: blue;"&gt;new&lt;/span&gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mouseMoveEvents.Add(&lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MouseMoveEvent&lt;/span&gt; { Send = x =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _eventAggregator.SendMessage(&lt;span style="color: blue;"&gt;new&lt;/span&gt; T { InputState = x }) });&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;KeyEvent&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Keys&lt;/span&gt; Key;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IInputState&lt;/span&gt;&amp;gt; Send;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;MouseMoveEvent&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IInputState&lt;/span&gt;&amp;gt; Send;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;During each update, InputMapper is told to handle input and is passed an IInputState reference.&amp;nbsp; Based on this input state, it finds any message-sending delegates who&amp;rsquo;s conditions match the current conditions and executes those delegates.&amp;nbsp; InputMapper doesn&amp;rsquo;t know anything about who&amp;rsquo;s interested in input events, it just fires them.&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; HandleInput(&lt;span style="color: #2b91af;"&gt;IInputState&lt;/span&gt; inputState)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SendKeyPressMessages(inputState);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SendKeyDownMessages(inputState);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SendMouseMoveMessages(inputState);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SendKeyPressMessages(&lt;span style="color: #2b91af;"&gt;IInputState&lt;/span&gt; inputState)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; keyEvent &lt;span style="color: blue;"&gt;in&lt;/span&gt; _keyPressEvents.Where(keyEvent =&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inputState.IsKeyPressed(keyEvent.Key)))&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; keyEvent.Send(inputState);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I like how the responsibilities are clearly separated in this system:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Tracking input state changes - XnaInputState&lt;/li&gt;
&lt;li&gt;Firing events based on the current input state - InputMapper&lt;/li&gt;
&lt;li&gt;Actually sending the events to listeners - EventAggregator&lt;/li&gt;
&lt;li&gt;Receiving and acting on events &amp;ndash; Implementers of IListener&amp;lt;T&amp;gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I think it would be interesting to see how to incorporate the new Reactive Extensions into the input system.&amp;nbsp; Rather than checking the current input state against a set of mappings every time, the InputMapper would set up some LINQ expressions against an input event sequence.&amp;nbsp; I haven&amp;rsquo;t tried using the Reactive Extensions yet but from what I&amp;rsquo;ve read so far it seems like it should simplify the concepts here.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9986095" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>GenesisEngine: The Event Aggregator</title><link>http://blogs.msdn.com/b/elee/archive/2010/03/25/genesisengine-the-event-aggregator.aspx</link><pubDate>Thu, 25 Mar 2010 17:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9985168</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9985168</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/03/25/genesisengine-the-event-aggregator.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://github.com/SaintGimp/GenesisEngine"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/SaintGimp/GenesisEngine"&gt;GenesisEngine&lt;/a&gt; is still a pretty small code base at this point but there are some design elements that I&amp;rsquo;m pretty happy with.&amp;nbsp; I&amp;rsquo;ll run through a series of posts describing these parts so that people can learn from them or maybe critique them and find ways to make them even better.&lt;/p&gt;
&lt;h4&gt;Event Aggregator&lt;/h4&gt;
&lt;p&gt;I lifted the design of the event aggregator directly from Jeremy Miller&amp;rsquo;s &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2009/07/21/braindump-on-the-event-aggregator-pattern.aspx"&gt;posts&lt;/a&gt; on the &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2009/07/23/how-i-m-using-the-event-aggregator-pattern-in-storyteller.aspx"&gt;subject&lt;/a&gt; and from his implementation in &lt;a href="http://storyteller.tigris.org/"&gt;StoryTeller&lt;/a&gt;.&amp;nbsp; There&amp;rsquo;s not much I can add to what Jeremy&amp;rsquo;s already said but I&amp;rsquo;ll summarize the concept.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the very small interface for my aggregator:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IEventAggregator&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SendMessage&amp;lt;T&amp;gt;(T message);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; AddListener(&lt;span style="color: blue;"&gt;object&lt;/span&gt; listener);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;An event, or message, can be any type you want to use.&amp;nbsp; You can put as much context data as you wish into your message object.&amp;nbsp; When you send a message, the message object is forwarded to all listeners who have stated a desire to receive that type of message.&lt;/p&gt;
&lt;p&gt;When you add listeners to the event aggregator you don&amp;rsquo;t explicitly list what messages you want the listener to receive.&amp;nbsp; Instead, the listener&amp;rsquo;s class definition is marked up by implementing one or more flavors of IListener&amp;lt;T&amp;gt;, like so:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;interface&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;T&amp;gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Handle(T message);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;Settings&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;ISettings&lt;/span&gt;,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;INotifyPropertyChanged&lt;/span&gt;,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;ToggleDrawWireframeSetting&lt;/span&gt;&amp;gt;,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;ToggleUpdateSetting&lt;/span&gt;&amp;gt;,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;ToggleSingleStepSetting&lt;/span&gt;&amp;gt;,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IncreaseCameraSpeed&lt;/span&gt;&amp;gt;,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;DecreaseCameraSpeed&lt;/span&gt;&amp;gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The event aggregator looks for those interfaces to figure out which messages the listener is interested in:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; SendMessage&amp;lt;T&amp;gt;(T message)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt; recipients;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;lock&lt;/span&gt; (_lockObject)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; recipients = FindEligibleListeners&amp;lt;T&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SendMessageToRecipients(message, recipients);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt; FindEligibleListeners&amp;lt;T&amp;gt;()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; eligibleListeners = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;T&amp;gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; weakReference &lt;span style="color: blue;"&gt;in&lt;/span&gt; _listeners)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// We need to create a strong reference before testing aliveness&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// so that the GC doesn't yank it out from under us.&amp;nbsp; Don't convert&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// this to a LINQ expression because it doesn't guarentee that behavior&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;var&lt;/span&gt; strongReference = weakReference.Target &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;T&amp;gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;if&lt;/span&gt; (strongReference != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; eligibleListeners.Add(strongReference);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; eligibleListeners;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I use StructureMap as my IoC container and I&amp;rsquo;m using Jeremy&amp;rsquo;s neat trick of auto-registering listeners when they are created by the container, so most of the time I don&amp;rsquo;t even have to explicitly add listeners to the aggregator:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;EventAggregatorTypeInterceptor&lt;/span&gt; : &lt;span style="color: #2b91af;"&gt;TypeInterceptor&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;object&lt;/span&gt; Process(&lt;span style="color: blue;"&gt;object&lt;/span&gt; target, &lt;span style="color: #2b91af;"&gt;IContext&lt;/span&gt; context)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; context.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;IEventAggregator&lt;/span&gt;&amp;gt;().AddListener(target);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; target;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; MatchesType(&lt;span style="color: #2b91af;"&gt;Type&lt;/span&gt; type)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;return&lt;/span&gt; type.ImplementsInterfaceTemplate(&lt;span style="color: blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af;"&gt;IListener&lt;/span&gt;&amp;lt;&amp;gt;));&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t have a RemoveListener() method on my event aggregator right now for two reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The event aggregator holds weak references to all listeners so it&amp;rsquo;s not necessary to explicitly remove them for garbage-collection purposes.&lt;/li&gt;
&lt;li&gt;So far I haven&amp;rsquo;t had a need to remove a listener before the end of its lifetime so there&amp;rsquo;s been no need to implement that functionality yet.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&amp;rsquo;m very happy with this eventing design.&amp;nbsp; It&amp;rsquo;s simple, has low overhead, and just feels elegant to me.&lt;/p&gt;
&lt;p&gt;The source for GenesisEngine is available &lt;a href="http://github.com/SaintGimp/GenesisEngine/"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9985168" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>GenesisEngine: Don’t Get Domain Objects From The Container</title><link>http://blogs.msdn.com/b/elee/archive/2010/03/23/genesisengine-don-t-get-domain-objects-from-the-container.aspx</link><pubDate>Wed, 24 Mar 2010 06:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9984112</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9984112</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/03/23/genesisengine-don-t-get-domain-objects-from-the-container.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;IoC containers are awesome and I use them in all my non-trivial projects.&amp;nbsp; However, there&amp;rsquo;s an interesting caveat when it comes to using IoC containers that isn&amp;rsquo;t totally obvious: don&amp;rsquo;t get domain entities straight from the container.&lt;/p&gt;
&lt;p&gt;Surprisingly, this rule doesn&amp;rsquo;t seem to have a lot of source material.&amp;nbsp; It&amp;rsquo;s well-known among the IoC experts (you might run into terse &amp;ldquo;don&amp;rsquo;t do that&amp;rdquo; comments on mailing lists and discussion boards) but I&amp;rsquo;ve had a really hard time finding a clear, concise explanation for exactly why getting domain objects from the container is an anti-pattern.&amp;nbsp; Maybe my web search kung fu is weak, I dunno.&amp;nbsp; &lt;a href="http://blog.vuscode.com/malovicn/archive/2009/10/16/inversion-of-control-single-responsibility-principle-and-nikola-s-laws-of-dependency-injection.aspx"&gt;This post&lt;/a&gt; is about the best I&amp;rsquo;ve been able to find and even it doesn&amp;rsquo;t do into the reasons behind the rule.&amp;nbsp; If anyone has a better source, let me know.&lt;/p&gt;
&lt;p&gt;Unfortunately I&amp;rsquo;m not going to write that definitive explanation either but I can at least demonstrate what happened when I ignored it.&amp;nbsp; I already knew that domain objects don&amp;rsquo;t belong in the container before I started writing &lt;a href="http://github.com/SaintGimp/GenesisEngine"&gt;GenesisEngine&lt;/a&gt; but for some reason I wasn&amp;rsquo;t really thinking of the Planet class (and all of its component classes) as domain objects.&amp;nbsp; I&amp;rsquo;m not sure why; probably because I started with the assumption that there would be one and only one planet, but of course it&amp;rsquo;s really a domain entity because it has uniquely identifying information (its location and radius).&lt;/p&gt;
&lt;p&gt;So what happened?&lt;/p&gt;
&lt;h4&gt;How it was&lt;/h4&gt;
&lt;p&gt;My MainPresenter was created from the container and received an injected IPlanet from the container, like so:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; MainPresenter(&lt;span style="color: #2b91af;"&gt;IPlanet&lt;/span&gt; planet, &lt;span style="color: #2b91af;"&gt;ICamera&lt;/span&gt; camera, &lt;span style="color: #2b91af;"&gt;IWindowManager&lt;/span&gt; windowManager,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;Statistics&lt;/span&gt; statistics, &lt;span style="color: #2b91af;"&gt;ISettings&lt;/span&gt; settings)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _planet = planet;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _planet.Initialize(&lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;.Zero, &lt;span style="color: #2b91af;"&gt;PhysicalConstants&lt;/span&gt;.RadiusOfEarth);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera = camera;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _windowManager = windowManager;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _statistics = statistics;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _windowManager.ShowAllWindows();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _settings = settings;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _settings.ShouldUpdate = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The container created the Planet object but it couldn&amp;rsquo;t give it any uniquely identifying information because the container didn&amp;rsquo;t know anything about what kind of planet I wanted to create.&amp;nbsp; So in the MainPresenter constructor, I had to call IPlanet::Initialize() to pass in the unique attributes.&amp;nbsp; This two-stage construction is a definite anti-pattern because there&amp;rsquo;s no safety net to prevent the consumer of IPlanet from forgetting to initialize the injected dependency.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the construction and initialization of the planet class where you can see the two-stage construction.&amp;nbsp; Note that the concept of &amp;ldquo;inject then initialize&amp;rdquo; was cascading to the Planet dependencies like the PlanetRenderer as well.&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; Planet(&lt;span style="color: #2b91af;"&gt;IPlanetRenderer&lt;/span&gt; renderer, &lt;span style="color: #2b91af;"&gt;ITerrainFactory&lt;/span&gt; terrainFactory,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IHeightfieldGenerator&lt;/span&gt; generator, &lt;span style="color: #2b91af;"&gt;Statistics&lt;/span&gt; statistics)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _renderer = renderer;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _terrainFactory = terrainFactory;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _generator = generator;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _statistics = statistics;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _clippingPlanes = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ClippingPlanes&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Initialize(&lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; location, &lt;span style="color: blue;"&gt;double&lt;/span&gt; radius)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _location = location;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _radius = radius;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CreateTerrain();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _renderer.Initialize(_radius);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Aside from obtuse code that was likely to break, my main problem was that I could only have one planet in my program.&amp;nbsp; What if I wanted to put a moon in orbit around my planet, or model a solar system?&amp;nbsp; Clearly injecting planets from the container into the MainPresenter wasn&amp;rsquo;t the right approach.&amp;nbsp; I guess I could have had the MainPresenter grab additional planets straight from the container itself, but it&amp;rsquo;s a code smell to reference the container outside of bootstrapper/setup code.&lt;/p&gt;
&lt;p&gt;Interestingly, this poor design was indirectly causing bizarre problems in other seemingly-unrelated areas of the code.&amp;nbsp; For instance, I had this comment in my initialize method for the main Genesis program class:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Initialize()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.IsMouseVisible = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mainPresenter = &lt;span style="color: #2b91af;"&gt;ObjectFactory&lt;/span&gt;.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;MainPresenter&lt;/span&gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// TODO: we really don't need a reference to the camera controller here but&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// no one else seems to need a reference to it either and it needs to be&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// created otherwise the event aggregator won't subscribe it.&amp;nbsp; Is there a&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: green;"&gt;// better way to handle this?&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _cameraController = &lt;span style="color: #2b91af;"&gt;ObjectFactory&lt;/span&gt;.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;ICameraController&lt;/span&gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputState = &lt;span style="color: #2b91af;"&gt;ObjectFactory&lt;/span&gt;.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;IInputState&lt;/span&gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper = &lt;span style="color: #2b91af;"&gt;ObjectFactory&lt;/span&gt;.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;IInputMapper&lt;/span&gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetInputBindings();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;base&lt;/span&gt;.Initialize();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I had a CameraController object that needed to exist but nothing in the whole app seemed to have a reference to it.&amp;nbsp; I had to hack in a reference in my main program class just to force the object to be created and to stay around.&amp;nbsp; Turns out that problem was caused by my pulling domain objects out of the container.&amp;nbsp; The IPlanet was being directly injected into the CameraController when it should have gone a different route.&lt;/p&gt;
&lt;h4&gt;How I fixed it&lt;/h4&gt;
&lt;p&gt;Fixing this kind of mess usually involves factories.&lt;/p&gt;
&lt;p&gt;Rather than injecting the IPlanet from the container I injected an IPlanetFactory into the MainPresenter.&amp;nbsp; MainPresenter can now use the planet factory to create as many planets as it needs.&amp;nbsp; It turns out that MainPresenter now has kind of a two-step creation process &amp;ndash; construct it then show it, but that makes logical sense for a presenter and actually helps straighten out the flow of showing other windows, etc.&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; MainPresenter(&lt;span style="color: #2b91af;"&gt;IPlanetFactory&lt;/span&gt; planetFactory, &lt;span style="color: #2b91af;"&gt;ICamera&lt;/span&gt; camera, &lt;span style="color: #2b91af;"&gt;ICameraController&lt;/span&gt; cameraController, &lt;span style="color: #2b91af;"&gt;IWindowManager&lt;/span&gt; windowManager, &lt;span style="color: #2b91af;"&gt;Statistics&lt;/span&gt; statistics, &lt;span style="color: #2b91af;"&gt;ISettings&lt;/span&gt; settings)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _planetFactory = planetFactory;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _camera = camera;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _cameraController = cameraController;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _windowManager = windowManager;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _statistics = statistics;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _settings = settings;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _settings.ShouldUpdate = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Show()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _planet = _planetFactory.Create(&lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt;.Zero, &lt;span style="color: #2b91af;"&gt;PhysicalConstants&lt;/span&gt;.RadiusOfEarth);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _cameraController.AttachToPlanet(_planet);&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _windowManager.ShowAllWindows();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Note that the CameraController is injected into the MainPresenter and is explicitly attached to a particular planet which fixed my phantom CameraController problem since now the container actually needs to create it and MainPresenter holds a reference to it.&amp;nbsp; The bizzaro reference I had in the Genesis program class went away and the handling of MainPresenter is more logical (get it from the container and then show it).&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; Initialize()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.IsMouseVisible = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mainPresenter = &lt;span style="color: #2b91af;"&gt;ObjectFactory&lt;/span&gt;.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;MainPresenter&lt;/span&gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _mainPresenter.Show();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputState = &lt;span style="color: #2b91af;"&gt;ObjectFactory&lt;/span&gt;.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;IInputState&lt;/span&gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _inputMapper = &lt;span style="color: #2b91af;"&gt;ObjectFactory&lt;/span&gt;.GetInstance&amp;lt;&lt;span style="color: #2b91af;"&gt;IInputMapper&lt;/span&gt;&amp;gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetInputBindings();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;base&lt;/span&gt;.Initialize();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Finally, the Planet class is simpler and there&amp;rsquo;s no cascading Initialize calls to the renderer any more:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; Planet(&lt;span style="color: #2b91af;"&gt;DoubleVector3&lt;/span&gt; location, &lt;span style="color: blue;"&gt;double&lt;/span&gt; radius, &lt;span style="color: #2b91af;"&gt;ITerrain&lt;/span&gt; terrain,&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #2b91af;"&gt;IPlanetRenderer&lt;/span&gt; renderer, &lt;span style="color: #2b91af;"&gt;IHeightfieldGenerator&lt;/span&gt; generator, &lt;span style="color: #2b91af;"&gt;Statistics&lt;/span&gt; statistics)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;{&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _location = location;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _radius = radius;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _terrain = terrain;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _renderer = renderer;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _generator = generator;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _statistics = statistics;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _clippingPlanes = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;ClippingPlanes&lt;/span&gt;();&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;}&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can see the GitHub Compare View of all of the changes &lt;a href="http://github.com/SaintGimp/GenesisEngine/compare/10d183f469f126d43f2a7d7ed28966ec5d646682...87ece4e4ada64930362b8fd789d1fbe61e06599e"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9984112" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>The GenesisEngine Project</title><link>http://blogs.msdn.com/b/elee/archive/2010/03/20/the-genesisengine-project.aspx</link><pubDate>Sat, 20 Mar 2010 08:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9982285</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9982285</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/03/20/the-genesisengine-project.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been working on a personal project off and on for awhile now.&amp;nbsp; It&amp;rsquo;s called GenesisEngine and it&amp;rsquo;s a program that generates and renders a procedurally-generated planet.&amp;nbsp; I can take in the view down at ground level with the terrain generated at ~1-meter precision, or I can zoom all the way out into high orbit and see the entire planet at once.&amp;nbsp; This requires relatively little memory and no storage because the whole landscape is generated on demand via fractal algorithms.&lt;/p&gt;
&lt;p&gt;Now that I&amp;rsquo;ve got it to a decent alpha state where it renders mildly interesting terrain I decided to throw it up on GitHub for public amusement.&amp;nbsp; I don&amp;rsquo;t have any grand plans for this project; it&amp;rsquo;s just a little laboratory where I can experiment with new code design ideas or new tools, and in the process maybe build something that looks cool and teaches me more about graphics and other stuff that I&amp;rsquo;m interested in.&amp;nbsp; It&amp;rsquo;s already been a useful experience for me because I&amp;rsquo;ve taken several concepts that I read about, tried them out in GenesisEngine, and incorporated them into my code bases at work.&lt;/p&gt;
&lt;p&gt;Along the way I plan to blog about the lessons I learn.&amp;nbsp; I&amp;rsquo;m certainly not blazing any new trails here; I&amp;rsquo;m just picking up good ideas from people who are much smarter than me and implementing them in a non-trivial project.&amp;nbsp; I hope my successes and failures, and the source code itself, might be of use to others who want to learn.&lt;/p&gt;
&lt;p&gt;The code can be found at at &lt;a title="http://github.com/SaintGimp/GenesisEngine" href="http://github.com/SaintGimp/GenesisEngine"&gt;http://github.com/SaintGimp/GenesisEngine&lt;/a&gt;.&amp;nbsp; Git is another thing I&amp;rsquo;ve been learning about thanks to GenesisEngine.&amp;nbsp; It&amp;rsquo;s well worth the time to explore either &lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt; or &lt;a href="http://mercurial.selenic.com/"&gt;Mercurial&lt;/a&gt; or both if you&amp;rsquo;re not already familiar with distributed version control systems.&amp;nbsp; It&amp;rsquo;s slightly bewildering at first to a Perforce/TFS guy but I&amp;rsquo;m beginning to see what people are so excited about.&lt;/p&gt;
&lt;p&gt;If you want to download and build it you&amp;rsquo;ll first need to install &lt;a href="http://www.microsoft.com/express/Downloads/"&gt;Visual Studio 2008&lt;/a&gt; (you can use the C# Express Edition if you like) and &lt;a href="http://creators.xna.com/en-US/downloads"&gt;XNA Game Studio 3.1&lt;/a&gt;.&amp;nbsp; Everything else should be included in the repository.&amp;nbsp; You should probably check the README file for additional information.&lt;/p&gt;
&lt;p&gt;I want to emphasize a couple of points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This is absolutely not a Microsoft sample/demo/guidance project.&amp;nbsp; This is my own work that I&amp;rsquo;m doing on my own time.&lt;/li&gt;
&lt;li&gt;There are areas of the code that I&amp;rsquo;m pretty happy with and areas that I know are abominable and need to be reworked.&amp;nbsp; This is not a tutorial or a best-practices showcase.&amp;nbsp; This is just a real-world developer working on real-world code.&amp;nbsp; I suspect the best lessons to be drawn from this project will be not how the code looks at any particular point in time but rather how it grows and evolves over time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ok, is that enough caveats, self-deprecations, and disclaimers?&amp;nbsp; Anyway, here are a few screenshots to illustrate what I&amp;rsquo;ve got so far.&amp;nbsp; There&amp;rsquo;s no texturing or atmosphere yet so think &amp;ldquo;ice moon&amp;rdquo;.&amp;nbsp; The red lines mark the boundaries of the individual terrain patches.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On the ground:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/elee/WindowsLiveWriter/TheGenesisEngineProject_C46/image_10.png"&gt;&lt;img style="display: inline; border: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/elee/WindowsLiveWriter/TheGenesisEngineProject_C46/image_thumb_4.png" width="618" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;At airplane level:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/elee/WindowsLiveWriter/TheGenesisEngineProject_C46/image_2.png"&gt;&lt;img style="display: inline; border: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/elee/WindowsLiveWriter/TheGenesisEngineProject_C46/image_thumb.png" width="618" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Low orbit:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/elee/WindowsLiveWriter/TheGenesisEngineProject_C46/image_4.png"&gt;&lt;img style="display: inline; border: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/elee/WindowsLiveWriter/TheGenesisEngineProject_C46/image_thumb_1.png" width="618" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;High orbit:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/elee/WindowsLiveWriter/TheGenesisEngineProject_C46/image_6.png"&gt;&lt;img style="display: inline; border: 0px;" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/elee/WindowsLiveWriter/TheGenesisEngineProject_C46/image_thumb_2.png" width="618" height="484" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9982285" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/GenesisEngine/">GenesisEngine</category></item><item><title>My BDD Naming Macro</title><link>http://blogs.msdn.com/b/elee/archive/2010/02/28/my-bdd-naming-macro.aspx</link><pubDate>Mon, 01 Mar 2010 04:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9970628</guid><dc:creator>SaintGimp</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9970628</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/02/28/my-bdd-naming-macro.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Over the years &lt;a href="http://code.mattcalla.com/2008/01/15/bdd-style-naming-macro.aspx"&gt;several&lt;/a&gt; &lt;a href="http://www.lostechies.com/blogs/jason_meridth/archive/2007/11/25/bdd-macro-and-reshaper-template.aspx"&gt;people&lt;/a&gt; have &lt;a href="http://codebetter.com/blogs/jean-paul_boodhoo/archive/2008/04/14/bdd-test-naming-macro-speed-update.aspx"&gt;shared&lt;/a&gt; the Visual Studio macros they use to make the BDD boxcar naming style easier to work with.&amp;nbsp; I thought I&amp;rsquo;d add my own, not because it&amp;rsquo;s any better than the others but because it&amp;rsquo;s built for a slightly different workflow and someone might find it useful.&lt;/p&gt;
&lt;p&gt;First, here&amp;rsquo;s the macro:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;Imports &lt;span style="color: #000000;" color="#000000"&gt;System&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;Imports&lt;/span&gt; System.Windows.Forms&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;Imports&lt;/span&gt; EnvDTE&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;Imports&lt;/span&gt; EnvDTE80&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;Imports&lt;/span&gt; System.Diagnostics&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;Public&lt;/span&gt; &lt;span style="color: blue;"&gt;Module&lt;/span&gt; BDDNaming&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;Public&lt;/span&gt; &lt;span style="color: blue;"&gt;Sub&lt;/span&gt; ReplaceSpacesInTestNameWithUnderscores()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;If&lt;/span&gt; DTE.ActiveDocument &lt;span style="color: blue;"&gt;Is&lt;/span&gt; &lt;span style="color: blue;"&gt;Nothing&lt;/span&gt; &lt;span style="color: blue;"&gt;Then&lt;/span&gt; &lt;span style="color: blue;"&gt;Return&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;Dim&lt;/span&gt; selection &lt;span style="color: blue;"&gt;As&lt;/span&gt; TextSelection = &lt;span style="color: blue;"&gt;CType&lt;/span&gt;(DTE.ActiveDocument.Selection(), EnvDTE.TextSelection)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;If&lt;/span&gt; selection.IsEmpty &lt;span style="color: blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ReplaceSpacesAtEditPoint(selection)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;Else&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ReplaceSpacesInSelection(selection)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;End&lt;/span&gt; &lt;span style="color: blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;End&lt;/span&gt; &lt;span style="color: blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;Private&lt;/span&gt; &lt;span style="color: blue;"&gt;Sub&lt;/span&gt; ReplaceSpacesInSelection(&lt;span style="color: blue;"&gt;ByVal&lt;/span&gt; selection &lt;span style="color: blue;"&gt;As&lt;/span&gt; TextSelection)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;Dim&lt;/span&gt; text &lt;span style="color: blue;"&gt;As&lt;/span&gt; &lt;span style="color: blue;"&gt;String&lt;/span&gt; = selection.Text&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; text = text.ToLower()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; text = text.Replace(&lt;span style="color: #a31515;"&gt;" "&lt;/span&gt;, &lt;span style="color: #a31515;"&gt;"_"&lt;/span&gt;)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; text = text.Replace(&lt;span style="color: #a31515;"&gt;""""&lt;/span&gt;, &lt;span style="color: blue;"&gt;String&lt;/span&gt;.Empty)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; selection.Text = text&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;End&lt;/span&gt; &lt;span style="color: blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;Private&lt;/span&gt; &lt;span style="color: blue;"&gt;Sub&lt;/span&gt; ReplaceSpacesAtEditPoint(&lt;span style="color: blue;"&gt;ByVal&lt;/span&gt; selection &lt;span style="color: blue;"&gt;As&lt;/span&gt; TextSelection)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; selection.CharLeft(&lt;span style="color: blue;"&gt;True&lt;/span&gt;, 1)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;While&lt;/span&gt; selection.Text(0) &amp;lt;&amp;gt; &lt;span style="color: #a31515;"&gt;""""&lt;/span&gt; &lt;span style="color: blue;"&gt;AndAlso&lt;/span&gt; (&lt;span style="color: blue;"&gt;Not&lt;/span&gt; selection.ActivePoint.AtStartOfLine)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; selection.CharLeft(&lt;span style="color: blue;"&gt;True&lt;/span&gt;, 1)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;End&lt;/span&gt; &lt;span style="color: blue;"&gt;While&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;If&lt;/span&gt; selection.Text(0) = &lt;span style="color: #a31515;"&gt;""""&lt;/span&gt; &lt;span style="color: blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ReplaceSpacesInSelection(selection)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DeleteTrailingQuote(selection)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;Else&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; selection.CharRight(&lt;span style="color: blue;"&gt;False&lt;/span&gt;, 1)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;End&lt;/span&gt; &lt;span style="color: blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;End&lt;/span&gt; &lt;span style="color: blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;Private&lt;/span&gt; &lt;span style="color: blue;"&gt;Sub&lt;/span&gt; DeleteTrailingQuote(&lt;span style="color: blue;"&gt;ByVal&lt;/span&gt; selection &lt;span style="color: blue;"&gt;As&lt;/span&gt; TextSelection)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; selection.CharRight(&lt;span style="color: blue;"&gt;True&lt;/span&gt;, 1)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;If&lt;/span&gt; selection.Text(0) = &lt;span style="color: #a31515;"&gt;""""&lt;/span&gt; &lt;span style="color: blue;"&gt;Then&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; selection.Delete()&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;Else&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; selection.CharLeft(&lt;span style="color: blue;"&gt;False&lt;/span&gt;, 1)&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;End&lt;/span&gt; &lt;span style="color: blue;"&gt;If&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;End&lt;/span&gt; &lt;span style="color: blue;"&gt;Sub&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&lt;span style="color: blue;"&gt;End&lt;/span&gt; &lt;span style="color: blue;"&gt;Module&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I usually bind this macro to Alt-- (Alt-[dash]) because it&amp;rsquo;s easy to remember and it&amp;rsquo;s not bound by default to anything important.&lt;/p&gt;
&lt;p&gt;To use it, I start by typing an open quote mark where I want to type a BDD context or spec name.&amp;nbsp; I use Resharper so it automatically inserts two quote marks for me, but the macro works equally well without Resharper.&amp;nbsp; The quotes prevent Intellisense from freaking out as I start to type the context or spec name:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #a31515;"&gt;""&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Then I type the context or spec name as a normal sentence using the space bar like so:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #a31515;"&gt;"when a message with no eligible listeners is sent"&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Then I hit Alt-- to convert the sentence to a proper boxcar-style identifier:&lt;/p&gt;
&lt;div style="font-family: courier new; background: white; color: black; font-size: 9pt;"&gt;
&lt;p style="margin: 0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: #2b91af;"&gt;when_a_message_with_no_eligible_listeners_is_sent&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I can also highlight any arbitrary piece of text and hit Alt-- to convert the spaces to underscores.&lt;/p&gt;
&lt;p&gt;Other people like to put a lot of boilerplate code into the macro to make it easier to set up contexts and specs quickly, but I prefer this macro that does just one thing and does it well.&amp;nbsp; Hopefully someone else will find it useful too!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9970628" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/BDD/">BDD</category></item><item><title>Hiring Managers for Agile Teams</title><link>http://blogs.msdn.com/b/elee/archive/2010/02/12/hiring-managers-for-agile-teams.aspx</link><pubDate>Fri, 12 Feb 2010 18:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9962005</guid><dc:creator>SaintGimp</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/elee/rsscomments.aspx?WeblogPostID=9962005</wfw:commentRss><comments>http://blogs.msdn.com/b/elee/archive/2010/02/12/hiring-managers-for-agile-teams.aspx#comments</comments><description>&lt;p&gt;&lt;em&gt;Update: this blog is no longer active. For new posts and RSS subscriptions, please go to &lt;a href="http://saintgimp.org/"&gt;http://saintgimp.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Someone asked a question along the lines of, &amp;ldquo;Let&amp;rsquo;s say you were hiring senior managers for a group made up of multiple agile teams.&amp;nbsp; What qualities would you look for in an interview?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The very first thing I&amp;rsquo;d look for would be a strong understanding of and belief in agile principles and philosophy.&amp;nbsp; There are a lot of people out there who say, &amp;ldquo;Yeah, sure, agile&amp;rsquo;s great!&amp;rdquo; but they panic and revert to non-agile strategies when the going gets tough.&amp;nbsp; Does the candidate deeply understand not just &lt;span style="text-decoration: underline;"&gt;how&lt;/span&gt; agile works mechanically, but &lt;span style="text-decoration: underline;"&gt;why&lt;/span&gt; it works and the factors that can help or hinder success in that model?&amp;nbsp; Do they know how to fix it when it breaks?&lt;/p&gt;
&lt;p&gt;The absolute worst thing you can have when in a difficult situation is a senior manager who doesn&amp;rsquo;t truly trust agile and knee-jerks back to traditional methods when the risks get high (which of course is precisely when traditional methods don&amp;rsquo;t work).&amp;nbsp; A thrashing manager can absolutely destroy even a strong agile team.&lt;/p&gt;
&lt;p&gt;I guess I could drill down into specific beliefs and name things like support for self-directed teams, a passion for delivering real value rather than just sticking to a pre-determined plan, and a willingness to blur traditional role lines (dev, test, PM) in the interest of a cohesive team.&lt;/p&gt;
&lt;p&gt;Of course, many of the usual things like the ability to hire and grow quality people, real-world experience with shipping software, a strategic understanding of the business environment, etc, are still critical.&amp;nbsp; That stuff doesn&amp;rsquo;t go away.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9962005" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/elee/archive/tags/project+management/">project management</category></item></channel></rss>
