<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://codebetter.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>Howard Dierking</title><link>http://codebetter.com/blogs/howard.dierking/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Vanilla Yet Composable HTTP Services With WCF 4 and Windsor</title><link>http://codebetter.com/blogs/howard.dierking/archive/2010/01/18/vanilla-yet-composable-http-services-with-wcf-4-and-windsor.aspx</link><pubDate>Tue, 19 Jan 2010 07:30:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:594780</guid><dc:creator>hdierking</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=594780</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2010/01/18/vanilla-yet-composable-http-services-with-wcf-4-and-windsor.aspx#comments</comments><description>&lt;p&gt;Recently in my team, there&amp;rsquo;s been a lot of discussion about how we should go about implementing a service layer for various orthogonal behaviors.&amp;nbsp; At the center of the conversation is the question of whether or not we should develop this layer using MVC or WCF.&amp;nbsp; On first look, MVC paints a pretty compelling picture &amp;ndash; particularly since the majority of our services will be consumed in a simple HTTP services fashion (Note: I&amp;rsquo;m intentionally avoiding the term RESTful service because these services will not necessarily be resource/noun focused &amp;ndash; however, they will be plain old JSON or XML over HTTP &amp;ndash; not something that requires a proxy in order to work with it).&amp;nbsp; Specifically, here are the some of the things that makes MVC look appealing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;rsquo;s really easy &amp;ndash; just create a controller and action method &lt;/li&gt;
&lt;li&gt;Friendly URLs ala core routing &lt;/li&gt;
&lt;li&gt;IIS hosted &lt;/li&gt;
&lt;li&gt;JSON formatting is as simple as returning the JSON action result from the action method &lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s easy to leverage an IoC container &amp;ndash; simply create/plug in a custom controller factory &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So that&amp;rsquo;s a pretty good list.&amp;nbsp; However, even with all of those benefits, I kept coming back to a couple problems with using MVC as a general purpose service layer.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It tightly couples your service to a specific host (IIS) &lt;/li&gt;
&lt;li&gt;It tightly couples your service to protocol (HTTP) &lt;/li&gt;
&lt;li&gt;it tightly couples your service to an addressing scheme (URL) &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now I know that some of you are reading this and calling YAGNI on me &amp;ndash; and that may be fair to some degree.&amp;nbsp; However, for what will be publically facing services (which implies that there needs to be some degree of longevity), I&amp;rsquo;m hesitant to take a dependency on an underlying &amp;ldquo;service platform&amp;rdquo; (in quotes since MVC wasn&amp;rsquo;t really meant to be this) that takes so many dependencies on things that I consider to be an architectural style (remember, it wasn&amp;rsquo;t that long ago that SOAP was the last thing we would ever need &amp;ndash; and DCOM/CORBA before that).&amp;nbsp; And technically, I&amp;rsquo;m not really talking about building anything based on unknown future requirements, but on choosing a platform on which to take a dependency.&lt;/p&gt;
&lt;p&gt;Philosophically, I&amp;rsquo;m a big fan of WCF because as one of its key characteristics, it decouples the programming model (the service definition) from both the networking stack that exposes and pipes data into the service and from the process that hosts and manages the service.&amp;nbsp; However, the initial versions of WCF provided all of this philosophical goodness at a cost &amp;ndash; and that cost was complexity &amp;ndash; particularly in the area of the host and network stack configuration.&amp;nbsp; And that complexity grew pretty significantly the further off the path you traveled.&lt;/p&gt;
&lt;p&gt;That said, with each successive release of WCF, the level of complexity in configuration has been shrinking &amp;ndash; to the point where as of WCF 4, the configuration piece has dwindled away to almost nothing.&lt;/p&gt;
&lt;p&gt;At any rate, like I mentioned, I wanted to see whether I could build simple JSON over HTTP services in a way that leveraged all of WCF&amp;rsquo;s philosophical goodness but would give me the simplicity of development that I would find doing it in MVC.&amp;nbsp; More specifically, here&amp;rsquo;s what I was testing for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Standard WCF programming model &lt;/li&gt;
&lt;li&gt;JSON by configuration &lt;/li&gt;
&lt;li&gt;Use of IoC to resolve the service graph &lt;/li&gt;
&lt;li&gt;Hosted in IIS &lt;/li&gt;
&lt;li&gt;Friendly URLs &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jumping right in, WCF has a really straightforward programming model.&amp;nbsp; It centers around the use of .NET interfaces decorated with a few attributes &amp;ndash; these (along with some configuration around address and network stack) are exposed as WCF endpoints &amp;ndash; and classes that implement one or more of those interfaces &amp;ndash; these are WCF services and are the smallest units when it comes to hosting.&amp;nbsp; The big idea here is that by using plain old .NET constructs, you can completely decouple your service logic and even contracts from all the details around hosting it and exposing it to the network.&amp;nbsp; I started out in developing my service against this standard programming model.&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;[ServiceContract(Namespace = &amp;quot;urn:Spikes-WCF-JSONTests:IPersonService&amp;quot;)]
public interface IPersonService
{
    [OperationContract]
    [WebGet(UriTemplate = &amp;quot;Find/{firstName}&amp;quot;, BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
    Person FindPerson(string firstName);
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you can see, I&amp;rsquo;ve got a standard service contract with one operation.&amp;nbsp; The WebGetAttribute allows me to specify a URI template with parameter placeholders.&amp;nbsp; It&amp;rsquo;s worth noting here that this doesn&amp;rsquo;t give us complete MVC-ish friendly URLs &amp;ndash; this is still relative to the service address, which if it&amp;rsquo;s hosted in IIS is that *.svc file.&amp;nbsp; However, as I&amp;rsquo;ll show in a second, WCF 4 helps us remedy this little bit of trailing ugliness.&amp;nbsp; Additionally, I&amp;rsquo;ve declared my message formatting in the WebGetAttribute class.&amp;nbsp; I suspect that this can actually be externalized to config, but I haven&amp;rsquo;t figured out how to do this yet, and and attribute is still less invasive than returning a JsonActionResult in MVC &amp;ndash; so for now, that&amp;rsquo;s what I&amp;rsquo;m going with.&lt;/p&gt;
&lt;p&gt;The service itself is a pretty straightforward implementation of this interface &amp;ndash; with one exception..&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class PersonService : IPersonService
{
    readonly IPersonRepository _personRepository;

    public PersonService(IPersonRepository personRepository) {
        _personRepository = personRepository;
    }

    public Person FindPerson(string firstName) {
        return _personRepository.GetPeople().FirstOrDefault(p =&amp;gt; p.FirstName == firstName);
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Notice that I have added a parameter to my constructor which declares that my service has a dependency on a concrete implementation of IPersonRepository.&amp;nbsp; One of the things that I love about MVC is how straightforward it is to create a custom ControllerFactory that can use an IoC container to resolve a controller&amp;rsquo;s entire dependency graph.&amp;nbsp; As such, I wanted to make sure that I could do the same thing in WCF.&amp;nbsp; Early on in my searching, I was very fortunate to come across a &lt;a href="http://weblogs.asp.net/fabio/archive/2009/03/24/inversion-of-control-with-wcf-and-unity.aspx"&gt;2 part blog series&lt;/a&gt; on doing just this.&amp;nbsp; I have adapted the source just a bit to use Windsor and to account for a thing or 2 in WCF 4, but the bulk of the code (and my sincerest thanks) go to &lt;a href="http://weblogs.asp.net/fabio/"&gt;Fabio Cozzolino&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In short, the ControllerFactory equivalent in WCF is called the instance provider, and it&amp;rsquo;s any class that implements IInstanceProvider.&amp;nbsp; Here&amp;rsquo;s an instance provider that&amp;rsquo;s built to use a Windsor container:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;class WindorInstanceProvider : IInstanceProvider
{
    readonly WindsorContainer _container;
    readonly Type _contractType;

    public WindorInstanceProvider(WindsorContainer container, Type contractType) {
        _container = container;
        _contractType = contractType;
    }

    public object GetInstance(InstanceContext instanceContext) {
        return GetInstance(instanceContext, null);
    }

    public object GetInstance(InstanceContext instanceContext, Message message) {
        return _container.Resolve(_contractType);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance) {
        _container.Release(instance);
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I would elaborate, but there&amp;rsquo;s just not that much of interest going on here.&amp;nbsp; The instance provider is constructed with the container itself and the service type.&amp;nbsp; When asked, it turns around and asks the container to resolve the dependency graph and create an instance of the service type.&amp;nbsp; What&amp;rsquo;s more interesting is how the instance provider gets plugged in so that it can do its thing.&lt;/p&gt;
&lt;p&gt;In the same way that ASP.NET (and MVC by extension) has a request pipeline, WCF has a channel stack.&amp;nbsp; However, unlike the case of ASP.NET, the WCF channel stack was meant to work across a myriad number of protocols and network topologies &amp;ndash; as such, it&amp;rsquo;s a great deal more extensible &amp;ndash; and that extensibility can sometimes bring with it some additional complexity.&amp;nbsp; In this case, that complexity exists in the form of a couple extra points of indirection &amp;ndash; the first of which is a service behavior.&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;public class WindsorServiceBehavior : IServiceBehavior
{
    readonly WindsorContainer _container;

    public WindsorServiceBehavior(WindsorContainer container) {
        _container = container;
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {}

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
                                     Collection&amp;lt;ServiceEndpoint&amp;gt; endpoints,
                                     BindingParameterCollection bindingParameters) {}

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
        foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
            foreach (var endpointDispatcher in channelDispatcher.Endpoints) {
                if (endpointDispatcher.ContractName == &amp;quot;IMetadataExchange&amp;quot; || endpointDispatcher.ContractName == &amp;quot;IHttpGetHelpPageAndMetadataContract&amp;quot;)
                    return;
                string contractName = endpointDispatcher.ContractName;
                ServiceEndpoint serviceEndpoint =
                    serviceDescription.Endpoints.FirstOrDefault(e =&amp;gt; e.Contract.Name == contractName);
                endpointDispatcher.DispatchRuntime.InstanceProvider =
                    new WindorInstanceProvider(_container, serviceEndpoint.Contract.ContractType);
            }
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The purpose of my service behavior is simply to iterate through each endpoint in my service and set the endpoint&amp;rsquo;s instance provider to a new instance of my WindsorInstanceProvider, passing it an instance of my container (which I supply in the behavior&amp;rsquo;s constructor).&amp;nbsp; I&amp;rsquo;m only doing this for custom endpoints &amp;ndash; not for the metadata endpoint sometimes added somewhat transparently by a different behavior.&amp;nbsp; It&amp;rsquo;s also worth pointing out that with WCF 4, I need to add a second type of metadata endpoint, IHttpGetHelpPageAndMetadataContract (I fully expect that we&amp;rsquo;ll see interface names that are complete sentences before long), to the exclusions list.&lt;/p&gt;
&lt;p&gt;So you can now see where the instance provider comes from, but what about the container itself?&amp;nbsp; And where is the behavior wired up.&amp;nbsp; Enter the custom service host and custom service host factory&amp;nbsp; First the factory:&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;public class WindsorServiceHostFactory : WebServiceHostFactory
{
    readonly WindsorContainer _container;

    public WindsorServiceHostFactory() {
        _container = new WindsorContainer(new XmlInterpreter(new ConfigResource(&amp;quot;castle&amp;quot;)));
    }

    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses) {
        //ctor string is the qualified serviceType name 
        var t = Type.GetType(constructorString);
        if (t == null)
            throw new ArgumentNullException(&amp;quot;Could not resolve type &amp;#39;&amp;quot; + constructorString + &amp;quot;&amp;#39;&amp;quot;);
        return CreateServiceHost(t, baseAddresses);
    }

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) {
        var serviceHost = new WindsorServiceHost(_container, serviceType, baseAddresses);
        return serviceHost;
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you can see, this is the point at which I&amp;rsquo;m actually creating the container.&amp;nbsp; When asked to create the service host, I simply create and return an instance of my custom service host and pass my container to it.&amp;nbsp; My service host, then, takes care of wiring up the behavior and you already know the rest of that story.&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;public class WindsorServiceHost : WebServiceHost
{
    readonly WindsorContainer _container;

    public WindsorServiceHost(WindsorContainer container, Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses) {
        _container = container;
    }

    protected override void OnOpening() {
        if (Description.Behaviors.Find&amp;lt;WindsorServiceBehavior&amp;gt;() == null)
            Description.Behaviors.Add(new WindsorServiceBehavior(_container));

        base.OnOpening();
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So, the chief complaint that I&amp;rsquo;ve heard about WCF is how painful the XML configuration is &amp;ndash; here&amp;rsquo;s the great part &amp;ndash; in WCF 4, the configuration is insanely straightforward &amp;ndash; here&amp;rsquo;s the configuration to get this all up and going (keep in mind that I would actually like to externalize more of my current sample into configuration &amp;ndash; but this should give you a pretty good sense of how much has been improved in this area).&lt;/p&gt;
&lt;pre class="xml" name="code"&gt;&amp;lt;system.serviceModel&amp;gt;
  &amp;lt;serviceHostingEnvironment aspNetCompatibilityEnabled=&amp;quot;true&amp;quot; /&amp;gt;
  &amp;lt;standardEndpoints&amp;gt;
    &amp;lt;webHttpEndpoint&amp;gt;
      &amp;lt;standardEndpoint name=&amp;quot;&amp;quot; helpEnabled=&amp;quot;true&amp;quot; automaticFormatSelectionEnabled=&amp;quot;true&amp;quot;/&amp;gt;
    &amp;lt;/webHttpEndpoint&amp;gt;
  &amp;lt;/standardEndpoints&amp;gt;
&amp;lt;/system.serviceModel&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So deploying to IIS is as simple as building this into an *.svc file and writing a directive to point to my custom service host factory.&amp;nbsp; But then I still end up with odd-looking URLs like http://localhost/SimpleWCFTestHost/PersonService.svc/Find/Howard.&amp;nbsp; It would be even better if I could just drop that *.svc file and have completely clean URLs &amp;ndash; just like I can do with MVC.&amp;nbsp; Firstly, remember that MVC doesn&amp;rsquo;t actually give you clean URLs &amp;ndash; it simply plugs into the new core routing engine that&amp;rsquo;s backed into ASP.NET 4.&amp;nbsp; And that&amp;rsquo;s exactly the capability that WCF 4 gives you as well.&amp;nbsp; To light this up, all I had to do was add this to my global.asax.cs file.&lt;/p&gt;
&lt;pre class="c-sharp" name="code"&gt;public class Global : HttpApplication&lt;br /&gt;{
    protected void Application_Start(object sender, EventArgs e) {
        RegisterRoutes(RouteTable.Routes);
    }

    static void RegisterRoutes(RouteCollection routes) {
        routes.Add(new ServiceRoute(&amp;quot;&amp;quot;, new WindsorServiceHostFactory(), typeof(PersonService)));
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This simple entry and I now have the ability to address my service as http://localhost/SimpleWCFTestHost/Find/Howard.&amp;nbsp;&amp;nbsp; Had I wanted to give the service its own path segment, I could have specified my desired segment name as the first parameter to the ServiceRoute constructor.&lt;/p&gt;
&lt;p&gt;After this experiment, WCF is at this point in time the more natural choice in my mind for building a general service layer.&amp;nbsp; Note &amp;ndash; I&amp;rsquo;m not saying that you shouldn&amp;rsquo;t use MVC to create services for the AJAX components on your pages.&amp;nbsp; Just that if those services grow in scope such that they have other clients than your view, it might be time to look at a truer service platform &amp;ndash; with WCF 4, it&amp;rsquo;s not *that* much more complicated. &lt;/p&gt;
&lt;p&gt;Finally, I stumbled across a multi-part series that&amp;rsquo;s currently being developed on this topic over at &lt;a href="http://blogs.msdn.com/endpoint/"&gt;The .NET Endpoint&lt;/a&gt; &amp;ndash; It looks like they are just on part 4 of 12, so that&amp;rsquo;s only around the first 30 minutes of the movie &amp;ndash; there&amp;rsquo;s still plenty of great stuff to come!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=594780" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/architecture/default.aspx">architecture</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/WCF/default.aspx">WCF</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/IoC/default.aspx">IoC</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/Windsor/default.aspx">Windsor</category></item><item><title>New Machine Parts List</title><link>http://codebetter.com/blogs/howard.dierking/archive/2010/01/10/new-machine-parts-list.aspx</link><pubDate>Sun, 10 Jan 2010 17:09:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:580137</guid><dc:creator>hdierking</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=580137</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2010/01/10/new-machine-parts-list.aspx#comments</comments><description>&lt;p&gt;I guess there&amp;rsquo;s something in the water &amp;ndash; I&amp;rsquo;ve now been bitten by the &amp;ldquo;upgrade my dev machine&amp;rdquo; bug.&amp;nbsp; In my case, it really comes down to one very fundamental gap in my current setup &amp;ndash; my &amp;gt; 3 yr old machine is still running a 32 bit proc which means that I can&amp;rsquo;t really take advantage of any improved virtualization technology.&amp;nbsp; I had decided when I bought my current machine (Dell Dimension E510) that I was done building my own machines because of the potential time commitment and because I wasn&amp;rsquo;t convinced that I was really saving all that much money from buying parts vs. buying a machine.&amp;nbsp; However, I also like to stretch the life of my machines as long as possible, and in looking around at Dell and Lenovo offerings, I&amp;rsquo;m not really seeing any offerings comparable to what I could buy/build &amp;ndash; I&amp;rsquo;m thinking specifically around the processor and some little things like USB 3.0.&amp;nbsp; Also, by building a machine, I can also cannibalize some of my current machine and upgrade those parts over time.&lt;/p&gt;
&lt;p&gt;Anyways, here&amp;rsquo;s the list of parts I was looking at (I&amp;rsquo;ve also highlighted the parts I plan on reusing in the short term).&amp;nbsp; I&amp;rsquo;m not a hardware guy so let me know if I&amp;rsquo;ve missed something or if there&amp;rsquo;s a better option.&lt;/p&gt;
&lt;table width="500" border="1" cellpadding="0" cellspacing="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="85"&gt;parts&lt;/td&gt;
&lt;td width="68"&gt;buy/reuse&lt;/td&gt;
&lt;td width="43"&gt;price&lt;/td&gt;
&lt;td width="24"&gt;qty&lt;/td&gt;
&lt;td width="55"&gt;subtotal&lt;/td&gt;
&lt;td width="320"&gt;buy link&lt;/td&gt;
&lt;td width="85"&gt;Notes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;case&lt;/td&gt;
&lt;td width="68"&gt;buy&lt;/td&gt;
&lt;td width="43"&gt;89.99&lt;/td&gt;
&lt;td width="24"&gt;1&lt;/td&gt;
&lt;td width="55"&gt;$89.99&lt;/td&gt;
&lt;td width="320"&gt;&lt;a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16811133098"&gt;http://www.newegg.com/Product/Product.aspx?Item=N82E16811133098&lt;/a&gt;&lt;/td&gt;
&lt;td width="85"&gt;includes 450W power supply - 18.90&amp;quot; x 8.27&amp;quot; x 20.67&amp;quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;case fan&lt;/td&gt;
&lt;td width="68"&gt;buy&lt;/td&gt;
&lt;td width="43"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="24"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="55"&gt;$0.00&lt;/td&gt;
&lt;td width="320"&gt;N/A&lt;/td&gt;
&lt;td width="85"&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;cpu&lt;/td&gt;
&lt;td width="68"&gt;buy&lt;/td&gt;
&lt;td width="43"&gt;288.99&lt;/td&gt;
&lt;td width="24"&gt;1&lt;/td&gt;
&lt;td width="55"&gt;$288.99&lt;/td&gt;
&lt;td width="320"&gt;&lt;a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16819115202"&gt;http://www.newegg.com/Product/Product.aspx?Item=N82E16819115202&lt;/a&gt;&lt;/td&gt;
&lt;td width="85"&gt;mboard req - LGA 1366 socket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;cpu fan&lt;/td&gt;
&lt;td width="68"&gt;buy&lt;/td&gt;
&lt;td width="43"&gt;39.99&lt;/td&gt;
&lt;td width="24"&gt;1&lt;/td&gt;
&lt;td width="55"&gt;$39.99&lt;/td&gt;
&lt;td width="320"&gt;&lt;a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16835207004"&gt;http://www.newegg.com/Product/Product.aspx?Item=N82E16835207004&lt;/a&gt;&lt;/td&gt;
&lt;td width="85"&gt;Sunbeam CR-CCTF 120 mm Core-Contact Freezer CPU Cooler W/TX-2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;motherboard&lt;/td&gt;
&lt;td width="68"&gt;buy&lt;/td&gt;
&lt;td width="43"&gt;309.99&lt;/td&gt;
&lt;td width="24"&gt;1&lt;/td&gt;
&lt;td width="55"&gt;$309.99&lt;/td&gt;
&lt;td width="320"&gt;&lt;a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16813131614"&gt;http://www.newegg.com/Product/Product.aspx?Item=N82E16813131614&lt;/a&gt;&lt;/td&gt;
&lt;td width="85"&gt;ASUS P6X58D Premium LGA 1366 Intel X58 SATA 6Gb/s USB 3.0 ATX Intel Motherboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;video card&lt;/td&gt;
&lt;td width="68"&gt;reuse&lt;/td&gt;
&lt;td width="43"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="24"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="55"&gt;$0.00&lt;/td&gt;
&lt;td width="320"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="85"&gt;Had already upgraded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;hard drive&lt;/td&gt;
&lt;td width="68"&gt;reuse&lt;/td&gt;
&lt;td width="43"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="24"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="55"&gt;$0.00&lt;/td&gt;
&lt;td width="320"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="85"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;ram&lt;/td&gt;
&lt;td width="68"&gt;buy&lt;/td&gt;
&lt;td width="43"&gt;57.99&lt;/td&gt;
&lt;td width="24"&gt;3&lt;/td&gt;
&lt;td width="55"&gt;$173.97&lt;/td&gt;
&lt;td width="320"&gt;&lt;a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16820104136"&gt;http://www.newegg.com/Product/Product.aspx?Item=N82E16820104136&lt;/a&gt;&lt;/td&gt;
&lt;td width="85"&gt;Kingston - 2GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;card reader&lt;/td&gt;
&lt;td width="68"&gt;reuse&lt;/td&gt;
&lt;td width="43"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="24"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="55"&gt;$0.00&lt;/td&gt;
&lt;td width="320"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="85"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;dvd r/w&lt;/td&gt;
&lt;td width="68"&gt;reuse&lt;/td&gt;
&lt;td width="43"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="24"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="55"&gt;$0.00&lt;/td&gt;
&lt;td width="320"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="85"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="85"&gt;Total&lt;/td&gt;
&lt;td width="68"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="43"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="24"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="55"&gt;$902.93&lt;/td&gt;
&lt;td width="320"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="85"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=580137" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/my+setup/default.aspx">my setup</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/hardware/default.aspx">hardware</category></item><item><title>More on Perceived Performance</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/12/13/more-on-perceived-performance.aspx</link><pubDate>Mon, 14 Dec 2009 05:50:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:519043</guid><dc:creator>hdierking</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=519043</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/12/13/more-on-perceived-performance.aspx#comments</comments><description>&lt;p&gt;In &lt;a href="http://codebetter.com/blogs/howard.dierking/archive/2009/12/11/understanding-perceived-performance.aspx"&gt;my last post&lt;/a&gt;, I talked about some of the key takeaways (for me) after reading the book &lt;a href="http://www.amazon.com/Designing-Engineering-Time-Psychology-Perception/dp/0321509188/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1260410750&amp;amp;sr=8-1"&gt;Designing and Engineering Time: The Psychology of Time Perception in Software&lt;/a&gt;.&amp;nbsp; Unfortunately, I had to run out before I noted all of the items on my list, so I&amp;rsquo;m going to finish that list up here.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If performance is a &lt;i&gt;differentiating&lt;/i&gt; factor between a function of your product and a similar function in a competitor&amp;rsquo;s product, you may not want to (or be able to) spend the time and money that it would take to make your product objectively faster.&amp;nbsp; So how much faster do you need to worry about making your product in order to neutralize performance as a differentiating factor?&amp;nbsp; According to the findings presented, researchers have determined that this bar is the &lt;i&gt;geometric&lt;/i&gt; mean between the 2 performance measures.&amp;nbsp; Users will associate a duration higher than this bar with the higher number and a duration lower than the bar with the lower number.&lt;/li&gt;
&lt;li&gt;There are 2 important qualities to consider when collecting performance data &amp;ndash; reliability and validity.&amp;nbsp; Reliability, as it is explained, seems to be synonymous with repeatability (as a side note, when I look at our current measuring methods for MSDN and TechNet, reliability is one area where we need pretty dramatic improvement).&amp;nbsp; Validity describes whether or not you&amp;rsquo;re actually measuring what you&amp;rsquo;re trying to measure.&amp;nbsp; Since reliability and validity are independent of one another, a given method can fall into any of the 4 combinations of the 2.&lt;/li&gt;
&lt;li&gt;Define your start and end events from the user&amp;rsquo;s point of view &amp;ndash; not from whatever available options your tools give you.&amp;nbsp; Not only does this give you a better picture of how your users perceive your application, but it means that you aren&amp;rsquo;t going to have to change your measuring method when you start optimizing the responsiveness characteristics of your application.&lt;/li&gt;
&lt;li&gt;When measuring, choose an appropriate precision based on the responsiveness you&amp;rsquo;re shooting for.&amp;nbsp; Just like performance tuning shouldn&amp;rsquo;t be some kind of open-ended &amp;ldquo;let&amp;rsquo;s just make everything as fast as possible&amp;rdquo; kind of exercise, it&amp;rsquo;s pointless to measure an Ajax call down to the milliseconds, since most of these operations will fall into the &amp;lsquo;continuous&amp;rsquo; aka &amp;lsquo;user flow&amp;rsquo; or even &amp;lsquo;captive&amp;rsquo; interaction classes (for more on interaction classes, see the &lt;a href="http://www.stevenseow.com/papers/UI%20Timing%20Cheatsheet.pdf"&gt;UI Timing Cheatsheet&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;For assessing user tolerance, one technique is to have a user interact with several different prototypes of a given feature (in random order, even repeating some prototypes) and have them rate the experience along some scale of responsiveness.&amp;nbsp; This can help to identify what are the key factors that influence tolerance.&lt;/li&gt;
&lt;li&gt;One technique that I thought was pretty cool for managing a user&amp;rsquo;s perception of performance for a lengthy process (think product install) is to order the sub processes so that they proceed from longest duration to shortest duration.&amp;nbsp; Research shows that users are more likely to watch the tail end of a process, so having the sub processes with shorter durations at the end leaves users feeling as though the overall process was faster (recall how annoying it is when the last 5% of an operation takes 95% of the time &amp;ndash; see what I mean?)&lt;/li&gt;
&lt;li&gt;Another technique that I thought was equally cool is one that the author calls &amp;ldquo;End on Time&amp;rdquo;.&amp;nbsp; The basic premise is that rather than spend all of your energy trying to predict the end time with pinpoint accuracy, &amp;ldquo;Give approximate remaining time in time anchors while a process is running, but when the process is actually complete, add a few seconds and show the process counting down to and ending exactly at zero&amp;rdquo;.&amp;nbsp; This is a great perception managing technique in that it creates the illusion of precision and builds confidence with your users.&amp;nbsp; Keep in mind that the applicability here is for processes that are measured in terms of minutes &amp;ndash; adding 3 seconds to a 2 second process will likely not create the desired perception.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So that wraps up my key takeaways from the book.&amp;nbsp; Keep in mind that there is a ton of great stuff in there &amp;ndash; I just pulled out some of the things that resonated with me.&amp;nbsp; I&amp;rsquo;ll be trying to put some of this information to use over the next 6-9 months and will be sure to see how some of these techniques work in my own context.&amp;nbsp; If you do the same, or if you&amp;rsquo;re currently using some similar techniques, do share.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=519043" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/performance/default.aspx">performance</category></item><item><title>Understanding Perceived Performance</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/12/11/understanding-perceived-performance.aspx</link><pubDate>Sat, 12 Dec 2009 01:50:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:509931</guid><dc:creator>hdierking</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=509931</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/12/11/understanding-perceived-performance.aspx#comments</comments><description>&lt;p&gt;I recently finished reading the book &lt;a href="http://www.amazon.com/Designing-Engineering-Time-Psychology-Perception/dp/0321509188/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1260410750&amp;amp;sr=8-1"&gt;Designing and Engineering Time: The Psychology of Time Perception in Software&lt;/a&gt;, by Steven Seow.&amp;#160; If you care about performance (rhetorical – you should), you should definitely take a look at this book, as&amp;#160; – as a developer, I know that I have tended to look at performance in a very 1-dimensional fashion.&amp;#160; When I focused on performance, I did so without any well-reasoned goals (and as such without any well reasoned measures (measures were driven by whatever tools I had on hand)) – I just wanted to make everything faster.&amp;#160; Conversely, when I wanted to be lazy about performance, I rationalized it in the way of building more expressive code (sometimes I got away with this rationalization – when I didn’t, it hurt).&lt;/p&gt;  &lt;p&gt;Wouldn’t it have been better if I could have identified the human-computer interactions that my software enabled and then set real performance goals based on research in human cognitive psychology rather than on my own vague notions on “fast enough”?&amp;#160; That’s what Seow’s book is all about – and in addition to the insights that he articulates, he also provides a plethora of references to the research that support those insights.&amp;#160; What I’m going to here is just to outline a couple of the key points from the book – hopefully to entice you to read the book for yourself and in part to record my notes before I have to return the book to the library :)&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Maister’s First Law of Service – satisfaction is the result of the difference between what the customer experiences (perceives) and what he/she expected (this is called disconfirmation) &lt;/li&gt;    &lt;li&gt;The way that perception (and the things that influence perception) can predict things like adoption and use of technology can be illustrated in a model called the Technology Acceptance Model (TAM) – created by Fred Davis &lt;/li&gt;    &lt;li&gt;There are three basic aspects of performance that influence a user’s overall experience, and as such there are three main approaches for managing performance-related issues: &lt;/li&gt; &lt;/ul&gt;  &lt;table border="1" cellspacing="0" cellpadding="5" width="453"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="215"&gt;Performance Dimension&lt;/td&gt;        &lt;td valign="top" width="236"&gt;Management Strategy&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="216"&gt;Actual Performance – the precise time durations for completing a task&lt;/td&gt;        &lt;td valign="top" width="236"&gt;Operational Management – purely technical strategy (e.g. change the way it works to make it faster)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="216"&gt;Perceived Performance – the approximate duration for completing a task as experienced by the user&lt;/td&gt;        &lt;td valign="top" width="236"&gt;Perception Management – make the task feel like it takes less time (examples include distractions, progress indicators, etc.)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="216"&gt;User Tolerance – based on expectations, the approximate duration threshold where anything beyond will be considered slow by a user&lt;/td&gt;        &lt;td valign="top" width="236"&gt;Tolerance Management – focus on making users more tolerant of a longer duration when it cannot be shortened or “disguised”&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;ul&gt;   &lt;li&gt;Vierordt’s Law describes how humans tend to overestimate short durations and underestimate long durations when asked to recall the duration of a recent activity &lt;/li&gt;    &lt;li&gt;When thinking about performance from the user’s perspective, it’s more productive to think about responsiveness in terms of various buckets based on the user’s expectations.&amp;#160; The book introduces interaction classes to help categorize these various types of responsiveness.&amp;#160; Actually, the author provides these details for free in his &lt;a href="http://www.stevenseow.com/papers/UI%20Timing%20Cheatsheet.pdf"&gt;UI Timing Cheatsheet&lt;/a&gt;.&amp;#160; I’m not going to talk about interaction classes more here because Seow does a much better job in this doc than I could do here anyway. &lt;/li&gt;    &lt;li&gt;The 20% rule is an average Weber ratio which basically says that users &lt;em&gt;notice&lt;/em&gt; a difference in performance of a function/feature when difference is more than 20% of the previous performance. &lt;/li&gt;    &lt;li&gt;Users don’t estimate time in terms of actual numbers (e.g. 4.67 seconds).&amp;#160; Instead, they tend to gravitate towards “Time Anchors” (e.g. 1, 2, 3, 5, 10, 15, etc.) – see the cheatsheet for more details about the time anchor matrix. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I’ve gotta run and catch my bus, but when I get some time, I’ll follow this up with some of my book notes on measuring time.&amp;#160; However, like I said, I would definitely recommend you checking out this quick read.&lt;/p&gt;  &lt;p&gt;Update: &lt;a href="http://codebetter.com/blogs/howard.dierking/archive/2009/12/13/more-on-perceived-performance.aspx"&gt;the follow up can be found here&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=509931" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/performance/default.aspx">performance</category></item><item><title>Astoria, SSIS Adapters and BDD – Projecting Projections</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/11/18/astoria-ssis-adapters-and-bdd-projecting-projections.aspx</link><pubDate>Wed, 18 Nov 2009 22:19:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:436470</guid><dc:creator>hdierking</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=436470</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/11/18/astoria-ssis-adapters-and-bdd-projecting-projections.aspx#comments</comments><description>&lt;p&gt;The big idea behind ADO.NET Data Services is that it enables a data source (generally a relational data source) to be exposed via a RESTful service.&amp;nbsp; In the context of fetching data &amp;ndash; which is the principle concern of our SSIS data source component, data is returned as either an ATOM feed or as a JSON list.&amp;nbsp; Despite the particular data format, the general principles are the same &amp;ndash; you&amp;rsquo;re taking a relational model and projecting it in a more serial structure.&amp;nbsp; Now, if all you&amp;rsquo;re querying is a single table, it doesn&amp;rsquo;t matter all that much &amp;ndash; you&amp;rsquo;re simply taking a tabular data set and serializing each row as an entry in the ATOM feed.&amp;nbsp; However, ADO.NET Data Services provides an expansion feature that traverses a relationship and inserts the child data inline in the resulting feed.&amp;nbsp; Keep in mind that the ADO.NET Data Services API is based on HTTP &amp;ndash; and the expansion feature is exposed simply as a querystring parameter.&lt;/p&gt;
&lt;h3&gt;Looking At the Data&lt;/h3&gt;
&lt;p&gt;Consider the following query: &lt;span style="font-family:courier new;"&gt;http://localhost:7558/northwind.svc/Products&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This will return the following ATOM feed (fragment):&lt;/p&gt;
&lt;pre name="code" class="xml"&gt;&amp;lt;feed xml:base=&amp;quot;http://localhost:7558/Northwind.svc/&amp;quot; 
   xmlns:d=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices&amp;quot; 
   xmlns:m=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&amp;quot; 
   xmlns=&amp;quot;http://www.w3.org/2005/Atom&amp;quot;&amp;gt;
   &amp;lt;title type=&amp;quot;text&amp;quot;&amp;gt;Products&amp;lt;/title&amp;gt; 
   &amp;lt;id&amp;gt;http://localhost:7558/northwind.svc/Products&amp;lt;/id&amp;gt; 
   &amp;lt;updated&amp;gt;2009-11-17T22:45:22Z&amp;lt;/updated&amp;gt; 
   &amp;lt;link rel=&amp;quot;self&amp;quot; title=&amp;quot;Products&amp;quot; href=&amp;quot;Products&amp;quot; /&amp;gt; 
   &amp;lt;entry&amp;gt;
      &amp;lt;id&amp;gt;http://localhost:7558/Northwind.svc/Products(1)&amp;lt;/id&amp;gt; 
      &amp;lt;title type=&amp;quot;text&amp;quot; /&amp;gt; 
      &amp;lt;updated&amp;gt;2009-11-17T22:45:22Z&amp;lt;/updated&amp;gt; 
      &amp;lt;author&amp;gt;
         &amp;lt;name /&amp;gt; 
      &amp;lt;/author&amp;gt;
      &amp;lt;link rel=&amp;quot;edit&amp;quot; title=&amp;quot;Products&amp;quot; href=&amp;quot;Products(1)&amp;quot; /&amp;gt; 
      &amp;lt;link rel=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/related/Categories&amp;quot; 
         type=&amp;quot;application/atom+xml;type=entry&amp;quot; 
         title=&amp;quot;Categories&amp;quot; 
         href=&amp;quot;Products(1)/Categories&amp;quot; /&amp;gt; 
      &amp;lt;link rel=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/related/Order_Details&amp;quot; 
         type=&amp;quot;application/atom+xml;type=feed&amp;quot; 
         title=&amp;quot;Order_Details&amp;quot; 
         href=&amp;quot;Products(1)/Order_Details&amp;quot; /&amp;gt; 
      &amp;lt;link rel=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/related/Suppliers&amp;quot; 
         type=&amp;quot;application/atom+xml;type=entry&amp;quot; 
         title=&amp;quot;Suppliers&amp;quot; 
         href=&amp;quot;Products(1)/Suppliers&amp;quot; /&amp;gt; 
      &amp;lt;category term=&amp;quot;NorthwindModel.Products&amp;quot; 
         scheme=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/scheme&amp;quot; /&amp;gt; 
      &amp;lt;content type=&amp;quot;application/xml&amp;quot;&amp;gt;
         &amp;lt;m:properties&amp;gt;
            &amp;lt;d:Discontinued m:type=&amp;quot;Edm.Boolean&amp;quot;&amp;gt;false&amp;lt;/d:Discontinued&amp;gt; 
            &amp;lt;d:ProductID m:type=&amp;quot;Edm.Int32&amp;quot;&amp;gt;1&amp;lt;/d:ProductID&amp;gt; 
            &amp;lt;d:ProductName&amp;gt;Chai&amp;lt;/d:ProductName&amp;gt; 
            &amp;lt;d:QuantityPerUnit&amp;gt;10 boxes x 20 bags&amp;lt;/d:QuantityPerUnit&amp;gt; 
            &amp;lt;d:ReorderLevel m:type=&amp;quot;Edm.Int16&amp;quot;&amp;gt;10&amp;lt;/d:ReorderLevel&amp;gt; 
            &amp;lt;d:UnitPrice m:type=&amp;quot;Edm.Decimal&amp;quot;&amp;gt;18.0000&amp;lt;/d:UnitPrice&amp;gt; 
            &amp;lt;d:UnitsInStock m:type=&amp;quot;Edm.Int16&amp;quot;&amp;gt;39&amp;lt;/d:UnitsInStock&amp;gt; 
            &amp;lt;d:UnitsOnOrder m:type=&amp;quot;Edm.Int16&amp;quot;&amp;gt;0&amp;lt;/d:UnitsOnOrder&amp;gt; 
         &amp;lt;/m:properties&amp;gt;
      &amp;lt;/content&amp;gt;
   &amp;lt;/entry&amp;gt;
   ...
&amp;lt;/feed&amp;gt;&lt;/pre&gt;
&lt;p&gt;As you can see, for a single resource query, the resulting feed is pretty simple with a feed consisting of multiple entries.&amp;nbsp; Each entry (in addition to the basic metadata) contains properties for the actual row values and links for relationships.&amp;nbsp; To leverage the expansion functionality &amp;ndash; in this case, we&amp;rsquo;ll expand Suppliers, we would modify the query to look like the following: &lt;span style="font-family:courier new;"&gt;http://localhost:7558/northwind.svc/Products?$expand=Suppliers&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;From this query, we would get the following, expanded result:&lt;/p&gt;
&lt;pre name="code" class="xml"&gt;&amp;lt;entry&amp;gt;
   &amp;lt;id&amp;gt;http://localhost:7558/Northwind.svc/Products(1)&amp;lt;/id&amp;gt; 
   &amp;lt;title type=&amp;quot;text&amp;quot; /&amp;gt; 
   &amp;lt;updated&amp;gt;2009-11-17T23:04:46Z&amp;lt;/updated&amp;gt; 
   &amp;lt;author&amp;gt;
      &amp;lt;name /&amp;gt; 
   &amp;lt;/author&amp;gt;
   &amp;lt;link rel=&amp;quot;edit&amp;quot; title=&amp;quot;Products&amp;quot; href=&amp;quot;Products(1)&amp;quot; /&amp;gt; 
   &amp;lt;link rel=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/related/Categories&amp;quot; 
      type=&amp;quot;application/atom+xml;type=entry&amp;quot; title=&amp;quot;Categories&amp;quot; href=&amp;quot;Products(1)/Categories&amp;quot; /&amp;gt; 
   &amp;lt;link rel=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/related/Order_Details&amp;quot; 
      type=&amp;quot;application/atom+xml;type=feed&amp;quot; title=&amp;quot;Order_Details&amp;quot; href=&amp;quot;Products(1)/Order_Details&amp;quot; /&amp;gt; 
   &amp;lt;link rel=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/related/Suppliers&amp;quot; 
      type=&amp;quot;application/atom+xml;type=entry&amp;quot; title=&amp;quot;Suppliers&amp;quot; href=&amp;quot;Products(1)/Suppliers&amp;quot;&amp;gt;
      &amp;lt;m:inline&amp;gt;
         &amp;lt;entry m:etag=&amp;quot;W/&amp;quot;&amp;#39;49%20Gilbert%20St.&amp;#39;,&amp;#39;London&amp;#39;,&amp;#39;EC1%204SD&amp;#39;&amp;quot;&amp;quot;&amp;gt;
            &amp;lt;id&amp;gt;http://localhost:7558/Northwind.svc/Suppliers(1)&amp;lt;/id&amp;gt; 
            &amp;lt;title type=&amp;quot;text&amp;quot; /&amp;gt; 
            &amp;lt;updated&amp;gt;2009-11-17T23:04:46Z&amp;lt;/updated&amp;gt; 
            &amp;lt;author&amp;gt;
               &amp;lt;name /&amp;gt; 
            &amp;lt;/author&amp;gt;
            &amp;lt;link rel=&amp;quot;edit&amp;quot; title=&amp;quot;Suppliers&amp;quot; href=&amp;quot;Suppliers(1)&amp;quot; /&amp;gt; 
            &amp;lt;link rel=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/related/Products&amp;quot; 
               type=&amp;quot;application/atom+xml;type=feed&amp;quot; title=&amp;quot;Products&amp;quot; href=&amp;quot;Suppliers(1)/Products&amp;quot; /&amp;gt; 
            &amp;lt;category term=&amp;quot;NorthwindModel.Suppliers&amp;quot; 
               scheme=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/scheme&amp;quot; /&amp;gt; 
            &amp;lt;content type=&amp;quot;application/xml&amp;quot;&amp;gt;
               &amp;lt;m:properties&amp;gt;
                  &amp;lt;d:Address&amp;gt;49 Gilbert St.&amp;lt;/d:Address&amp;gt; 
                  &amp;lt;d:City&amp;gt;London&amp;lt;/d:City&amp;gt; 
                  &amp;lt;d:CompanyName&amp;gt;Exotic Liquids&amp;lt;/d:CompanyName&amp;gt; 
                  &amp;lt;d:ContactName&amp;gt;Charlotte Cooper&amp;lt;/d:ContactName&amp;gt; 
                  &amp;lt;d:ContactTitle&amp;gt;Purchasing Manager&amp;lt;/d:ContactTitle&amp;gt; 
                  &amp;lt;d:Country&amp;gt;UK&amp;lt;/d:Country&amp;gt; 
                  &amp;lt;d:Fax m:null=&amp;quot;true&amp;quot; /&amp;gt; 
                  &amp;lt;d:HomePage m:null=&amp;quot;true&amp;quot; /&amp;gt; 
                  &amp;lt;d:Phone&amp;gt;(171) 555-2222&amp;lt;/d:Phone&amp;gt; 
                  &amp;lt;d:PostalCode&amp;gt;EC1 4SD&amp;lt;/d:PostalCode&amp;gt; 
                  &amp;lt;d:Region m:null=&amp;quot;true&amp;quot; /&amp;gt; 
                  &amp;lt;d:SupplierID m:type=&amp;quot;Edm.Int32&amp;quot;&amp;gt;1&amp;lt;/d:SupplierID&amp;gt; 
               &amp;lt;/m:properties&amp;gt;
            &amp;lt;/content&amp;gt;
         &amp;lt;/entry&amp;gt;
      &amp;lt;/m:inline&amp;gt;
   &amp;lt;/link&amp;gt;
   &amp;lt;category term=&amp;quot;NorthwindModel.Products&amp;quot; 
      scheme=&amp;quot;http://schemas.microsoft.com/ado/2007/08/dataservices/scheme&amp;quot; /&amp;gt; 
   &amp;lt;content type=&amp;quot;application/xml&amp;quot;&amp;gt;
      &amp;lt;m:properties&amp;gt;
         &amp;lt;d:Discontinued m:type=&amp;quot;Edm.Boolean&amp;quot;&amp;gt;false&amp;lt;/d:Discontinued&amp;gt; 
         &amp;lt;d:ProductID m:type=&amp;quot;Edm.Int32&amp;quot;&amp;gt;1&amp;lt;/d:ProductID&amp;gt; 
         &amp;lt;d:ProductName&amp;gt;Chai&amp;lt;/d:ProductName&amp;gt; 
         &amp;lt;d:QuantityPerUnit&amp;gt;10 boxes x 20 bags&amp;lt;/d:QuantityPerUnit&amp;gt; 
         &amp;lt;d:ReorderLevel m:type=&amp;quot;Edm.Int16&amp;quot;&amp;gt;10&amp;lt;/d:ReorderLevel&amp;gt; 
         &amp;lt;d:UnitPrice m:type=&amp;quot;Edm.Decimal&amp;quot;&amp;gt;18.0000&amp;lt;/d:UnitPrice&amp;gt; 
         &amp;lt;d:UnitsInStock m:type=&amp;quot;Edm.Int16&amp;quot;&amp;gt;39&amp;lt;/d:UnitsInStock&amp;gt; 
         &amp;lt;d:UnitsOnOrder m:type=&amp;quot;Edm.Int16&amp;quot;&amp;gt;0&amp;lt;/d:UnitsOnOrder&amp;gt; 
      &amp;lt;/m:properties&amp;gt;
   &amp;lt;/content&amp;gt;
&amp;lt;/entry&amp;gt;&lt;/pre&gt;
&lt;p&gt;While this example demonstrates expansion of a single link resource, ADO.NET Data Services allows you to expand a single link, multiple links, or multiple nested links.&amp;nbsp; The funny thing about this is that the SSIS data flow engine takes much more of a relational view of the world with its stream architecture.&amp;nbsp; This means that we&amp;rsquo;re starting with a relational model, projecting into a hierarchical model, and then projecting back to a relational model.&amp;nbsp; The question, then, is how we go about designing (and testing) this projection.&lt;/p&gt;
&lt;p&gt;To start, here&amp;rsquo;s a few high level design principles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every resource usage (primary and all expanded) should yield a unique output stream in an SSIS data flow which is visible in the data flow designer &lt;/li&gt;
&lt;li&gt;Composition of output streams (e.g. joining) should be done via data flow designer transform components &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;A Unique Stream Per Resource&lt;/h3&gt;
&lt;p&gt;Every resource that is returned as part of an ADO.NET Data Services query, whether it is the primary resource (e.g. Products) or an expanded resource, should have a unique output in the data flow designer.&amp;nbsp; Moreover, if a resource is referenced in more than 1 role (e.g. http://localhost:7558/northwind.svc/Products?$expand=Suppliers/Products), an output stream should be created for each role.&amp;nbsp; The goal of having multiple output streams is that each one can then by manipulated independently using the data flow designer.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/multioutputdesigner_5F00_52919AA5.png"&gt;&lt;img height="344" width="598" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/multioutputdesigner_5F00_thumb_5F00_348366E4.png" alt="multi-output-designer" border="0" title="multi-output-designer" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;Enabling Composition&lt;/h3&gt;
&lt;p&gt;One of the primary reasons behind creating unique streams per resource *role* is to enable granular composition/branching inside the data flow designer (as shown above).&amp;nbsp; The service metadata provided by a data service provides a type definition for each resource managed by the service.&amp;nbsp; This makes it initially straightforward for determining data shape from a data services query.&amp;nbsp; However, in order to effectively project the parent/child relationship specified with the expansion feature, we need to make sure we include the identifiers of the parent record in context of the child record.&amp;nbsp; I started with the following specifications:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class when_employees_resource_query_expands_territories : with_northwind_CSDL
{
    Establish context = () =&amp;gt; {
        queryBuilder.ResourcePath = &amp;quot;Employees&amp;quot;;
        queryBuilder.OperationsString = &amp;quot;$expand=Territories&amp;quot;;
    };

    Because of = () =&amp;gt; query = queryBuilder.GetQuery();

    It should_declare_2_resources = () =&amp;gt; query.DataShape.Count().ShouldEqual(2);

    It should_have_1_reference_property_for_territories =
        () =&amp;gt; query.DataShape.ElementAt(1).Properties
            .Where(p =&amp;gt; p.GetType() == typeof (RefProperty)).Count()
            .ShouldEqual(1);

    It should_have_2_properties_for_territories =
        () =&amp;gt; query.DataShape.ElementAt(1).Properties
            .Where(p =&amp;gt; p.GetType() == typeof (Property)).Count()
            .ShouldEqual(2);

    It should_have_correct_query_string = 
        () =&amp;gt; query.ToString().ShouldEqual(
            string.Format(&amp;quot;{0}/Employees?$expand=Territories&amp;quot;, Constants.SERVICE_URI));

    It should_have_employees_as_first_resource = 
        () =&amp;gt; query.DataShape.ElementAt(0).Name.ShouldEqual(&amp;quot;Employees&amp;quot;);

    It should_have_territories_as_the_second_resource =
        () =&amp;gt; query.DataShape.ElementAt(1).Name.ShouldEqual(&amp;quot;Territories&amp;quot;);
}&lt;/pre&gt;
&lt;p&gt;First, note the with_northwind_CSDL base class.&amp;nbsp; Aaron brought up in an earlier post that this &amp;ldquo;with&amp;hellip;&amp;rdquo; convention was one that he was actually moving further away from, so in this point, I want to call out more specifically what is happening here.&amp;nbsp; The basic point of this shared context is to setup a mock reader to get the XML metadata from a file rather than from the $metadata clause, which is what is used at runtime.&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class with_northwind_CSDL
{
    const string NORTHWIND_METADATA_PATH = &amp;quot;svc_metadata.xml&amp;quot;;
    protected static DataServicesQuery query;
    protected static IDataServicesQueryBuilder queryBuilder;

    Establish context = () =&amp;gt; {
        var mockMetadataReader = new Mock&amp;lt;IReader&amp;gt;();
        mockMetadataReader.Setup(r =&amp;gt; r.GetData(Constants.SERVICE_URI + &amp;quot;/$metadata&amp;quot;))
            .Returns(new StreamReader(NORTHWIND_METADATA_PATH));

        queryBuilder = new DataServicesQueryBuilder(new CSDLResourceBuilder(), 
            mockMetadataReader.Object) {ServiceURI = Constants.SERVICE_URI};
    };
}&lt;/pre&gt;
&lt;p&gt;Setting this up in a base class rather than in every spec class saved me a fair amount of repetitive typing &amp;ndash; especially since my specifications here are pivoting on how the query shapes the data shape rather than on how the metadata is acquired.&lt;/p&gt;
&lt;p&gt;So once I had my basic specs setup, all that remained was the implementation.&amp;nbsp; As you can see from the following, the basic task of creating the data shape is effectively divided among 3 types:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/core_5F00_39F1D788.png"&gt;&lt;img height="312" width="549" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/core_5F00_thumb_5F00_513CDBF9.png" alt="core" border="0" title="core" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the data reader is responsible for getting the metadata from some source (in the running service, this is done using a HTTP GET request &amp;ndash; for my specs, this was mocked with an XML file reader) &lt;/li&gt;
&lt;li&gt;the resource builder is responsible for producing resources (the main elements of the data shape) from the metadata provided by the data reader &lt;/li&gt;
&lt;li&gt;the query builder is responsible for knowing how to interpret the query URI and ensuring that parent/child projections are correctly constructed. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Based on this separation of roles, you can see that the bulk of the projection logic resides in the query builder class &amp;ndash; specifically in the GetResources method.&amp;nbsp; This logic looks like the following:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;IEnumerable&amp;lt;Resource&amp;gt; GetResources() {
    var metadata = _metadataReader.GetData(string.Format(&amp;quot;{0}/$metadata&amp;quot;, ServiceURI));
    _resourceBuilder.Initialize(metadata);

    // initialize resourcs collection with primary resource
    var resources = new List&amp;lt;Resource&amp;gt; {
                                           _resourceBuilder.GetResource(ResourcePath.Split(new[] {&amp;#39;/&amp;#39;}).Last())
                                       };

    //add resources specified by the presence of an $expand query operation
    if (!string.IsNullOrEmpty(OperationsString)) {
        var expandOperation = QueryOperation.ParseQueryOperations(OperationsString).Expand();

        foreach (var expandedPath in expandOperation.ResourcePaths)
            if (expandedPath.Contains(&amp;quot;/&amp;quot;)) {
                var pathAxes = expandedPath.Split(new[] {&amp;#39;/&amp;#39;});
                for (var i = 0; i &amp;lt; pathAxes.Length; i++)
                    resources.Add(_resourceBuilder.GetResource(pathAxes[ i ], resources.Last()));
            }
            else
                resources.Add(_resourceBuilder.GetResource(expandedPath, resources.Last()));
    }

    return resources;
}&lt;/pre&gt;
&lt;p&gt;As you can see, this method is basically getting resource names from the data services query string and then asking the resource builder to build those resources.&amp;nbsp; For expanded resources, the builder is asked to produce the resource incorporating the keys of the parent resource.&lt;/p&gt;
&lt;p&gt;In sum, I think that dealing with $expand is one of the more interesting aspect of this component, so I wanted to spend a bit more time going through it.&amp;nbsp; To see all of the components working together, you can download the entire source code at &lt;a href="http://code.msdn.microsoft.com/ssisastoria" title="http://code.msdn.microsoft.com/ssisastoria"&gt;http://code.msdn.microsoft.com/ssisastoria&lt;/a&gt;.&amp;nbsp; But in sum, the problem looks like: DB (relational) &amp;ndash;&amp;gt; Data Services (hierarchical) &amp;ndash;&amp;gt; SSIS (relational).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=436470" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/BDD/default.aspx">BDD</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/SSIS/default.aspx">SSIS</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/MSpec/default.aspx">MSpec</category></item><item><title>Astoria, SSIS Adapters and BDD – Class Design</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/11/18/astoria-ssis-adapters-and-bdd-class-design.aspx</link><pubDate>Wed, 18 Nov 2009 20:11:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:436155</guid><dc:creator>hdierking</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=436155</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/11/18/astoria-ssis-adapters-and-bdd-class-design.aspx#comments</comments><description>&lt;p&gt;In the process of writing a post about one specific feature of the design, I realized that I hadn’t actually described the moving parts in the solution.&amp;#160; There are 3 projects in the VS solution: the SSIS-specific code, the core application logic, and the application logic tests (specifications).&amp;#160; I’ll talk more about the SSIS part later and focus here on the core application logic and tests.&lt;/p&gt;  &lt;p&gt;At a high level, there are 2 major logical components that interact to support SSIS at design time and runtime – those are DataServicesQuery and DataServicesQueryBuilder.&amp;#160; &lt;/p&gt;  &lt;h3&gt;The DataServicesQueryBuilder Object&lt;/h3&gt;  &lt;p&gt;The query builder is responsible for getting the metadata from ADO.NET Data Services and constructing the resources that are used by SSIS during the design time experience (those resources are also passed to the query to be used at runtime for making sure that a data element gets put in the right place in the buffer).&amp;#160; The basic elements of the query builder are shown below:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/core_5F00_50D0F3F6.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="core" border="0" alt="core" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/core_5F00_thumb_5F00_6CB20321.png" width="559" height="422" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As you can see, responsibilities are further decomposed as follows:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The DataServicesQueryBuilder class is responsible for understanding an ADO.NET Data Services query and producing a query that can be consumed by the SSIS runtime &lt;/li&gt;    &lt;li&gt;The IReader interface is responsible for getting stream data from some data source – the concrete implementation used by the query builder is the HttpRequestReader.&amp;#160; This implementation is used by the query builder to get service metadata as follows: &lt;/li&gt; &lt;/ul&gt;  &lt;pre class="c-sharp" name="code"&gt;var metadata = _metadataReader.GetData(
    string.Format(&amp;quot;{0}/$metadata&amp;quot;, ServiceURI));&lt;/pre&gt;

&lt;ul&gt;
  &lt;li&gt;The IResourceBuilder interface is responsible for producing Resource instances from whatever stream data is handed to it.&amp;#160; Since ADO.NET Data Services currently has a dependency on EDM (more specifically, CSDL), the only relevant concrete class at the moment is CSDLResourceBuilder. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only other thing I want to point out from the query builder classes is that we have a class for both Property and for RefProperty.&amp;#160; Resource properties are the equivalent of columns (if looking at the data from a tabular perspective) and RefProperties are the equivalent of links.&amp;#160; This will become more obvious when I discuss use of the $expand keyword in a future post, but the difference between parent/child (and subsequently, the driver behind inheritance) is based on the following runtime behavior (when extracting data from results data):&lt;/p&gt;

&lt;pre class="c-sharp" name="code"&gt;public class Property
{
    ...

    public virtual object GetValue(XElement element) {
        var propertyElement = element.Element(XName.Get(&amp;quot;content&amp;quot;, XmlNamespaces.AtomXmlNamespace))
            .Element(XName.Get(&amp;quot;properties&amp;quot;, XmlNamespaces.DataServicesMetadataXmlNamespace))
            .Element(XName.Get(Name, XmlNamespaces.DataServicesXmlNamespace));

        var propertyVal = propertyElement.Value;

        var val = Convert.ChangeType(propertyVal, PropertyType);

        return val;
    }
}

public class RefProperty : Property
{
    public RefProperty(string name, Type type, int? maxLength, bool? unicode)
        : base(name, type, maxLength, unicode) { }

    public override object GetValue(XElement element) {
        return element.Parent.Name.LocalName==&amp;quot;feed&amp;quot; 
            ? base.GetValue(element.Parent.Parent.Parent.Parent) 
            : base.GetValue(element.Parent.Parent.Parent);
    }
}&lt;/pre&gt;

&lt;h3&gt;The DataServicesQuery object&lt;/h3&gt;

&lt;p&gt;Ultimately, the SSIS code simply uses the query builder in order to get a DataServicesQuery object.&amp;#160; The query builder configures the query with the collection of resources that it created (called the data shape).&amp;#160; The query is responsible for executing the actual query and extracting the results from the returned XML (ATOM feed) into a tabular format which can be used to populate SSIS output buffers.&amp;#160; As you can see below, the query class layout is much simpler than the builder:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/QueryClasses_5F00_156D686B.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Query Classes" border="0" alt="Query Classes" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/QueryClasses_5F00_thumb_5F00_79E86667.png" width="511" height="255" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As you can see, the reader is again used to pull down stream data.&amp;#160; The query then uses it’s data shape (resources) to take the XML data stream and create a ResultSet for each resource.&amp;#160; 1..n ResultSets are then handed back as the result of executing the query – this is what gets handed back to SSIS and allows the SSIS adapter code to populate the SSIS buffers.&lt;/p&gt;

&lt;p&gt;You can download and look at the complete source at &lt;a title="http://code.msdn.microsoft.com/ssisastoria" href="http://code.msdn.microsoft.com/ssisastoria"&gt;http://code.msdn.microsoft.com/ssisastoria&lt;/a&gt;.&amp;#160; As always, please let me know if there’s stuff that doesn’t make sense or that could be refactored to be improved.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=436155" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/SSIS/default.aspx">SSIS</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>Astoria, SSIS Adapters and BDD – On BDD and MSpec</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/11/12/astoria-ssis-adapters-and-bdd-on-bdd-and-mspec.aspx</link><pubDate>Fri, 13 Nov 2009 01:04:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:424518</guid><dc:creator>hdierking</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=424518</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/11/12/astoria-ssis-adapters-and-bdd-on-bdd-and-mspec.aspx#comments</comments><description>&lt;p&gt;Let me preface this post by saying that it is about my (early) experiences practicing &lt;a href="http://en.wikipedia.org/wiki/Behavior_driven_development"&gt;BDD&lt;/a&gt; in the context of a specific specification framework &amp;ndash; &lt;a href="http://codebetter.com/blogs/aaron.jensen/archive/2008/05/08/introducing-machine-specifications-or-mspec-for-short.aspx"&gt;MSpec&lt;/a&gt;.&amp;nbsp; There are plenty of folks out there who are much more authoritative on this subject than I.&amp;nbsp; And if you happen to be one of those people, I would love to get your feedback on what I&amp;rsquo;ve done here and how I could do it better.&lt;/p&gt;
&lt;p&gt;In developing a &lt;a href="http://codebetter.com/blogs/howard.dierking/archive/2009/10/28/astoria-ssis-adapters-and-bdd-take-1.aspx"&gt;SSIS data source to talk to an ADO.NET Data Services&lt;/a&gt; endpoint, shifting my approach from a basic &lt;a href="http://en.wikipedia.org/wiki/Test_Driven_Development"&gt;TDD&lt;/a&gt; style to specifications was not originally part of the plan.&amp;nbsp; However, as I got deeper into development, I felt as though I actually wanted a bit more rigor in terms of semantic restrictions (e.g. arrange/act/assert) than I was getting out of the box from my unit test framework.&amp;nbsp; MSpec had been on my radar for a little while (I was introduced to both this framework and BDD in general at &lt;a href="http://msdn.microsoft.com/en-us/magazine/cc337902.aspx"&gt;ALT.NET&lt;/a&gt;), so I took a quick look - and after staring oddly for a moment at the =()=&amp;gt; syntax decided that it provided the kind of semantic consistency I was really looking for.&amp;nbsp; Additionally, the fact that it could plug into the &lt;a href="http://www.jetbrains.com/resharper/"&gt;ReSharper&lt;/a&gt; unit test runner (with underscores removed from boxcar casing no less!) made it quick and very easy to get up and going on the journey writing specifications rather than tests.&amp;nbsp; Going through the specification writing exercise on this project has me convinced at this point that as someone else once said, BDD is TDD done right.&amp;nbsp; I certainly plan to keep pursuing specifications over traditional unit tests in future efforts.&lt;/p&gt;
&lt;p&gt;So where to start?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not going to spend time in this post talking about how to use MSpec &amp;ndash; there&amp;rsquo;s already lots of good guidance out there.&amp;nbsp; That said, because the syntax initially looks a bit funky, I will say 2 quick things that are helpful to keep in mind when you first look at specifications built on top of MSpec.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Everything in your specification (test) class is a field.&amp;nbsp; And all of the work&amp;nbsp; gets down via delegate fields which are of types with names like &amp;ldquo;Establish&amp;rdquo;, &amp;ldquo;Because&amp;rdquo;, and &amp;ldquo;It&amp;rdquo; &lt;/li&gt;
&lt;li&gt;Regarding the =()=&amp;gt; syntax, you are probably already comfortable with lambda expressions, so you can ignore the =&amp;gt; on the right - and you can get the assignment operator on the left.&amp;nbsp; Therefore, that just leaves the empty parenthetical &amp;ndash; and this just means that your delegate (lambda) is for a function that has no arguments.&amp;nbsp; There, all better? &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I already had some unit tests written &amp;ndash; though some of them were more of integration tests and revealed some pretty serious problems in my design &amp;ndash; but we&amp;rsquo;ll deal more with those topics later.&amp;nbsp; So my starting point was to try and re-write some of my existing tests as specifications.&amp;nbsp; For example, take the following:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;[Test]
public void Given_Null_URI_Throw_Exception() {
    try {
        new DataServicesQuery(_dataServicesQueryBuilder, null, &amp;quot;Suppliers&amp;quot;);
    }
    catch(ArgumentNullException ex) {
        Assert.AreEqual(&amp;quot;serviceUri&amp;quot;, ex.ParamName);
    }
}&lt;/pre&gt;
&lt;p&gt;Re-writing this as a specification resulted in the following:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class when_service_uri_is_null : with_dummy_resource_builder_and_reader
{
    static NullReferenceException lastException;

    Because service_uri_is_null = () =&amp;gt; {
        try {
            queryBuilder.ServiceURI = null;
            queryBuilder.ResourcePath = &amp;quot;Products&amp;quot;;
            queryBuilder.GetQuery();
        }
        catch (NullReferenceException ex) {
            lastException = ex;
        }
    };

    It should_have_specific_error_message = 
        () =&amp;gt; lastException.Message.ShouldEqual(&amp;quot;Service URI must be provided&amp;quot;);

    It should_raise_an_exception = 
        () =&amp;gt; lastException.ShouldNotBeNull();
}&lt;/pre&gt;
&lt;p&gt;A couple things to point out here.&amp;nbsp; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First and foremost, there is a more rigid semantic that is enforced by both convention and even by the type system.&amp;nbsp; The convention is that classes follow a &amp;ldquo;when X [with Y]&amp;rdquo; pattern (I found that this class name should map very tightly to the instructions contained in the Establish and/or Because expressions &amp;ndash; if it does not, you may have a problem in your design).&amp;nbsp; Also, assertion (&amp;ldquo;It&amp;rdquo; expressions) delegates should follow a naming convention whereby &amp;ldquo;should &amp;hellip;&amp;rdquo; is followed by a description of the assertion.&amp;nbsp; MSpec also uses the type system to enforces this convention in how the delegate types are named (e.g. &amp;ndash; &amp;ldquo;Because&amp;rdquo;, &amp;ldquo;It&amp;rdquo;). &lt;/li&gt;
&lt;li&gt;All of the NUnit attributes identifying test fixtures and tests are gone.&amp;nbsp; MSpec is smart enough to figure out what is a test vs. what is a regular old class based on the MSpec delegates that make up the class.&amp;nbsp; When looked at through the &lt;a href="http://www.nunit.org/index.php"&gt;NUnit&lt;/a&gt; lens, the specification class remains the test fixture, and each &amp;ldquo;It&amp;rdquo; delegate instance becomes an NUnit test. &lt;/li&gt;
&lt;li&gt;Notice the with_dummy_resource_builder_and_reader class.&amp;nbsp; As with unit tests, inheritance can be a great way to provide shared context to multiple test fixtures.&amp;nbsp; This base class is responsible for 2 things: 1) exposing a few data fields for its child classes, and 2) providing its own Establish delegate to setup those data fields. &lt;/li&gt;
&lt;li&gt;For me, this format of specifications seemed to yield another benefit &amp;ndash; without explicit effort.&amp;nbsp; That benefit was more tests with each test having a much better definition around its responsibility. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This particular type of test &amp;ndash; one where you&amp;rsquo;re expecting an exception &amp;ndash; was one where I wasn&amp;rsquo;t 100% confident in my approach.&amp;nbsp; However, I didn&amp;rsquo;t find any baked in support from MSpec &amp;ndash; and frankly, for the framework to provide a feature similar to NUnit&amp;rsquo;s ExpectedExceptionAttribute doesn&amp;rsquo;t really make a lot of sense to me for writing specifications anyway.&amp;nbsp; You can see above the approach that I took &amp;ndash; simply trap the exception and then run a couple tests over the exception to assert various characteristics of it.&amp;nbsp; If there&amp;rsquo;s a better way to go about this, I would love to hear it.&lt;/p&gt;
&lt;p&gt;After I started getting the hang of writing specifications by rewriting my tests, I began venturing into new parts of my application &amp;ndash; and this is where I really started realizing just how much ceremony exists in traditional unit testing frameworks compared to something like MSpec.&amp;nbsp; Because mostly everything in MSpec is a field, there&amp;rsquo;s no need to provide any kind of method body, etc. after declaring the title of the specification.&amp;nbsp; So, for example, when I wanted to write specifications around executing a query, I was able to quickly capture the specs as follows:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;public class when_query_is_executed_for_products_with_expanded_suppliers
     : with_query_shape_factory
{
    It should_have_2_result_sets;
    It should_have_a_result_set_named_products;
    It should_have_8_columns_in_products_result_set;
    It should_have_77_rows_in_products_result_set;
    It should_have_a_result_set_named_suppliers;
    It should_have_13_columns_in_suppliers_result_set;
    It should_have_77_rows_in_suppliers_result_set;
}&lt;/pre&gt;
&lt;p&gt;Remember, &amp;ldquo;It&amp;rdquo; is simply a type and &amp;ldquo;should_have_2_result_sets&amp;rdquo; is simply a field declaration &amp;ndash; no need to initialize it with anything just yet.&amp;nbsp; When the MSpec runner is executing, it checks to see whether the field has been initialized &amp;ndash; if it hasn&amp;rsquo;t, as in this case, it flags it as if you used NUnit&amp;rsquo;s IgnoreAttribute.&lt;/p&gt;
&lt;p&gt;Finally, I mentioned earlier in this post about using ReSharper to run MSpec specifications.&amp;nbsp; While I would probably still be interested in MSpec if this integration didn&amp;rsquo;t exist, the fact that it was there removed any question or hesitation.&amp;nbsp; We talk a lot about the readability of tests, and of tests being the spec &amp;ndash; and this is, based on what I&amp;rsquo;ve experienced so far, where specification frameworks like MSpec really shine.&amp;nbsp; Bringing that goodness directly into Visual Studio ala ReSharper mades the feedback loop even tighter, and really made for a happy development process.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/Untitled_5F00_06CF122B.png"&gt;&lt;img height="731" width="499" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/Untitled_5F00_thumb_5F00_48F27AAE.png" alt="Untitled" border="0" title="Untitled" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;ve read this far and you have no clue what this project is that I&amp;rsquo;m talking about, see the overview &lt;a href="http://codebetter.com/blogs/howard.dierking/archive/2009/10/28/astoria-ssis-adapters-and-bdd-take-1.aspx"&gt;here&lt;/a&gt;.&amp;nbsp; If you want to download the code and look at it yourself, check it out at &lt;a href="http://code.msdn.microsoft.com/ssisastoria" title="http://code.msdn.microsoft.com/ssisastoria"&gt;http://code.msdn.microsoft.com/ssisastoria&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=424518" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/R_2300_/default.aspx">R#</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/BDD/default.aspx">BDD</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/SSIS/default.aspx">SSIS</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>Using Latest NUnit Version With MSpec</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/11/08/using-latest-nunit-version-with-mspec.aspx</link><pubDate>Sun, 08 Nov 2009 20:11:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:416195</guid><dc:creator>hdierking</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=416195</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/11/08/using-latest-nunit-version-with-mspec.aspx#comments</comments><description>&lt;p&gt;As I&amp;rsquo;ve been working another blog post about my adventures in learning BDD ala &lt;a href="http://codebetter.com/blogs/aaron.jensen/archive/2008/05/08/introducing-machine-specifications-or-mspec-for-short.aspx"&gt;MSpec&lt;/a&gt;, I ran into something that I wanted to share as the problem wasn&amp;rsquo;t immediately obvious (to me anyway).&lt;/p&gt;
&lt;p&gt;The problem is that MSpec has a dependency on version 2.4.6.0 of the nunit.framework assembly &amp;ndash; and frankly, it&amp;rsquo;s not really a very big problem.&amp;nbsp; In fact, I didn&amp;rsquo;t even notice it until now because I had been &lt;a href="http://www.lostechies.com/blogs/seanbiefeld/archive/2009/08/25/step-by-step-to-using-machine-specifications-with-resharper.aspx"&gt;running all of my specs exclusively through the Resharper runner (enabled by the MSpec plugin&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;** As a side note, using R# with the MSpec plugin absolutely rocks, and while the runner is needed for integrating MSpec with your automated builds, I would totally recommend R# for your regular dev rhythm.&lt;/p&gt;
&lt;p&gt;In my project, I originally had some integration tests in the same assembly as my specifications.&amp;nbsp; As a result, I had a direct reference to NUnit (version 2.5.2.9222) in addition to the reference to Machine.Specifications and Machine.Specifications.NUnit (which has a reference to version 2.4.6.0).&amp;nbsp; As a result, the later version of NUnit was being copied to my bin folder and throwing a file load exception for every specification when run using the console runner.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/Untitled_5F00_549F853E.png"&gt;&lt;img height="224" width="668" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/Untitled_5F00_thumb_5F00_31FB46C3.png" alt="Untitled" border="0" title="Untitled" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;My initial reaction was to simply move all my integration tests to a different assembly and remove the direct NUnit reference in my specifications assembly (remember that referencing Machine.Specifications.NUnit will copy the version of NUnit to the bin folder that MSpec expects.&amp;nbsp; No problem &amp;ndash; everything works as you would expect.&lt;/p&gt;
&lt;p&gt;However, it seems reasonable to me that, at least in larger projects that are wanting to incorporate specs and not have to re-write all existing tests, that it would be good to simply reconfigure the MSpec console runner to use the latest version of NUnit.&amp;nbsp; This can be done easily using the standard .NET assembly binding redirection feature.&amp;nbsp; Simply create a file named Machine.Specifications.ConsoleRunner.exe.config and drop it into the MSpec folder that contains your console runner (Machine.Specifications.ConsoleRunner.exe).&amp;nbsp; The contents of the file should look like this.&lt;/p&gt;
&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;runtime&amp;gt;
      &amp;lt;assemblyBinding xmlns=&amp;quot;urn:schemas-microsoft-com:asm.v1&amp;quot;&amp;gt;
        &amp;lt;dependentAssembly&amp;gt;
          &amp;lt;assemblyIdentity name=&amp;quot;nunit.framework&amp;quot;
                            publicKeyToken=&amp;quot;96d09a1eb7f44a77&amp;quot;
                            culture=&amp;quot;neutral&amp;quot; /&amp;gt;
          &amp;lt;bindingRedirect oldVersion=&amp;quot;2.4.6.0&amp;quot;
                           newVersion=&amp;quot;2.5.2.9222&amp;quot;/&amp;gt;
        &amp;lt;/dependentAssembly&amp;gt;
      &amp;lt;/assemblyBinding&amp;gt;
    &amp;lt;/runtime&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;
&lt;p&gt;Run the MSpec console again, and voila! Works like a charm.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/Untitled2_5F00_5EA4009C.png"&gt;&lt;img height="199" width="529" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/Untitled2_5F00_thumb_5F00_6B9DE0AD.png" alt="Untitled2" border="0" title="Untitled2" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=416195" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/R_2300_/default.aspx">R#</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/BDD/default.aspx">BDD</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/MSpec/default.aspx">MSpec</category></item><item><title>Astoria, SSIS Adapters and BDD – Code</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/11/06/astoria-ssis-adapters-and-bdd-code.aspx</link><pubDate>Fri, 06 Nov 2009 19:57:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:413671</guid><dc:creator>hdierking</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=413671</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/11/06/astoria-ssis-adapters-and-bdd-code.aspx#comments</comments><description>&lt;p&gt;I&amp;rsquo;m currently working on the post talking about how, in the course of writing my SSIS data source for ADO.NET Data Services, I stumbled into replacing my unit tests with specifications.&amp;nbsp; However, in advance of that, I wanted to go ahead and provide the link to the source code.&amp;nbsp; I would love to get feedback on what&amp;rsquo;s working and what&amp;rsquo;s not so that I can get better &amp;ndash; and so that ideally, those the random stranger who downloads and looks at it on some idle Tuesday gets better as well.&lt;/p&gt;
&lt;p&gt;The code can be found at &lt;a href="http://code.msdn.microsoft.com/ssisastoria" title="http://code.msdn.microsoft.com/ssisastoria"&gt;http://code.msdn.microsoft.com/ssisastoria&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=413671" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/SSIS/default.aspx">SSIS</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>Getting Your Groove Off</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/10/29/getting-your-groove-off.aspx</link><pubDate>Thu, 29 Oct 2009 21:26:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:403450</guid><dc:creator>hdierking</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=403450</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/10/29/getting-your-groove-off.aspx#comments</comments><description>&lt;p&gt;Until recently, the only knowledge I had of Groove was that it was some kind of collaboration product that we got as a result of bringing in &lt;a href="http://www.microsoft.com/presspass/exec/ozzie/?tab=biography"&gt;Ray Ozzie&lt;/a&gt;.&amp;nbsp; Then I got a new manager who insisted that our team standardize on Groove for the team document repository - so I got setup on Groove and went on with my life.&amp;nbsp; In general, there&amp;rsquo;s nothing I found terribly impressive about it, but it wasn&amp;rsquo;t really getting in my way so no reason to get too upset&amp;hellip;&lt;/p&gt;
&lt;p&gt;Until my &lt;a href="http://tortoisesvn.net/"&gt;Tortoise SVN&lt;/a&gt; icon overlays stopped working.&lt;/p&gt;
&lt;p&gt;I ended up spending quite a bit of time this morning trying to figure out exactly why they weren&amp;rsquo;t working.&amp;nbsp; It was odd &amp;ndash; I had no problems on my home machine &amp;ndash; but on both of my work machines, same result &amp;ndash; no TSVN icons.&amp;nbsp; Finally, &lt;a href="http://twitter.com/pilotbob"&gt;@pilotbob&lt;/a&gt; pointed me to &lt;a href="http://msdn.microsoft.com/en-us/library/cc144123%28VS.85%29.aspx"&gt;this article&lt;/a&gt; which set off a chain of recollections &amp;ndash; most notably that the major difference between my work machines and my home machine had to do with the order that I installed stuff.&amp;nbsp; On my home machine, I installed Office after I got my dev environment setup.&amp;nbsp; However, on my work machine, Office was installed as a part of the default OS install image - and Groove was included in that installation.&lt;/p&gt;
&lt;p&gt;So why is this important?&amp;nbsp; Because if you remember from the article, Windows supports only 15 overlay handler slots &amp;ndash; and installing Groove puts 5 handlers right there on top of my TSVN handlers &amp;ndash; the net result being that my TSVN icon overlays don&amp;rsquo;t load.&lt;/p&gt;
&lt;p&gt;To fix, I simply went into the registry, deleted all of the Groove overlay handlers from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/reg_5F00_5DBA9B31.png"&gt;&lt;img height="464" width="644" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/reg_5F00_thumb_5F00_1F059DCB.png" alt="reg" border="0" title="reg" style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Then rebooted.&amp;nbsp; Voila!&amp;nbsp; TSVN icon overlays come right back up!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=403450" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/TortoiseSVN/default.aspx">TortoiseSVN</category></item><item><title>Astoria, SSIS Adapters and BDD – Take 1</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/10/28/astoria-ssis-adapters-and-bdd-take-1.aspx</link><pubDate>Wed, 28 Oct 2009 16:00:17 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:400446</guid><dc:creator>hdierking</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=400446</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/10/28/astoria-ssis-adapters-and-bdd-take-1.aspx#comments</comments><description>&lt;p&gt;Yea I know – 3 things you never thought you would hear mentioned together.&amp;#160; And to be really honest, I didn’t start out trying to build this in a BDD fashion – and since I’m totally new to the disciplines of BDD, I may not have been all that successful.&amp;#160; But hey, it’s all about the journey, and so I wanted to at least go ahead and start posting about the work I’ve been doing here, partly to share and partly to get your input ways to improve my design/specs.&lt;/p&gt;  &lt;p&gt;So here was the initial goal – I was studying ADO.NET Data Services (previously known as Astoria) when I remembered &lt;a href="http://msdn.microsoft.com/en-us/library/bb245659.aspx"&gt;this article that I once read&lt;/a&gt; in the Architecture Journal about using RSS as a technique for surfacing data to load into an enterprise data warehouse.&amp;#160; That led me to think that it would be a cool opportunity to simultaneously learn Astoria and feed my BI sweet tooth by writing a SSIS data source that could consume an Astoria endpoint.&amp;#160; Given the fact that &lt;a href="https://blogs.msdn.com/astoriateam/archive/2009/10/21/using-data-services-over-sharepoint-2010-part-1-getting-started.aspx"&gt;more and more systems are exposing data using syndication&lt;/a&gt;, it seemed like creating an SSIS data source was something that could be helpful beyond my simply wanting to play with the technology.&lt;/p&gt;  &lt;p&gt;Wait - ADO.NET Data Services what??&lt;/p&gt;  &lt;p&gt;Just in case you weren’t 100% sure what ADO.NET Data Services is, it’s technology to expose data and enable operations on data via RESTful operations.&amp;#160; You can find out much more about it &lt;a href="http://msdn.microsoft.com/en-us/data/bb931106.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/astoriateam/"&gt;here&lt;/a&gt;, but for the purposes of this exercise, here are the 3 things you need to know.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;It uses all standard HTTP operations – which means that for getting data, you simply format a HTTP GET request for the service URL plus additional path information and optional querystring arguments to tell the framework how to shape the data. &lt;/li&gt;    &lt;li&gt;While there’s not a dependency on the Entity Framework, there is a dependency on the Entity Data Model in that metadata is exposed as &lt;a href="http://msdn.microsoft.com/en-us/library/bb399292.aspx"&gt;CSDL&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;Though you have a couple formatting options when getting data, the primary one (and the one used by the data source component) is to get the data as an ATOM feed.&amp;#160; The data source component can then project the XML into the appropriate output buffer (or buffers as you’ll see later). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Wait – SSIS what??&lt;/p&gt;  &lt;p&gt;Sql Server Integration Services is Microsoft’s ETL tool that ships with SQL Server.&amp;#160; You can start learning more about it &lt;a href="http://msdn.microsoft.com/en-us/library/ms141026.aspx"&gt;here&lt;/a&gt;, but for the purpose of this exercise, here are the 3 things you need to know.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The unit of execution in SSIS is the package.&amp;#160; This is really similar nomenclature to DTS because, not surprisingly, SSIS evolved out of DTS. &lt;/li&gt;    &lt;li&gt;Every package contains 2 kinds of logic: 1 “Control Flow” and zero-to-many “Data Flows”.&amp;#160; Control flow is meant for larger operations like copying files or running some kind of database maintenance operation (and while interesting, it’s not something I care about for this exercise).&amp;#160; The real meat of SSIS (IMHO) happens within a data flow – this is where data is extracted from a source, massaged, and put into a destination.&amp;#160; Data flows maintain the entire pipeline of operations between source and destination via in memory buffers. &lt;/li&gt;    &lt;li&gt;Data flows use data source components to extract data from the source and add it to the appropriate buffers in the pipeline.&amp;#160; Data source components are also used to provide metadata to the SSIS design-time experience so that package designers can use it to clean up and massage the data using transformation components (** for those experienced SSIS folks, it’s worth noting that there is an XML data source component that is a part of the product, and since ADO.NET Data Services returns data as an ATOM feed, is is absolutely possible to consume it directly.&amp;#160; However, in order to take this approach, you will need to generate a XSD schema and associate it with the component at design time for the metadata – and every time you change the shape of your data services query, you will have to re-generate and re-associate a new schema.&amp;#160; This was one of the primary motivators for me to create a custom data source). &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So then, the initial goals were as follows -&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Create an SSIS data source component that could consume an ADO.NET Data Services endpoint &lt;/li&gt;    &lt;li&gt;Ensure that the component participated in both the design time and runtime experiences &lt;/li&gt;    &lt;li&gt;Ensure that the component was able to handle projections of ADO.NET Data services queries that took advantage of the $&lt;a href="http://msdn.microsoft.com/en-us/library/cc668798.aspx"&gt;expand clause&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;As I got into the development I was pretty quickly able to accomplish the first 2 goals.&amp;#160; For example, given the following query configuration..&lt;/p&gt;  &lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/ConfigDialog_5F00_76A43385.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="ConfigDialog" border="0" alt="ConfigDialog" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/ConfigDialog_5F00_thumb_5F00_05F79595.png" width="244" height="230" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I was able to get the data shape using ADO.NET Data Service’s &lt;a href="http://blogs.thinktecture.com/cweyer/archive/2007/12/11/415061.aspx"&gt;$metadata&lt;/a&gt; option and expose it back to the designer..&lt;/p&gt;  &lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/ColumnMappings_5F00_395358F1.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="ColumnMappings" border="0" alt="ColumnMappings" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/ColumnMappings_5F00_thumb_5F00_36CA2733.png" width="244" height="230" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;I was even able to run the package for a simple data services query and pipe the results to a flat file..&lt;/p&gt;  &lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/simpleExample_5F00_47622221.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="simpleExample" border="0" alt="simpleExample" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/simpleExample_5F00_thumb_5F00_740ADBFA.png" width="170" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;However, when I started implementing that 3rd goal of managing projections, I quickly realized my quick and dirty project need more thought in its design.&amp;#160; This drove me to add a few more goals.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Project should separate the core logic of the component from the SSIS infrastructure – which is heavily reliant on inheritance &lt;/li&gt;    &lt;li&gt;Core component logic should be independently testable without requiring a running data services endpoint &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Separating the logic out into a different assembly wasn’t really all that painful – just a few keystrokes of Resharper, a couple file moves, a reference added, and I was good to go.&amp;#160; However, because this started as a quick and dirty project (I should have known better), I hadn’t designed for data source independence and as such had some larger refactorings to do.&amp;#160; And in that process (** keep in mind that this started as an remains primarily a learning exercise for me – I would NEVER recommend taking this kind of “while I’m at it approach” on a real project), I decided that my tests weren’t really where I wanted them and that I had always wanted to get my hands dirty with BDD anyway, so why not?&amp;#160; It’s just one more goal.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Tests should be written as specifications &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I’ve read from some that BDD is really meant more for testing larger behaviors in business applications.&amp;#160; However, it feels pretty good (though initially uncomfortable) at the grain at which I’m using it.&amp;#160; For example..&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;public class when_products_resource_is_queried : with_northwind_CSDL
{
    Establish context = () =&amp;gt; queryBuilder.ResourcePath = &amp;quot;Products&amp;quot;;

    Because of = () =&amp;gt; query = queryBuilder.GetQuery();

    It should_have_8_properties = () =&amp;gt; 
        query.DataShape.First().Properties.Count.ShouldEqual(8);

    It should_have_a_single_resource = () =&amp;gt; 
        query.DataShape.Count().ShouldEqual(1);

    It should_have_1_key_property = () =&amp;gt; 
        query.DataShape.First().Keys.Count.ShouldEqual(1);

    It should_have_correct_query_string = () =&amp;gt;
        query.ToString().ShouldEqual(string.Format(
            &amp;quot;{0}/Products&amp;quot;, Constants.SERVICE_URI));
}&lt;/pre&gt;

&lt;p&gt;Ok – so those were the goals as they evolved. Going forward, my plan is to dig into the logic design and specifications, then talk specifically about projections, then finally talk about how this stuff works with SSIS (and how I would like to see the SSIS API simplified).&amp;#160; Sorry to not get into all that tonight, but as my friend &lt;a href="http://blogs.msdn.com/gblock/archive/2007/08/29/improving-blogging-efficiency.aspx"&gt;Glenn has advised me countless times&lt;/a&gt;, if you wait to blog until everything is nice and tidy and completed, you may never blog again.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=400446" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/BDD/default.aspx">BDD</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/SSIS/default.aspx">SSIS</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/ADO.NET+Data+Services/default.aspx">ADO.NET Data Services</category></item><item><title>Goodbye MSDN Magazine</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/09/22/goodbye-msdn-magazine.aspx</link><pubDate>Wed, 23 Sep 2009 05:28:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:358629</guid><dc:creator>hdierking</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=358629</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/09/22/goodbye-msdn-magazine.aspx#comments</comments><description>&lt;p&gt;I am a huge fan of &lt;em&gt;&lt;a href="http://msdn.microsoft.com/magazine/default.aspx"&gt;MSDN Magazine&lt;/a&gt;&amp;nbsp;&lt;/em&gt;(and it&amp;rsquo;s predecessor publications going back to MSJ).&amp;nbsp; There are just a handful of resources that have been so constant throughout the bulk of my career and &lt;em&gt;MSDN Magazine &lt;/em&gt;is unquestionably one of those.&amp;nbsp; This is why when Matt Carter pinged me over 2 years ago to tell me that there was an opening for the Editor-in-Chief role, I jumped at the opportunity without a moment of hesitation.&amp;nbsp; And it&amp;rsquo;s been a great and wild ride these last couple of years.&amp;nbsp; More importantly, I think that we&amp;rsquo;ve done some good in trying to improve the way that people think about building and constructing software.&amp;nbsp; It&amp;rsquo;s always a tricky balancing act trying to cover new technologies and simultaneously trying to help people do a better job with the technologies they are already using, but I&amp;rsquo;m pleased with some of the directional shifts we made as a magazine favoring practices over technology &amp;ndash; and really, those shifts wouldn&amp;rsquo;t have been possible without so many people like &lt;a href="http://codebetter.com/blogs/jeremy.miller/"&gt;Jeremy Miller&lt;/a&gt;, &lt;a href="http://codebetter.com/blogs/david_laribee/default.aspx"&gt;Dave Laribee&lt;/a&gt;, &lt;a href="http://codebetter.com/blogs/james.kovacs/"&gt;James Kovacs&lt;/a&gt;, &lt;a href="http://ayende.com/Blog/"&gt;Ayende Rahien&lt;/a&gt; (December spoiler!), and so many other from what began as ALT.NET stepping up and writing for us.&amp;nbsp; I hope that this is indicative of a trend that continues long after my departure.&lt;/p&gt;
&lt;p&gt;So then why leave?&amp;nbsp; In the end, I just came to the realization that the passion that initially drove me to the magazine was for creating software &amp;ndash; not running a magazine business.&amp;nbsp; And as the business elements became more and more consuming &amp;ndash; and as the time that they occupied pushed out my ability to stay close to the technology, I came to conclude 2 things &amp;ndash; 1) I was finding it harder to sustain the passion I came to the role with (because the object of that passion was fading) and 2) I was losing skill at an alarming rate.&amp;nbsp; Summary &amp;ndash; I needed to move back into the engineering world.&amp;nbsp; As such, when a role opened up on the MSDN and TechNet Web platform team, I decided to move.&amp;nbsp; There&amp;rsquo;s a lot of work to be done on those websites (a LOT) and most of the current work is around the more aesthetic elements of the UX.&amp;nbsp; These things are certainly good and necessary, but I still don&amp;rsquo;t think they are anything remotely close to what&amp;rsquo;s necessary to make the sites truly helpful.&amp;nbsp; In my new role, I&amp;rsquo;ll be focusing on driving &amp;ldquo;intelligent Web&amp;rdquo; innovations into the platform &amp;ndash; so at the very least, I&amp;rsquo;ll get to play with some really cool tech..&lt;/p&gt;
&lt;p&gt;So to wrap it up, it&amp;rsquo;s been awesome &amp;ndash; but now time to try something different &amp;ndash; and maybe finally have time to blog again!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=358629" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/MSDN+Magazine/default.aspx">MSDN Magazine</category></item><item><title>Windows 7 Boot from VHD – A Few Gotchas</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/08/08/windows-7-boot-from-vhd-a-few-gotchas.aspx</link><pubDate>Sat, 08 Aug 2009 17:33:21 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:278456</guid><dc:creator>hdierking</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=278456</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/08/08/windows-7-boot-from-vhd-a-few-gotchas.aspx#comments</comments><description>&lt;p&gt;When I first read about the capability in Windows 7 to natively boot a VHD, I was ecstatic – finally I could install all of my beta software in a sandboxed environment without having to put up with the performance cost of virtualized hardware.&amp;#160; So I read through several posts such as &lt;a href="http://www.hanselman.com/blog/LessVirtualMoreMachineWindows7AndTheMagicOfBootToVHD.aspx"&gt;this one from Scott&lt;/a&gt; and then proceeded to modify my boot record accordingly – pointing it at a vhd that I had already created via Windows Virtual PC.&amp;#160; As those of you who have played with this already know, it’s not quite that simple, and it took me a little bit of time and digging to figure out exactly where the problems were – so I want to take a second and list out the major gotchas that I ran into – hopefully this will save you some extra digging.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;By default, Windows Virtual PC puts both your vhd and vm config files in “C:\Users\[you]\AppData\Local\Microsoft\Windows Virtual PC\Virtual Machines” – this folder has restricted permissions and while pointing your master boot record at a vhd file found in this location will not raise an error when running bcdedit, it will rear its ugly head when you reboot.&amp;#160; And while the error is recoverable and harmless, it looks a bit scary – something about the master boot record database being corrupted – yikes!&lt;/li&gt;    &lt;li&gt;You must run sysprep on the vm that you intend to boot from – and you need to use the “generalize” option.&amp;#160; Otherwise, your system will blue-screen when trying to boot your vhd because it will try and use the virtual machine drivers and not auto-detect the drivers for the physical hardware.&lt;/li&gt;    &lt;li&gt;(this was the one that gave me fits) Pay attention to the size of your vhd file, even if you’re creating a dynamically sized disk.&amp;#160; By default, the disk size for a dynamically expanding disk (when created through Windows Virtual PC) is 130 GB.&amp;#160; If this size exceeds the amount of available storage on your physical disk, your vhd will start to boot and then blue-screen.&amp;#160; Fortunately, the stop error is actually comprehensible – it will tell you that you don’t have enough physical storage to enable the vhd to expand to its maximum capacity (or something equivalent).&amp;#160; So in short, be explicit in configuring your vhd, and make sure that the vhd size doesn’t exceed available physical storage limits (even on dynamically expanding disks).&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Once I got through those problems, I was able to boot from my vhd and created a nice little testing environment for VS 2010.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=278456" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/Windows+7/default.aspx">Windows 7</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/virtualization/default.aspx">virtualization</category></item><item><title>2010 Column Planning</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/08/07/2010-column-planning.aspx</link><pubDate>Fri, 07 Aug 2009 23:55:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:277316</guid><dc:creator>hdierking</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=277316</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/08/07/2010-column-planning.aspx#comments</comments><description>&lt;p&gt;It&amp;rsquo;s that time of year once again where I go through my column lineup to see how individual columns are performing and then use that data, along with various other inputs (like what topics I think are emerging and want to get ahead of, etc.) to determine next year&amp;rsquo;s column lineup.&amp;nbsp; I want to extend my process to you and get your feedback on which columns are working well and which ones aren&amp;rsquo;t.&amp;nbsp; Additionally, just to give you a bit of additional insight, here is some of the data that I&amp;rsquo;m looking at as I go through the process.&amp;nbsp; Obviously, this is just one dimension of performance, but it&amp;rsquo;s also one that has a pretty large sample size so I generally trust it more than I do other measures, such as the &amp;ldquo;5-star&amp;rdquo; ratings.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/image_5F00_71396F48.png"&gt;&lt;img height="500" width="635" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/image_5F00_thumb_5F00_0FA3B032.png" alt="image" border="0" title="image" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;So give me your thoughts.&amp;nbsp; If it were up to you, which columns would you run more frequently?&amp;nbsp; Which ones would you cancel?&amp;nbsp; Or more generally, is there anything on this chart that surprised you?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=277316" width="1" height="1"&gt;</description></item><item><title>R# Refactoring Steps For Introducing a Const</title><link>http://codebetter.com/blogs/howard.dierking/archive/2009/07/21/r-refactoring-steps-for-introducing-a-const.aspx</link><pubDate>Tue, 21 Jul 2009 21:03:14 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:251830</guid><dc:creator>hdierking</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/howard.dierking/rsscomments.aspx?PostID=251830</wfw:commentRss><comments>http://codebetter.com/blogs/howard.dierking/archive/2009/07/21/r-refactoring-steps-for-introducing-a-const.aspx#comments</comments><description>&lt;p&gt;I’m currently writing some pipeline components for SSIS and I’m curious as to whether there is a commonly followed refactoring pattern for extracting constants.&amp;#160; For example, consider the following.&lt;/p&gt;  &lt;pre class="c-sharp" name="code"&gt;var authenticationType = ComponentMetaData.CustomPropertyCollection.New();
authenticationType.Name = C_AUTHENTICATIONTYPE;&lt;/pre&gt;

&lt;p&gt;There’s nothing unique to this code.&amp;#160; In fact, if you looked further at the surrounding code, you would see a whole bunch of similar declarations – and that’s where it can get a bit annoying.&amp;#160; If C_AUTHENTICATIONTYPE were anything other than a const, I wouldn’t think twice about simply typing in the above code and letting ReSharper prompt me to create a variable/field/etc.&amp;#160; However, I haven’t found a similar pattern for creating a const – and I *hate* the idea of manually entering the const declaration as it throws me out of my rhythm.&amp;#160; &lt;/p&gt;

&lt;p&gt;So here’s what I’m currently doing – let me know if there’s a better way.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/image_5F00_6D03B981.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/image_5F00_thumb_5F00_1E22F422.png" width="407" height="172" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;First, I’m having R# create a new local variable (standard alt+enter).&amp;#160; Next I’m executing the “Introduce Field” refactoring on the new variable and selecting the “Introduce constant” option (note that if you haven’t initialized your local variable, this option will be unavailable). &lt;/p&gt;

&lt;p&gt;&lt;a href="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/image_5F00_7D2F817A.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://codebetter.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/howard.dierking/image_5F00_thumb_5F00_491AE227.png" width="841" height="303" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;This works pretty well – certainly better than having to context switch in order to go declare a const.&amp;#160; I did see that there is a “to const” option for variables.&amp;#160; However, this option creates a local const which doesn’t help all that much, and I couldn’t find a secondary refactoring to extract the const from the method to the class scope (at least not in R#).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=251830" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/Refactoring/default.aspx">Refactoring</category><category domain="http://codebetter.com/blogs/howard.dierking/archive/tags/R_2300_/default.aspx">R#</category></item></channel></rss>