<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-393540894130950585</id><updated>2012-01-31T05:43:10.658-08:00</updated><category term='Enterprise applications'/><category term='Composite UI Application Block'/><category term='SCSF'/><category term='ajax'/><category term='CAB'/><title type='text'>Never In Doubt</title><subtitle type='html'>Often wrong but never in doubt ... an opinionated romp through .NET</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default?start-index=101&amp;max-results=100'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>104</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-7186754085925588445</id><published>2011-11-11T14:03:00.001-08:00</published><updated>2011-11-12T16:03:23.812-08:00</updated><title type='text'>Build business apps in .NET - not HTML &amp; JavaScript</title><content type='html'>&lt;p&gt;A lot of people are freaking out about the apparent decline of .NET client technologies such as WPF and Silverlight. I’m one of those people. How can one, in good conscience, advocate new development in WPF or Silverlight (or Windows Forms)?&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;span style="font-size: small"&gt;Well I can advocate it, I do advocate it, and I’m sleeping well at night.&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;A recent comment to one of &lt;a href="http://neverindoubtnet.blogspot.com/2011/10/windows-8-metro-apps-in-javascript.html"&gt;my post on WinRT&lt;/a&gt; provoked an outsized reaction that has become this post. Here’s that comment:&lt;/p&gt;  &lt;blockquote&gt;&lt;em&gt;&lt;span style="font-size: small"&gt;Given that most people who are skilled in HTML5+JS write applications that are cross-browser and cross-OS every day; why would they ever consider writing for a single OS?&lt;/span&gt;&lt;/em&gt;&lt;/blockquote&gt;  &lt;p&gt;This fellow managed to capture in a few words the current mood and madness. My rant follows:&lt;/p&gt;  &lt;h2&gt;Who are you kidding?&lt;/h2&gt;  &lt;p&gt;First, hardly anyone is skilled in HTML &lt;span style="background-color: yellow"&gt;&lt;strong&gt;&lt;u&gt;5&lt;/u&gt;&lt;/strong&gt;&lt;/span&gt;. Period. That’s just wrong on the facts.&lt;/p&gt;  &lt;p&gt;Secondly, most people “&lt;em&gt;who are skilled in HTML + JavaScript&lt;/em&gt;” – cross-browser or otherwise - &lt;strong&gt;do not have a clue how to write a business application in JavaScript&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Most people who write apps that emit HTML do not write much JavaScript; they exploit controls that rely on JavaScript and they may write a little decorative JavaScript but that's the extent of their experience.&lt;/p&gt;  &lt;p&gt;How do I know that? I've been hanging out where the experts in JavaScript hang ... and the recurring verities are (a) most people write horrible JavaScript (hence the need for Crockford's &amp;quot;JavaScript - The Good Parts&amp;quot;), the apps are almost unmaintainable when they do, and (c) the appropriate design and implementation patterns for JavaScript are in flux.&lt;/p&gt;  &lt;p&gt;This is a fascinating and creative time in the evolution of JavaScript programming. New frameworks are popping up left and right. Lots of lectures and discussions about how to do it right. That's all healthy.&lt;/p&gt;  &lt;p&gt;But the sheer wildness and variety of competing and overlapping toolkits/frameworks/guidance &lt;strong&gt;reveals the immaturity of the JavaScript environment as a business application development platform&lt;/strong&gt;.&lt;/p&gt;  &lt;h2&gt;Get real about business application development&lt;/h2&gt;  &lt;p&gt;Let me be crystal clear about what I mean when I talk about a &amp;quot;business application&amp;quot; … because I want to confine my remarks to just this one kind of app. I take a completely different position on the appropriate development and delivery platform for other kinds of applications. &lt;strong&gt;This post is about business applications only&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;[&lt;span style="font-size: small"&gt;&lt;strong&gt;Warning&lt;/strong&gt;: &lt;strong&gt;I will delete every comment&lt;/strong&gt;&lt;/span&gt; that attempts to refute my argument by reference to any other kind of application. I will be especially dismissive of counter-claims which only make sense with regard to consumer facing, social networking, content broadcasting apps. You are simply not paying attention if you respond in that way and I will not waste my time or my reader(s) time with your inappropriate reply.]&lt;/p&gt;  &lt;p&gt;Here is what I mean by a “business application”:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;It is a &amp;quot;&lt;strong&gt;&lt;span style="font-size: small"&gt;sovereign app&lt;/span&gt;&lt;/strong&gt;&amp;quot;. That one app will dominate a user's attention for hours at a time, day after day.       &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;The &lt;strong&gt;&lt;span style="font-size: small"&gt;user is paid to use the app&lt;/span&gt;&lt;/strong&gt;. The person who pays him/her requires that user to get work done with the app as quickly and efficiently as possible.       &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;It is &lt;strong&gt;&lt;span style="font-size: small"&gt;data-centric&lt;/span&gt;&lt;/strong&gt;. The user consumes a large volume and &lt;strong&gt;variety&lt;/strong&gt; of data. More importantly, the user routinely adds and updates that data in all of its variety.       &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Therefore, the app must be&lt;strong&gt; &lt;span style="font-size: small"&gt;highly responsive and immersive&lt;/span&gt;&lt;/strong&gt; in order to maximize user productivity. It must present data and accept user input at top speed. Every moment spent waiting or wondering or searching around or flipping pages is wasted user time and wasted business owner money. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;In my experience, the only apps that hit the required standard of user efficiency are apps that execute predominantly on the client. I don't care if its written in Windows Forms, WPF, Silverlight, Java, or in JavaScript ... it has to execute on the client and make only the minimally necessary trips to the server. &lt;/p&gt;  &lt;p&gt;This is the context for answering your question. &lt;strong&gt;&lt;em&gt;&lt;span style="font-size: small"&gt;Why would I write for one OS?&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If I'm writing a business app, in all likelihood there is only one OS that matters: Windows. Windows just happens to own 95% of my targeted user base (my estimate) ... today and for the near term. &lt;/p&gt;  &lt;p&gt;[Note: The &lt;a href="http://en.wikipedia.org/wiki/Usage_share_of_desktop_operating_systems#Estimates_for_2011"&gt;OS-on-a-PC figures&lt;/a&gt; are imperfect but the consensus is that Windows has no less than 88% share of all PCs which includes home PCs. Home PCs don’t matter for this analysis.] &lt;/p&gt;  &lt;p&gt;Don't bother telling me about mobile. Don't bother giving me statistics on web traffic by OS (where &lt;a href="http://marketshare.hitslink.com/operating-system-market-share.aspx?qprid=8"&gt;Windows gets 86% of 2011 web traffic&lt;/a&gt;, btw). Don't tell me your vision for the future. This discussion is about business apps today and they run on PCs ... period.&lt;/p&gt;  &lt;p&gt;If the time &amp;amp; cost of developing and maintaining business apps in HTML/JS were anywhere close to the marks of a .NET client platform I'd say &amp;quot;go HTML/JS&amp;quot;.&lt;/p&gt;  &lt;p&gt;But they aren't. Not close. Not soon to be close. And that fact is nowhere in dispute, not even among the most ardent HTML/JS fans.&lt;/p&gt;  &lt;p&gt;So, as a business person, I've got a decision to make. The economics of today tell me &amp;quot;build it in .NET&amp;quot; because I can do it cheaply, effectively, with great quality using readily available resources, mature tools and experienced developers.&lt;/p&gt;  &lt;p&gt;Of course, as a business man, I'll be concerned about the future and the long-term viability of my application. I’m perturbed that the app I am building today will be seen in 3 years as pinned to a legacy technology. That's a tough pill ... and it's why there is so much consternation. No one wants the “legacy” sign hanging around his neck.&lt;/p&gt;  &lt;p&gt;But it’s not like everyone is going to forget how to write in .NET. Support won’t vanish. I will be able to find technology and people to keep the application alive in ten or fifteen years. I’ve got time to amortize my development costs and prepare for the inevitable transition(s) down the road.&lt;/p&gt;  &lt;p&gt;The alternative - writing a business app in HTML/JS today – makes no economic sense. It doesn’t give me more reach because there are virtually no targeted users that I can’t reach today and for years to come. They are running Windows. &lt;/p&gt;  &lt;p&gt;For sure the application will take 2 to 3 times as long to build in HTML/JS. I don’t have – nor can I find - the developers with the skills and experience for building an app like mine. The tools and frameworks they need don’t quite exist yet; the current prototypes are re-released with breaking changes every couple of months. My developers will be following half-baked implementation regimes, borrowed from other platforms (… oh, like .NET), that are as yet unproven for JavaScript business apps.&lt;/p&gt;  &lt;p&gt;Yes … I could trust my critical business application development to HTML+JavaScript … if I’m a nutter.&lt;/p&gt;  &lt;h2&gt;Summary&lt;/h2&gt;  &lt;p&gt;Let me net it out for you:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;A tiny % of today's developers are capable of writing an HTML/JS business application.      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;There are almost no examples of such apps today and almost no place to go to learn how to make them.      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;For most business apps there is only one OS that matter: Windows      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;The economics of developing a business app that runs on Windows are vastly superior to the economics of developing a business app in HTML/JS. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;All that can change. All that &lt;strong&gt;&lt;em&gt;will&lt;/em&gt;&lt;/strong&gt; change. But not this year, not next year, and maybe not in 2013 either.&lt;/p&gt;  &lt;p&gt;If you have the luxury of screwing around, have fun in HTML/JS. I know that I have that luxury and I am, indeed, having fun.&lt;/p&gt;  &lt;p&gt;If you must write a business app for delivery in the next 12 months, do it in a .NET client technology.&lt;/p&gt;  &lt;h2&gt;Update 11/12&lt;/h2&gt;  &lt;p&gt;A discussion of this post has emerged on &lt;a href="https://plus.google.com/u/0/118303283951449952966/posts/iQG1JWqENZX?hl=en#118303283951449952966/posts/iQG1JWqENZX"&gt;a G+ thread&lt;/a&gt; that you may find entertaining or even illuminating.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-7186754085925588445?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/7186754085925588445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=7186754085925588445' title='42 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7186754085925588445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7186754085925588445'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/11/build-business-apps-in-net-not-html-or.html' title='Build business apps in .NET - not HTML &amp;amp; JavaScript'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>42</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-7749192731098598560</id><published>2011-11-03T10:56:00.001-07:00</published><updated>2011-11-03T11:17:12.425-07:00</updated><title type='text'>DevForce Code First with AOP</title><content type='html'>We recently released &lt;a href="http://www.ideablade.com/"&gt;DevForce 6.1.3&lt;/a&gt; whose signature feature is Code First development of a distributed entity model, implemented with Aspect Oriented Programming (AOP). Let me unpack that for you.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Code First&lt;/strong&gt; – You write the entity classes and only the entity classes. You don’t use a visual designer. You let the Entity Framework map your classes by convention to database objects and clarify in code those mappings that can’t be inferred.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Distributed Entity Model&lt;/strong&gt; – “Distributed” is the key word: in a DevForce application, the client may have to rely on an intermediary server to reach the database. In DevForce, you program with a single set of entity classes, the classes you wrote, on both the server and client. DevForce handles the coordination and movement of data across tiers and over the network. The client could be Windows Forms, WPF, or Silverlight. The server could run as a Windows Service, in IIS, or in Azure. The network could be a LAN or the web.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aspect Oriented Programming&lt;/strong&gt; – Who needs change notification, property validation, change tracking, lazy loading, client-side caching? &lt;strong&gt;You do&lt;/strong&gt; … if you want to query, save, and bind a WinForms or XAML UI directly to your interrelated collections of entities. That takes infrastructure (&lt;em&gt;INotifyPropertyChanged&lt;/em&gt;, &lt;em&gt;INotifyDataErrorInfo&lt;/em&gt;, etc) that you should not write yourself. Where is that infrastructure hiding when your source code only says: &lt;span style="font-family: Consolas;"&gt;&lt;em&gt;public string Name {get; set;}&lt;/em&gt;&lt;/span&gt;?&amp;nbsp; It’s inside your entity model assembly, after we rewrote it with &lt;a href="http://www.sharpcrafters.com/"&gt;PostSharp&lt;/a&gt;. The infrastructure you need is ready at runtime.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/code-first"&gt;read all about DevForce Code First here&lt;/a&gt;. There’s a six part &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/code-sample-code-first-walk"&gt;walkthrough of a WPF sample here&lt;/a&gt;. Right now, I want to talk about why I am personally jazzed about the DevForce Code First approach.&lt;br /&gt;&lt;h2&gt;Why Code First?&lt;/h2&gt;&lt;br /&gt;DevForce has long been friendly to Entity Framework. Heretofore, we integrated closely with the Entity Data Model Designer in Visual Studio and relied upon the resultant EDMX file as the basis for generating entity classes with our own T4 template (which you can customize). That approach is still enormously popular and we remain enthusiastic about it.&lt;br /&gt;&lt;br /&gt;But I am smitten by our new Code First option. I like Code First because I think it can &lt;strong&gt;reduce the friction&lt;/strong&gt; of developing and maintaining my entity model. Let me show you a &lt;strong&gt;&lt;em&gt;Product&lt;/em&gt;&lt;/strong&gt; class I wrote in Code First:&lt;br /&gt;&lt;pre class="csharpcode"&gt;[ProvideEntityAspect]&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Product&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; ProductId { get; set; }&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ProductName { get; set; }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; CategoryId { get; set; } &lt;span class="rem"&gt;// Foreign key for "Category"&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Category Category { get; set; }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Guid SupplierKey { get; set; } &lt;span class="rem"&gt;// Foreign key for "Supplier"&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; Supplier Supplier { get; set; }&lt;br /&gt;}&lt;/pre&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;&lt;em&gt;Product&lt;/em&gt; has six properties: the key (&lt;em&gt;ProductId&lt;/em&gt;), a name, two foreign keys (&lt;em&gt;CategoryId&lt;/em&gt;, &lt;em&gt;SupplierId&lt;/em&gt;) and two “navigation properties” that return related parent entities (&lt;em&gt;Category&lt;/em&gt;, &lt;em&gt;Supplier&lt;/em&gt;). There’s no base class … unless I want one. The only evidence of infrastructure is that peculiar &lt;em&gt;ProvideEntityAspect&lt;/em&gt; attribute … to which we will return.&lt;br /&gt;&lt;br /&gt;This code is obvious and easy to write. The class conforms to Entity Framework &lt;a href="http://msdn.microsoft.com/en-us/library/hh161541%28v=VS.103%29.aspx"&gt;naming conventions&lt;/a&gt; so there is no need for explicit mapping with &lt;a href="http://msdn.microsoft.com/en-us/library/gg197525%28v=VS.103%29.aspx"&gt;attributes&lt;/a&gt; or the &lt;a href="http://msdn.microsoft.com/en-us/library/hh295844(v=VS.103).aspx"&gt;fluent API&lt;/a&gt; at this point. You’re welcome to add explicit mapping as you choose or need to do so. I didn’t need to … and I prefer to stick with the conventions.&lt;br /&gt;&lt;br /&gt;I hammered out this class as it occurred to me. I didn’t fire up the EDM Designer in Visual Studio. I don’t have an EDMX file to manage. No partial classes separate the generated code from my custom entity business logic (of which there is none at the moment but it’s coming). There are no companion metadata classes for manipulating attributes of generated properties. There is no code generation for Silverlight clients as there is in RIA Services. The entity source code you see is the same source code living in all .NET server and client environments.&lt;br /&gt;&lt;br /&gt;I can evolve this class as I go … with or without a pre-existing database. I can add validation attributes when and where I want them. Or I can add &lt;em&gt;Product&lt;/em&gt; &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/validate"&gt;validation rules&lt;/a&gt; separately if I don’t want them buried in the entity. I can write DevForce &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/property-interceptors"&gt;property interceptors&lt;/a&gt; to inject behavior when a Product consumer gets or set any of these properties. What begins as little more than a property bag can grow to have as much (or as little) business logic as I think the entity requires … without touching the properties; they remain exactly as you see them.&lt;br /&gt;&lt;br /&gt;I can write tests for my added business logic - including tests that exercise the navigations from &lt;em&gt;Product&lt;/em&gt; to &lt;em&gt;Category&lt;/em&gt; and &lt;em&gt;Supplier&lt;/em&gt; – without ever contacting a server or a database.&lt;br /&gt;&lt;br /&gt;I’m focused on the &lt;em&gt;Product&lt;/em&gt; class and just what it needs to function properly in my business domain. The infrastructure is invisible … although accessible when I want it.&lt;br /&gt;&lt;br /&gt;It’s not zero friction. But it’s as frictionless an approach to entity model development as I’ve seen. Which means I should be able to move my development forward faster, with higher quality, and a better chance of conveying my intentions clearly to the developer who picks up after I’ve left the project.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Beyond Entity Framework&lt;/h2&gt;&lt;br /&gt;At first blush, what I’ve described … the &lt;em&gt;Product&lt;/em&gt; class I’ve shown … could come straight out of an Entity Framework tutorial. If you add .NET validation attributes to the properties, Entity Framework will perform object validation for you and reject attempts to save invalid entities. These DevForce entities actually are ready-to-go as Entity Framework entities. What value is DevForce adding that’s not already in Entity Framework?&lt;br /&gt;&lt;br /&gt;DevForce brings two huge advantages:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;DevForce entities are queried and saved in n-tier deployments … such as Silverlight and cloud applications.&lt;br /&gt;&amp;nbsp; &lt;/li&gt;&lt;li&gt;DevForce entities are equipped to participate in Windows Forms, WPF, and Silverlight UIs.&lt;/li&gt;&lt;/ol&gt;&lt;strong&gt;Native Entity Framework is a strictly 2-tier technology&lt;/strong&gt;. The client must have line-of-sight to the database. You can’t serialize and de-serialize entity graphs across the web. You can’t compose LINQ queries on a remote client. You can’t query asynchronously and manage exceptions remotely. You can’t prepare change-sets remotely and save them remotely. Such capabilities become possible only if you write a ton of difficult infrastructure … or use DevForce.&lt;br /&gt;&lt;br /&gt;You are welcome to march into the wilderness on your own. Go write and maintain the myriad services that shuffle data into and out of DTOs (Data Transfer Objects). Try that on today’s line-of-business application with its hundreds of interrelated entities and see how much time you waste on those subterranean layers while the UI languishes and your customer taps his toes.&lt;br /&gt;&lt;br /&gt;If you stay 2-tier and you’re pushing entity data into an ASP Web Form, the native Entity Framework entity may be good enough. Your UI controls can translate the validation attributes to JavaScript. You have little use for property change notification. You’re web server has line-of-sight to the database and can run EF on its full .NET stack.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;That is&lt;/strong&gt; &lt;strong&gt;not good enough for Windows Forms, or WPF, or Silverlight&lt;/strong&gt; … the preferred client environments for line of business applications. These client technologies favor bi-directional data binding. Their controls listen for the &lt;em&gt;PropertyChanged&lt;/em&gt; event to fire when something sets the property of a bound entity object. Many grid controls respond to hints they discover in attributes decorating the entity properties. Many controls can cancel and roll back user changes automatically if the entity supports &lt;em&gt;IEditableObject&lt;/em&gt;. They can light up with validation error information when the entity supports &lt;em&gt;IDataErrorInfo&lt;/em&gt; or &lt;em&gt;INotifyDataErrorInfo&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://lh4.ggpht.com/-_tSdDN3Q5Ro/TrLVz8huaRI/AAAAAAAAAKk/bS4_L76RdDI/s1600-h/image%25255B13%25255D.png"&gt;&lt;img alt="Entity Validation in WPF" border="0" height="166" src="http://lh5.ggpht.com/-JNXbKp0R5dY/TrLV0T9tUWI/AAAAAAAAAKs/7i1IZ2jOIaw/image_thumb%25255B7%25255D.png?imgmax=800" style="background-image: none; border-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="Entity Validation in WPF" width="685" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;In this &lt;/em&gt;&lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/code-sample-code-first-walk"&gt;&lt;em&gt;WPF sample&lt;/em&gt;&lt;/a&gt;&lt;em&gt; screen shot, the “Supplier” text box is bound to the &lt;strong&gt;Product.Supplier.CompanyName&lt;/strong&gt; property. DevForce navigates from the &lt;strong&gt;Product&lt;/strong&gt; to the &lt;strong&gt;Supplier&lt;/strong&gt; instance in cache. The user entered a value in mixed case (“All Fine Foods has a name that is far too long”). A “get-interceptor” converts the value to uppercase before returning it to the text box. The property validation mechanism immediately applies the property length validation rule and records the rule violation. The binding, which detects that Product implements &lt;strong&gt;IDataErrorInfo&lt;/strong&gt;, displays the validation message.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Developers want their entities to provide this kind of support automatically. They don’t want to write it. They don’t want to see it. Developers are really tired of writing … or wading through … pages of property definitions such as&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ProductName&lt;br /&gt;{&lt;br /&gt;    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; _productName; } &lt;br /&gt;    set&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (_productName != &lt;span class="kwrd"&gt;value&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (Validate(&lt;span class="kwrd"&gt;value&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;                _productName = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br /&gt;                RaisePropertyChanged(&lt;span class="str"&gt;"ProductName"&lt;/span&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _productName;&lt;/pre&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;That’s all noise and no business value. It should be quieter and simpler:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ProductName { get; set; }&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;br /&gt;&lt;/style&gt;&lt;/pre&gt;&lt;br /&gt;Let’s push it a bit farther and think about what must be going on inside a property that returns a related entity. Here is how you write the &lt;em&gt;Product&lt;/em&gt;’s &lt;em&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/em&gt; property in DevForce Code First:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; Category Category { get; set; }&lt;/pre&gt;&lt;style type="text/css"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: consolas, "Courier New", courier, monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;br /&gt;It is as plain, expressive, and simple as &lt;em&gt;ProductName&lt;/em&gt;. We have the same need for validation and notification. We have two additional requirements, neither of them met by Entity Framework: (a) we must &lt;strong&gt;&lt;em&gt;have&lt;/em&gt;&lt;/strong&gt; the machinery for retrieving, caching and saving the related &lt;em&gt;Category&lt;/em&gt; entity on a remote client and (b) we must &lt;strong&gt;&lt;em&gt;plug&lt;/em&gt;&lt;/strong&gt; that machinery into the property’s get and set methods at runtime.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The apparent innocence of the &lt;em&gt;ProductName&lt;/em&gt; and &lt;em&gt;Category&lt;/em&gt; properties is possible thanks to some nifty work behind the curtain.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Aspect Oriented Programming (AOP)&lt;/h2&gt;&lt;br /&gt;DevForce makes writing properties as simple as shown while endowing them with the capabilities necessary for participation in the .NET client UI technologies. Clearly the “&lt;em&gt;property as shown&lt;/em&gt;” cannot be the actual implementation at runtime. Somehow the infrastructure code has to insinuate itself into the property. &lt;br /&gt;&lt;br /&gt;DevForce uses &lt;a href="http://www.sharpcrafters.com/"&gt;PostSharp&lt;/a&gt; and Aspect Oriented Programming (AOP) to inject the infrastructure into your classes. It re-writes the compiled model assembly at build time. That &lt;em&gt;ProvideEntityAspect&lt;/em&gt; attribute adorning the top of the &lt;em&gt;Product&lt;/em&gt; class tells DevForce that &lt;em&gt;Product&lt;/em&gt; is a kind of entity and should implement the behaviors that all entities exhibit. DevForce and PostSharp replace the &lt;em&gt;get&lt;/em&gt; and &lt;em&gt;set&lt;/em&gt; methods of entity properties with code that ties into DevForce infrastructure. The revised &lt;em&gt;Product&lt;/em&gt; class inherits from and implements the interfaces that light up the UI controls. It also acquires support for querying, caching, change-tracking, and saving product data. The &lt;em&gt;Product&lt;/em&gt; class, after re-write, is an enriched version of the original &lt;em&gt;Product&lt;/em&gt; class you wrote. The &lt;em&gt;Product&lt;/em&gt; objects that you “new” at runtime are instances of the enriched &lt;em&gt;Product&lt;/em&gt; class. When a binding reflects into an instance of &lt;em&gt;Product&lt;/em&gt;, it finds the interfaces it’s looking for.&lt;br /&gt;&lt;br /&gt;Many frameworks, including Entity Framework and NHibernate, use an alternative approach called “dynamic proxies.” They leave the original compiled classes alone. Instead, they rely on an external component (e.g., a “Context” or “Session”) to encase new and queried entities in a wrapper class that derives from your entity class. This wrapper overrides your entity’s properties with implementations that delegate (“proxy”) to the framework’s infrastructure.&lt;br /&gt;&lt;br /&gt;That infrastructure, if expanded appropriately, could do all of the interception, routing, and notification that DevForce does. You’d have to adapt your entity and workflow to play along. All of your entity properties would have to be virtual. You couldn’t construct them directly with “new”; in fact, you’d have to be careful always to reference the proxied object. You’d also have to get used to debugging with strange wrapper types, sporting bizarre long names.&lt;br /&gt;&lt;br /&gt;We like the AOP approach better. We think most people will find it more natural to work with a class that is fully baked at build time rather than maneuver to consume proxies that are emitted dynamically at runtime.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Could this be magic?&lt;/h2&gt;&lt;br /&gt;“&lt;em&gt;I don’t trust all that magic!&lt;/em&gt;'” That’s a common early reaction to Code First, AOP (and dynamic proxies). When I rely on Entity Framework naming conventions to map class and property names to tables and columns, how do I know what it did or did not map? When AOP is injecting logic into my classes that I can’t see, how do I know what it is doing?&lt;br /&gt;&lt;br /&gt;I push the button on my coffee maker and good, hot brown stuff pours into my cup. That’s magic to me. The compiler turns my auto-property into two &lt;em&gt;get&lt;/em&gt; and &lt;em&gt;set&lt;/em&gt; methods with a backing field. That’s magic. Then it becomes IL code which becomes machine code which makes the hardware jump. That’s magic.&lt;br /&gt;&lt;br /&gt;The difference is that coding by convention and AOP are &lt;em&gt;new&lt;/em&gt; magic for most of us. We’re used to the &lt;em&gt;old&lt;/em&gt; magic. We probably never truly understood it; we just stopped worrying about it. Before, when the property code was visible and the entity-data map was in an EDMX file, we felt the visceral comfort of touching the code and displaying the XML if we wanted to. But we rarely wanted to. When we did look, we were as often confused by what we saw as not.&lt;br /&gt;&lt;br /&gt;What matters most is good diagnostics and easy debugging. I need a clear explanation when things go wrong and I need to know what to do about it. Fortunately, the Entity Framework mapping error messages are pretty good. I think the AOP debugging experience will feel familiar to you. You breakpoint your custom code exactly as you did before. You step through your code as you did before. You test your code as you did before.&lt;br /&gt;&lt;br /&gt;I am keen to know what you think after you’ve tried it. We’re eager to hear your suggestions. IdeaBlade issues DevForce updates every six-to-eight weeks so we can respond quickly.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What about existing databases?&lt;/h2&gt;&lt;br /&gt;I often hear that Code First is only for “&lt;strong&gt;greenfield&lt;/strong&gt;” development and small database schemas. Perhaps half of our customers (re)build existing applications for existing databases with hundreds of tables some of which have hundreds of columns. Heaven help them.&lt;br /&gt;&lt;br /&gt;Such “&lt;strong&gt;brownfield&lt;/strong&gt;” development presents at least three challenges:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Getting started … because no one wants to write all those entities by hand. &lt;/li&gt;&amp;nbsp;&lt;li&gt;Evolving the entity model and a production database as requirements change. &lt;/li&gt;&amp;nbsp;&lt;li&gt;Keeping the model and the database in sync without the assistance of the EDM Designer.&lt;/li&gt;&lt;/ol&gt;We meet the first challenge with an approach we call “&lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/code-second"&gt;Code Second&lt;/a&gt;”. Speaking schematically, you aim the EDM Designer at the database and generate DevForce “Code First” classes. Then you throw away the EDMX file and proceed in Code First style.&lt;br /&gt;&lt;br /&gt;I’m optimistic but less confident in my response to the second and third challenges. I know developers in other communities (NHibernate in particular) have confronted these demons and wrestled them to the ground. They’ve survived without Database First tooling as far as I can tell. I’m betting they’ve discovered successful practices we can learn from and adapt.&lt;br /&gt;&lt;br /&gt;Code First style entails evolving the model and existing database in small doses, supported by tests. Runtime mapping exceptions are sufficiently informative in the context of small changes; repairing small breaks should be easy. You shouldn’t wake up in shocked surprise one morning to find that the model or the database have been massively transformed. That’s a disaster for Database First as much as Code First; it indicates far more fundamental flaws in your development process.&lt;br /&gt;&lt;br /&gt;A new module may require many new entity types to support its scenarios. The new entity types can be related to other types, new and existing. The new model ultimately translates to new tables and foreign key relationships to new and existing tables. I think I would develop a new module as I would a “greenfield” project with stubbed stand-ins for the existing entities and tables.&lt;br /&gt;&lt;br /&gt;It may be wise to preserve this separate model and separate database … forever. But if that’s not in the cards, when the new project matures, I’d fold my Code First model into the existing model. I’d script database changes from the generated Code First design database and apply them to the existing database.&lt;br /&gt;&lt;br /&gt;I readily admit that I do not have the concrete experience to back up these suggestions. I expect to have more to say on this subject in future posts. One of our customers hired us to help them rebuild their 500 table application in DevForce Code First. I promise to report back on do’s and don’ts.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What next?&lt;/h2&gt;&lt;br /&gt;I’d love to know what you think. Is Code First attractive to you? Do you have pros and cons to share? Would you &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/code-sample-code-first-walk"&gt;explore our walkthrough&lt;/a&gt; and give me your feedback? Is there something that bothers you about what I’ve said? Anything you want me to expand upon?&lt;br /&gt;&lt;br /&gt;I’m here for you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-7749192731098598560?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/7749192731098598560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=7749192731098598560' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7749192731098598560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7749192731098598560'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/11/devforce-code-first-with-aop.html' title='DevForce Code First with AOP'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-JNXbKp0R5dY/TrLV0T9tUWI/AAAAAAAAAKs/7i1IZ2jOIaw/s72-c/image_thumb%25255B7%25255D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-3525094672635883265</id><published>2011-10-10T14:35:00.001-07:00</published><updated>2011-10-10T19:06:06.363-07:00</updated><title type='text'>Windows 8 Metro apps in JavaScript</title><content type='html'>&lt;p&gt;I’m having a blast exploring Windows 8 Metro app development and poking around in the preview bits shipped at the &lt;strong&gt;&lt;a href="http://www.buildwindows.com/"&gt;2011 BUILD conference&lt;/a&gt;&lt;/strong&gt;.&amp;#160; Last weekend, I presented on Metro app development using &lt;strong&gt;JavaScript&lt;/strong&gt; at the &lt;a href="http://www.siliconvalley-codecamp.com/"&gt;Silicon Valley Code Camp&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I’ve &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/windows-8-metro-javascript"&gt;posted the sample code, my presentation script, and my slide deck on the IdeaBlade wiki&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;I have not gone crazy and transferred my affections from .NET to JavaScript. I’m just curious about all the hub-bub. It’s also the only fair way to confront the assertions that JavaScript has grown up and that we’ll all soon be JavaScript programmers.&lt;/p&gt;  &lt;p&gt;What is all this noise about “programming in standards-based HTML5 and JavaScript” … which is technically possible in Windows 8 … although in practice you’ll be so imbricated in Windows that you might as well have written it in COM.&lt;/p&gt;  &lt;p&gt;I exaggerate … slightly. I’m not being critical though. You want to program for the iPad? You’ll use Objective C. For the Android? You’ll write in Java. At least for a Windows 8 device you can write your app in Javascript … or C++ … or C#/VB. The languages are (mostly) open; the application code is locked in.&lt;/p&gt;  &lt;p&gt;I had tons of fun following along with &lt;a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-501T"&gt;Chris Tavares and Chris Sells&lt;/a&gt; as they built a Metro RSS Reader in JavaScript. The resulting demo app looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh6.ggpht.com/-oOT_RZpZjmw/TpNlF6FDEUI/AAAAAAAAAKI/rVwS0cwUXhw/s1600-h/WinJsDemo-Part%2525205%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="WinJsDemo-Part 5" border="0" alt="WinJsDemo-Part 5" src="http://lh6.ggpht.com/-eOcXHVCaT-c/TpNlGYX1RWI/AAAAAAAAAKM/wyn6MMsC1Zo/WinJsDemo-Part%2525205_thumb%25255B2%25255D.png?imgmax=800" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I &lt;strike&gt;stole&lt;/strike&gt; borrowed almost everything I showed from &lt;a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-501T"&gt;Chris’ talk&lt;/a&gt; … unless I pinched it from &lt;a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-533T"&gt;Luke Hoban’s talk&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;It’s always a kick to take a new technology out for a spin. The Microsoft folks are doing wonders with JavaScript on Windows but it’s still a dog walking on hind legs and always will be. I get … and approve of … what they’re doing: embracing the fresh faces coming out of school who “know” (be very wary of that verb!) HTML and JavaScript … not C#. That’s smart business.&lt;/p&gt;  &lt;p&gt;I expect to keep playing with JavaScript and writing about my experiences. I’m sure that it’s the perfect tool for many jobs. HTML and JavaScript (of a more general variety) &lt;strong&gt;&lt;em&gt;may turn out to be&lt;/em&gt;&lt;/strong&gt; the universal solvent for cross-vendor mobility apps.&lt;/p&gt;  &lt;p&gt;But not now and not soon. When it’s time to get serious about writing business applications, I’m sticking with the XAML technologies, Silverlight especially. Far more productive, less painful, and less risky in the hands of muggles … which is to say, most of us.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-3525094672635883265?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/3525094672635883265/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=3525094672635883265' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/3525094672635883265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/3525094672635883265'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/10/windows-8-metro-apps-in-javascript.html' title='Windows 8 Metro apps in JavaScript'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/-eOcXHVCaT-c/TpNlGYX1RWI/AAAAAAAAAKM/wyn6MMsC1Zo/s72-c/WinJsDemo-Part%2525205_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-771828324223904424</id><published>2011-09-22T22:24:00.001-07:00</published><updated>2011-09-23T08:26:24.332-07:00</updated><title type='text'>“Desktop” could be Win 8’s killer feature with consumers</title><content type='html'>&lt;p&gt;Crazy? Or just counter intuitive? Give me a moment to explain.&lt;/p&gt;  &lt;p&gt;The story everyone tells goes something like this: Microsoft is strongly entrenched on the PC and in the enterprise. But (XBox and Kinect aside) it’s lost touch with the consumer. &lt;strong&gt;Lose the consumer and you will lose the enterprise&lt;/strong&gt;. It’s only a matter of time before iPads displace PCs just as PCs displaced IBM 3270 terminals. Microsoft must respond quickly with consumer-friendly mobile products.&lt;/p&gt;  &lt;p&gt;I agree for the most part. And I feel terrific about the Windows 8 preview and tablet that Microsoft unveiled at &lt;strong&gt;&lt;a href="http://channel9.msdn.com/Events/BUILD/"&gt;//build/&lt;/a&gt;&lt;/strong&gt;. Microsoft definitely got some of its mojo back. I’m not just on a “sugar high” as some would have it. Windows 8 is a giant step in the right direction. Regular folks really do like that Metro look. The “developers’ preview” is obviously not as polished as the iPad but there is time before release to perfect the fit and finish.&lt;/p&gt;  &lt;p&gt;Unfortunately, it won’t be released until December 2012 (give or take). Fifteen months! In a few weeks, after we’ve sobered up, that’s going to feel like forever. Sure, when the grand day finally arrives, we’ll be cheering for the underdog, the version 1.0 Win 8 newbie against the heavyweight 3.0 iPad market leader. &lt;/p&gt;  &lt;p&gt;Hmmm. Should we be worried about a replay of the Windows Phone adoption debacle?&lt;/p&gt;  &lt;h3&gt;Lessons from Windows Phone 7&lt;/h3&gt;  &lt;p&gt;There is nothing seriously wrong with the Windows Phone itself. It’s a joy to use, in some respects superior to the iPhone and in no material respects is it worse. It’s where Metro was born … the same Metro that’s going to wow the tablet market in 2012. Critics loved it … as they love the Windows 8 preview.&lt;/p&gt;  &lt;p&gt;We can’t fault Microsoft for losing sight of the consumer. The Windows Phone is totally consumer-focused; two years in and we still lack an enterprise story. To make sure we get the point and avoid all possible confusion, Microsoft killed off WP7’s enterprisey predecessor. &lt;/p&gt;  &lt;p&gt;How is that working out? Microsoft’s share of the phone market has declined steadily and is headed for 1%. Great phone, unwavering consumer focus, pitiful results.&lt;/p&gt;  &lt;p&gt;“&lt;em&gt;But wait,&lt;/em&gt;” they say, “&lt;em&gt;it will all get better with Mango!&lt;/em&gt;” Really? Mango is indeed a huge technical improvement. But I don’t understand why that will make a difference in the marketplace. It is not sufficiently different from the iPhone. Seriously, what will I be able to do with a Mango phone that I can’t do with the iPhone? I’m sure you have a list; will anything on that list be enough to change consumer behavior? Will any of it change the foot-dragging behavior of the sales channel? I don’t get it.&lt;/p&gt;  &lt;p&gt;Look, I completely buy the consumer friendliness bit. The traditional desktop experience doesn’t fly on the phone and it won’t fly on the tablet. The way we write business apps today is totally alienating. So I’m down with the design vision: “Metro good, touch good, square windows bad, icon overload bad, mouse-and-keyboard bad.” &lt;/p&gt;  &lt;p&gt;The Metro-ish design changes are absolutely necessary … but they aren’t sufficient … because the iPad (like the iPhone) has a commanding lead in these respects. &lt;/p&gt;  &lt;p&gt;Windows 8 can be super great … and still bomb at the box office. “Great” isn’t good enough. If it were, Apple might have displaced Microsoft on the desktop long ago. The Mac was always prettier and easier to use. Didn’t matter; share never broke 10%. Twenty years and the Mac couldn’t knock Microsoft out of the ring. It was Microsoft’s ring.&lt;/p&gt;  &lt;p&gt;If “great design” isn’t good enough, what is good enough? What does Microsoft have that Apple lacks? What would make someone choose a Microsoft tablet over an iPad tablet … maybe even put down the iPad and take up a Win 8 device.&lt;/p&gt;  &lt;h3&gt;Enterprise software&lt;/h3&gt;  &lt;p&gt;I argue that consumers – not all, but millions of them – would put down their iPads and buy Windows 8 tablets if they had the ability … nay, the ease … of running their existing enterprise applications on that same fun tablet.&lt;/p&gt;  &lt;p&gt;We consumers aren’t just sitting around watching the Price is Right while stuffing Twinkies into our mouths. Most of us have jobs. Many of us use computers on the job. And while we may season our days with guilty pleasures (“hello, Twitter”), we occasionally get work done.&lt;/p&gt;  &lt;p&gt;News flash: &lt;strong&gt;people&lt;/strong&gt; &lt;strong&gt;take their work home!&lt;/strong&gt; Americans especially. &lt;strong&gt;The work we take home is often written for and running on a Microsoft Windows machine&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Why does Microsoft appear to be running away from this obvious fact? Microsoft could … and should make work life – the life bound up in Microsoft-based business applications – a high-profile component of the Win 8 marketing plan. &lt;/p&gt;  &lt;p&gt;Unfortunately, conventional wisdom says they shouldn’t do that. Conventional wisdom says that mobile devices must cater exclusively to an infantilized consumer.&amp;#160; Little baby consumer want pretty applications that are fast and fluid. Little baby consumer want an RSS reader with big pictures … like this one straight from the Jensen Harris Metro-style keynote:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-RPJdlbWdgqw/TnwYDR1BkQI/AAAAAAAAAKA/1kX3JSFSrRE/s1600-h/image%25255B4%25255D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/-z6DF1YFzyQo/TnwYDgmPZPI/AAAAAAAAAKE/l1KM8JNbjMA/image_thumb%25255B2%25255D.png?imgmax=800" width="404" height="252" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Say what? Geez, who doesn’t need a little pizzaz in his life but call me different: my RSS reader is for &lt;strong&gt;&lt;em&gt;reading&lt;/em&gt;&lt;/strong&gt;. Jensen, dude, you’re showing me eight pointless photographs when I want a list of twenty titles and abstracts … you know, something I can use.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;But I digress … &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Where did we get this limiting caricature of the consumer? &lt;strong&gt;I think we bought it from Apple&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Where did Apple get it? Market research? I don’t believe it. I believe Apple made it up. It’s too convenient.&lt;/p&gt;  &lt;p&gt;Apple has no enterprise play. They couldn’t promote enterprise applications on the iPad because they have no enterprise applications to promote. So they follow the Apple playbook: &lt;em&gt;&lt;strong&gt;if we can’t do it, you shouldn’t want to do it&lt;/strong&gt;&lt;/em&gt;. They pretend that mobile is some kind of other worldly, purely personal experience where work does not belong. &lt;/p&gt;  &lt;p&gt;The sad thing is that Microsoft is falling for it. They fell for it with the phone. They’re poised to fall for it again on the tablet. By slavishly chanting Apple’s mantra, Microsoft effectively disarms itself.&lt;/p&gt;  &lt;p&gt;Let me be crystal clear.&amp;#160; The tablet is not a PC. Mobile is not the office. Traditional business application UX is tired, clumsy, and unfriendly; todays business apps are as ill-suited for work as they are for play. WIndows 8 Metro is cool beans and a necessary way forward.&lt;/p&gt;  &lt;p&gt;But its not all about fun and games. &lt;em&gt;Apple owns that market anyway&lt;/em&gt;. Microsoft must wrest it away from them. Microsoft can’t win with great design. It can’t win share with advertising. &lt;/p&gt;  &lt;p&gt;Let me channel today’s consumer for you. I …. don’t … care! Microsoft, I think you’re irrelevant. You’re going to have to rip that iPad out of my hands and compel me to use Windows 8. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Convince&lt;/strong&gt; &lt;strong&gt;me&lt;/strong&gt;, Microsoft, that I can play while I work on that one hot device that covers &lt;strong&gt;&lt;em&gt;both&lt;/em&gt;&lt;/strong&gt; my personal life &lt;strong&gt;&lt;em&gt;and&lt;/em&gt;&lt;/strong&gt; my job life. &lt;strong&gt;Convince my boss &lt;/strong&gt;that the Windows 8 tablet is &lt;strong&gt;&lt;em&gt;both&lt;/em&gt;&lt;/strong&gt; a match for the iPad &lt;strong&gt;&lt;em&gt;and&lt;/em&gt; &lt;/strong&gt;a productivity platform for enterprise applications … at no additional cost.&lt;/p&gt;  &lt;p&gt;Perfect execution of the perfect Windows 8 design won’t move the needle in 2013. By then it will be “&lt;em&gt;me too, too late&lt;/em&gt;”.&amp;#160; &lt;/p&gt;  &lt;p&gt;But enterprise software is the differentiator that Apple can’t match. Exploit that. Don’t let Apple fake you out. Leverage your strength. The enterprise angle must be a strategic element of your consumer play.&lt;/p&gt;  &lt;p&gt;That’s why I think the Windows 8 “Desktop” stack is the killer feature in Windows 8. Ignore the voices that tell you otherwise. Is “Desktop” too confusing to some consumers? Work on making it less confusing. Don’t kill it; invigorate it. &lt;/p&gt;  &lt;p&gt;Energize your enterprise developers – hundreds of thousands strong – who want to Metro-ize their business apps. Stop telling them what they can’t do in Metro. Inspire them to build great Metro business apps. Get moving on the roadmap for the &lt;strong&gt;&lt;em&gt;enterprise&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;store&lt;/em&gt;&lt;/strong&gt;; get a proto-type out there. Reassure your corporate customers and developers that you mean business by investing meaningfully in the evolution and marketing of the mature technologies they use today. Praise Silverlight 5 and get hopping on Silverlight 6. We aren’t writing business applications in HTML and JavaScript today. We’re not going to have production ready HTML/JS apps in 2012. That’s just jerking us around. If you really don’t think Metro is the answer for all desktop application needs, then paint us a Windows future that is an answer and build us a bridge from here to there.&lt;/p&gt;  &lt;p&gt;I realize I’m proposing an “&lt;em&gt;and&lt;/em&gt;” strategy – consumer apps and business apps - not an “&lt;em&gt;or&lt;/em&gt;” strategy. “&lt;em&gt;And&lt;/em&gt;” strategies are dangerous because they tend to defocus. You have limited resources to be sure. But you can’t just go to market with a carbon copy of Apple’s strategy. They’ll kill you like they’re killing you on the phone. How many billions will you spend for a few points of share? Redirect a fraction of those billions to &lt;strong&gt;make enterprise software a first class, integrated pillar of your tablet … on day one&lt;/strong&gt;. That’s a damn cheap hedge against a repeat of the Windows Phone launch if you ask me.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-771828324223904424?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/771828324223904424/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=771828324223904424' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/771828324223904424'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/771828324223904424'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/09/desktop-could-be-win-8s-killer-feature.html' title='“Desktop” could be Win 8’s killer feature with consumers'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/-z6DF1YFzyQo/TnwYDgmPZPI/AAAAAAAAAKE/l1KM8JNbjMA/s72-c/image_thumb%25255B2%25255D.png?imgmax=800' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-721582770580333186</id><published>2011-09-20T09:09:00.001-07:00</published><updated>2011-09-21T11:12:19.422-07:00</updated><title type='text'>Metro Business Apps</title><content type='html'>&lt;p&gt;At //build/ we learned that Metro is for content-centric “immersive” apps and Desktop is for data-centric “enterprise” apps. Jensen Harris said it in his &lt;a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/BPS-1004"&gt;8 traits of great Metro style apps&lt;/a&gt;. Joe Stegman repeated it in his talk, &lt;a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/APP-737T"&gt;Metro style apps using XAML: what you need to know&lt;/a&gt;. That’s the Microsoft party line and outsiders have been repeating it.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Don’t believe it&lt;/strong&gt;. The real world doesn’t honor marketing boundaries. Expect to see data-centric applications appear on Win 8 almost from the moment of release.&lt;/p&gt;  &lt;p&gt;Why am I so sure? Because the same divide has been crossed elsewhere. You’ll find business applications on the iPad today. Is the iPad any friendlier to enterprise apps than Metro? Tell me how … because I don’t see it. I don’t see any way to keep business applications out of Metro.&lt;/p&gt;  &lt;p&gt;They tell us “Metro is optimized for immersive content-centric apps”. Well Viagra was optimized to treat hypertension. What’s your point? What is more “immersive” than a business application that fills the users screen for hours at a time?&lt;/p&gt;  &lt;p&gt;I had lunch today with one of our long-time customers. They showed me their iPad port of their &lt;a href="http://www.ideablade.com"&gt;DevForce-based&lt;/a&gt; Windows Forms desktop application. It’s almost a complete port and they don’t foresee any barrier to finishing the job. &lt;/p&gt;  &lt;p&gt;It looks remarkably like a typical Windows Forms app: the same gray background, same simple icons, same grids and forms over data, same tabbed interface. They made adjustments of course to accommodate touch and asynchronous server communications. There was no attempt to fancy it up; it doesn’t pretend to be a typical consumer facing iPad app.&lt;/p&gt;  &lt;p&gt;Customer acceptance has been fantastic … because it does the job in a familiar way. We could talk about UX design all day and it wouldn’t change a thing. The UX app is exactly what users expect. And not just existing customers; the iPad version appears to be driving new sales.&lt;/p&gt;  &lt;p&gt;What could keep them – or anyone – from porting to Metro WinRT? Three obstacles come to mind.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Must deploy with the Windows Store &lt;/li&gt;    &lt;li&gt;Metro app certification &lt;/li&gt;    &lt;li&gt;Paucity of data-centric features &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Our customer could leap these hurdles effortlessly.&lt;/p&gt;  &lt;h3&gt;Windows store deployment&lt;/h3&gt;  &lt;p&gt;I’m mildly concerned that there is no substantive enterprise deployment story. Ted Dworkin mentions it once in his talk, &lt;a href="http://channel9.msdn.com/Events/BUILD/BUILD2011/APP-121T"&gt;Introducing the Windows Store&lt;/a&gt;, before returning to the talk’s thesis:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;We have an enterprise story that supports their unique needs … but fundamentally the Windows store is the only place that Metro-style apps can be acquired. (11:20)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I can hardly wait for that “enterprise story”. Big companies simply will not deploy their apps through a Microsoft store. I hope that Microsoft talks sensibly about an acceptable alternative – probably in the form of an enterprise store – within the next six months. I’ll take up this subject in a later post.&lt;/p&gt;  &lt;p&gt;However, smaller companies may not be inhibited by the lack of private store. Our customer delivers its iPad client as a free app via the Apple store. Anyone could download it … but only their customers actually would. You can’t do anything with it unless you’ve first deployed the companion backend server; you acquire the server and pay for that server separately.&lt;/p&gt;  &lt;h3&gt;Metro app certification&lt;/h3&gt;  &lt;p&gt;Apple’s &lt;a href="http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/Introduction/Introduction.html"&gt;iOS interface guidelines&lt;/a&gt; run over 100 pages. Yet our customer passed Apple’s certification with a Windows Forms UI. Would it pass Win 8 Metro App certification?&lt;/p&gt;  &lt;p&gt;It wouldn’t pass the Windows Phone certification which dictates fine points of UI style such as application navigation. We don’t have a software certification guide for Metro apps. But we have some clues sprinkled among the //build/ talks and we have the example of applications shipped in the preview.&lt;/p&gt;  &lt;p&gt;My reading is that the Metro specs would not adversely constrain a business application experience – even if the application looked like a Windows Forms MDI application. I saw rules about screen and image resolutions requirements. I didn’t seen anything that dictated how I use the back button. I can’t have a child window; I can overlay the screen with some something that achieves a modal dialog effect. The keynote on Day 1 demonstrated conversion of Scott Guthrie’s Silverlight business app. I look at the Metro version of Internet Explorer and I know I can write a conforming business application. &lt;/p&gt;  &lt;h3&gt;Missing data-centric features&lt;/h3&gt;  &lt;p&gt;The Metro preview and sample applications emphasize content consumption. There are essential input controls such as textboxes, radio buttons, list boxes. But they appear to have forgotten about data grids. &lt;/p&gt;  &lt;p style="font-style: italic; margin-left: 20px"&gt;if you follow this space, you remember that I dislike data grids; I think they’re a design cop out. That’s my opinion, shared by a tiny minority; the rest of you want your data grid … and you should have.&lt;/p&gt;  &lt;p&gt;The Validation attributes in &lt;em&gt;System.ComponentModel.DataAnnotations&lt;/em&gt; are missing as are related interfaces such as &lt;em&gt;IDataErrorInfo&lt;/em&gt; and &lt;em&gt;INotifyDataErrorInfo&lt;/em&gt;. Apparently, in it’s wisdom, Microsoft thinks that client-side validation of input is unnecessary even for consumer apps. I hope they reconsider before release but we’ve survived without them before and can do so again.&lt;/p&gt;  &lt;h3&gt;Why would you want to build a Metro Business App?&lt;/h3&gt;  &lt;p&gt;Metro apps will only run on Windows 8 (and later … if you’re the optimistic sort). I’m guessing Windows 8 won’t release until this summer of 2012. Most companies have not yet or have only recently adopted Windows 7; optimistically, a significant number get to Windows 8 late 2013. Most of us don’t write software today for first deployment in 2013.&lt;/p&gt;  &lt;p&gt;The Windows 8 tablet is the wild card. If it has the hoped for reception in 2012 it could be a factor in driving Win 8 into the corporation … not as a replacement for existing desktops but as the viral alternative to the Apple iPad. We can dream, right?&lt;/p&gt;  &lt;p&gt;If the Win 8 tablet is a hit, you’ll want to be on it … and not just in the blue “Desktop” stack. Some reasons:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;ARM tablets, with their better battery life, could dominate. Metro apps will run on ARM. Desktop? They will probably only run on power hungry Intel tablets.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;High performance Metro XAML in native code with GPU acceleration; Desktop XAML is managed code with more limited GPU support.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Ready-to-wear Metro Visual Studio templates.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Superior touch support and easier access to tablet hardware.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Win 8 “contracts” for integration with other Metro apps and cloud services      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Better cloud integration facilitating “continuous applications” that move application state across devices as the user switches from phone to tablet to desktop.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Ride the software platform that Microsoft is promoting and evolving.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;The “Hotness” factor … don’t discount it! &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Those are big draws. Why should I toe the “Desktop for LOB” Microsoft line when I can sneak into Metro and party with the cool kids?&lt;/p&gt;  &lt;h3&gt;Get ready for Metro&lt;/h3&gt;  &lt;p&gt;Whoa, cowboy. This is the time to pay attention to Metro … and little more. Right now I wouldn’t take my business application beyond exploratory stage in Metro or WinRT. &lt;/p&gt;  &lt;p&gt;How would I build production applications? I’d write them in &lt;strong&gt;Silverlight&lt;/strong&gt; until the fog clears. I’d write with a &lt;strong&gt;Metro mindset&lt;/strong&gt;. I’d isolate anything in Silverlight that isn’t in Metro – hide it behind a service interface - so I’d be prepared to swap out the implementation later.&lt;/p&gt;  &lt;p style="font-style: italic; margin-left: 20px"&gt;See Brian Noyes high-level discussion of what this entails in his post, “&lt;a href="http://www.softinsight.com/bnoyes/2011/09/15/SilverlightDevelopersHaveTheSmoothestRoadToMetro.aspx"&gt;Silverlight Developers have the smoothest road to metro.&lt;/a&gt;”&lt;/p&gt;  &lt;p&gt;If I could I’d design all new screens to follow the Metro style guidelines. The Windows Phone 7 Metro style was crossing over to Silverlight design before Build; Win 8 should accelerate that trend.&lt;/p&gt;  &lt;p&gt;If Metro is as successful in the consumer space as we hope, business applications will be written as Metro apps.&lt;/p&gt;  &lt;p&gt;Fortuitously, I noticed that &lt;strong&gt;Rocky Lhotka&lt;/strong&gt; agrees as he explains in &amp;quot;&lt;a href="http://www.lhotka.net/weblog/WinRTAndBusinessApps.aspx"&gt;WinRT and business apps&lt;/a&gt;”.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-721582770580333186?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/721582770580333186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=721582770580333186' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/721582770580333186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/721582770580333186'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/09/metro-business-apps.html' title='Metro Business Apps'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-4839580302452519148</id><published>2011-09-13T13:35:00.001-07:00</published><updated>2011-09-13T13:58:06.097-07:00</updated><title type='text'>The BUILD Report #1: Sinofsky keynote</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Here’s my &lt;strong&gt;unedited feed/stream-of-consciousness&lt;/strong&gt; from the cheap seats in the arena where Steven Sinofsky is giving his Win8 Keynote. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-__amAmsWgNU/Tm--mYWWEiI/AAAAAAAAAJY/ov_EPpikc5Y/s1600-h/Build%252520Keynote%252520from%252520cheap%252520seats%25255B4%25255D.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="Build Keynote from cheap seats" border="0" alt="Build Keynote from cheap seats" src="http://lh5.ggpht.com/-LeR0i0-Frvc/Tm--mqOjc0I/AAAAAAAAAJc/rB4IF5PBBhI/Build%252520Keynote%252520from%252520cheap%252520seats_thumb%25255B1%25255D.jpg?imgmax=800" width="362" height="272" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Sinovsky opens touting WIn 7 and IE 9 market success to date. &lt;/p&gt;  &lt;p&gt;Claims touch is so compelling that once you have it on your screen you’ll want on all screens; not my experience in the last year … and that’s not because it doesn’t work. Don’t like leaving the keyboard. As the demos proceed, I start to wonder if I’m going to have to use touch to use Win8. See below&lt;/p&gt;  &lt;p&gt;Emphasizes that no matter how new Win8 is, everything running on Win7 will run on it. Reiterated throughout the keynote. That’s important to business which must migrate more slowly and a strong contrast with Apple. Means you can be sure the .NET apps you write today will have a good run on the next h/w and OS.&lt;/p&gt;  &lt;p&gt;Win8 memory footprint and CPU efficiency improves on Win 7 … by a lot. That’s encouraging again for companies with tight capital budgeting.&lt;/p&gt;  &lt;p&gt;Julie Larson-Green demos. Nice “picture password” = gesture login. No password … just gestures. Sweet. Audience applauds. Twitterverse agrees. Business should like too.&lt;/p&gt;  &lt;p&gt;The demo is all touch. It’s a little balky but that’s not what concerns me. I’m not sure I want to interact this way. Great for casual user (consumer) but, when you live on a computer, do you want to touch? Maybe I’m freaking out prematurely. It’s not that much different from using a mouse. They recognize my anxiety and reassure us that keyboard and mouse are there for everything. Later, S “I’m a keyboard person” reiterates and demos later (although he does mouse in his demo).&lt;/p&gt;  &lt;p&gt;The “chrome-free” browser gag went over well. But it really IS nice that the IE browser has no chrome. Very metro … and the cleanliness works (despite the onstage demo struggles).&lt;/p&gt;  &lt;p&gt;The “fast and fluid” principle is more than fluff. It’s a design principle that makes a genuine difference in comfort. Shown effectively in Julie’s demo.&lt;/p&gt;  &lt;h2&gt;“How to build” &lt;/h2&gt;  &lt;p&gt;S: “You pick the language/platform you want to use”. Windows Runtime (WinRT) with client tech (HTML, C++, C#/VB) riding above without privileging any one of them. S. reiterates this point several times throughout, trying to drive that home.&lt;/p&gt;  &lt;p&gt;The first development demo starts with JavaScript templates in VS. That might make a XAML worrier nervous. But I’m convinced that S means it and that XAML is first class. The port of the Silverlight 2 demo was effective (note to self: what am I to make of a port of Silverlight TWO). This is a big deal to “my people” so I’ll be talking more about that for sure.&lt;/p&gt;  &lt;p&gt;Metro is the privileged design language … which is a good thing for business app devs as I’ve said elsewhere before.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;“Windows” javascript api grants access to the OS somehow, as in “Windows.Storage.Pickers.FileOpen …”&lt;/p&gt;  &lt;p&gt;Big cheers for Blend as an HTML/JS tool. Expected, sure, but it’s still important. The layout ease, the Metro-built-in is nice and productive. Some noise about how this isn’t new in the world. So what. The issues isn’t whether it breaks ground but whether it delivers on the productivity promise. Looks like it will.&lt;/p&gt;  &lt;p&gt;The write-build-show cycle is crisp.&lt;/p&gt;  &lt;p&gt;Windows App Store: Store menu in Visual Studio. Built-in licensing model includes trials (but can put your own in). That shows seriousness. They will have a certification process. What about bureaucracy (we know how ugly that is in WP7)? They hope they can allay with (a) a process queue and (b) automated compliance checking tools [big applause for that one]. Now making it easier to find s/w in categories (a problem in today’s WP7 marketplace).&lt;/p&gt;  &lt;p&gt;The Win App Store is written in HTML/JS. They ballyhooed as a vote-of-confidence in that app technology. Is there a reason it should be HTML/JS? It could only host apps for Windows platform so no x-plat justification. Could have been … should have been? … in Silverlight.&lt;/p&gt;  &lt;p&gt;So what about deployment of LOB apps in the metro/immersive app environment.&lt;/p&gt;  &lt;h3&gt;XAML segment&lt;/h3&gt;  &lt;p&gt;Sinofsky cheer leads. That’s important to dispelling the belief/suspicion that S hates .NET.&lt;/p&gt;  &lt;p&gt;Nice job of taking an old SL2 Gu app and migrating to Win8 w/o changing the app itself.&lt;/p&gt;  &lt;p&gt;Then metro-izes by swapping one XAML control for a new Win8 grid control + 2 lines of code-behind + manifest tweak to make it searchable in Win8 =&amp;gt; looks metro. Nice. Search and runnable from the dekstop. &lt;/p&gt;  &lt;p&gt;This deployment is to the NEW Win8 look. In the prior Win8 show, they created fear that would only run in the old Win7 shell. This time, not seeing an old shell. Only showing one shell. AND XAML apps run in it. I couldn’t see any distinction between HTML and XAML app in the shell.&lt;/p&gt;  &lt;p&gt;Another tweak and it runs in the phone. Very nice. Ok, demo alert, right? It won’t be that easy in reality. That doesn’t diminish the direction; they are putting their back into making XAML apps metro and their deployment easy with tooling.&lt;/p&gt;  &lt;p&gt;S emphasizes again that Win8 is supportive of your technology choice.&lt;/p&gt;  &lt;p&gt;The sensor fusion stuff could get you thinking about how tilting the tablet could be used in a bus app UX. It’s easy enough to justify exploring it and using it without fear that you’ve saddled the non-geek dev with incomprehensible, maintenance problem. NFC (near field communication) support makes it easier to write apps that interact with the physical world. POS and field inspection apps come to mind.&lt;/p&gt;  &lt;h2&gt;Renovated OS tools&lt;/h2&gt;  &lt;p&gt;Control Panel, Task Manager, PC Reset … just plain nice for developers. Hyper-V in the Windows client.ISO mounting built-in. &lt;/p&gt;  &lt;p&gt;“Ease of Access” support could matter to those of you who have regulatory requirements affecting your app’s UX.&lt;/p&gt;  &lt;p&gt;Ink / Touch disambiguation revives pen and the accuracy that comes with it. Take that, Steven Jobs.&lt;/p&gt;  &lt;p&gt;Windows Live is the backbone of the roaming features with which you propagate settings across devices.&lt;/p&gt;  &lt;h2&gt;Cloud Integration&lt;/h2&gt;  &lt;p&gt;Chris Jones talking about Cloud Services. The mail client is HTML/JS … as it should be as it must be x-plat. The app metro design is straight out of WP7 mail app. It certainly is responsive. But have to say that some of the views are clunky.&lt;/p&gt;  &lt;p&gt;The WP7 hub paradigm is now on Windows Live. People, Photos, Mail. The hub paradigm works; this is a great move.&lt;/p&gt;  &lt;p&gt;“Every Win8 user has a SkyDrive”. Of course that is great for consumers. But this could be a terrific guarantee for bus. app developers too … assuming that business allows that kind of personalization in the app. When you know that SkyDrive is there, the integration is there, and it’s easy to reach … you can consider making that integral to the app w/o worrying if the user is configured for it … because she always is.&lt;/p&gt;  &lt;p&gt;I don’t think it’s Drop Box (no auto synchronization), but its great ‘cause it’s in there. Now what about security? I haven’t been that careful with my Live password. Time to get serious. Would need to work on that if I was building Windows Live into my application assumptions.&lt;/p&gt;  &lt;p&gt;Not available today? The APIs are there today but we’ll have to wait a little for the releases in the cloud … and that’s ok.&lt;/p&gt;  &lt;h2&gt;The Big Giveaway&lt;/h2&gt;  &lt;p&gt;Hard to deny the enthusiasm for the Samsung tablet – an Opra moment.&lt;/p&gt;  &lt;h2&gt;The Mom Factor&lt;/h2&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/dwahlin/" target="_blank"&gt;Dan Wahlin&lt;/a&gt; told me (I paraphrase) “My mom would love Windows 8 – she would get it – and that’s important to the Microsoft business application developer. The Microsoft platform has to succeed broadly; if the consumer deserts Microsoft, so … ultimately … would business apps.”&lt;/p&gt;  &lt;p&gt;I agree strongly.&lt;/p&gt;  &lt;h2&gt;Release Schedule&lt;/h2&gt;  &lt;p&gt;The “Preview” looks impressive… for a preview. S says “No release date because driven by quality, not the date”. Sure … but I get the feeling it won’t be far off. They’re going wide tonight (8 pm PST) at &lt;a href="http://dev.windows.com" target="_blank"&gt;dev.windows.com&lt;/a&gt;. No activation. That’s a strong statement because you know how many people are going to write apps on that preview in volume.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-4839580302452519148?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/4839580302452519148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=4839580302452519148' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4839580302452519148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4839580302452519148'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/09/build-report-1-sinofsky-keynote.html' title='The BUILD Report #1: Sinofsky keynote'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-LeR0i0-Frvc/Tm--mqOjc0I/AAAAAAAAAJc/rB4IF5PBBhI/s72-c/Build%252520Keynote%252520from%252520cheap%252520seats_thumb%25255B1%25255D.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-9053885823656059872</id><published>2011-09-13T07:35:00.001-07:00</published><updated>2011-09-13T14:16:23.875-07:00</updated><title type='text'>The BUILD Report: get it while it’s hot</title><content type='html'>&lt;p&gt;The Microsoft BUILD conference starts tomorrow. My IdeaBlade buddies will be there. I will be there. In a flurry of small posts over the next four days I’ll be reporting on what’s being said officially and unofficially, on stage and in the hallways. I’ll give you immediate reactions and instant analysis from the perspective of the business application developer.&lt;/p&gt;  &lt;p&gt;I’ll be interviewing many fascinating folks and passing along their insights …I hope with attribution.&lt;/p&gt;  &lt;p&gt;Clearly I can’t cover everything. And “instant analysis” is … well it’s instant. Enough said?&lt;/p&gt;  &lt;p&gt;When I get back, catch my breath, and have time to reflect, I’ll try to make sense of it all.&lt;/p&gt;  &lt;p&gt;Meanwhile,&amp;#160; ride with me, send in your comments and questions, and enjoy.&lt;/p&gt;  &lt;h2&gt;&lt;/h2&gt;  &lt;h3&gt;Posts in this series:&lt;/h3&gt;  &lt;h5&gt;&lt;a href="http://neverindoubtnet.blogspot.com/2011/09/build-report-1-sinofsky-keynote.html"&gt;The BUILD Report #1: Sinofsky keynote&lt;/a&gt;&lt;/h5&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-9053885823656059872?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/9053885823656059872/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=9053885823656059872' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/9053885823656059872'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/9053885823656059872'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/09/build-report-get-it-while-its-hot.html' title='The BUILD Report: get it while it’s hot'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-7337110046528145252</id><published>2011-08-09T21:50:00.001-07:00</published><updated>2011-08-09T21:51:57.804-07:00</updated><title type='text'>And the (ORM) survey said …</title><content type='html'>&lt;p&gt;In mid-May 2011 I ran a short &lt;a href="https://www.surveymonkey.com/s/EFDevStyle"&gt;survey&lt;/a&gt; about ORM usage among .NET developers. I wrote a draft of this blog post back then … and forgot to publish it (doh!). I’m finally doing so now in August in hopes that it remains relevant. I don’t know if attitudes have changed (do you?) but what the heck … I might as well …&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="#Survey"&gt;Tell you what the survey asked.&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#Results"&gt;Give you the summary statistics for its two questions.&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Link you to a &lt;a href="http://www.ideablade.com/wardsblog/ORM_Survey_Results.zip" target="_blank"&gt;spreadsheet of individual responses&lt;/a&gt;, including comments. &lt;/li&gt;    &lt;li&gt;&lt;a href="#Goals"&gt;Describe the survey’s manifest goals.&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#Design"&gt;Discuss the survey design and comments on that design.&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="#Interpretations"&gt;Offer my interpretation of the results.&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;&lt;a name="Survey"&gt;The Survey&lt;/a&gt;&lt;/h2&gt;  &lt;p&gt;The survey was prepared on and hosted by &lt;a href="https://www.surveymonkey.com"&gt;SurveyMonkey&lt;/a&gt;, a free/low-cost survey site. It ran from Monday, 9 May, to Wednesday, 18 May, 2011. It consisted of two questions. Here’s question #1:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-o_FEMzvpb0A/TkIN70F3XBI/AAAAAAAAAI0/8KSvhMVucTI/s1600-h/ORM_Survey_q115.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ORM_Survey_q1" border="0" alt="ORM_Survey_q1" src="http://lh6.ggpht.com/-ShOOQg0NWl4/TkIN8Ez3pnI/AAAAAAAAAI4/NbzeZxdZV2o/ORM_Survey_q1_thumb9.png?imgmax=800" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If … and only if … you answered “Entity Framework” did you get to see question #2:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/-wWG_T8qSJEQ/TkIN8ce3_eI/AAAAAAAAAI8/1weevdMxa9M/s1600-h/ORM_Survey_q24.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ORM_Survey_q2" border="0" alt="ORM_Survey_q2" src="http://lh5.ggpht.com/-bCv8WQMB8xM/TkIN9D0WUeI/AAAAAAAAAJA/tiOBpPvYRPk/ORM_Survey_q2_thumb2.png?imgmax=800" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The survey permitted only one survey answer per person but you could come back later and revise your answer if you wished.&lt;/p&gt;  &lt;h2&gt;&lt;a name="Results"&gt;The Results&lt;/a&gt;&lt;/h2&gt;  &lt;p&gt;You can see the survey &lt;a href="https://www.surveymonkey.com/sr.aspx?sm=bgyJ4ipGXAiTAf2W09hoyLuice_2fMprLdjvnulk2Icyc_3d" target="_blank"&gt;results on the SurveyMonkey website&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I downloaded all 896 individual responses as of May 18 into &lt;a href="http://www.ideablade.com/wardsblog/ORM_Survey_Results.zip"&gt;an Excel spreadsheet&lt;/a&gt;.The spreadsheet is useful if you want to correlate comments with question answers. The comments can be entertaining.&lt;/p&gt;  &lt;p&gt;Here’s a picture of the statistics as displayed in the spreadsheet:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/-887mAmCsWpQ/TkIN9oyUyoI/AAAAAAAAAJE/IcPukebiZiE/s1600-h/ORM_Survey_stats4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="ORM_Survey_stats" border="0" alt="ORM_Survey_stats" src="http://lh4.ggpht.com/-Tp7BtAQAfPw/TkIN94JiTMI/AAAAAAAAAJI/-RUFf5uNRzM/ORM_Survey_stats_thumb2.png?imgmax=800" width="528" height="581" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h2&gt;&lt;a name="Goals"&gt;Survey Goals&lt;/a&gt;&lt;/h2&gt; The survey seeks insight into how developers of .NET data-driven applications prefer to manage their data. More specifically:   &lt;ol&gt;   &lt;li&gt;Would they use an &lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping" target="_blank"&gt;ORM&lt;/a&gt;&lt;/a&gt; … or not.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;If they would use an ORM, would they use Microsoft’s &lt;a href="http://en.wikipedia.org/wiki/ADO.NET_Entity_Framework" target="_blank"&gt;Entity Framework&lt;/a&gt;; the popular, open source &lt;a href="http://en.wikipedia.org/wiki/NHibernate" target="_blank"&gt;NHibernate&lt;/a&gt;; or some other ORM tool.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;If they would use Entity Framework (EF), which style would they use to develop their entity models. As of version 4.1, EF offers three styles called “Database First”, “Model First”, and “Code First”.      &lt;br /&gt;      &lt;br /&gt;For you readers who don’t know what those styles are, I recommend Julie Lerman’s &lt;a href="http://thedatafarm.com/blog/data-access/model-first-database-first-or-code-first-ndash-update-to-data-points-column/" target="_blank"&gt;summary of these styles&lt;/a&gt; (she calls them “workflows”) and her &lt;a href="http://msdn.microsoft.com/en-us/magazine/hh148150.aspx" target="_blank"&gt;May 2011 MSDN article&lt;/a&gt; on the subject. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;I wanted developers to respond as if they were: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;building an application with a medium to large model &lt;/li&gt;    &lt;li&gt;free to choose the data modeling/access technology &lt;/li&gt;    &lt;li&gt;required to work with an existing relational database of many tables, filled with irreplaceable production data. &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;&lt;a name="Design"&gt;Survey Design&lt;/a&gt;&lt;/h2&gt;  &lt;p&gt;In this section I talk about how the questions were formed, how I found the respondents, and survey bias.&lt;/p&gt;  &lt;h3&gt;The questions&lt;/h3&gt;  &lt;p&gt;The survey only had two questions – and you couldn’t reach the second question unless you answered “Entity Framework” to the first. I was adamant about keeping it short. I hate long surveys and assume others do too. &lt;/p&gt;  &lt;p&gt;I really wanted to ask demographic questions. I wanted to know about respondent backgrounds, what kinds of apps they built in which client technologies for what kinds of customers. Were they architects, trainers, or practitioners? Were they actually committed to building with the selected technologies or only hoping to do so or merely advising others to do so?&lt;/p&gt;  &lt;p&gt;I backed off mostly because it would have bulked up the survey but also because I had no hypotheses at that time that required demographic information. As a general rule flailing away with pointless questions invites spurious correlations. If the survey results suggest new hypotheses, someone can pursue them independently.&lt;/p&gt;  &lt;p&gt;Some folks were miffed that they couldn’t answer the EF development style question unless they intended to use EF. Sorry … sort of. Question #2 is about how&lt;strong&gt; &lt;em&gt;EF people&lt;/em&gt;&lt;/strong&gt; would use EF. How an NHibernate person would develop an NHibernate model is interesting but out-of-scope. Moreover, I didn’t want to muddy the interpretation with advice to EF developers from people who wouldn’t use EF. The second question is not a vote on best practices or preferred technologies; it’s trying to surface the practices that EF people intend to use.&lt;/p&gt;  &lt;p&gt;A number of respondents want to pick more than one answer. They wanted checkboxes instead of radio buttons. Sorry but you’ll have to come up with your own survey. I deliberately forced you to choose … as you would have to choose when faced with one application to build. You were not granted the consultant’s luxury of saying “it depends”. I left you room to vacillate in the comments.&lt;/p&gt;  &lt;p&gt;I have one regret about question #2. I failed to make clear that the “100+ table, RDB application” context that I described in question #1 &lt;em&gt;should apply to question #2 as well&lt;/em&gt;. That was my intention. I didn’t say so in the phrasing of the question; it is clear from some of the comments that many respondents weren’t sure about this. I’ll never know the degree to which that uncertainty skewed the results. &lt;/p&gt;  &lt;p&gt;I’m going to do the only responsible thing and blame my survey reviewers for failing to raise the alarm before I launched the survey; shame on you guys!&lt;/p&gt;  &lt;h3&gt;The Sample&lt;/h3&gt;  &lt;p&gt;The sample is far from “scientific”. I did not ask an independent, qualified research group to identify and survey an unbiased sample. I simply announced the survey on Twitter on May 9th. I asked everyone I could think of to re-tweet it; many of them did. I learned that IdeaBlade announced it on the DevForce forum but no one, to my knowledge, sent email to any of our lists. I figure if you answered the survey, you learned about it on Twitter. Which means you probably follow me or follow someone who follows me.&lt;/p&gt;  &lt;p&gt;It’s reasonable to suppose that we have interests, opinions, and experiences in common. We are in none of these respects the norm for the general .NET developer population. Accordingly, I’m reluctant to apply my interpretation to that broader population. Well … kind of reluctant.&lt;/p&gt;  &lt;p&gt;Frankly, I am too cheap to do it properly. While I think the survey questions are defensible, I’ll concede that the sampling technique is not … and introduces a significant bias of some sort. Of what sort? I take that up next.&lt;/p&gt;  &lt;h3&gt;Survey Bias&lt;/h3&gt;  &lt;p&gt;Many of you took me to task on my approach to sampling … and we’re free with your conclusions about how that would bias the results. My secret pleasure in this is that you had so many different and conflicting notions about what that bias would be. &lt;/p&gt;  &lt;p&gt;Some were sure that it biased the survey toward EF. Some said it biased the survey against CQRS and NoSQL. Some said it biased the survey against native ADO approaches. Some said it biased the survey in favor of egghead pontificators who have no practical experience.&lt;/p&gt;  &lt;p&gt;Some people see a bias in the survey’s &lt;strong&gt;&lt;em&gt;goals&lt;/em&gt;&lt;/strong&gt;. I suppose there is an existential “bias” in one’s research interests. I’m please to ponder the significance of wanting to know one thing versus another. Don’t stop there; ask me why I’m running a survey about ORMs instead of world peace.&lt;/p&gt;  &lt;p&gt;I’m more concerned about survey bias. What factors in the questions, the sampled population, the conduct of the survey, and the interpretation of results that undermines the survey’s avowed research goals?&amp;#160; I’m sure there are plenty of such factors. I’m not sure where they point.&lt;/p&gt;  &lt;p&gt;I was twice accused of &lt;a href="http://en.wikipedia.org/wiki/Confirmation_bias" target="_blank"&gt;confirmation bias&lt;/a&gt;, which in brief means “a tendency for people to favor information that confirms their preconceptions or hypotheses regardless of whether the information is true.”&amp;#160; I’d be more susceptible to this charge if I had preconceptions to confirm. Take question #2 for example. I don’t have a theory about which EF development style people will prefer. I guessed that “Code First” would win about 10% of the votes, not 42%. But I was no more invested in the outcome than I am when guessing the number of jelly beans in a jar.&lt;/p&gt;  &lt;p&gt;Question #1 is a more delicate matter. My company placed a bet several years ago that EF would eventually dominate the .NET ORM space. Around 66% of survey respondents favored EF; NHibernate was a distant second at 18%. This outcome is certainly consistent with my expectations. Is that evidence of “confirmation bias”? You can’t call a survey “biased” simply because the results seem to favor the author’s prediction. You have to explain how the question or the conduct of the survey favored EF. I don’t understand how that could be in this case. The question seems innocuous to me. And while my twitter-verse is indeed ORM friendly, it is not pre-disposed for or against EF; I’ve got a ton of EF-hating friends.&lt;/p&gt;  &lt;p&gt;So you still think my audience tilts towards EF? Maybe it does. But is it significant? The gap between the EF preference (62%) and the preference for all other ORMs (18%) is 44%. How do you explain that?&lt;/p&gt;  &lt;h3&gt;Bias toward ORM uses&lt;/h3&gt;  &lt;p&gt;As I see it, the gravest potential for misinterpretation would be the misguided assumption that most developers know about, care about, or use ORMs.&lt;/p&gt;  &lt;p&gt;People reading this blog as well as people who took the survey are acquainted with ORMs. We either use one or have used one. We like them or we hate them. Remember, only 7% of respondents said they wouldn’t use an ORM&lt;/p&gt;  &lt;p&gt;The sample must be severely skewed if only 7% say they won’t use an ORM. I know that &lt;strong&gt;the majority of developers in the general population don’t use an ORM&lt;/strong&gt;. How do I know ? OK … I don’t have hard facts. But I have strong anecdotal evidence. Most of our customers and prospects have never used an ORM before. I’ve been to a lot of user group meetings and, based on a show of hands … on several occasions …, a tiny few of the attendees know squat about ORM.&lt;/p&gt;  &lt;p&gt;We have to be careful in our interpretation of this survey. We can’t say much about developers in general. We might have gleaned something useful about developers who use ORMs.&lt;/p&gt;  &lt;h2&gt;&lt;a name="Interpretations"&gt;Interpreting the Results&lt;/a&gt;&lt;/h2&gt;  &lt;p&gt;I wasn’t surprised by EF’s dominance … as I noted above. It seems EF v.4 is finally over the bad press that greeted v.1 and is begrudgingly accepted as “viable” even by staunch NH supporters.&lt;/p&gt;  &lt;p&gt;I was surprised at the affection for Code First. Few could yet have tried it. Evidently it taps into some disaffection with the “database first” workflow and its visual designer. People I deeply respect have tried it a few times and they like it a lot. They haven’t built anything significant with it yet … but what they like about it resonates strongly with me. I’ll have more to say in a future post.&lt;/p&gt;  &lt;p&gt;On the other hand, “database first” has ardent fans (read the comments). It’s the majority choice and will remain so as long as most developers who conceive of their applications primarily in terms of the data they store. Database management tooling is capable and the practice of simultaneously evolving schema and code is entrenched.&lt;/p&gt;  &lt;p&gt;I’ve tried both “database first” and “code first” development. There isn’t an obvious productivity winner. One could pick a side on other grounds, but only a clear productivity edge will shift the balance among active developers.&lt;/p&gt;  &lt;p&gt;So it looks like “Code First” will have a strong following much sooner than I expected. But it won’t hurt “Database First” which will remain the popular choice.&lt;/p&gt;  &lt;h2&gt;&lt;a name="Intentions"&gt;My Commercial Agenda&lt;/a&gt;&lt;/h2&gt;  &lt;p&gt;I’m a curious guy … but I don’t run surveys for the fun of it. The survey was honest but it wasn’t innocent.&lt;/p&gt;  &lt;p&gt;Consider the survey’s framing context: an application built to accommodate a 100-table existing database. My company, &lt;a href="http://www.ideablade.com" target="_blank"&gt;IdeaBlade&lt;/a&gt;, makes and sells a product called &lt;strong&gt;DevForce&lt;/strong&gt;. DevForce helps you build data-driven, Rich Internet Applications. Our sweet spot is the customer who intends to migrate an existing Line-of-Business (LOB) application to Silverlight or WPF. The existing data store is almost always a relational database. &lt;/p&gt;  &lt;p&gt;This customer is torn about how to get there. He’s acknowledged that the application will have to be rewritten back-to-front … which opens the door to a new data access architecture. But he’s not completely free to start from scratch. He has an existing business to run with real customers and real data. He’ll have to maintain the existing application while building its eventual replacement. He is naturally reluctant to rip out the database or even restructure it. I wanted the survey to elicit responses from professional developers facing a comparable situation. &lt;/p&gt;  &lt;h3&gt;EF First&lt;/h3&gt;  &lt;p&gt;The attention to Entity Framework is no coincidence either. DevForce is not an ORM and can work with any source of data; our value really kicks in after you’ve defined your entities and figured out how you will persist them.&lt;/p&gt;  &lt;p&gt;But DevForce is cozy with the Entity Framework. Close alignment with EF was a &lt;strong&gt;&lt;em&gt;business decision&lt;/em&gt;&lt;/strong&gt;, not a technology judgment. It has worked out well for us and our customers. The survey results indicate that we made a sound choice … and shouldn’t bother integrating with NHibernate or another ORM; the commercial demand is simply not there.&lt;/p&gt;  &lt;p&gt;You may feel differently. You’re not selling an infrastructure product. You may have good technical reasons to prefer a different ORM. I suggest, however, that you factor industry trends into your decision.&lt;/p&gt;  &lt;h3&gt;Code First&lt;/h3&gt;  &lt;p&gt;We really wanted to assess the appetite for the new EF “Code First” style. DevForce currently favors the “Database First” and “Model First” styles. We extend the EDM with our own attributes, the EDM Designer with our own properties, and we can generate our own classes from the conceptual model’s XML. &lt;/p&gt;  &lt;p&gt;Should we stick with those workflows or add support for “Code First”? We suspected that “Code First” would attract an audience. We weren’t sure how big or when. &lt;/p&gt;  &lt;p&gt;The survey tells us it’s going to be big soon; nearly 42% of EF respondents chose “Code First” as their preferred style, just 5 points below “Database First”. So we’re hustling on our Code First support. We just released the first preview which gets us more than half way home. You can &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/code-first"&gt;read about it here&lt;/a&gt; and I'll have more to say in future blog posts.&lt;/p&gt;  &lt;p&gt;Got an opinion? I want to hear it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-7337110046528145252?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/7337110046528145252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=7337110046528145252' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7337110046528145252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7337110046528145252'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/08/and-orm-survey-said.html' title='And the (ORM) survey said …'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/-ShOOQg0NWl4/TkIN8Ez3pnI/AAAAAAAAAI4/NbzeZxdZV2o/s72-c/ORM_Survey_q1_thumb9.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-5661300560343275215</id><published>2011-07-01T16:21:00.001-07:00</published><updated>2011-07-08T18:20:59.183-07:00</updated><title type='text'>Read “Win 8-Longhorn Dream Reborn”</title><content type='html'>&lt;p&gt;Unless you’ve been taking a long and much needed vacation in the woods, you’ve heard something about Windows 8, Microsoft’s promotion of HTML5, and it’s coy silence about the future of .NET.&amp;#160; You are &lt;a href="http://arstechnica.com/microsoft/news/2011/06/html5-centric-windows-8-leaves-microsoft-developers-horrified.ars" target="_blank"&gt;probably a little spooked&lt;/a&gt; if you’ve committed some part of yourself, your product, or your company to WPF or Silverlight. Does anyone know what is &lt;em&gt;really&lt;/em&gt; going on?&lt;/p&gt;  &lt;p&gt;I have no revelations for you. I wouldn’t be allowed to blog about revelations if I had them. I don’t have anything fresh to say either. I do have opinions ... details of which must await a future post.&lt;p&gt;In summary until then ... I’m not worried. While we at IdeaBlade are exploring what it means to have a DevForce JavaScript client, no one should mistake that interest for wavering in our commitment to .NET. We are confident that XAML clients will thrive for a long time to come.&lt;/p&gt;  &lt;p&gt;Of course that’s what &lt;strong&gt;&lt;em&gt;we&lt;/em&gt;&lt;/strong&gt; think. Microsoft has done a fabulous job of creating uncertainty about the future of Silverlight and .NET. I’ve had plenty of conversations with colleagues and customers who are paralyzed by doubt. Frankly, that’s not good for our business. I don’t think its good for &lt;strong&gt;&lt;em&gt;your&lt;/em&gt;&lt;/strong&gt; business either. Perhaps you can afford to wait … and wait … for some magic moment of clarity. Will we know more in three months at the &lt;a href="http://www.buildwindows.com/" target="_blank"&gt;BUILD conference&lt;/a&gt;? Sure … although if I’m certain of anything it is that Microsoft will keep the mixed messages coming. &lt;/p&gt;  &lt;p&gt;You have to make a decision at some point based on the best information available. To that end, I direct your attention to a highly-regarded, week-old article in &lt;em&gt;&lt;strong&gt;ars technica&lt;/strong&gt;&lt;/em&gt; by Peter Bright: “&lt;a href="http://arstechnica.com/microsoft/news/2011/06/windows-8-for-software-developers-the-longhorn-dream-reborn.ars" target="_blank"&gt;&lt;font size="3"&gt;Windows 8 for software developers: the Longhorn dream reborn?&lt;/font&gt;&lt;/a&gt;” It’s well-written, well-reasoned, and grounded in a bit more than opinion and rumor … as in the author is talking about what’s actually in some of the early bits.&lt;/p&gt;  &lt;p&gt;I’ve read it over a few hundred times and … honestly … it still seems right to me … right down to it’s stirring conclusion:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;font color="#4f81bd" size="4"&gt;Far from being a developer disaster, Windows 8 should be a huge leap forward: a release that threatens to make development a pleasure for native, managed, and Web developers alike.&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Here are my favorite excerpts:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Windows 8 will ship with a pair of runtimes; a new .NET runtime and a native code C++ runtime.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;There will be a new native user interface library, DirectUI      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;A new version of Silverlight (v.6? codenamed Jupiter?) will run on top of DirectUI      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;DirectUI is built around a core subset of current WPF/Silverlight technology and includes support for XAML.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;This core will give C++ programs their modern user interface toolkit and, at its heart, it will be the same toolkit that .NET developers use too.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;XAML and the WPF-like, Silverlight-like way of developing GUIs are going to be absolutely central to Windows development in the future.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;It gives parity to native C++ and managed .NET code. Instead of being separate, each with its own different capabilities and strengths, they will be peers.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Want to write an immersive application in native C++? That's cool. Want to use C# and Silverlight? That's cool too. Both will be supported. Far from being left behind on the legacy desktop—which was the impression that many took from the presentation—native C++ and managed C# will both be first-class, supported ways of developing immersive, touch-first, tablet-friendly Windows 8-style applications.      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;HTML5 and JavaScript will be an option too [with] greater access to operating system functionality than regular webpages … Feature-wise, they should be at the same level as .NET and native programs. It's just that they'll use an HTML5 programming model and JavaScript. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Wouldn’t it be great if Microsoft came out and said this? Or said anything?&lt;/p&gt;  &lt;p&gt;They won’t … not until their &lt;a href="http://www.buildwindows.com/" target="_blank"&gt;BUILD conference in Anaheim in September&lt;/a&gt;. Microsoft isn’t deaf. They know all about developer anxiety on this score and have decided to do nothing to allay that anxiety.&lt;/p&gt;  &lt;p&gt;Fine. Be that way. Meanwhile, those of us who have work to do are wise to keep moving along the .NET client track.&lt;/p&gt;&lt;h3&gt;Related Articles&lt;/h3&gt;&lt;p&gt;A David Burela post, "&lt;a href="http://davidburela.wordpress.com/2011/06/14/premature-cries-of-silverlight-wpf-skill-loss-windows-8-supports-all-programming-models/" target="_blank"&gt;Premature cries of Silverlight / WPF skill loss. Windows 8 supports all programming models&lt;/a&gt;", offers a wealth of detail extracted from the Windows 8 Milestone 3 leak, all consistent with the &lt;b&gt;ars technica&lt;/b&gt; article.&lt;/p&gt;On July 6, InfoWorld published their take on these matters in "&lt;a href="http://www.infoworld.com/d/application-development/the-fall-and-rise-microsoft-silverlight-163" target="_blank"&gt;The fall and rise of Microsoft Silverlight&lt;/a&gt;"&lt;p style="margin-left:20px"&gt;&lt;i&gt;Silverlight found a foothold in Windows Phone and has more recently emerged as a key component of the Jupiter application framework and programming model for Windows 8. If Silverlight has become less important as a rich Internet application (RIA) framework, it has become more important to Microsoft's desktop and mobile platforms overall.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Again, it's more tea-leaf reading than hard news ... but it reflects the emerging consensus that .NET and XAML clients remain at the forefront of Microsoft development technologies.&lt;p&gt;Stephen Forte of Telerik &lt;a href="http://www.stephenforte.net/PermaLink,guid,8b91d036-01b1-4a3e-9391-615eb801b969.aspx" target="_blank"&gt;posted his musings&lt;/a&gt; on the future of XAML clients. Noteworthy to me is what Telerik is actually &lt;b&gt;doing about it&lt;/b&gt;:&lt;p style="margin-left:20px"&gt;&lt;i&gt;I don't see Silverlight as being dead, but rather reborn bigger and better. Instead of being its funeral, the Build Conference will be Silverlight and XAML's graduation party. At Telerik, we are also going to double down on our XAML strategy. ... We see Native XAML as a massive opportunity and will continue to support our XAML tools now and in the future.&lt;/i&gt;&lt;/p&gt;&lt;p&gt;That's putting serious money where their mouth is. Why not you?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-5661300560343275215?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/5661300560343275215/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=5661300560343275215' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5661300560343275215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5661300560343275215'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/07/read-win-8-longhorn-dream-reborn.html' title='Read “Win 8-Longhorn Dream Reborn”'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-1941723540725868542</id><published>2011-06-10T18:19:00.001-07:00</published><updated>2011-06-10T18:19:04.404-07:00</updated><title type='text'>Intersoft ClientUI does Photos</title><content type='html'>&lt;p&gt;I’ve written twice before, &lt;a href="http://neverindoubtnet.blogspot.com/2010/11/clientui-sample-mvvm-for-wpf.html" target="_blank"&gt;here&lt;/a&gt; and &lt;a href="http://neverindoubtnet.blogspot.com/2010/12/sandbox-editors-with-clientui-contacts.html" target="_blank"&gt;here&lt;/a&gt;, about the &lt;a href="http://www.intersoftpt.com/" target="_blank"&gt;Intersoft Solutions&lt;/a&gt; MVVM sample that relies on &lt;a href="http://www.ideablade.com/" target="_blank"&gt;DevForce&lt;/a&gt; for model development and distributed data access. The sample is most notable technically for its MVVM style and the surprising fact that &lt;strong&gt;&lt;em&gt;the source code compiles both to WPF and to Silverlight&lt;/em&gt;&lt;/strong&gt;. Just about every line is the same across platform … including the XAML. The dual-platforming is a signature feature of Intersoft’s UI control suite … and DevForce itself. We’re both kind of proud about it.&lt;/p&gt;  &lt;p&gt;I’m writing this post to tell you that the good folks at &lt;strong&gt;Intersoft&lt;/strong&gt; have added some new features in version 3 of the sample. I encourage you to &lt;a href="http://intersoftpt.wordpress.com/2011/06/08/clientui-devforce-part-3-enhance-editing-experiences-with-mvvm-advanced-input-controls/" target="_blank"&gt;check out Jimmy’s post&lt;/a&gt; to learn the details, see some gorgeous screen shots, and &lt;a href="http://www.intersoftpt.com/ClientUI/ClientUI_DevForceIntegration_v3.zip" target="_blank"&gt;download the source code&lt;/a&gt;. &lt;/p&gt;  &lt;h2&gt;Uploading photos&lt;/h2&gt;  &lt;p&gt;My favorite new feature is the ability to upload images from the client. &lt;strong&gt;Intersoft&lt;/strong&gt; offers a new &lt;strong&gt;&lt;em&gt;UXFileUpload&lt;/em&gt;&lt;/strong&gt; control to manage the user interaction and the mechanics of copying an image to a directory on your server. To quote Jimmy, this control enables “multiple file upload, progress indicator, upload cancellation, and a fully customizable look and feel”.&lt;/p&gt;  &lt;p&gt;In the featured scenario, the application stores the URL of the uploaded image in the Contact entity which is saved in turn to the Contact table in the database. The sample shows how to bind the &lt;em&gt;UploadedFileUrl&lt;/em&gt; of the upload control to a property of the Contact in a manner consistent with the MVVM architectural style.&lt;/p&gt;  &lt;p&gt;Here’s a screen shot of the “Edit Contact” screen displaying the photo.&lt;/p&gt;  &lt;p&gt;&lt;img src="http://intersoftpt.files.wordpress.com/2011/06/image1.png" width="637" height="416" /&gt;&lt;/p&gt;  &lt;h2&gt;Other cool stuff&lt;/h2&gt;  &lt;p&gt;&lt;strong&gt;Intersoft&lt;/strong&gt; keeps adding to and improving its controls. One of them, the &lt;strong&gt;&lt;em&gt;UXMaskedInput&lt;/em&gt;&lt;/strong&gt;, gets a workout in this sample where it &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Automatically uppercases the ID input &lt;/li&gt;    &lt;li&gt;Limits the zip code to five digits &lt;/li&gt;    &lt;li&gt;Masks the phone numbers in the Phone, Cell and Fax textboxes &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you’re looking for beautiful controls, an MVVM mindset, and developer productivity for your next WPF or Silverlight application (or your next WPF+Silverlight application) … &lt;a href="http://intersoftpt.wordpress.com/2011/06/08/clientui-devforce-part-3-enhance-editing-experiences-with-mvvm-advanced-input-controls/" target="_blank"&gt;head over to Intersoft&lt;/a&gt; and see what they’ve got going.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-1941723540725868542?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/1941723540725868542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=1941723540725868542' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1941723540725868542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1941723540725868542'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/06/intersoft-clientui-does-photos.html' title='Intersoft ClientUI does Photos'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-4545337127625690462</id><published>2011-05-24T19:22:00.001-07:00</published><updated>2011-05-24T19:22:45.599-07:00</updated><title type='text'>Use wildcards to include resource files in a project</title><content type='html'>&lt;p&gt;Just discovered from &lt;a href="http://www.wintellect.com/CS/blogs/krome/archive/2011/04/21/wildcard-inclusions-in-c-project-files.aspx"&gt;Keith Rome’s blog post&lt;/a&gt; that you can use wildcards to include files in a project. This is occasionally useful as when you have lots of resources.&lt;/p&gt;  &lt;p&gt;For example, in the &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/code-sample-bookshelf"&gt;IdeaBlade Bookshelf sample application&lt;/a&gt; (based on &lt;a href="http://channel9.msdn.com/events/PDC/PDC10"&gt;John Papa’s BookClub sample&lt;/a&gt;) there is a folder of 58 images:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_iOCgrkgC3Tk/Tdxn8PvDZnI/AAAAAAAAAIU/XE2hGqqcl8M/s1600-h/clip_image001%5B3%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image001" border="0" alt="clip_image001" src="http://lh6.ggpht.com/_iOCgrkgC3Tk/Tdxn8mMb2NI/AAAAAAAAAIY/qTcEyz5Q1uk/clip_image001_thumb.png?imgmax=800" width="198" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You can add and remove these files by hand. I admit it’s not that hard to do by clicking “Show all”, scatter selecting the ones that aren’t already part of the project and adding them. But it’s still a maintenance chore.&lt;/p&gt;  &lt;p&gt;Alternatively you can edit the project file once to pick up all of the jpgs and never worry about it again.&lt;/p&gt;  &lt;p&gt;Begin by opening the project file in a text editor (or within VS by unloading the project and editing the project file; commands for this purpose are available from the context menu). &lt;/p&gt;  &lt;p&gt;Each of the image files is mentioned by name in an &lt;font face="Courier New"&gt;&amp;lt;ItemGroup/&amp;gt;&lt;/font&gt; as shown here.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_iOCgrkgC3Tk/Tdxn8gHNJaI/AAAAAAAAAIc/CDWZCMVqUdA/s1600-h/clip_image002%5B4%5D.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://lh4.ggpht.com/_iOCgrkgC3Tk/Tdxn9MGDPYI/AAAAAAAAAIg/PPMdLaxtw88/clip_image002_thumb%5B1%5D.png?imgmax=800" width="523" height="181" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Replace the entire&lt;font face="Courier New"&gt; &amp;lt;ItemGroup/&amp;gt;&lt;/font&gt; block with the following:&lt;/p&gt; &lt;font face="Courier New"&gt;&amp;#160; &amp;lt;ItemGroup&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Content Include=&amp;quot;Assets\Images\*.jpg&amp;quot;&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;CopyToOutputDirectory&amp;gt;PreserveNewest&amp;lt;/CopyToOutputDirectory&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/Content&amp;gt;&amp;#160; &lt;br /&gt;&amp;#160; &amp;lt;/ItemGroup&amp;gt;&lt;/font&gt;   &lt;p&gt;Save and reload the project. Henceforth, the images will be self-included. &lt;/p&gt;  &lt;p&gt;As long as a matching file (any jpg) is in the folder, the build will pick it up. Remove the file and it disappears (no lingering missing link). You may have to click “refresh” in Solution Explorer to get the project to show you the latest list.&lt;/p&gt;  &lt;p&gt;Of course you can no longer set properties on the files individually or include/exclude individuals. But it’s a pretty cool trick when you have a pile of identical resources like this.&lt;/p&gt;  &lt;p&gt;Who knew?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-4545337127625690462?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/4545337127625690462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=4545337127625690462' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4545337127625690462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4545337127625690462'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/05/use-wildcards-to-include-resource-files.html' title='Use wildcards to include resource files in a project'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_iOCgrkgC3Tk/Tdxn8mMb2NI/AAAAAAAAAIY/qTcEyz5Q1uk/s72-c/clip_image001_thumb.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-4625899163140033963</id><published>2011-05-23T09:13:00.001-07:00</published><updated>2011-05-25T17:38:48.921-07:00</updated><title type='text'>MVVM Backlash</title><content type='html'>&lt;p&gt;I and many others have pushed hard for Model-View-ViewModel (MVVM) design over the last few years. No wonder people are pushing back. Two recent conversations have stirred me to reexamine my affection for MVVM screen design. What surprises me is that I’m feeling we slightly oversold it.&lt;/p&gt;  &lt;p&gt;In the end, I am unrepentant: I continue to practice MVVM and recommend it to others. &lt;/p&gt;  &lt;p&gt;But today I am going to take it down from its pedestal and give it a good thrashing. I’ll admit begrudgingly that you can build a large, maintainable application without it. I will discover that MVVM has only two truly distinctive technical advantages: automated testing of the view logic and integrated design time data. Lots of developers don’t care about either. MVVM may not be for those people. &lt;/p&gt;  &lt;p&gt;I’m not going to call them bad programmers. They could be good programmers. They could be great programmers. Are you being bad when you don’t write view-logic automated tests? I’m inclined to say so but not prepared to hang you for it.&lt;/p&gt;  &lt;h2&gt;Disquieting conversations&lt;/h2&gt;  &lt;p&gt;I have had a long running conversation with sage and MVVM skeptic, &lt;a href="http://www.billyhollis.com" target="_blank"&gt;Billy Hollis&lt;/a&gt; about MVVM. Billy finds a way to talk trash about MVVM just about every chance he gets. His oeuvre on the subject consists largely of twitter bon mots, barbed asides in lectures, and assorted podcast witticisms. He may have penned his opinions on MVVM somewhere but I don’t know where. Therefore, at some risk of misrepresenting his position, I summarize his position as follows:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;MVVM is a way for code-addicted developers to deflect attention from the horrible designs they inflict on users, &lt;/li&gt;    &lt;li&gt;MVVM complicates development with little or no compensating benefit, &lt;/li&gt;    &lt;li&gt;there is too much strident, jargon-filled, punishing MVVM rhetoric that alienates the mass of developers. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;I agree completely with #1. MVVM does nothing to improve UX; our obsession with it robs us of time better spent enriching our design education and delivering more satisfying applications. Nonetheless, I expect to continue that trend with this post and more MVVM commentary to come. I do not apologize; while it is one of my obsessions, it’s your fault if you make it yours. &lt;/p&gt;  &lt;p&gt;I ruefully acknowledge his 3rd objection although I believe we’ve largely outgrown it.&lt;/p&gt;  &lt;p&gt;Objection #2 – that MVVM adds complexity without benefit – is the controversial claim that I address today. That leads me to my second conversation, the one precipitating this post.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://johnpapa.net/" target="_blank"&gt;John Papa&lt;/a&gt; is developing an outline for his forthcoming video series on MVVM. The series targets developers who know nothing about MVVM. It will explain what MVVM is and explore MVVM techniques. &lt;/p&gt;  &lt;p&gt;But why bother with MVVM in the first place?&amp;#160; Why not do the most obvious thing and write all code in the View’s code-behind? What is wrong with that? John wants to address those questions in his video in a direct, matter-of-fact way that any developer can appreciate. That isn’t going to be as easy as he first thought&amp;#160; &lt;/p&gt;  &lt;p&gt;MVVM is second nature to John as it is for many of use. We’ve forgotten how we got here. We can recite the academic arguments. We have the PowerPoint slides we’ve used over the years. But if you were susceptible to academic argument, you’d be using MVVM already. &lt;/p&gt;  &lt;p&gt;What if we couldn’t get by with the old bromides like “Separation of Concerns” and we couldn’t thump Martin Fowler’s pattern book from 2003 like a bible at a revival meeting? How would we demonstrate that MVVM is better than code-behind? &lt;/p&gt;  &lt;p&gt;John kindly called me to puzzle this through with him. We had some fun watching the wheels come off. This post is my account of what we learned. It represents my conclusions, not John’s … although I hope he agrees with me.&lt;/p&gt;  &lt;h2&gt;The usual arguments for MVVM&lt;/h2&gt;  &lt;p&gt;Here are bullets from a hypothetical MVVM benefits slide; I’ve drawn them from several presentations, blogs, and discussions.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Separation of concerns (SoC) &lt;/li&gt;    &lt;li&gt;Loose coupling &lt;/li&gt;    &lt;li&gt;Data Binding &lt;/li&gt;    &lt;li&gt;Designer / developer symbiosis &lt;/li&gt;    &lt;li&gt;Reusability &lt;/li&gt;    &lt;li&gt;Avoid spaghetti code &lt;/li&gt;    &lt;li&gt;Consistent, maintainable, scalable &lt;/li&gt;    &lt;li&gt;Support for design time data &lt;/li&gt;    &lt;li&gt;Automated view-logic testing &lt;/li&gt;    &lt;li&gt;Multiple views over the same view logic &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;John and I kicked these around. It turns out that many of them don’t hold water.&lt;/p&gt;  &lt;p&gt;We ruled out “&lt;strong&gt;separation of concerns&lt;/strong&gt;” and “&lt;strong&gt;loose coupling&lt;/strong&gt;” right away because they are just jargon to many people.&lt;/p&gt;&lt;p style="margin-left:20px"&gt;[&lt;i&gt;update: "ruled out" was a poor verb choice. What I meant was that we didn't want to &lt;b&gt;chant&lt;/b&gt; "SoC" and "Loose Coupling". We wanted to get behind the familiar rhetoric. These principles remain fundamental to us ... as I explained in the next paragraph.&lt;/i&gt;]&lt;/p&gt;&lt;p&gt;To me they are a convenient short hand for guidance that has always served me well. But for many they’re just slogans, shouted from a little red book.&lt;/p&gt;  &lt;p&gt;John and I aren’t sending anyone to re-education camp. We wanted to show concretely how code-behind necessarily betrays you and ViewModel saves you. When we really looked, we realized that ViewModel isn’t intrinsically more SoC or more loosely coupled than code-behind (stay tuned).&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Data binding&lt;/strong&gt;? The practical implementation of the MVVM pattern requires a powerful data binding infrastructure. But you don’t have to use MVVM to use data binding. You can bind the view to the code-behind.&lt;/p&gt;  &lt;p&gt;“&lt;strong&gt;Designer / developer symbiosis&lt;/strong&gt;” refers to the ability of a designer and a developer to work on the view independently without risk of corrupting the other’s work.&amp;#160; In MVVM, no matter what the designer does to the View, the ViewModel code is untouched. Nothing the developer does to the ViewModel code affects the View XAML. Upon closer examination (see below), I feel that MVVM doesn’t have a strong advantage here … even when (as is extremely rare) the project is blessed with a crew of designer people to assist the developer people.&lt;/p&gt;  &lt;p&gt;The “&lt;strong&gt;spaghetti code&lt;/strong&gt;” argument is a canard. MVMV in not inherently more “consistent, maintainable, and scalable.” Bad code is bad code whether it’s in the ViewModel or the code-behind. The view logic is not magically transformed by refactoring to a separate class. If you are inclined to reduce repetition and externalize dependencies into supporting services, you will do so in code-behind as surely as you will do it in a ViewModel. If not … well we’ve all seen train-wreck ViewModels haven’t we?&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Design time data&lt;/strong&gt; support? &lt;strong&gt;Check!&lt;/strong&gt; John and I believe developers and designers are more effective when they &lt;em&gt;design, maintain and evolve&lt;/em&gt; the view in Blend (or Cider) using design time data. A ViewModel can easily deliver design data to the tooling and “real” data to the runtime application. The code-behind cannot provide design data to the tooling because the design tools don’t execute the code behind.&amp;#160; I expand on this point below.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Automated view-logic testing&lt;/strong&gt;? &lt;strong&gt;Check!&lt;/strong&gt; We agreed that automated testing of code-behind is so difficult as to be impractical. Billy agrees too. Score one for MVVM. &lt;em&gt;Of course if you don’t do automated testing of view logic …&lt;/em&gt;&amp;#160;&amp;#160; I talk more about this below.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Multiple views&lt;/strong&gt; over the same view logic? &lt;strong&gt;Check!&lt;/strong&gt; ViewModel is for you if you think you’ll need different views for different users – perhaps as part of a localization requirement or perhaps because the presentation should vary based on role. You can build such variation into a single xaml view but that gets messy quickly.&lt;/p&gt;  &lt;h2&gt;Definitive benefits&lt;/h2&gt;  &lt;p&gt;Three claims survive close analysis; ViewModel has a decisive advantage when you care about&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;design time data &lt;/li&gt;    &lt;li&gt;automated view testing &lt;/li&gt;    &lt;li&gt;multiple views over the same view logic &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Do you really care?&lt;/h2&gt;  &lt;p&gt;I do care … as I said at the top. I care about view-logic testing and design time data. Multiple views are usually just a nice-to-have; but I care a great deal about the first two.&lt;/p&gt;  &lt;p&gt;The unfortunate reality is that many (most?) developers don’t seem to care about these things. I can want them to care … but I haven’t figured out how to make them care.&lt;/p&gt;  &lt;p&gt;I believe the “design time data” argument may become attractive. Not many people design with data yet. I think that’s because they don’t know about it. Once they discover it and see how handy it is … and see that ViewModel is easy … that could shift the balance.&lt;/p&gt;  &lt;p&gt;People have heard the argument for testing for years. I don’t think there is anything new to say, nothing more persuasive to say, that hasn’t been said. The testing adoption statistics are not encouraging. My anecdotal evidence is not encouraging. You know how many ViewModels I’ve seen tested in the wild? You know how many ViewModels I’ve seen tested in a book, article, or demo that cites “testability” as a reason for MVVM? I want to say “none.” &lt;/p&gt;  &lt;p&gt;Actually I’ve done it and I’ve got a &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/code-sample-bookshelf" target="_blank"&gt;BookClub demo&lt;/a&gt; that shows how. ViewModel automated testing is the way &lt;a href="http://www.ideablade.com" target="_blank"&gt;IdeaBlade&lt;/a&gt; professional services rolls. &lt;/p&gt;  &lt;p&gt;Please, please, please prove me wrong and tell us all where we can see some ViewModel testing.&lt;/p&gt;  &lt;h2&gt;I might do it if it’s easy&lt;/h2&gt;  &lt;p&gt;I fear that the &lt;em&gt;unequivocal&lt;/em&gt; arguments for MVVM will have only a tenuous grasp on the hearts of many developers. I will argue until the cows come home that MVVM inclines you toward good practices (e.g., SoC, loose coupling). I must admit that if you have good discipline you’ll be fine without it.&lt;/p&gt;  &lt;p&gt;I remind you, &lt;em&gt;pace&lt;/em&gt; Billy Hollis, that MVVM won’t do a thing for your application’s user experience. Don’t get caught up in the code at the expense of the design! That’s unbalanced. That’s not healthy.&lt;/p&gt;  &lt;p&gt;I suppose what I am saying (and lot of people are saying ) is “&lt;strong&gt;&lt;em&gt;take this MVVM medicine … it’s good for you … even though you may not feel different right away&lt;/em&gt;&lt;/strong&gt;. ”&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;That means MVVM must be easy to do&lt;/strong&gt;. If it were hard you would be mad to follow our lead on the strength of these assurances. We’re telling you to create an extra class – the ViewModel class – for almost every View in your application. You might write a hundred “extra” classes in a big application. That’s a tough sell right there. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Fortunately, MVVM is easy to do&lt;/strong&gt;. There’s always someone around to make a good thing harder than it needs to be. Laurent Bugnion’s &lt;a href="http://mvvmlight.codeplex.com/" target="_blank"&gt;MVVM Light&lt;/a&gt; proves it doesn’t have to be hard. I hope you’ll find – as we have – that you’ll quickly get the hang of it and it’s smooth sailing once you do. Design data and automated testing will rapidly reveal their value.&lt;/p&gt;  &lt;p&gt;I have a good feeling about John’s video series. I think it’s going to help you feel good about MVVM.&lt;/p&gt;  &lt;h2&gt;Appendix: Observation Details&lt;/h2&gt;  &lt;p&gt;The remainder of this post explores a few of the earlier observations in a bit more detail. Indulge yourself if you will.&lt;/p&gt;  &lt;h3&gt;Separation of Concerns&lt;/h3&gt;  &lt;p&gt;Code-behind is code that supports the view. It sits in its own file, apart from the XAML file that determines what the user sees and touches. It’s purpose is to assist the View in presenting data and responding to user gestures. Well that’s the definition of a ViewModel too.&lt;/p&gt;  &lt;p&gt;To be sure the view and its code-behind are the same class. In this respect, the visual design and view logic are technically comingled in a clear violation of SoC.&amp;#160; Practical consequences attend. But are they sufficiently compelling? Or can a good developer achieve practical separation with little effort?&lt;/p&gt;  &lt;p&gt;Naïve developers tend to crowd the code-behind with logic that doesn’t belong there. I’ve seen people implement data access in code-behind. I’ve done it myself … in quick demos. That’s a bad idea for a real application. But it’s not a better idea when you relocate that code to a ViewModel. Pesistence logic belongs in a service that you make available to the ViewModel … or the code-behind.&lt;/p&gt;  &lt;p&gt;The same argument applies to logging, and navigation, and all other cross-cutting, re-usable tasks that should be treated as external dependencies by the ViewModel or code-behind. You either think this way or you don’t.&lt;/p&gt;  &lt;p&gt;I considered a detailed discussion of Robert Martin’s &lt;a href="http://en.wikipedia.org/wiki/Solid_(object-oriented_design)" target="_blank"&gt;SOLID&lt;/a&gt; principles as they apply to using or not using a ViewModel. It struck me as an arid exercise. Only “single responsibility” and “dependency inversion” seemed to have practical relevance; there’s not much use for inheritance or interfaces in view design. I’d make the same argument as I did for SoC. &lt;/p&gt;  &lt;p&gt;Culturally ViewModel is more aligned with SOLID thinking but, as I said, you can get the practical benefits in code-behind without much effort.&lt;/p&gt;  &lt;h3&gt;Loose Coupling&lt;/h3&gt;  &lt;p&gt;The code-behind approach makes it easy to tightly couple the UI elements to the code. That sounds really bad. I think it sounds bad. Then I try to think of all the awful things that will happen to you … and I don’t come up with any; not unless you care about testability which I do. But bear with me. If I didn’t care about testability – if I merely paid it lip service – would tight coupling matter? I’m having a tough time showing how.&lt;/p&gt;  &lt;p&gt;It’s not as if the View and the code-behind are living separate lives. How often (outside of tests) would you instantiate one without the other?&lt;/p&gt;  &lt;p&gt;Moreover, if I do care about tight coupling, I can easily loosen it in the code-behind approach. Nothing stops me. It’s no harder (or easier) than coupling to a ViewModel.&amp;#160; I can data bind the xaml to the code-behind and use Behaviors to bind to methods and events in the code-behind. All I have to do is set the view’s &lt;em&gt;&lt;strong&gt;DataContext&lt;/strong&gt;&lt;/em&gt; to &lt;em&gt;&lt;strong&gt;this&lt;/strong&gt;&lt;/em&gt; in the constructor. Done. The choice is mine.&lt;/p&gt;  &lt;h3&gt;Automated Testing&lt;/h3&gt;  &lt;p&gt;Testability is MVVM’s sole uncontested and incontrovertible advantage. I can think of no one who argues that it is practical to test logic in the code-behind.&lt;/p&gt;&lt;p style="margin-left:20px"&gt;Update: Bill Kempf took up the challenge in a &lt;a href="http://digitaltapestry.net/blog/look-ma-no-viewmodel" target="_blank"&gt;follow-up blog post&lt;/a&gt; that shows you can (a) write a code-behind ViewModel and (b) test it. Thus he reminds us that MVVM is a &lt;b&gt;pattern&lt;/b&gt; admitting of many &lt;b&gt;implementations&lt;/b&gt; ... including, it seems, a code-behind implementation. p.s: Bill was making a point, not a recommendation. Be amused by it but please don't follow it!&lt;/p&gt;&lt;p&gt; ViewModel testability alone should be sufficient reason to adopt MVVM designs. And MVVM proponents dutifully recite MVVM’s testability advantage.&lt;/p&gt;  &lt;p&gt;Too bad so few MVVM proponents actually write ViewModel tests. Find me a demo with automated ViewModel tests. Do they even exist? The hypocrisy is mildly amusing.&lt;/p&gt;  &lt;p&gt;One possible explanation: &lt;em&gt;demo&lt;/em&gt; ViewModels don’t seem worthy of tests. The first ViewModel you write is typically just a bunch of properties. Property tests are low priority because they generally lack decision logic. Testing simple getters and setters is a complete waste of time.&lt;/p&gt;  &lt;p&gt;Even a primitive ViewModel gets its model from somewhere, typically a data service. However, in the beginning, the data service is usually a fake that always delivers the goods in a timely fashion. Nothing goes wrong so you let it slide. Later, if you are inclined toward automated testing, you will test the data service independently of the ViewModel.&amp;#160; VM testing can seem a well-intentioned luxury that you never get around to doing. &lt;/p&gt;  &lt;p&gt;In fact, in a mature ViewModel there will be plenty to test. The VM is an integration point for asynchronous services and user interactions. Users do weird things and services fail. How does the ViewModel handle service exceptions? How does it handle null results, empty results, one result, multiple results? Does it signal changes to &lt;em&gt;&lt;strong&gt;IsBusy&lt;/strong&gt;&lt;/em&gt; at the right times … as when the service fails? Can the VM run offline? What if the user isn’t authenticated? What if the save fails with a concurrency failure? How does the VM respond to tombstoning if this is a Windows Phone application? Does the VM signal view state transitions? Does it wait for view animations to complete and, if so, how do you test the timing? Does the VM send messages? Does it respond to messages? How does it learn which data to show? What if the requested data item doesn’t exist or is invalid?&lt;/p&gt;  &lt;p&gt;I don’t anticipate all of these possibilities at the start. Instead I write a few minimal ViewModel tests to put the structure in place. Once I get the hang of it in a new project, this takes a couple of minutes for each new VM. If it takes longer, I count myself blessed because I’ve discovered trouble in my MVVVM triad before the heat is on. I act immediately to get it pointed in the right direction; then I move on. Let me repeat, I make no attempt to test everything. I make sure I have at least one test. Then I add tests for whatever happens to catch my interest.&lt;/p&gt;  &lt;p&gt;Over time I’ll trace a number of bugs to the VM. Over time I’ll add capabilities or refactor portions of the VM to helper classes. When I fix those bugs, add new logic, or refactor, the friction of adding supporting tests is low because I’ve established a base line.&lt;/p&gt;  &lt;p&gt;This approach works for me. I’m not a testing fanatic. I skip tests even when I know that I shouldn’t. But let me say this: I never regret writing them. I’ve been saved by tests many times and suffered as many times for lack of them. If we work together on a project, we’re going to write tests together. That’s how I roll.&lt;/p&gt;  &lt;h3&gt;Design time data&lt;/h3&gt;  &lt;p&gt;John and I believe strongly in the virtue of designing screens with realistic design data that is shaped exactly like the runtime data. We can’t think of any way to satisfy this requirement in the code behind approach. The design tools don’t run the code-behind so the code-behind can’t deliver design time data.&lt;/p&gt;  &lt;p&gt;Some folks recommend Blend’s XML sample data, a secondary data source that doesn’t depend upon a ViewModel. That’s a viable way to drive out the first draft of a view. I feel it is a significantly inferior alternative because:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You can’t re-use the sample data as fakes for developer, QA, and automated testing. &lt;/li&gt;    &lt;li&gt;Many data types (e.g., DateTime) are represented as strings in sample data. You don’t bind to a string as you would a DateTime. That means you write two bindings – one for design, one for production – or devise some other hideous workaround. &lt;/li&gt;    &lt;li&gt;Complex object graphs are trickier to maintain in XML sample data &lt;/li&gt;    &lt;li&gt;You have to update the sample data structures as your model evolves &lt;/li&gt;    &lt;li&gt;Sample data files tend to be scattered around your projects, complicating maintenance. &lt;/li&gt;    &lt;li&gt;It’s tedious at best to keep the sample data out of the production builds. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The first objection is a big one for me. I’ve always got fake data around during development and testing.&lt;/p&gt;  &lt;p&gt;Forget about automated testing for the moment. Everyone tests their applications in some fashion. You make a change to a view, you want to see how it looks … now … before you forget what you changed. You want quick turnaround, not a long delay while the application tries to reach the server … which could be down. View development shouldn’t depend on a data service that’s broken or hasn’t been written yet.&lt;/p&gt;  &lt;p&gt;It will take effort to create and maintain fake development and test data. I don’t want to do that twice – once for runtime simulations and again – in a completely different format - for view design.&lt;/p&gt;  &lt;h3&gt;Designer / developer symbiosis&lt;/h3&gt;  &lt;p&gt;We can’t count this as a huge plus for MVVM. The separation of the XAML and the code behind is pretty good to begin with. It is not like Windows Forms where the changes made on the design surface produced reams of code-behind. The risk of developer/designer cross-contamination is low and reasonable, easy-to-follow work rules reduce it further. &lt;/p&gt;  &lt;p&gt;There are no technical obstacles to a designer and developer working on the view simultaneously because the view xaml and code-behind are in separate physical files.&lt;/p&gt;  &lt;p&gt;The greater risk is that a designer or developer will introduce breaking changes that aren’t detected until runtime. MVVM is no help here at all. In fact, the risk of conflicting changes is slightly higher due to View/ViewModel separation. Each party works happily in isolation, unaware of the effects on the other. The compiler is no help … as it &lt;em&gt;might be&lt;/em&gt; if the designer’s changes happen to corrupt the code. ViewModel automated tests don’t help because, by nature, they don’t consider the view at all.&amp;#160; &lt;/p&gt;  &lt;p&gt;On the plus side, ViewModel &lt;em&gt;discipline&lt;/em&gt; prohibits references to View components; it even prohibits references to most types in the presentation technology. If you follow that discipline, you free the designer to explore visuals and interaction patterns without worrying about breaking the code. While technically, you can be as rigorous in code-behind, the temptation to be lax is almost irresistible. Accordingly, I count “Designer / developer symbiosis” among the cultural claims to MVVM advantage.&lt;/p&gt;  &lt;h3&gt;Caliburn&lt;/h3&gt;  &lt;p&gt;I am a &lt;a href="http://caliburn.codeplex.com/" target="_blank"&gt;Caliburn&lt;/a&gt; fan but I am positioning it as an afterthought in today’s discussion. Caliburn is an UI framework grounded in MVVM. Caliburn automatically wires visual components to code by applying conventions. It can automatically wire a button named “Save” to the “Save” and “CanSave” methods in the ViewModel. The designer doesn’t add &lt;em&gt;behaviors &lt;/em&gt;to the XAML; the developer doesn’t write &lt;em&gt;ICommands&lt;/em&gt;. There is less manual work for everyone. And Caliburn offers other convention-based time-savers throughout the UI development workflow. Its contributions could weigh heavily in the balance for MVVM. &lt;/p&gt;  &lt;p&gt;On the other hand, it’s one more framework to learn and it’s not in the MVVM mainstream. Developers new to MVVM are usually new to the entire XAML platform; they are overwhelmed by foreign concepts and unprepared to shoulder the additional burden of learning Caliburn. Great as it is, the road to Caliburn is bumpier than it could be. We at &lt;a href="http://www.ideablade.com" target="_blank"&gt;IdeaBlade&lt;/a&gt; are doing our part to smooth that road.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-4625899163140033963?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/4625899163140033963/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=4625899163140033963' title='40 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4625899163140033963'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4625899163140033963'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/05/mvvm-backlash.html' title='MVVM Backlash'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>40</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-980034842497290038</id><published>2011-03-11T13:42:00.001-08:00</published><updated>2011-04-01T12:16:08.187-07:00</updated><title type='text'>EFProf First Look: profiling a DevForce SL app</title><content type='html'>&lt;p&gt;We are destined to fall into a performance tar pit. It’s bound to happen. The real question is how to get out.&lt;/p&gt;  &lt;p&gt;It starts with finding &lt;em&gt;where&lt;/em&gt; performance goes south. That alone can be a mind-numbing slog that eats hours of expensive time better spent on improving the application. Good tools are a godsend. &lt;/p&gt;  &lt;p&gt;Which brings me to &lt;a href="http://efprof.com/" target="_blank"&gt;EFProf&lt;/a&gt;, the Entity Framework profiling tool from Oren Eini’s Hibernating Rhinos. Most DevForce applications rely on the Entity Framework for database access and database access is often the &lt;strong&gt;&lt;em&gt;suspected&lt;/em&gt;&lt;/strong&gt; cause of performance problems. &lt;/p&gt;  &lt;p&gt;Well, is it or isn’t it? EF Prof can help settle the question. Oren (better known by his nome-de-blog of &lt;a href="http://ayende.com/blog/" target="_blank"&gt;Ayende Rahien&lt;/a&gt;) is the principal behind EFProf; that’s reason enough to give his tool a look.&lt;/p&gt;  &lt;p&gt;There are free alternatives. You can fire up the SQL Server Profiler … and I do. The DevForce DebugLog is a crucial resource that every  experienced DevForce developer consults as assiduously as the weather report. But I had the feeling that EFProf might provide better insights more quickly. I’m pleased to report that it does.&lt;/p&gt;  &lt;h3&gt;Setup&lt;/h3&gt;  &lt;p&gt;Ridiculously easy. &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Download and extract the zip (duh) &lt;/li&gt;    &lt;li&gt;Add to the web application project a reference to the EFProf profiler library, &lt;em&gt;HibernatingRhinos.Profiler.Appender.v4.0&lt;/em&gt; &lt;/li&gt;    &lt;li&gt;Initialize the profiler in the &lt;em&gt;Application_Start method&lt;/em&gt; of the &lt;em&gt;Global.asax     &lt;br /&gt;&lt;/em&gt;&lt;div style="margin: 0px; padding: 0px; float: none; display: inline;" id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:e3312624-f6b4-4e52-a6d7-b135a9ca4767" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: c#;auto-links:false;"&gt;#if DEBUG&lt;br /&gt;   // Engage EF Profiler: http://efprof.com &lt;br /&gt;   HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize();&lt;br /&gt;#endif&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application is now instrumented in a debug build. Time to listen for those profile results …&lt;/p&gt;&lt;/li&gt;&lt;li&gt;Run the profiler UI executable, &lt;em&gt;EFProf.exe&lt;/em&gt; &lt;/li&gt;&lt;li&gt;Enter your license key (first time only; there’s a 30 day trial) &lt;/li&gt;&lt;li&gt;Launch the Silverlight application. &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;Now even easier&lt;/strong&gt;:&lt;/em&gt; add it to your solution &lt;a href="http://blogs.hibernatingrhinos.com/archive/2011/03/31/nuget-packages-and-an-example-use-of-the-profiler.aspx" target="_blank"&gt;with Nuget&lt;/a&gt; and get updates automatically.&lt;/p&gt;&lt;h3&gt;What you get&lt;/h3&gt;&lt;p&gt;This is a “First Look”, not a tutorial, so all I’m going to do is tease you with a few screenshots.&lt;/p&gt;&lt;p&gt;Here is the main screen after running a DevForce Silverlight automated test sequence.&lt;/p&gt;&lt;p&gt;e:&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TXqXIdBJENI/AAAAAAAAAGk/z1hwD2HxDcg/s1600-h/EFProf-statements1%5B4%5D.png"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-statements1" border="0" alt="EFProf-statements1" src="http://lh4.ggpht.com/_iOCgrkgC3Tk/TXqXI3FyUGI/AAAAAAAAAGo/kFHH7DDfIfI/EFProf-statements1_thumb%5B2%5D.png?imgmax=800" width="331" height="221" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Each statement was the result of a DevForce client request sent to the server and forwarded to EntityFramework; the “Object context #1” is the Entity Framework &lt;em&gt;ObjectContext&lt;/em&gt; instance created in the DevForce &lt;em&gt;EntityServer&lt;/em&gt; query pipeline. The highlighted request is the first query:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TXqXJBEKYAI/AAAAAAAAAGs/OssT3X9l-ng/s1600-h/EFProf-first-query%5B4%5D.png"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-first-query" border="0" alt="EFProf-first-query" src="http://lh5.ggpht.com/_iOCgrkgC3Tk/TXqXJZ3RrAI/AAAAAAAAAGw/KuHVOmrC4yM/EFProf-first-query_thumb%5B2%5D.png?imgmax=800" width="440" height="166" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;That’s a query for all customers. The total time of 178 milliseconds is dominated by something outside the database. Here is that same customer query, issued a second time.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_iOCgrkgC3Tk/TXqXJ6a0efI/AAAAAAAAAG0/lt9qQ0eQ2YM/s1600-h/EFProf-second-query%5B3%5D.png"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-second-query" border="0" alt="EFProf-second-query" src="http://lh5.ggpht.com/_iOCgrkgC3Tk/TXqXKMYykrI/AAAAAAAAAG4/rgblIex4DcU/EFProf-second-query_thumb%5B1%5D.png?imgmax=800" width="451" height="133" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Didn’t take nearly as long, did it. That’s because there is a hefty start-up time for both Entity Framework and the database.&lt;/p&gt;&lt;p&gt;Notice the ball in the “Alerts” column. EFProf evaluates each Entity Framework operation and reports an alert if it thinks there is potential trouble in that operation. The alerts tab explains:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TXqXKZ2BpbI/AAAAAAAAAG8/0_S6Ncmg-Qs/s1600-h/EFProf-unbounded-alert%5B4%5D.png"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-unbounded-alert" border="0" alt="EFProf-unbounded-alert" src="http://lh4.ggpht.com/_iOCgrkgC3Tk/TXqXKp33w4I/AAAAAAAAAHA/jJiXK8Zi1Rk/EFProf-unbounded-alert_thumb%5B2%5D.png?imgmax=800" width="310" height="83" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;If I don’t know what “unbounded result set” means, I click “read more” and see a web page that tells me the query could return far more data than would be good for me. It’s right in this case because the query lacks a “Where” clause; it fetches all customers … as can be seen in the Details tab:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_iOCgrkgC3Tk/TXqXLP3QT4I/AAAAAAAAAHE/RrrTgln2djs/s1600-h/EFProf-all-customers-query-sql%5B3%5D.png"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-all-customers-query-sql" border="0" alt="EFProf-all-customers-query-sql" src="http://lh5.ggpht.com/_iOCgrkgC3Tk/TXqXLSNdaLI/AAAAAAAAAHI/8FPpLLBvJHU/EFProf-all-customers-query-sql_thumb%5B1%5D.png?imgmax=800" width="273" height="168" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Here’s what an individual update operation looks like:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_iOCgrkgC3Tk/TXqXL0Oy73I/AAAAAAAAAHM/rwbDcMg2H1I/s1600-h/EFProf-save-cust-update%5B4%5D.png"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-save-cust-update" border="0" alt="EFProf-save-cust-update" src="http://lh3.ggpht.com/_iOCgrkgC3Tk/TXqXMJxYpCI/AAAAAAAAAHQ/AmsvCR9pLl4/EFProf-save-cust-update_thumb%5B2%5D.png?imgmax=800" width="414" height="165" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;EF uses parameterized values in updates. That’s an essential guard against SQL injection attacks but it makes it a little rough on humans reading the SQL. EF Prof offers a friendlier view.&lt;/p&gt;&lt;h3&gt;Analysis&lt;/h3&gt;&lt;p&gt;So far this is a more pleasant experience than working with the SQL Profiler. We’re getting a bridge between SQL and Entity Framework, the presentation is more helpful, and we’re getting some advice by way of alerts. &lt;/p&gt;&lt;p&gt;It gets better. Check out the Analysis choices. Three strike me as most useful for a DevForce Silverlight application:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_iOCgrkgC3Tk/TXqXMbR6w3I/AAAAAAAAAHU/K6QhmV5Wux0/s1600-h/EFProf-analysis-overview%5B8%5D.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-analysis-overview" border="0" alt="EFProf-analysis-overview" src="http://lh6.ggpht.com/_iOCgrkgC3Tk/TXqXM62cvnI/AAAAAAAAAHY/gMBT2-oBPvc/EFProf-analysis-overview_thumb%5B4%5D.png?imgmax=800" width="543" height="181" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_iOCgrkgC3Tk/TXqXNEZlntI/AAAAAAAAAHc/Wspee8H2EGo/s1600-h/EFProf-analysis-expensive-queries%5B7%5D.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-analysis-expensive-queries" border="0" alt="EFProf-analysis-expensive-queries" src="http://lh6.ggpht.com/_iOCgrkgC3Tk/TXqXNcnSJ7I/AAAAAAAAAHg/wPaAELGoCoc/EFProf-analysis-expensive-queries_thumb%5B3%5D.png?imgmax=800" width="541" height="120" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TXqXN7kb9KI/AAAAAAAAAHk/B_qYuJLB228/s1600-h/EFProf-analysis-unique-queries%5B3%5D.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-analysis-unique-queries" border="0" alt="EFProf-analysis-unique-queries" src="http://lh3.ggpht.com/_iOCgrkgC3Tk/TXqXOAUYg_I/AAAAAAAAAHo/LKM1Lv5R3vY/EFProf-analysis-unique-queries_thumb%5B1%5D.png?imgmax=800" width="543" height="130" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Queries by Uri isn’t that helpful in DevForce Silverlight because the requests come as WCF Posts to two service addresses. That analytic tab would be more useful in a DevForce web application or when analyzing the DevForce OData activity with a phone application.&lt;/p&gt;&lt;p&gt;You can &lt;strong&gt;apply filters&lt;/strong&gt; to scope the analysis:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_iOCgrkgC3Tk/TXqXOXnLuLI/AAAAAAAAAHs/5aisBwNMpXE/s1600-h/EFProf-filter-choices%5B4%5D.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-filter-choices" border="0" alt="EFProf-filter-choices" src="http://lh4.ggpht.com/_iOCgrkgC3Tk/TXqXO35C3SI/AAAAAAAAAHw/xfL1lSGQp48/EFProf-filter-choices_thumb%5B2%5D.png?imgmax=800" width="323" height="263" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;And apply them in combination:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_iOCgrkgC3Tk/TXqXPLwxajI/AAAAAAAAAH0/AMNQx3nyhSg/s1600-h/EFProf-filters-applied%5B4%5D.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="EFProf-filters-applied" border="0" alt="EFProf-filters-applied" src="http://lh3.ggpht.com/_iOCgrkgC3Tk/TXqXPVyrEpI/AAAAAAAAAH4/0ERP7OQ_QOY/EFProf-filters-applied_thumb%5B2%5D.png?imgmax=800" width="428" height="223" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;In this case, I marked selected “Object context” cases with colored stars (I get to pick the color) and restricted to operations within those contexts that took more than 25 milliseconds.&lt;/p&gt;&lt;p&gt;I think the combination of filters and summarizations will be a powerful lens on the data both for finding trouble and conveying my “actionable” message to the developer who needs to fix it.&lt;/p&gt;&lt;h3&gt;Cost and ROI&lt;/h3&gt;&lt;p&gt;An EFProf license costs ~$300.&lt;/p&gt;&lt;p&gt;Hey, I love free – who doesn’t -  but I am more than happy to pay up for a tool that spares me pain. I flatter myself by thinking I’m worth at least $50 per hour. I figure EFProf is sure to save me six hours of fumbling through database profile logs, documenting the madness, and confirming that someone fixed it. It’s all gravy if it saves me more.&lt;/p&gt;&lt;p&gt;Take a look – it’s got a 30 day trial. You’ll be glad you did.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-980034842497290038?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/980034842497290038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=980034842497290038' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/980034842497290038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/980034842497290038'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/03/efprof-first-look-profiling-devforce-sl.html' title='EFProf First Look: profiling a DevForce SL app'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_iOCgrkgC3Tk/TXqXI3FyUGI/AAAAAAAAAGo/kFHH7DDfIfI/s72-c/EFProf-statements1_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-2632208768693919587</id><published>2011-03-10T17:23:00.001-08:00</published><updated>2011-03-10T17:23:58.378-08:00</updated><title type='text'>VS Designer can’t find Resource</title><content type='html'>&lt;p&gt;We got bit by this one today. &lt;/p&gt;  &lt;p&gt;We asked the &lt;em&gt;App.xaml&lt;/em&gt; to create a &lt;em&gt;ViewModelLocator&lt;/em&gt; as a resource.&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;lt;local:ViewModelLocator x:Key=&amp;quot;Locator&amp;quot; /&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Blend&lt;/strong&gt; was fine with that. But the &lt;strong&gt;Visual Studio Designer (“Cider”)&lt;/strong&gt; reported an error along the lines of “&lt;em&gt;Cannot find key ‘Locator’&lt;/em&gt;” and “&lt;em&gt;Cannot add type to ResourceDictionary&lt;/em&gt;”. Of course the view failed to show in the Cider designer. Not good.&lt;/p&gt;  &lt;p&gt;We know &lt;em&gt;ViewModelLocator&lt;/em&gt; type is defined in “local”. Blend could find it. Why not Cider? Utterly maddening.&lt;/p&gt;  &lt;p&gt;We noticed that &lt;em&gt;ViewModelLocator&lt;/em&gt; derived from a base class – call it &lt;em&gt;&lt;em&gt;ViewModelLocator&lt;/em&gt;Base –&lt;/em&gt; which happed to be defined in a &lt;strong&gt;referenced&lt;/strong&gt; assembly. &lt;/p&gt;  &lt;p&gt;When we redefined the &lt;em&gt;ViewModelLocator&lt;/em&gt; without the base class, Cider was happy. When we copied the base class into the same project as the &lt;em&gt;ViewModelLocator&lt;/em&gt; and derived from the copy, Cider was happy.&lt;/p&gt;  &lt;p&gt;There was nothing wrong with the base class itself.&amp;#160; Cider just wouldn’t find the derived class when it was located in a foreign assembly. We couldn’t get it to pay attention to the assembly reference. “Copy local = true” didn’t help. &lt;/p&gt;  &lt;p&gt;Adding an xmlns reference to that foreign assembly in the App.xaml didn’t help either.&lt;/p&gt;  &lt;h3&gt;&lt;strong&gt;Solution&lt;/strong&gt;: &lt;strong&gt;Give the referenced assembly an XmlnsDefinition&lt;/strong&gt;&lt;/h3&gt;  &lt;p&gt;We stumbled into this workaround on a hunch. We opened the &lt;em&gt;AssemblyInfo.cs&lt;/em&gt; of the project in which &lt;em&gt;&lt;em&gt;ViewModelLocator&lt;/em&gt;Base&lt;/em&gt; is defined and added an Xmlns definition attribute … such as this one:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;[assembly: XmlnsDefinition(&lt;/font&gt;&lt;font face="Courier New"&gt;http://schemas.ideablade.com/presentation&lt;/font&gt;&lt;font face="Courier New"&gt;, &amp;quot;IdeaBlade.Presentation&amp;quot;)]&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;We recompiled the project and added this xmlns to the top of App.xaml. &lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;xmlns:ibp=&amp;quot;http://schemas.ideablade.com/presentation&amp;quot;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Cider smiled upon us at last.&lt;/p&gt;  &lt;p&gt;We don’t know if this is the only way to recover. We just know that it works.&lt;/p&gt;  &lt;h3&gt;Notes:&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Learn more about XmlnsDefinition &lt;a href="http://blog.pixelingene.com/?p=45" target="_blank"&gt;here&lt;/a&gt;.&lt;/li&gt;    &lt;li&gt;Remember to add a separate XmlnsDefinition for each namespace in that project.&lt;/li&gt;    &lt;li&gt;You only encounter this problem when the &lt;strong&gt;resource&lt;/strong&gt; class or one of its ancestors lives in a referenced assembly. It is ok if the resource needs something that resides in a referenced assembly.There’d be no problem if the &lt;em&gt;ViewModelLocator&lt;/em&gt; created a &lt;em&gt;Foo&lt;/em&gt; and &lt;em&gt;Foo&lt;/em&gt; is defined in a separate assembly; &lt;em&gt;Foo&lt;/em&gt; isn’t a resource. The problem arose because &lt;em&gt;ViewModelLocator&lt;/em&gt; – which is a resource – depends upon the &lt;em&gt;&lt;em&gt;ViewModelLocator&lt;/em&gt;Base&lt;/em&gt; class that resides in a separate referenced assembly.&lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-2632208768693919587?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/2632208768693919587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=2632208768693919587' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2632208768693919587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2632208768693919587'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/03/vs-designer-cant-find-resource.html' title='VS Designer can’t find Resource'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-2690590499251667400</id><published>2011-02-23T15:30:00.001-08:00</published><updated>2011-02-23T15:33:01.778-08:00</updated><title type='text'>Nested sandbox editors?</title><content type='html'>&lt;p&gt;I received an interesting question in the mail today regarding Sandbox Editors and the advice I offered in &lt;a href="http://neverindoubtnet.blogspot.com/2010_12_01_archive.html" target="_blank"&gt;a previous post&lt;/a&gt;:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;I am using the Contact example with the SandBoxEditor and Editor for the basis of my app. When I have a listView which pops up a dialog should my dialog always use a separate repository instance to work with the detail record? If the detail record pops up a new dialog to gather some additional information should it also use a separate repository instance.&lt;/p&gt;    &lt;p&gt;I guess what I am asking &lt;strong&gt;should I always protect a parent view from changes in a child until the user make the change permanent&lt;/strong&gt;? Is this what you would do in a real application?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;The essence of the question is in this one line: “should I always protect a parent view from changes in a child?”&lt;/p&gt;  &lt;p&gt;First of all, I always avoid the word “&lt;em&gt;always&lt;/em&gt;”.&amp;#160; But seriously …&lt;/p&gt;  &lt;p&gt;The point of the separate repository is to isolate the editing context from the main application context. &lt;em&gt;Within&lt;/em&gt; the sandbox I would tend to use the second, isolated repository everywhere … unless I thought the user experience required secondary isolation in which case I would “sub-sandbox.”&amp;#160; I’d be surprised if this is really what the user wants.&lt;/p&gt;  &lt;p&gt;Let’s step back a bit. Early &lt;a href="http://neverindoubtnet.blogspot.com/2010_12_01_archive.html" target="_blank"&gt;in my Sandbox Editor post&lt;/a&gt; I stressed that some folks &lt;strong&gt;&lt;em&gt;prefer&lt;/em&gt;&lt;/strong&gt; seeing the provisional changes propagated across the UI … &lt;i&gt;as they happen&lt;/i&gt;. In my mind that is a perfectly reasonable experience. If the user expects it and the view design supports that expectation, all is well. &lt;/p&gt;  &lt;p&gt;For example, if the grid and the detail form are side-by-side on the page, I personally would expect the grid to update as I typed in the detail form. &lt;/p&gt;  &lt;p&gt;However, when the editor &lt;em&gt;hovers&lt;/em&gt; &lt;em&gt;on top&lt;/em&gt; of the grid (as it does in the Intersoft sample), I’m more inclined toward the sandbox editor. Even then it’s an option, not a rule. You have to feel it out with your users.&lt;/p&gt;  &lt;p&gt;Notice that John Papa’s Book Club application has only one “DataService”. He does not sandbox. Changes in the overlay editor are reflected immediately in the grid. Is that good or bad?&lt;/p&gt;  &lt;p&gt;Back to your question: should you “&lt;b&gt;&lt;u&gt;sub&lt;/u&gt;&lt;/b&gt;-sandbox”? Only you know what makes the best user experience for your application. The way you design the screens may influence your decision. &lt;/p&gt;  &lt;p&gt;Myself, I would not sub-sandbox. To sub-sandbox would make it more complicated for me and, more importantly, seems likely to confuse my users. I would try to arrange the view so that they expected to see values propagate to the parent window. Maybe I wouldn’t have a parent/child window.&lt;/p&gt;  &lt;p&gt;You won’t know what is “best” until you give your users a chance to try it. Maybe you can show them both designs (in a paper model) and see what they think.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-2690590499251667400?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/2690590499251667400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=2690590499251667400' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2690590499251667400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2690590499251667400'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/02/nested-sandboxes-editors.html' title='Nested sandbox editors?'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-5676584396944479141</id><published>2011-01-29T16:27:00.001-08:00</published><updated>2011-01-29T16:27:13.584-08:00</updated><title type='text'>MVVM Party: Data Service Required</title><content type='html'>&lt;p&gt;Aren’t we all tired of the consultant weasel-words “it depends”? Every once in awhile it is possible to speak in unequivocal and unambiguous language. This is one of those moments. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;A ViewModel should never reference the persistence machinery directly; it should always delegate the getting and saving of Model objects to a helper such as a DataService (aka Repository, aka ServiceAgent).&lt;/font&gt;&lt;/strong&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Are there exceptions? I can’t think of a single one. I wouldn’t break this rule in an MVVM demo.&lt;/p&gt;  &lt;p&gt;Now if I’m not using the MVVM pattern, fine. I just mandated a rule for ViewModel, not a rule for all UI architectures. &lt;/p&gt;  &lt;p&gt;This really is one of the &lt;strong&gt;laws of ViewModel construction&lt;/strong&gt;, taking a privileged place besides a very few other such laws as “&lt;em&gt;The ViewModel may not have a reference to the View&lt;/em&gt;” and “&lt;em&gt;The ViewModel may not refer to a type that requires a running view to construct&lt;/em&gt;.” &lt;/p&gt;  &lt;p&gt;If you break these laws, you are not using MVVM. You’re doing something else. And I’m pretty sure you’re going to suffer for it.&lt;/p&gt;  &lt;p&gt;You won’t suffer because the MVVM Police will get you. You’ll suffer because you added MVVM complexity to your application for nothing. You paid the price for a UI separation pattern … and destroyed that separation. You now have an application that is harder to read and maintain than if you’d put everything in code behind.&lt;/p&gt;  &lt;h3&gt;Who Put The Hot Sauce in Grandpa’s Oatmeal?&lt;/h3&gt;  &lt;p&gt;I’ll give you backstory and then I’ll repeat here what &lt;a href="http://forums.silverlight.net/forums/p/217498/517690.aspx#517690" target="_blank"&gt;I said on the WCF RIA Services forum&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I frequently troll the WCF RIA Services forum to find out what RIA developers are thinking and &amp;lt;grin&amp;gt; to learn of the many ways in which IdeaBlade’s DevForce is superior.&amp;lt;/grin&amp;gt;&lt;/p&gt;  &lt;p&gt;I’m especially fond of &lt;a href="http://www.colinblair.com/Blog/" target="_blank"&gt;Colin Blair&lt;/a&gt;’s contributions. Colin knows more about RIA Services than almost anyone; sometimes I think he knows more than the product team. But I especially like Colin’s posts because he always goes beyond the “how to”. He’s deeply interested in understanding what you are trying to do and in helping you move in a direction that gets you where you want to be. And I probably like his stuff because I agree with it. Except this time. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://forums.silverlight.net/forums/p/217498/517690.aspx#517690" target="_blank"&gt;This time&lt;/a&gt; he gave bad advice.&lt;/p&gt;  &lt;p&gt;A developer identified as “lein4d” posted the following question (amended for grammar and style, &lt;font style="background-color: #ffff00"&gt;highlights&lt;/font&gt; added)&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;When using MVVM Pattern with WCF RIA Services, is it better to encapsulate the client side RIA code in service classes than to have it directly inside the ViewModel?&lt;/p&gt;    &lt;p&gt;&lt;a href="http://weblogs.asp.net/dwahlin/archive/2010/12/20/wcf-ria-services-domaincontext-abstraction-strategies-say-that-10-times.aspx"&gt;In many of the recent MVVM examples&lt;/a&gt; I've seen, the classes are separated into ViewModel, IServiceAgent, and ServiceAgent classes, in which only the ServiceAgent Class knows about RIA details. &lt;/p&gt;    &lt;p&gt;I've been following this approach for a while, but I &lt;font style="background-color: #ffff00"&gt;found it too cumbersome to create all the boilerplate code each time&lt;/font&gt; I create another ViewModel.[???] The application I'm creating &lt;font style="background-color: #ffff00"&gt;doesn't have unit tests, and is not making use of design-time data&lt;/font&gt;.[!!!]&lt;/p&gt;    &lt;p&gt;In this case, is it still necessary to abstract away the RIA service detail? I think it'll be more productive and write less duplicate code if I have DomainContext class directly inside ViewModel and load entities from there. &lt;/p&gt;    &lt;p&gt;What is the rationale behind having IServiceAgent and ServiceAgent classes? As for sharing queries between ViewModels, isn't it sufficient to put shared queries in the server side?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This is a great question for which there is a definitive answer. Unfortunately, Colin gave him the wrong answer. He told lein4d that it is ok to call the DomainContext directly in the ViewModel. Kyle McClellan of the RIA Services team added “&lt;em&gt;Feel free to use the DomainContext directly in your ViewModel.&lt;/em&gt;”&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;It is never ok to call the DomainContext (or the DevForce EntityManager) within a ViewModel. You should not be “feeling free” when you do that.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Although I am shy and generally unwilling to express myself forcefully, I found myself writing this spirited reply.&lt;/p&gt;  &lt;h3&gt;Why ViewModel Should Delegate Persistence To A Service&lt;/h3&gt;  &lt;p&gt;@Lein4d, why are you using ViewModel at all? Why not put everything in the code behind? It's a lot easier and there are fewer classes to worry about. The primary benefits of ViewModel are single responsibility, design/development independence, and testability. You don't seem to be interested in any of them … in which case the MVVM pattern isn't pulling its weight.&lt;/p&gt;  &lt;p&gt;I don't have a lot of hard and fast rules. I do have a few. This is one of them.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;quot;No persistence machinery in the ViewModel&amp;quot; &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I'm going to try to persuade you of this even if you don't seem to care if your ViewModels are readable (sigh), don't test your ViewModels (sigh), and don't design with data (sigh). &lt;/p&gt;  &lt;p&gt;I'm going to make my case solely on the Single Responsibility Principle and its implications for consistency and maintainability. If these characteristics don't matter to you ... stop reading ... and stop bothering with MVVM or any other pattern.&lt;/p&gt;  &lt;p&gt;I ask all of my customers to write ViewModels that &lt;strong&gt;concentrate &lt;/strong&gt;on providing state (data) and behavior (logic) that their views need. Complex tasks that are not strictly concerned with the view (e.g., how to query for entities or save them) should be delegated to supporting &amp;quot;services&amp;quot;. A focused ViewModel is easier to understand and easier to test [oops ... I mentioned those points again]. It is also &lt;strong&gt;less vulnerable to changes that have nothing to do with the View&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;The DomainContext itself is already a step along this road. Without it, in the extreme case, your ViewModel would be making its own connections to the server, issuing web requests on a background thread, waiting for the response, interpreting the response, mapping received data into entities and marshalling them back to the UI thread.&amp;#160; You wouldn't dream of writing that code in each of your Views or ViewModels. The DC abstracts that for you.&lt;/p&gt;  &lt;p&gt;But it's not a sufficient abstraction for the ViewModel. There are still too many mechanics. Let's get concrete.&lt;/p&gt;  &lt;p&gt;Suppose the ViewModel provides Customers to the View. That's really all the VM cares about ... some notion of a list of Customers. It wants to have a method like &amp;quot;GetCustomers&amp;quot;. Why should it care about how that method is implemented?&lt;/p&gt;  &lt;p&gt;Should that method return all customers or only active customers? Only customers that the current user is allowed to see? Can it be customers in cache or should it be customers fresh from the database? Should the query be for customers only or should the query include related entities as well? Should the customers be sorted? Is there an upper bound on the number of Customers to retrieve for this view? Should the query use an existing DomainContext or create a new one? What if the user isn't authenticated? Or not authorized? What if the DC can't connect to the server? What if the server returns an error? &lt;/p&gt;  &lt;p&gt;These are all important considerations. None of them have anything to do with getting customers onto the screen ... which is the VM's job.&lt;/p&gt;  &lt;p&gt;Will you worry about all of these considerations on day one? Probably not. But when they do become important to you, would you expect to edit all of your ViewModels to address them? Or would you expect to edit a Data Service to address them? &lt;/p&gt;  &lt;p&gt;For me the answer turns on this: would changing the way I get the customers change the appearance of the view or how the user interacts with the view? If the answer is &amp;quot;no&amp;quot;, then the code belongs in a Data Service, not the ViewModel.&lt;/p&gt;  &lt;p&gt;Let's generalize that thought. You should be able to answer the following question for all code in your ViewModel: &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Would changing this code alter the appearance of the view or how the user interacts with the view? If &amp;quot;yes&amp;quot;, the code can stay. If &amp;quot;no&amp;quot;, the code belongs elsewhere, perhaps in a helper class to which the VM delegates.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; a hypothetical issue or an academic discussion. You asked for advice rooted in experience. Presumably if you were certain, you wouldn't ask. So listen up to someone who has been working in this corner of .NET since 2003.&lt;/p&gt;  &lt;p&gt;I've looked at a lot of customer code. That's part of my job description: work with customers who are building smart client / RIA applications. I’m kind of a code doctor. People call me when their code is sick.&lt;/p&gt;  &lt;p&gt;Obviously I wasn't always looking at Silverlight code; usually it was Windows Forms where the corresponding collaborator is the &amp;quot;Presenter&amp;quot; in an MVP pattern. Every time I saw persistence code in the VM or Presenter, I saw trouble. Every one of those VMs or Presenters implemented their queries differently. Quite often the same conceptual query would appear in multiple guises. I'd see three or four variations on GetCustomers, all of them unintentionally different. &lt;/p&gt;  &lt;p&gt;Why those differences?&amp;#160; Maybe the developers understood the business rules differently. Maybe the rules changed as the application evolved. Maybe some of the developers (or the same developer at different times) didn't understand how the persistence machinery works when they wrote the code. Maybe awareness of potential errors was acute on some days and not others.&lt;/p&gt;  &lt;p&gt;Whatever the cause, it's a mess ... a mess spread across your code base. Get that stuff out of there. Put it in a Data Service where you can find it, watch it, and tune it. &lt;/p&gt;  &lt;p&gt;P.S.: If you ever decide to test your ViewModels and/or test the many ways that your application accesses data, you'll be glad you made this move.&lt;/p&gt;  &lt;p&gt;A final detail. Your question seemed to imply that you were creating a new &amp;quot;ServiceAgent&amp;quot; and interface for each ViewModel. You wrote &amp;quot;&lt;em&gt;I found it too cumbersome to create all these boilerplate codes each time I create another ViewModel.&lt;/em&gt;&amp;quot;&lt;/p&gt;  &lt;p&gt;I would find that too cumbersome as well. I tend to write one &amp;quot;ServiceAgent&amp;quot; (DataService, Repository, whatever) per module. That's not a strict rule. But I do find that I use the same service across multiple VMs.&amp;#160; John Papa's tiny BookClub example has a single &amp;quot;BookService&amp;quot; that does the trick for both the BookViewModel and the CheckoutViewModel. You really don't need a lot of these services in your application.&lt;/p&gt;  &lt;h3&gt;Colin Replies&lt;/h3&gt;  &lt;p&gt;After I posted, Colin and I had a spirited exchange which you can &lt;a href="http://forums.silverlight.net/forums/p/217498/518312.aspx#518312" target="_blank"&gt;read on the forum&lt;/a&gt;. I won’t repeat it all here. But I will summarize his objections and my counter arguments. &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;#1 “The primary purpose of the ViewModel is data binding”.&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;  &lt;p&gt;No it isn’t. The powerful data binding in the XAML platforms made MVVM feasible. Just because we can do it, doesn’t mean we should. I favor MVVM because it encourages three good things: Single Responsibility, Designer / Developer independence, and automated testing.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;#2 [Paraphrasing] You don’t need a data service for a “Hello, World” application. &lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;True enough. You don’t need MVVM either. More to the point, you probably shouldn’t be using MVVM in a “Hello, World” application.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;#3 [Partial quotation? Misquotation? My interpretation] “I’m uncomfortable telling someone that they are a bad programmer because [they don’t do what I think they should do]”. &lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;I didn’t call anyone a bad programmer. Lein4d asked if he should use a Data Service in his real world MVVM-base application. I didn’t say “maybe”. I said emphatically “yes”. We should be comfortable in our convictions and &lt;strong&gt;uncomfortable when we waffle&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;I try to come clean when I’m unsure. Often the answer depends upon circumstances. Often I have opinions and experience but nothing I’d want to mandate and plenty of counter examples.&lt;/p&gt;  &lt;p&gt;On this particular and rare occasion, I harbor no such doubts. &lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;If you are going to adopt the MVVM pattern, realize that it adds complexity for a purpose: to improve your application’s intelligibility, maintainability, testability, and designability (ugh). Don’t pay the complexity cost and throw the benefits in the trash. Please delegate all persistence concerns to a helper service.&lt;/p&gt;  &lt;p&gt;You’ll be glad you did.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-5676584396944479141?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/5676584396944479141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=5676584396944479141' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5676584396944479141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5676584396944479141'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2011/01/mvvm-party-data-service-required.html' title='MVVM Party: Data Service Required'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-5382356319364173791</id><published>2010-12-17T16:48:00.001-08:00</published><updated>2011-02-23T15:39:42.284-08:00</updated><title type='text'>“Sandbox” Editors with ClientUI Contacts</title><content type='html'>&lt;p&gt;We’re developing a full-stack WPF/Silverlight development series in concert with &lt;a href="http://www.intersoftpt.com/" target="_blank"&gt;Intersoft Solutions&lt;/a&gt; using DevForce and Intersoft’s “ClientUI” technology. You can &lt;a href="http://links.ideablade.com/drc-clientui.devforce" target="_blank"&gt;learn about the series&lt;/a&gt; and keep up with the latest developments on our website.&lt;/p&gt;  &lt;p&gt;Today I’m announcing the second installment of the series which replaces the “synchronous” editor with a “sandboxed” editor. &lt;/p&gt;  &lt;p&gt;With the initial “synchronous” editor, users changes entered in the child window editor are visible immediately in the main view, the view that lists the contacts, as we see here:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_iOCgrkgC3Tk/TQwEwquhIZI/AAAAAAAAAGI/awsVkbG9Ffs/s1600-h/image%5B3%5D.png"&gt;&lt;img style="background-image: none; border: 0px none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px;" title="image" alt="image" src="http://lh3.ggpht.com/_iOCgrkgC3Tk/TQwExE3SqBI/AAAAAAAAAGM/49d-lZlmcVI/image_thumb%5B1%5D.png?imgmax=800" border="0" width="480" height="163" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;That immediacy is a good experience in some screen layouts … say when the detail editor is embedded in the same screen as the list view. But many people feel that a child window editor implies a temporary workspace. Unsaved changes should be confined to the editor; changes should propagate to the main view only after the user saves them.&lt;/p&gt;  &lt;p&gt;For example, the unfinished editing session in which we changed “Andre” to “Bob” should look like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_iOCgrkgC3Tk/TQwExUuGtCI/AAAAAAAAAGQ/X66XrG2k7Yw/s1600-h/image%5B8%5D.png"&gt;&lt;img style="background-image: none; border: 0px none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px;" title="image" alt="image" src="http://lh5.ggpht.com/_iOCgrkgC3Tk/TQwExvPqh6I/AAAAAAAAAGU/bD4i1iylagk/image_thumb%5B4%5D.png?imgmax=800" border="0" width="512" height="172" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In other words, the editing experience should take place “in a sandbox”, hence the name “sandboxed editor”. In the second sample in the DevForce/ClientUI series, we make some small changes to turn the “synchronous” editor into a “sandbox” editor.&lt;/p&gt;  &lt;p&gt;In a post to follow very soon, I’ll describe the issues in detail and the code to get it done.I’ll be excerpting from the &lt;a href="http://www.ideablade.com/ClientUISample/2_AddSandboxEditorToContactsApp.pdf" target="_blank"&gt;walkthrough document&lt;/a&gt; that accompanies the &lt;a href="http://www.ideablade.com/ClientUISample/ClientUI_DevForceIntegration_v2.zip" target="_blank"&gt;second code sample&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;While that walkthrough is specific to the ClientUI sample, all of the principles and many of the techniques are applicable no matter how you build your DevForce application.&lt;/p&gt;  &lt;p&gt;Go ahead … jump ahead of me and read that document. Or you can wait for me to re-cast it here in my blog in a few days. Either way, you can’t lose.&lt;/p&gt;  &lt;p&gt;Happy holidays!&lt;/p&gt; &lt;p&gt;Update: Checkout the related post in which I answer an email about &lt;a href="http://neverindoubtnet.blogspot.com/2011/02/nested-sandboxes-editors.html"&gt;nested sandbox editors&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-5382356319364173791?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/5382356319364173791/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=5382356319364173791' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5382356319364173791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5382356319364173791'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/12/sandbox-editors-with-clientui-contacts.html' title='“Sandbox” Editors with ClientUI Contacts'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_iOCgrkgC3Tk/TQwExE3SqBI/AAAAAAAAAGM/49d-lZlmcVI/s72-c/image_thumb%5B1%5D.png?imgmax=800' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-9034345742580295724</id><published>2010-12-05T10:37:00.001-08:00</published><updated>2010-12-09T19:34:26.012-08:00</updated><title type='text'>Design with Database Data in DevForce</title><content type='html'>&lt;p&gt;Recently I’ve migrated John Papa’s BookShelf (aka BookClub) example to DevForce. &lt;a href="http://www.ideablade.com/BookShelfDF/BookShelfDF.zip"&gt;Download the DevForce version (BookShelfDF) from our web site&lt;/a&gt;. You can learn about John’s original version and get his code from the PDC 2010 web &lt;a href="http://player.microsoftpdc.com/Session/76864d75-b4da-4858-aac7-786c5f28e344"&gt;page&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TPvbyTOAjII/AAAAAAAAAFY/qlmJBfYVQgE/s1600-h/clip_image002%5B4%5D.jpg"&gt;&lt;img style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-LEFT: 0px; WIDTH: 337px; PADDING-RIGHT: 0px; DISPLAY: inline; HEIGHT: 215px; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://lh5.ggpht.com/_iOCgrkgC3Tk/TPvbyppr_nI/AAAAAAAAAFc/VHdQG_CghKU/clip_image002_thumb%5B1%5D.jpg?imgmax=800" width="271" height="168" /&gt;&lt;/a&gt; &lt;br clear="all"&gt;&lt;br clear="all"&gt;The DevForce BookShelfDF includes a document describing the steps for migrating from RIA Services to DevForce and proceeds to describe the improvements that DevForce made possible. Among them is the ability to create design-time entities for display while developing your Views in visual design tools such as Blend and the Visual Studio designer (“Cider”). This post is a reprint of that section of the document.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Warning: this is a long-ish post.&lt;/strong&gt;&lt;/p&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;hr /&gt;&lt;br /&gt;&lt;p&gt;One way DevForce supports offline scenarios is by making it easy to extract, serialize, and store an EntityManager’s entity cache in a local file. That’s a great way to keep entities – even changed entities – available to an application that must operate offline. &lt;/p&gt;&lt;p&gt;Imagine walking into a customer’s office, prepared to review contracts, previous orders, pending orders, and everything necessary to secure the next big deal. You won’t be plugging into the customer’s network. You may be unable to establish a WiFi or mobile internet connection. But your DevForce-based Silverlight application continues to run with all of the data it needs because you stored a snapshot in isolated storage. You can take the new order and save that to isolated storage as well. You later save the new order to the server when you’ve re-established your connection.&lt;/p&gt;&lt;p&gt;We can use a similar approach using this same technology to support View development with visual design tools such as Blend.&lt;/p&gt;&lt;p&gt;You’ll produce better Views more quickly when you design them in Blend with representative data. Unfortunately, you cannot obtain representative data directly from the database because you cannot make a network connection (even within your development box) within the visual design tools. That’s why the BookShelf uses “Design Models” that create entities in code, on the fly, to populate the repository … and ultimately the ViewModel … when you’re working in Blend.&lt;/p&gt;&lt;p&gt;Writing a few design-entity creation classes as we do in the “DesignModels” folder is easy and it’s a highly recommended approach, especially in the early going before you have a database. &lt;/p&gt;&lt;p&gt;But, as your model grows, you may decide that the number of design creation classes has gotten out of hand. They’ve become yet another burden of classes to maintain. Meanwhile, you have a development database stocked with records that you display and manipulate during dry runs and smoke tests. Can they double as design entities? Yes they can. Follow these two steps:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Create a “data loader” that reads database entities and emits a file of serialized entities&lt;/li&gt;&lt;li&gt;Run the loader to create the file&lt;/li&gt;&lt;li&gt;When working with views inside visual design tools, read and reconstitute this file as design time entities and show them on screen.&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;Create the Data Loader&lt;/h2&gt;&lt;p&gt;The “Data Loader” is a &lt;b&gt;console application&lt;/b&gt; that loads selected entities into an EntityManager from the database using a synchronous, 2-tier DevForce client and then saves the manager’s cache (an &lt;b&gt;EntityCacheState&lt;/b&gt; or “&lt;b&gt;ECS&lt;/b&gt;”) to a local file in the project.&lt;/p&gt;&lt;p&gt;The downloaded example has completed project called “BookShelf.DataLoader”. The ECS file (about about 25KB) is named “DesignCacheState.dat”. It belongs to the project but has a “Build Action” of “None” which means it is not included in the assembly. &lt;/p&gt;&lt;p&gt;The primary steps to building it were:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Add a full .NET 4 Console Application project called “BookShelf.DataLoader”. &lt;/li&gt;&lt;li&gt;Add to the project a new text file called “DesignCacheState.txt”&lt;/li&gt;&lt;li&gt;Rename its extension to “.dat”&lt;/li&gt;&lt;li&gt;Open its property window and set its “Build Action” to “None”&lt;/li&gt;&lt;li&gt;Add references&lt;/li&gt;&lt;li&gt;Create an “app.config” file to tell DevForce how to find the database&lt;/li&gt;&lt;li&gt;Add a DataLoader class to do the work&lt;/li&gt;&lt;li&gt;Call the DataLoader in the &lt;b&gt;Main&lt;/b&gt; routine of the Program.cs &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Steps #5, #6, and #7 invite commentary.&lt;/p&gt;&lt;h5&gt;References&lt;/h5&gt;&lt;p&gt;The “data loader” needs references to&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The domain model which is defined in the web project in this example&lt;/li&gt;&lt;li&gt;IdeaBlade DevForce libraries&lt;/li&gt;&lt;li&gt;Two supporting .NET libraries.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The added references are highlighted as shown:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_iOCgrkgC3Tk/TPvby4ekygI/AAAAAAAAAFg/s8Dt5ZbufII/s1600-h/image%5B2%5D.png"&gt;&lt;img style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_iOCgrkgC3Tk/TPvbzW9aj5I/AAAAAAAAAFk/fe-XSa_fJK4/image_thumb.png?imgmax=800" width="244" height="240" /&gt;&lt;/a&gt; &lt;br clear="all"&gt;Remember to set the IdeaBlade library property “Specific Version” to “False” as we have elsewhere.&lt;/p&gt;&lt;h3&gt;App.config&lt;/h3&gt;&lt;p&gt;The console application runs as a 2-tier, “client/server” application which means the EntityManager in the console application (the client) will make direct contact with the database (the server).&lt;/p&gt;&lt;p&gt;This DevForce client has to know the Entity Framework connection string so that Entity Framework can find its schema files and connect with the database. DevForce looks for this information in the console application’s “app.config” file.&lt;/p&gt;&lt;p&gt;Only the &amp;lt;connectionStrings&amp;gt; element is needed and this we copy from the BookShelf.Web project’s “Web.config” file.&lt;/p&gt;&lt;p&gt;The shipped BookShelf package is configured to access the BookShelf database, located in the BookShelf.Web project’s “App_Data” directory, using SQL Server Express. Therefore, the app.config looks like this (after some reformatting and chopping):&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;div style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; WIDTH: 100%; PADDING-RIGHT: 0px; DIRECTION: ltr; BORDER-TOP-STYLE: none; BACKGROUND-: 0pxcolor:#f4f4f4;" id="codeSnippet" &gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;span style="color:#006080;"&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;/span&gt;&lt;span style="color:#006080;"&gt;&lt;!--CRLF--&gt;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;span style="color:#006080;"&gt;&lt;!--CRLF--&gt;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;div id="codeSnippetWrapper"&gt;&lt;div style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id="codeSnippet"&gt;&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:83f6a032-268a-4a0e-a977-57ee06272e73" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: xml;gutter:false;"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;  &amp;lt;connectionStrings&amp;gt;&lt;br /&gt;    &amp;lt;!-- SQL Server Connection String --&amp;gt;&lt;br /&gt;    &amp;lt;!--&amp;lt;add name="BookClubEntities" connectionString="metadata=res://*/Models.BookClubMo&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- SQL Server EXPRESS Connection String from BookShelf.Web/Web.config --&amp;gt;&lt;br /&gt;    &amp;lt;add name="BookClubEntities"&lt;br /&gt;         connectionString="metadata=res://*/Models.BookClubModel.csdl ...&lt;br /&gt;         provider connection string=&amp;amp;quot;Data Source=.\SQLEXPRESS;&lt;br /&gt;         AttachDbFilename=DataDirectory\BookClub.mdf;&lt;br /&gt;         Integrated Security=True;User Instance=True;MultipleActiveResultSets=True&amp;amp;quot;"&lt;br /&gt;         providerName="System.Data.EntityClient" /&amp;gt;&lt;br /&gt;  &amp;lt;/connectionStrings&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;span style="color:#006080;"&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;/span&gt;&lt;span style="color:#006080;"&gt;&lt;!--CRLF--&gt;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;span style="color:#006080;"&gt;&lt;!--CRLF--&gt;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The “DataDirectory” token is a wrinkle dealt with in the DataLoader.&lt;/p&gt;&lt;p&gt;The string refers to the application development database, the source for data while running the application as a developer and soon to be the source for design time data as well. Clearly the string for the production database would be something else in the production Web.config.&lt;/p&gt;&lt;h3&gt;DataLoader Class&lt;/h3&gt;&lt;p&gt;The “DataLoader” console application is a developer utility. It will never be deployed. Simplicity is the watchword; efficiency, robustness, and architecture are irrelevant.&lt;/p&gt;&lt;p&gt;The DataLoader has a single method, &lt;b&gt;Load&lt;/b&gt;, which is called by the static &lt;b&gt;Main&lt;/b&gt; in Program.cs:&lt;/p&gt;&lt;p&gt;&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:3dbf8b9f-317e-4146-b7eb-50b32da23460" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: c#;"&gt;public void Load()&lt;br /&gt; {&lt;br /&gt;     SetDataDirectory();&lt;br /&gt;     var context = new BookClubEntities();&lt;br /&gt;&lt;br /&gt;     // Get all categories, then hold onto the first one&lt;br /&gt;     var cat1 = context.Categories.ToList().First();&lt;br /&gt;     Console.WriteLine("Loaded categories including " + cat1.CategoryName);&lt;br /&gt;&lt;br /&gt;     // Get a subset of books belonging to the first category&lt;br /&gt;     var books = context.Books.Take(9)&lt;br /&gt;         .Where(b =&amp;gt; b.CategoryID == cat1.CategoryID)&lt;br /&gt;         .ToList();&lt;br /&gt;&lt;br /&gt;     // Customizing the design data&lt;br /&gt;     var firstBook = books.First();&lt;br /&gt;     firstBook.Title = "Developers in Wonderland";&lt;br /&gt;     firstBook.EntityAspect.AcceptChanges();&lt;br /&gt;&lt;br /&gt;     Console.WriteLine("Loaded books including " + firstBook.Title);&lt;br /&gt;&lt;br /&gt;     var bods = context.BookOfDays.Include(b =&amp;gt; b.Book).ToList();&lt;br /&gt;     Console.WriteLine("Loaded Book-of-the-days including " +&lt;br /&gt;                       bods.First().Book.Title);&lt;br /&gt;&lt;br /&gt;     var cos = context.Checkouts.Include(c =&amp;gt; c.Book).ToList();&lt;br /&gt;     Console.WriteLine("Loaded checkouts including " + cos.First().Book.Title);&lt;br /&gt;&lt;br /&gt;     context.CacheStateManager.SaveCacheState("../../"+DesignCacheStateFile);&lt;br /&gt;     Console.WriteLine("Save design-time ECS as file, "+DesignCacheStateFile);&lt;br /&gt; }&lt;/pre&gt;&lt;/div&gt;The “DataLoader” creates a BookShelf EntityManager (BookShelfEntities), queries selected entities from the development database, tweaks them, and writes the entity cache to file. &lt;p&gt;The console application executes four &lt;b&gt;&lt;i&gt;synchronous&lt;/i&gt;&lt;/b&gt; queries, something a Silverlight application can’t do.&lt;/p&gt;&lt;p&gt;The query results are often typically discarded; we only want the side-effect of filling the entity cache. But the loader can do more than just retrieve database entities. It can add and modify entities programmatically (see the updated title of “firstBook”) to suit specific design needs before writing the cache to file.&lt;/p&gt;&lt;h4&gt;Saving the ECS to file&lt;/h4&gt;&lt;p&gt;It takes just one line to both extract the EntityCacheState and write it to file:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;context.CacheStateManager.SaveCacheState("../../"+DesignCacheStateFile);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The “DesignCacheStateFile” is the name of the text file added to our project earlier. The “SaveCacheState” method would write to the executable directory which is two levels deeper (bin/Debug); the “../../” prefix backs up to the project directory level and overwrites the initial text file. Subsequent re-executions of the loader will overwrite previous versions of the file.&lt;/p&gt;&lt;h4&gt;SetDataDirectory&lt;/h4&gt;&lt;p&gt;The app.config holds the connection string to the database. This sample app assumes SQL Server Express and ships with a database in the web project; the given connection string instructs SQL Server Express to attach that database dynamically and locates the database symbolically:&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;AttachDbFilename=DataDirectory\BookClub.mdf;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The “DataDirectory” is a token which is replaced at runtime with the full file location. If we were in the web project, that location would be something like&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;C:\Users\Ward\Documents\Visual Studio 2010\Projects\&lt;br /&gt;Samples\BookShelf\BookShelfDF\BookShelf.Web\App_Data&lt;/span&gt;&lt;/p&gt;&lt;p&gt;That address changes as you move the solution around on your development machine. The “DataDirectory” token accounts for those shifts, leaving the relative part (“\BookClub.mdf”) undisturbed.&lt;/p&gt;&lt;p&gt;Unfortunately, the “DataDirectory” token is null in this DataLoader project. If we do nothing, the console application won’t be able to find the SQL Server Express database and will fail with a helpful error.&lt;/p&gt;&lt;p&gt;The SetDataDirectory method, called at the top of the Load method, determines the file location dynamically and sets the “DataDirectory” token accordingly. See the code for details.&lt;/p&gt;&lt;h3&gt;Run The DataLoader&lt;/h3&gt;&lt;p&gt;The DataLoader is a utility that you’ll run infrequently compared to running the application or its test. A simple way to run it:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Right-click the project file in the Visual Studio “Solution Explorer” window&lt;/li&gt;&lt;li&gt;Select “Debug Start new instance”&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The console window shows the loader in action&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_iOCgrkgC3Tk/TPvg_Ha3VfI/AAAAAAAAAFo/iyDxVOyTpik/s1600-h/image%5B7%5D.png"&gt;&lt;img style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-LEFT: 0px; WIDTH: 472px; PADDING-RIGHT: 0px; DISPLAY: inline; HEIGHT: 240px; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" title="image" border="0" alt="image" src="http://lh5.ggpht.com/_iOCgrkgC3Tk/TPvg_QQYz0I/AAAAAAAAAFs/s4CUW0fasY0/image_thumb%5B3%5D.png?imgmax=800" width="348" height="172" /&gt;&lt;/a&gt;&lt;br clear="all"&gt;Visual Studio doesn’t detect the changes to the ECS resource file and won’t know to rebuild the Silverlight application project on its own. You must manually rebuild the Silverlight BookShelf application whenever you run the Data Loader. &lt;/p&gt;&lt;p&gt;The serialized ECS is a product of a specific data model and DevForce version. Changing the model or upgrading DevForce could make the ECS file unreadable. Such vulnerability to change is a minor drawback of the ECS approach.&lt;/p&gt;&lt;h2&gt;Use the ECS File for Design-time Entities&lt;/h2&gt;&lt;p&gt;The third (and final) step is to retrieve design-time entities from the ECS file while in visual design tools. Please turn your attention to the BookShelf project.&lt;/p&gt;&lt;h4&gt;Review the DesignModels folder&lt;/h4&gt;&lt;p&gt;The “DesignModels” folder holds the classes that generate collections of entities for View development in visual design tools such as Blend. We’ll replace these design entity sources with the ECS file. We could delete this folder and its contents but we won’t because it’s useful, in a sample application, to show two reasonable ways to achieve this purpose.&lt;/p&gt;&lt;h4&gt;Add a linked ECS file as a Resource&lt;/h4&gt;&lt;p&gt;The Silverlight application needs access to the ECS file when open in Blend. We link to it much as we linked earlier to the generated entity class file to get a Silverlight version of the domain model in the web project.&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Select the DesignServices folder in the “Solution Explorer” window&lt;/li&gt;&lt;li&gt;Pick “Add Existing item” (Shift – Alt – A)&lt;/li&gt;&lt;li&gt;Navigate to the BookShelf.DataLoader project&lt;/li&gt;&lt;li&gt;Select the ECS file, “DesignCacheState.dat”&lt;/li&gt;&lt;li&gt;Click the drop-down arrow next to the “Add” button&lt;/li&gt;&lt;li&gt;Click “Add As Link”&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_iOCgrkgC3Tk/TPvg_5X3HBI/AAAAAAAAAFw/tdp0dE6-2-g/s1600-h/image%5B10%5D.png"&gt;&lt;img style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 0px; PADDING-LEFT: 0px; WIDTH: 287px; PADDING-RIGHT: 0px; DISPLAY: inline; HEIGHT: 135px; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" title="image" border="0" alt="image" src="http://lh3.ggpht.com/_iOCgrkgC3Tk/TPvhAA-v_rI/AAAAAAAAAF0/_eXOgsvbkVY/image_thumb%5B4%5D.png?imgmax=800" width="244" height="107" /&gt;&lt;/a&gt;&lt;br clear="all"&gt;A shortcut to that file appears among the members of the DesingServices folder:&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TPvhAVp89FI/AAAAAAAAAF4/KOrP7zohvQ8/s1600-h/image%5B13%5D.png"&gt;&lt;img style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" title="image" border="0" alt="image" src="http://lh4.ggpht.com/_iOCgrkgC3Tk/TPvhAy4J_XI/AAAAAAAAAF8/4Iy8gcs_ZvE/image_thumb%5B5%5D.png?imgmax=800" width="244" height="100" /&gt;&lt;/a&gt;&lt;br clear="all"&gt;Set the linked file’s “Build Action” to “Resource”.&lt;/p&gt;&lt;h4&gt;Revise the DesignEntityManagerProvider&lt;/h4&gt;&lt;p&gt;The design entities we see in Blend are created within the &lt;b&gt;DesignEntityManagerProvider&lt;/b&gt; located in the &lt;b&gt;DesignServices&lt;/b&gt; folder.&lt;/p&gt;&lt;p&gt;This provider, when it created entities from Design Model classes, looked like this:&lt;/p&gt;&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:1d371d0f-aa51-4859-84a9-64e6acefc809" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: c#;"&gt; public class DesignEntityManagerProvider : IEntityManagerProvider&lt;br /&gt; {&lt;br /&gt;     public BookClubEntities CreateManager()&lt;br /&gt;     {&lt;br /&gt;         var context = new BookClubEntities(false /* offline mode */);&lt;br /&gt;&lt;br /&gt;         // Populate cache with design data&lt;br /&gt;         PopulateFromDesignModels(context);&lt;br /&gt;&lt;br /&gt;         return context;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     /// &amp;lt;summary&amp;gt;&lt;br /&gt;     /// Populate the manager from design-time entities created by code.&lt;br /&gt;     /// &amp;lt;/summary&amp;gt;&lt;br /&gt;     private static void PopulateFromDesignModels(EntityManager context)&lt;br /&gt;     {&lt;br /&gt;         context.AttachEntities(new DesignCategories());&lt;br /&gt;         context.AttachEntities(new DesignBooks());&lt;br /&gt;         context.AttachEntities(new DesignCheckouts());&lt;br /&gt;         context.AttachEntity(new BookOfDay&lt;br /&gt;                              {&lt;br /&gt;                                  Day = DateTime.Today,&lt;br /&gt;                                  Book = DesignBooks.ExampleBook,&lt;br /&gt;                              });&lt;br /&gt;     }&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It created the BookShelf’s EntityManager (BookShelfEntities) and attached design-time entities to that manager – entities created in code.&lt;/p&gt;&lt;p&gt;Comment out the call to that method and add a call to a new method, &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;&lt;span style="color:#408080;"&gt;// Populate cache with design data&lt;br /&gt;// PopulateFromDesignModels(context);&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size:100%;"&gt;PopulateFromEntityCacheState(context)&lt;/span&gt;&lt;/b&gt;&lt;span style="font-size:100%;"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The “populator” that draws upon the ECS file takes a tad more work to set up.&lt;/p&gt;&lt;p&gt;It might not seem worthwhile in an application this size although it’s easy to forget the combined 100+ lines in the three Design Model classes. The ECS file approach really pays off when the application model has more than four entity types and the relationships among the entities are numerous and complex. &lt;/p&gt;&lt;p&gt;The ECS populator seen here remains the same whether the model is four entities or 400 entities. It proceeds in three stages:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Tell DevForce where to find the assembly with the BookShelf model in the static constructor.&lt;/li&gt;&lt;li&gt;Create an in-memory EntityCacheState object from the ECS file.&lt;/li&gt;&lt;li&gt;Populate the design-time EntityManager from the in-memory EntityCacheState object.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:f32c3428-b7e9-4f15-a8ea-c502c7ff2e88:05cf0152-a13a-49df-8446-243c37c8239f" class="wlWriterEditableSmartContent"&gt;&lt;pre class="brush: c#;"&gt;static DesignEntityManagerProvider()&lt;br /&gt;{&lt;br /&gt;    // Register the model's assembly name among probed assemblies&lt;br /&gt;    // Must be called BEFORE the first EM creation else&lt;br /&gt;    // GetDesignEntityCacheState fails w/ deserialization exception&lt;br /&gt;    IdeaBlade.Core.IdeaBladeConfig.Instance.ProbeAssemblyNames&lt;br /&gt;        .Add(typeof(BookClubEntities).Assembly.FullName);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Get the design-time &amp;lt;see cref="EntityCacheState"/&amp;gt; from resource file&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;private static EntityCacheState GetDesignEntityCacheState()&lt;br /&gt;{&lt;br /&gt;    const string filename =&lt;br /&gt;                   @"/BookShelf;component/DesignServices/DesignCacheState.dat";&lt;br /&gt;&lt;br /&gt;    var res = Application.GetResourceStream(new Uri(filename, UriKind.Relative));&lt;br /&gt;    return _designEntityCacheState = EntityCacheState.Restore(res.Stream);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static EntityCacheState _designEntityCacheState;&lt;br /&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Populate the manager from design-time entities held in&lt;br /&gt;/// an in-memory &amp;lt;see cref="EntityCacheState"/&amp;gt;.&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;private static void PopulateFromEntityCacheState(EntityManager context)&lt;br /&gt;{&lt;br /&gt;    var ecs = _designEntityCacheState ?? GetDesignEntityCacheState();&lt;br /&gt;    context.CacheStateManager.RestoreCacheState(ecs, RestoreStrategy.Normal);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here’s the BookView as seen in Blend, showing the design data sourced from the ECS file&lt;/p&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_iOCgrkgC3Tk/TPvhBB3_egI/AAAAAAAAAGA/exrkMSG2BI0/s1600-h/image%5B19%5D.png"&gt;&lt;img style="BACKGROUND-IMAGE: none; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; PADDING-LEFT: 0px; WIDTH: 561px; PADDING-RIGHT: 0px; DISPLAY: inline; HEIGHT: 303px; BORDER-TOP: 0px; BORDER-RIGHT: 0px; PADDING-TOP: 0px" title="image" border="0" alt="image" src="http://lh6.ggpht.com/_iOCgrkgC3Tk/TPvhBnDUTgI/AAAAAAAAAGE/gdsRUlG3FKk/image_thumb%5B9%5D.png?imgmax=800" width="538" height="285" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;p&gt;Hope you found this discussion illuminating. Happy Coding!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-9034345742580295724?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/9034345742580295724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=9034345742580295724' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/9034345742580295724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/9034345742580295724'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/12/design-with-database-data-in-devforce.html' title='Design with Database Data in DevForce'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_iOCgrkgC3Tk/TPvbyppr_nI/AAAAAAAAAFc/VHdQG_CghKU/s72-c/clip_image002_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-7126661312298699429</id><published>2010-11-22T21:25:00.001-08:00</published><updated>2010-12-17T16:22:21.497-08:00</updated><title type='text'>ClientUI Sample: MVVM for WPF &amp; Silverlight</title><content type='html'>&lt;p&gt;We just published &lt;a href="http://links.ideablade.com/drc-clientui.devforce" target="_blank"&gt;a new sample application&lt;/a&gt; in partnership with &lt;a href="http://www.intersoftpt.com/" target="_blank"&gt;Intersoft Solutions&lt;/a&gt;. Here’s what excites me about it:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Two solutions, in WPF and Silverlight, share the same source code and XAML &lt;/li&gt;&lt;li&gt;Demonstrates MVVM and Repository patterns &lt;/li&gt;&lt;li&gt;The views are Blendable and rely on design data delivered by ViewModels &lt;/li&gt;&lt;li&gt;It looks great &lt;/li&gt;&lt;li&gt;It’s concise and easy to read &lt;/li&gt;&lt;li&gt;Includes a fifty page walkthrough that explains how it is put together and why &lt;/li&gt;&lt;li&gt;A terrific mash-up of DevForce and some great Intersoft UI controls &lt;/li&gt;&lt;/ul&gt;&lt;p style="FONT-SIZE: 12pt; FONT-WEIGHT: bold"&gt;&lt;a href="http://links.ideablade.com/drc-clientui.devforce" target="_blank"&gt;Learn more&lt;/a&gt; about our evolving series of joint samples.&lt;/p&gt;&lt;p  style="FONT-SIZE: 12pt; FONT-WEIGHT: bold"&gt;&lt;a href="http://www.ideablade.com/ClientUISample/ClientUI_DevForceIntegration_v1.zip"&gt;Download the code&lt;/a&gt;&lt;/p&gt;&lt;p style="FONT-SIZE: 12pt; FONT-WEIGHT: bold"&gt;&lt;a href="http://intersoftpt.wordpress.com/2010/11/23/extending-contacts-application-silverlight-wpf-with-devforce-2010/" target="_blank"&gt;See what Jimmy Petrus of Intersoft says about it&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The Intersoft “ClientUI Sample” was the inspiration. It’s a lovely demo of a Forms-Over-Data application – a “Contact Editor” built with Intersoft controls. The UI presents two views: one lists all Contacts; the second is an overlay dialog for editing the currently selected contact and address. A “contact” is a person with an address. &lt;/p&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_iOCgrkgC3Tk/TOtQLSkxCKI/AAAAAAAAAFI/7ujY-mk-Qvc/s1600-h/ClientUIMainView5.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="ClientUIMainView" border="0" alt="ClientUIMainView" src="http://lh6.ggpht.com/_iOCgrkgC3Tk/TOtQLzcPv4I/AAAAAAAAAFM/KKZXmpGQOUY/ClientUIMainView_thumb3.png?imgmax=800" width="307" height="181" /&gt;&lt;/a&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TOtQMQDEM7I/AAAAAAAAAFQ/s_wDwXE7Qyg/s1600-h/ClientUIEditorView5.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" title="ClientUIEditorView" border="0" alt="ClientUIEditorView" src="http://lh4.ggpht.com/_iOCgrkgC3Tk/TOtQM_tZ_GI/AAAAAAAAAFU/sYp5pcly1Mc/ClientUIEditorView_thumb3.png?imgmax=800" width="247" height="165" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;The application appears and behaves the same in both WPF and Silverlight flavors. Intersoft’s APIs are identical for both WPF and Silverlight. They built both versions of the sample using the same code and xaml files, no changes required. They simply compiled separately against the WPF and Silverlight libraries. We thought that was pretty neat (and no mean feat).&lt;/p&gt;&lt;p&gt;Our two companies teamed-up to extend Intersoft’s “UI-only” sample with a DevForce entity model and our distributed persistence components so the editor could retrieve and save data from a database.&lt;/p&gt;&lt;p&gt;The DevForce APIs are the same for all .NET client platforms (ASP.NET, Windows Forms, WPF, Silverlight). As with Intersoft products, you write it once compile for the target libraries.&lt;/p&gt;&lt;p&gt;After integration with DevForce, the ClientUI sample became an end-to-end Contact editor that can save … delivered in WPF and Silverlight, built on a single code base.&lt;/p&gt;&lt;p&gt;Intersoft’s original ClientUI sample followed an MVVM design. That made our DevForce integration job easy. We hardly touched the views. We replaced the original, hand-coded model with a DevForce generated model that can exchange data with a database over the internet. We introduced a Repository and EntityManagerFactory, massaged the ViewModels, added a dash of configuration … and voila!&lt;/p&gt;&lt;p&gt;The conversion process is covered in detail - with digressions on patterns used and design choices -  in a fifty page PDF that is part of the downloaded zip file.&lt;/p&gt;&lt;p&gt;We have &lt;em&gt;our&lt;/em&gt; ideas for future development. We’ll surely demonstrate how to “sandbox” the editing dialog so that changes propagate to the main view only after they are saved. I’d like to add automated testing and maybe we’ll dare to use an IoC container. I’m sure you’ll tell us what you’d like to see.&lt;/p&gt;&lt;p&gt;Enjoy! &lt;/p&gt;&lt;h3&gt;Prerequisites&lt;/h3&gt;&lt;p&gt;The sample assumes you’ve installed IdeaBlade’s DevForce (6.0.7 or later, &lt;a href="http://links.ideablade.com/free" target="_blank"&gt;free version&lt;/a&gt; is fine) and Intersoft’s “ClientUI 2010” (v3.0.5000.11 or later, trial version is fine).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-7126661312298699429?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/7126661312298699429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=7126661312298699429' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7126661312298699429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7126661312298699429'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/11/clientui-sample-mvvm-for-wpf.html' title='ClientUI Sample: MVVM for WPF &amp;amp; Silverlight'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_iOCgrkgC3Tk/TOtQLzcPv4I/AAAAAAAAAFM/KKZXmpGQOUY/s72-c/ClientUIMainView_thumb3.png?imgmax=800' height='72' width='72'/><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-2652501253151892320</id><published>2010-11-12T16:38:00.001-08:00</published><updated>2010-11-12T16:38:44.645-08:00</updated><title type='text'>Silverlight Firestarter: See what’s coming</title><content type='html'>&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TN3eDMyjyCI/AAAAAAAAAFA/xjKZvoQY39g/s1600-h/headline%5B4%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="headline" border="0" alt="headline" src="http://lh6.ggpht.com/_iOCgrkgC3Tk/TN3eEY97-UI/AAAAAAAAAFE/OREelBKr4yo/headline_thumb%5B2%5D.jpg?imgmax=800" width="447" height="190" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Want to know what Silverlight is all about and what’s coming in Silverlight vNext? Reserve a few hours on Thursday 12/2 for a free seminar from the folks that know: the Microsoft Silverlight team and friends. &lt;/p&gt;  &lt;p&gt;You can catch it all online or be there in person and meet some wonderful people.&lt;/p&gt;  &lt;p&gt;What part of “Free” do you not understand? Go register: &lt;a href="http://jpapa.me/slfs10"&gt;http://jpapa.me/slfs10&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;P.S.: I’ll be there in person. Look me up.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-2652501253151892320?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/2652501253151892320/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=2652501253151892320' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2652501253151892320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2652501253151892320'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/11/silverlight-firestarter-see-whats.html' title='Silverlight Firestarter: See what’s coming'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_iOCgrkgC3Tk/TN3eEY97-UI/AAAAAAAAAFE/OREelBKr4yo/s72-c/headline_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-5702595119845427356</id><published>2010-11-10T11:29:00.001-08:00</published><updated>2010-11-10T12:05:38.325-08:00</updated><title type='text'>Silverlight’s Bright Future</title><content type='html'>&lt;p&gt;“&lt;b&gt;&lt;i&gt;Our strategy has shifted&lt;/i&gt;&lt;/b&gt;” may be the most unfortunate phrase ever uttered by a Microsoft exec. Bob Muglia, President of the Server and Tools Division, said it in his &lt;a href="http://www.zdnet.com/blog/microsoft/microsoft-our-strategy-with-silverlight-has-shifted/7834?tag=mantle_skin;content"&gt;interview with Mary Jo Foley&lt;/a&gt;. Pundits and Silverlight detractors have been partying on it for more than a week. &lt;/p&gt;  &lt;p&gt;It should just be good theater. Unfortunately, it has spooked the herd. More than a few of our customers and prospects are wondering if Silverlight is “dead”.&lt;/p&gt;  &lt;p&gt;Some Silverlight defenders counter by reminding us that HTML 5 is not ready and runs on less than 1% of installed browsers.&lt;/p&gt;  &lt;p&gt;But the merits and demerits of HTML 5 are beside the point. If you’re considering building in Silverlight, you have to know that Silverlight itself has a future. You don’t care about Silverlight 5. You want to know there will be a Silverlight 10. You want to believe that Microsoft sees Silverlight as a strategic, mainstream web development platform.&lt;/p&gt;  &lt;p&gt;I believe Microsoft sees Silverlight as a strategic, mainstream web development platform … &lt;strong&gt;&lt;em&gt;for many years to come&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Don’t take it &lt;i&gt;on my authority&lt;/i&gt;; I don’t have any authority. Believe Bob Muglia when he &lt;a href="http://team.silverlight.net/announcement/pdc-and-silverlight/"&gt;sets the record straight&lt;/a&gt;. If I may paraphrase, Bob said Microsoft is investing heavily in HTML 5 because that is the standards-based technology with the potential for the broadest possible reach. Investment in HTML 5 does not mean abandoning Silverlight. It’s not a retreat from Silverlight. Far from it. Silverlight thrives … on the web, on the desktop, and on the phone.&lt;/p&gt;  &lt;p&gt;Bob simply acknowledged that Microsoft will vigorously pursue multiple web technologies to meet diverse market needs.&lt;/p&gt;  &lt;h3&gt;Where is IdeaBlade going?&lt;/h3&gt;  &lt;p&gt;It’s IdeaBlade’s mission to help business application developers reach their users wherever they are, using whatever technology they want to use. Our DevForce product drives Console applications, “headless” services, Windows Forms, WPF, Silverlight, and HTML applications written with Web Forms and MVC.&amp;#160; Next month we’ll release our support for an OData API that enables any client … including any phone … to access your DevForce business model.&amp;#160; When there is a way to write applications in HTML 5, we’ll be there too.&lt;/p&gt;  &lt;p&gt;We are always balancing our portfolio of client technologies. But to be clear, we believe Silverlight is now – and will remain for the foreseeable future – the best way to build and deliver business applications to the web. Bob Muglia said it too: “Silverlight provides the richest way to build Web-delivered client apps”, especially “enterprise application[s] … both inside and outside the browser.”&lt;/p&gt;  &lt;p&gt;No HTML technology today can match Silverlight in capability or productivity for the web application developer. A comparable HTML 5 platform&lt;em&gt; by all accounts&lt;/em&gt; is years away.&lt;/p&gt;  &lt;h3&gt;What’s all the Fuss?&lt;/h3&gt;  &lt;p&gt;The story at last year’s PDC was “three screens and a cloud” glued together by Silverlight. Barely a year later they’re ballyhooing HTML 5 as the glue. A third of the keynote goes to IE 9 and HTML 5; Silverlight is hardly mentioned. Then Bob says “&lt;em&gt;strategic shift&lt;/em&gt;” and the stuff hits the fan.&lt;/p&gt;  &lt;p&gt;What we have here is a &lt;a href="http://www.youtube.com/watch?v=SnO9Jyz82Ps"&gt;failure to communicate&lt;/a&gt;. Microsoft evangelizes the shiny new balls but seems less adept at the sustained marketing necessary to keep existing brands burning bright – xBox excepted. The Silverlight team is going great guns on Silverlight vNext development back in Redmond but you would not know that at PDC and there is still no public target for a putative Silverlight 5 release. Other consumer-facing corporations invest in their brands, especially successful brands. Even soap is regularly “new and improved.” Microsoft can’t count on product development to keep the brand alive. They should be as relentless on the marketing front.&lt;/p&gt;  &lt;p&gt;They tried mightily to recover the Silverlight momentum. Muglia apologized (yes – he said “apologize”) for his part in launching the controversy. &lt;a href="http://team.silverlight.net/announcement/pdc-and-silverlight/"&gt;Read his post carefully&lt;/a&gt;; he was adamant that Silverlight is a strategic technology with a long future. When you’re done reading Bob, read &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/11/04/silverlight-questions.aspx"&gt;Scott Guthrie’s&lt;/a&gt; post which reiterates and elaborates on Bob’s themes; Scott is Vice President of the Developer Division and he ought to know.&lt;/p&gt;  &lt;p&gt;Of course they also have to promote HTML 5 in a big way and Silverlight must pay a price for its previously exaggerated ambitions. The truth is that Silverlight will have less reach than we once hoped. It will still be cross-platform – running in many browsers and on both Mac and Windows. But the grand vision of Silverlight on every device on the planet cannot be realized. That was always a tall order and, over the last year, it became obviously unachievable. Apple blocked them successfully on iPhone and iPad … and will continue to do so as long as their market share permits.&lt;/p&gt;  &lt;p&gt;Microsoft must have a future on these devices; they are too important to ignore. And Microsoft also must provide an alternative to Silverlight in other venues where Silverlight is shut out. We all know that some customers prohibit browser plug-ins … which precludes both Silverlight and Flash.&lt;/p&gt;  &lt;p&gt;Silverlight was never the only game in town. You’ve heard about MVC, yes? MVC is an HTML technology and will likely be the backbone of HTML 5 development. Scott Guthrie is as avid a promoter and staunch ally of MVC as he has been of Silverlight. His blog posts for the last few years give each technology equal love.&lt;/p&gt;  &lt;p&gt;MVC did not diminish Scott’s enthusiasm for Silverlight … and neither does the prospect of HTML 5.&lt;/p&gt;  &lt;h3&gt;Silverlight is not just the Phone&lt;/h3&gt;  &lt;p&gt;Reading some of the press, you might fear that Silverlight had been relegated to a phone development platform. They talked a ton about “Silverlight + Phone” at PDC. Silverlight is indeed the preferred platform for the Windows Phone 7; other than XNA it is the &lt;i&gt;only&lt;/i&gt; development platform for WP7. I suspect Muglia was so phone-conscious that, in the interview moment, he just didn’t think of what else we use Silverlight for … hence his unfortunate “&lt;em&gt;other sweet spots&lt;/em&gt;” comment. &lt;/p&gt;  &lt;p&gt;Give him a break. WP7 is the hot new thing. &lt;a href="http://blogs.pcmag.com/miller/2010/10/steve_ballmer_at_gartner_cloud.php"&gt;According to Steve Ballmer&lt;/a&gt;, it’s Microsoft’s next billion dollar product. It’s a big deal and a key theme at PDC. Talking up Silverlight on the phone is called “staying on message”.&lt;/p&gt;  &lt;p&gt;But Silverlight is also the premier client technology in many other spaces. For example, it’s the best way to build applications on top of SharePoint and that process got a lot easier with SharePoint 2010. We saw Silverlight front-ends on Azure. We are seeing Silverlight front-ends on Bing.&lt;/p&gt;  &lt;p&gt;From our perspective, the most important fact: Silverlight remains &lt;b&gt;&lt;i&gt;the recommended client platform for distributed business applications&lt;/i&gt;&lt;/b&gt;, both inside and outside the browser. &lt;a href="http://team.silverlight.net/announcement/pdc-and-silverlight/"&gt;Bob Muglia said it&lt;/a&gt;. &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/11/04/silverlight-questions.aspx"&gt;Scott Guthrie&lt;/a&gt; reiterated it.&lt;/p&gt;  &lt;h3&gt;The FUD Factor&lt;/h3&gt;  &lt;p&gt;Do you think it is curious that some in the technical press and the Silverlight detractors so eagerly cling to Muglia’s one inapt phrase? Why do they misrepresent and dismiss his clarification? Do these people really know something? Do they have secret inside Microsoft skinny? Do they mention unnamed sources? A “deep throat” of some kind?&lt;/p&gt;  &lt;p&gt;No. All they do is read the same tea leaves everyone else is stirring: Muglia’s interview, the IE9 PDC publicity parade, the lack of a big Silverlight announcement … and throw in their own wishful thinking (&lt;a href="http://voices.washingtonpost.com/fasterforward/2010/11/microsoft_still_confused_about.html"&gt;egregious example here&lt;/a&gt;).&lt;/p&gt;  &lt;p&gt;I have no inside scoop either. I’m reading what you’re reading.&lt;/p&gt;  &lt;p&gt;I do have real-world experience developing with Silverlight (question: can you name a “Silverlight is Dead” article by anyone who has written a Silverlight application?)&lt;/p&gt;  &lt;p&gt;I have my Microsoft contacts and I spoke to as many of them as I could reach. Every one of them … without exception and without equivocation … believes passionately that Microsoft is committed to Silverlight. They are dead certain that the Silverlight franchise is growing. They believe that HTML 5 is a big bet too … but that it does not dim Silverlight’s star. And no one expected a “strategic shift” announcement.&lt;/p&gt;  &lt;p&gt;I worked at GE for twelve years. I know what a “strategic shift” looks like. We would never learn of a “strategic shift” by reading a Friday afternoon interview in a trade rag.&amp;#160; GE doesn’t work that way. GE would prepare us for a bombshell like that. The board would know. The senior executives would know. The press kit would be prepared. Company meetings would be scheduled at every level.&lt;/p&gt;  &lt;p&gt;Microsoft is no GE … but it isn’t stupid either. There was no preparation. Muglia’s remarks were a bolt from the blue – as he said himself. There wasn’t supposed to be an announcement. All we have here is an interview by an executive trying to stay on message: Azure, WP7, IE9+HTML5.&lt;/p&gt;  &lt;p&gt;If you’ve ever worked for a business or run a business, you know how this happens: a casual remark to a journalist gets wildly misunderstood and misrepresented. You don’t make a critical decision on this basis. You exercise prudent judgment and listen when company executives correct the record.&lt;/p&gt;  &lt;h3&gt;Well … what of HTML 5?&lt;/h3&gt;  &lt;p&gt;Now I must speak for myself, not IdeaBlade.&lt;/p&gt;  &lt;p&gt;HTML is the way to get the broadest possible reach. HTML 4 is perceived to lack the pizzazz for the new breed of rich internet applications so everyone is pinning hopes on HTML 5. There are some problems with that:&lt;/p&gt;  &lt;p&gt;1. &lt;strong&gt;&lt;em&gt;Near zero reach for the next few years&lt;/em&gt;&lt;/strong&gt;. A tiny fraction of browsers installed today support HTML 5. It takes a long time to replace the installed base of browsers (proof: even Microsoft can’t seem to kill off IE6). Plug-ins (like Silverlight and Flash) have been adopted much more readily than new browsers.&lt;/p&gt;  &lt;p&gt;2. &lt;strong&gt;&lt;em&gt;HTML 5 is not a standard yet&lt;/em&gt;&lt;/strong&gt;. The WC3 doesn’t think it’s ready; see &lt;a href="http://images.infoworld.com/d/developer-world/w3c-hold-html5-in-websites-041?source=rss_developer_world"&gt;here&lt;/a&gt; and &lt;a href="http://www.w3.org/TR/html5/"&gt;here&lt;/a&gt;. The browser wars of the 1990s are coming back and it’s going to be hell for the developers trying to write applications that actually work on all the browsers on all the devices. One wag described HTML 5 as “Write once, test everywhere!”&lt;/p&gt;  &lt;p&gt;3. &lt;strong&gt;&lt;em&gt;The developer story is missing&lt;/em&gt;&lt;/strong&gt;. Applications don’t build themselves. You need libraries and tools to design, develop, debug, and test. None of this infrastructure exists for HTML 5. You need experience and best practices to build an application properly. No one has experience building HTML 5 applications. The essential foundation of human and physical capital is years away. &lt;/p&gt;  &lt;p&gt;4. &lt;strong&gt;&lt;em&gt;HTML 5 sets the lowest common denominator&lt;/em&gt;&lt;/strong&gt; for user experience. The Silverlight team wrote convincingly about this &lt;a href="http://team.silverlight.net/announcement/the-future-of-silverlight/"&gt;in a recent post&lt;/a&gt;. The comparatively low HTML standard and limited capabilities may be good enough for some applications; will it be good enough for yours? Or will it prevent your RIA developers from delivering the rich experience and features that your application requires and that your market demands? &lt;/p&gt;  &lt;p&gt;Ask yourself why your application is not on the web today? If HTML 4 were a viable option, why aren’t you there now? Is it because you can’t affordably deliver the rich responsive experience of your existing application? What is it about HTML 5 that will change that picture? What in HTML 5 will make your application better than it would be in HTML 4? &lt;/p&gt;  &lt;p&gt;Silverlight remains more productive, more testable, more maintainable than any HTML-targeted approach. I can think of other excellent reasons to build an HTML application. But if the balance of considerations favored Silverlight last week, I can’t imagine why the distant prospect of HTML 5 should change the equation today … as long as you believe Silverlight is going to continue to grow and improve … as I clearly do. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-5702595119845427356?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/5702595119845427356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=5702595119845427356' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5702595119845427356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5702595119845427356'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/11/silverlights-bright-future.html' title='Silverlight’s Bright Future'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-6505133927486391255</id><published>2010-09-05T22:39:00.001-07:00</published><updated>2010-09-09T13:50:46.641-07:00</updated><title type='text'>DevForce and RIA Services Compared Part 1: Getting Started</title><content type='html'>&lt;p&gt;Sorry folks. I've temporarily pulled my series of articles comparing WCF RIA Services with IdeaBlade's DevForce while I reconsider the approach. It will be back in another form.&lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;/ol&gt;&lt;ol&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-6505133927486391255?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/6505133927486391255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=6505133927486391255' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6505133927486391255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6505133927486391255'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/09/devforce-and-ria-services-compared-part.html' title='DevForce and RIA Services Compared Part 1: Getting Started'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-1027580281163136060</id><published>2010-09-04T16:35:00.001-07:00</published><updated>2010-09-04T16:39:48.462-07:00</updated><title type='text'>Billy sez: Design, Don’t Decorate</title><content type='html'>&lt;p&gt;&lt;a href="http://www.slmasters.net/#/Home"&gt;Billy Hollis&lt;/a&gt; writes about application UI design in this month’s &lt;a href="http://www.devproconnections.com/article/silverlight/Design-Your-User-Interfaces-Don-t-Just-Decorate-Them.aspx"&gt;DevProConnections&lt;/a&gt; and how that is not the same as hanging new draperies with WPF and Silverlight.&lt;/p&gt;  &lt;p&gt;Here’s what I want you to do:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Go read the article&lt;/li&gt;    &lt;li&gt;Look at the associated video&lt;/li&gt;    &lt;li&gt;Go to his &lt;a href="http://www.slmasters.net/#/Home"&gt;website&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Find yourself a class&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The rest of this post is commentary.&lt;/p&gt;  &lt;p&gt;Most of us (include me among the “us”) are stuck in a rut. We’re bringing to our Silverlight apps the same tired user interactions that we built for WinForms or the Web.&lt;/p&gt;  &lt;p&gt;I’ll make my point with a rant about the Editable Grid.&lt;/p&gt;  &lt;p&gt;I am &lt;em&gt;&lt;strong&gt;sick&lt;/strong&gt;&lt;/em&gt; of the Editable Grid. It won’t die. It pops up in one UI after another.&lt;/p&gt;  &lt;p&gt;It’s not that I’m bored with it. I’m not suffering from ennui. I’m not making a fashion statement.&lt;/p&gt;  &lt;p&gt;It’s just bad. It screams “&lt;strong&gt;&lt;em&gt;&lt;font size="4"&gt;I don’t know what the user wants, I don’t care what the user wants, I’ll just chuck every thing on the screen and let him figure it out.&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt;”&lt;/p&gt;  &lt;p&gt;The user, poor bastard, must scroll through endless columns until he stumbles on the one he wants. Every cell of every row is in the same font size and shade; he can’t visually distinguish the critical values from the &lt;em&gt;who-really-cares&lt;/em&gt; values. Want to tame the scrolling? let’s shrink the font and get more columns on the screen.&lt;/p&gt;  &lt;p&gt;It’s a nightmare to program &lt;strong&gt;&lt;em&gt;properly&lt;/em&gt;&lt;/strong&gt; with unlimited opportunities to screw up and confuse the user at the same time. &lt;/p&gt;  &lt;p&gt;Ah … but it’s so easy to get started, right? A line or two and you’re done. Now you can get back to wondering when the Reactive Framework will be part of the BCL.&lt;/p&gt;  &lt;p&gt;The 3rd party control vendors know you want this atrocity and to differentiate their grids from Microsoft’s DataGrid they trick ‘em out with ever more confusing options (filters, sorters, groupers, frozen columns, tear-aways, column-configuration-savers, etc.). &lt;/p&gt;  &lt;p&gt;All so you can tip-toe past the courageous, hard work of &lt;em&gt;demanding&lt;/em&gt; to know what the user really needs. Nah … just do the cowardly thing, give him every lever and dial imaginable, and tell him to figure it out for himself. Why think, Einstein, when you can make the user do it for you … and perfume the stench by saying “&lt;em&gt;I gave him choices&lt;/em&gt;&amp;quot;.&lt;/p&gt;  &lt;p&gt;Guess what control I use in 9 out of 10 demos? Yup, the editable grid.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;font size="4"&gt;I am as bad as you guys&lt;/font&gt;&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Like you, I’ve been happy as a clam, pasting a grid on page after page. The guy who woke me up … was Billy Hollis.&lt;/p&gt;  &lt;p&gt;Billy is here to remind us it doesn’t have to be that way. Silverlight and WPF have &lt;em&gt;&lt;strong&gt;technically&lt;/strong&gt;&lt;/em&gt; removed the barriers to efficiently writing productive user experiences.&lt;/p&gt;  &lt;p&gt;The problem isn’t the technology. It’s us. We are the problem. We aren’t clearing the cobwebs. We’re behaving like we did at the dawn of GUI interfaces … wondering how to port keystroke menus onto a window.&lt;/p&gt;  &lt;p&gt;Hey … the “Outlook” standard should be dead. It would be dead … if we didn’t grant it new zombie life in WPF.&lt;/p&gt;  &lt;p&gt;Billy is ready to show us how to move on.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="3"&gt;Did you know Billy offers WPF and Silverlight design training?&lt;/font&gt;&lt;/strong&gt; &lt;/p&gt;  &lt;p&gt;Not “Insert-Tab-A-into-Slot-B” training. I mean training your mind and your skills to get out of the rut. Sure you’ll learn WPF/Silverlight – duh. And I’m not knocking that kind of training either; it’s valuable too. &lt;/p&gt;  &lt;p&gt;What I really need is some help seeing UI differently and, most important, acquiring a discovery process to help me develop a UI that supports my user. Maybe … just maybe … I’ll finally learn to build a UI that is thoughtful and usable … and not waste weeks agonizing over my failures.&lt;/p&gt;  &lt;p&gt;It’s up to you. I recommend you hustle over to &lt;a href="http://www.slmasters.net/#/Home"&gt;&lt;strong&gt;&lt;font size="3"&gt;Billy’s website&lt;/font&gt;&lt;/strong&gt;&lt;/a&gt; and see if you can find a way to take one of his classes. That’s what I’m going to do … if they ever let me out of here.&lt;/p&gt;  &lt;p&gt;p.s.: I’m still doing editable grids in my demos. You can lead a horse to water …&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-1027580281163136060?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/1027580281163136060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=1027580281163136060' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1027580281163136060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1027580281163136060'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/09/billy-sez-design-dont-decorate.html' title='Billy sez: Design, Don’t Decorate'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-326992517350207845</id><published>2010-09-04T11:53:00.001-07:00</published><updated>2010-09-04T12:02:14.460-07:00</updated><title type='text'>Is Mvvm Light Right For You?</title><content type='html'>&lt;p&gt;I wrote in “&lt;a href="http://neverindoubtnet.blogspot.com/2010/09/devforce-meets-mvvm-light.html"&gt;DevForce Meets Mvvm Light&lt;/a&gt;” about how easy it is to use these products together on the same application.&lt;/p&gt;  &lt;p&gt;Is “Mvvm Light” the way to go?&lt;/p&gt;  &lt;p&gt;There is no right way to go. You have choices. There is &lt;a href="http://compositewpf.codeplex.com/"&gt;Prism&lt;/a&gt; to consider. I’m a big &lt;a href="http://caliburnmicro.codeplex.com/"&gt;Caliburn.Micro&lt;/a&gt; fan too.&lt;/p&gt;  &lt;p&gt;But those may be a bit daunting for folks just starting down the MVVM road and perhaps you don’t need their sophistication for your application … yet.&lt;/p&gt;  &lt;p&gt;I recently asked Laurent to give me the name of an Mvvm Light expert to help me build an example. That was before I downloaded the product. One look and I had a healthy laugh at myself. You don’t need no stinking expert to use this “framework”. It’s pretty darned obvious.&lt;/p&gt;  &lt;p&gt;It really lives up to its “Light” name. It is truly almost instantly accessible. To be honest, many of the applications our customers build would need more infrastructure than you’ll find in Mvvm Light. He made some choices that are too lightweight for these apps.&lt;/p&gt;  &lt;p&gt;But … and there is always a but … I sense this is a great way to get into the water and it will float you a nice distance before you decide you need something richer (and more obtuse). &lt;/p&gt;  &lt;p&gt;Maybe you’ll never need “more”. I’ll bet that, even if you do, you’ll be able to merge or port your Mvvm Light work straight into whatever framework you ultimately adopt.&lt;/p&gt;  &lt;p&gt;I’ll admit it; I’m a geeky guy with a weakness for unnecessary complexity. The angel on my shoulder says “cut your audience some slack and introduce them to Mvvm Light.”&amp;#160; The devil on my shoulder says “come on … they’re going to need the heavy machinery and you make your living showing off … this Mvvm Light stuff won’t burnish your reputation for arrogant sophistication!”&lt;/p&gt;  &lt;p&gt;Today, I’m listening to the angel. I think. Sometimes I can’t tell which is which. Whatever.&lt;/p&gt;  &lt;p&gt;Here’s some recent praise from other high-profile luminaries who favor Mvvm Light.&lt;/p&gt;  &lt;p&gt;=============================   &lt;br /&gt;From: Billy Hollis    &lt;br /&gt;Sent: Friday, September 03, 2010 7:40 AM    &lt;br /&gt;To: 'Ward Bell'     &lt;br /&gt;…&amp;#160; &lt;br /&gt;I prefer an approach of starting simpler and building just the complexity needed instead of starting complex and just putting up with all the complexity. I consider &lt;b&gt;MVVM Light&lt;/b&gt;, for example, to be a better starting point for the majority of teams.    &lt;br /&gt;…&lt;/p&gt;  &lt;p&gt;=============================&lt;/p&gt;  &lt;p&gt;Jonathan Goodyear’s &lt;a href="http://www.devproconnections.com/article/net-framework2/Moving-to-the-Microsoft-Model-View-ViewModel-Pattern.aspx"&gt;editorial&lt;/a&gt; in DevProConnections Magazine, August 2010&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;We reviewed several frameworks, among them Microsoft’s &lt;strong&gt;Prism&lt;/strong&gt; and &lt;strong&gt;Caliburn&lt;/strong&gt;. … we felt strongly … that the framework … should have as few moving parts as possible. Our team has a couple of designers on board, so compatibility with Expression Blend (or “blendability”) was important as well.&amp;#160; I think that we found a near perfect match in &lt;strong&gt;MVVM Light&lt;/strong&gt;.&lt;/p&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-326992517350207845?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/326992517350207845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=326992517350207845' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/326992517350207845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/326992517350207845'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/09/is-mvvm-light-right-for-you.html' title='Is Mvvm Light Right For You?'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-7121683788375071973</id><published>2010-09-04T11:24:00.001-07:00</published><updated>2010-09-04T11:24:56.450-07:00</updated><title type='text'>DevForce Meets Mvvm Light</title><content type='html'>&lt;p&gt;Model-View-ViewModel (MVVM) is THE most successful UI development paradigm ever …&amp;#160; measured by the number and variety of people talking about it. I don’t recall anything like this level of interest with respect to MVP or MVC. For most of UI history the majority of developers couldn’t name the pattern they were using … if they even thought they had a pattern. “MVC”, for most people, is a technology, not a design pattern.&lt;/p&gt;  &lt;p&gt;Today, MVVM is the jargon-du-jour. And I think that’s a good thing. &lt;/p&gt;  &lt;p&gt;We should retain some perspective. Not every view must be MVVM. And yet a healthy number of WPF/Silverlight screens should be done in MVVM style and I’d want to have a really good reason to depart from that standard.&lt;/p&gt;  &lt;p&gt;How do you write a screen in MVVM style? Do you need a framework?&lt;/p&gt;  &lt;p&gt;Some people think you do. There are plenty to choose from. And Laurent Bugnion’s “&lt;a href="http://galasoft.ch/mvvm/getstarted/"&gt;MVVM Light&lt;/a&gt;” has to be the most popular of the ulta-lightweight choices. &lt;/p&gt;  &lt;p&gt;One of our customers asked for an example of DevForce and Mvvm Light working together. I put such an example together and made it available on the “&lt;a href="http://www.ideablade.com/DRC"&gt;DevForce Resource Center” (DRC)&lt;/a&gt;; the Mvvm Light example page is &lt;a href="http://drc.ideablade.com/xwiki/bin/view/Documentation/DevForceWithMvvmLight"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I provide code that shows three ways to start a DevForce + Mvvm Light application and one “Hello World” example.&lt;/p&gt;  &lt;p&gt;Blend is a critical part of the story. “Blendability” is central to the Mvvm Light philosophy … and I agree. The working example view was written entirely in Blend.&lt;/p&gt;  &lt;p&gt;Expect more from me soon on developing with Blend.&lt;/p&gt;  &lt;p&gt;Meanwhile, here’s your launch point for Mvvm Light with DevForce.&lt;/p&gt;  &lt;p&gt;Enjoy!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-7121683788375071973?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/7121683788375071973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=7121683788375071973' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7121683788375071973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7121683788375071973'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/09/devforce-meets-mvvm-light.html' title='DevForce Meets Mvvm Light'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-1583496463053102995</id><published>2010-08-20T01:39:00.001-07:00</published><updated>2010-08-20T01:44:38.131-07:00</updated><title type='text'>DevForce “Blends”</title><content type='html'>&lt;p&gt;We are seeing an increasing interest among developers in using Blend to design application views. I think this is great. Silverlight and WPF are great technologies for building productive business applications. But you can’t be as productive and effective as you should be if you only work in XAML. You need the tools. &lt;/p&gt;&lt;p&gt;And Blend 4 is an incredibly great tool. I say this even though I’m only competent to use about $1.30 of it.&lt;/p&gt;&lt;p&gt;All of this is preface to a forum question we received:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;I’m attempting to mock data at *design* time. … Has anyone ever managed to get this to work? …Using DF to avoid creating dozens of mock repositories on a large project? Now that would be a coup!&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;My answer follows:&lt;/p&gt;&lt;p&gt;We are well on our way to making DevForce play well with Blend. Actually, we probably are THERE. But we haven't documented it well and I don't feel that I'm particularly close to anything worthy of calling a "Best Practice." Let's say I have some "ok" practices :-/ &lt;/p&gt;&lt;p&gt;Here's visual evidence of an existence proof: yes, you truly can use a DevForce EntityManager and entities at design time:&lt;/p&gt;&lt;p&gt;&lt;img title="ComboBox Sample in Blend" border="0" alt="ComboBox Sample in Blend" src="http://www.ideablade.com/forum/uploads/482/SimpleComboBoxInBlend.png" width="618" height="371" /&gt;&lt;/p&gt;&lt;p&gt;This example comes from my slight re-design of the "Simple ComboBox in Silverlight" sample code. &lt;/p&gt;&lt;p&gt;[Aside: the existing sample is on our web site now. The revised one will be released with our forthcoming "DevForce Cookbook." Look for the Cookbook to arrive within a matter of weeks.]&lt;/p&gt;&lt;p&gt;The original point of the sample was to demonstrate how to wire up a ComboBox to DevForce entities AND bind that ComboBox to other DevForce entities. &lt;/p&gt;&lt;p&gt;The previous version looked bloody awful; this one just looks bad.&lt;/p&gt;&lt;p&gt;However, it's beautiful for the purpose of this forum post!  You can plainly see employee, "Ima", in on the Blend art board. "Ima" does not exist in the Northwind tutorial database. She's a fake Employee, ginned up in a&lt;strong&gt; MainPageDesignViewModel&lt;/strong&gt; that derives from the production &lt;strong&gt;MainPageViewModel&lt;/strong&gt;. The view doesn't know; it's just binding to a ViewModel (VM).&lt;/p&gt;&lt;p&gt;All of the fakery happens in the design VM's constructor, shown here:&lt;/p&gt;&lt;pre&gt;    public MainPageDesignViewModel() {&lt;br /&gt;&lt;br /&gt;      EntityManager = new NorthwindManager(false);&lt;br /&gt;      EntityManager.DefaultQueryStrategy = QueryStrategy.CacheOnly;&lt;br /&gt;&lt;br /&gt;      var designEmp = new Employee {&lt;br /&gt;        EmployeeID = 1, FirstName = "Ima", LastName = "Blast", ReportsToEmployeeID = 2,&lt;br /&gt;      };&lt;br /&gt;      var designManagerEmp = new Employee {&lt;br /&gt;        EmployeeID = 2, FirstName = "Slim", LastName = "Ornun", ReportsToEmployeeID = null,&lt;br /&gt;      &lt;br /&gt;     EntityManager.AttachEntity(designEmp);&lt;br /&gt;      EntityManager.AttachEntity(designManagerEmp&lt;br /&gt;&lt;br /&gt;      PotentialManagers = new List&amp;lt;Employee&amp;gt; { designManagerEmp };&lt;br /&gt;      CurrentEmployee = designEmp;&lt;br /&gt;      Messages.Add("We're in DesignTime now !!!");&lt;br /&gt;    }&lt;/pre&gt;&lt;p&gt;The design version of the VM (a) creates two fake employess (Ima and her boss, Slim), (b) creates a disconnected, cache-only EntityManager (EM) - to ensure there is no attempt to talk to the database, and (c) adds the two employees to that EM. Because both fakes are in cache, DevForce can implement the navigation between Ima and Slim via the "Manager" property. I neglected to show this in the ComboBox but you can see it in the message which reads "Ima Blase whose manager is Slim Ornun".&lt;/p&gt;&lt;p&gt;It is only a few short hops from here to doing the cache-to-file trick that you want. In fact, I've done what you want on a different project and we'll provide a similar, smaller example in one of the Cookbook recipes .... although perhaps not in the first Cookbook edition. Trust me, it works great.&lt;/p&gt;&lt;p&gt;To be precise, it &lt;em&gt;worked&lt;/em&gt; great for test runs of your application that you wanted to be fast and free of the need to talk to a database. It didn't work in Blend (although for different reasons than Jason cites).&lt;/p&gt;&lt;p&gt;Until DF 2010 v. 6.0.5, it simply wasn't viable to use DF entities in Cider (Visual Studio visual designer) or Blend because we required that the &lt;em&gt;Desktop&lt;/em&gt; (aka Web aka "Full DotNet") model carry &lt;em&gt;the same assembly name as the Silverlight model&lt;/em&gt;. No problem for the CLR but most tools, including design tools, just choked.&lt;/p&gt;&lt;p&gt;Using the same assembly name is no longer required. In fact, is heavily discouraged.&lt;/p&gt;&lt;p&gt;Now this ComboBox sample dates from 6.0.2 (I think) ... certainly before we got rid of the assembly name restriction. It did not Blend.&lt;/p&gt;&lt;p&gt;All I had to do was some assembly renaming plus clean and re-build. The view popped right up in Cider and Blend. &lt;/p&gt;&lt;p&gt;There was no data visualization though. Just a bunch of weird boxes. The XAML looked ok ... obviously it ran ok ... but it made no sense rendered in Cider or Blend.&lt;/p&gt;&lt;p&gt;A little dragging around was helpful but I still wanted to see sample data.&lt;/p&gt;&lt;p&gt;So I refactored the ViewModel to facilitate a derived, design-time version of that ViewModel and, &lt;em&gt;presto&lt;/em&gt;, that's how I was able to get the layout you see in the image above. &lt;/p&gt;&lt;p&gt;[&lt;em&gt;While I was at it, I replaced the button click wiring with Blend Behaviors ... and deleted the entire custom code-behind&lt;/em&gt;]&lt;/p&gt;&lt;p&gt;You can do the same things to your application, or wait for the Cookbook if you want to see the details.&lt;/p&gt;&lt;p&gt;As I mentioned, the cache-to-file variation is not far off. That will take some explanation, however, as there are a few places you can stumble on the way ... as you discovered.   Please hang in there.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-1583496463053102995?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/1583496463053102995/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=1583496463053102995' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1583496463053102995'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1583496463053102995'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/08/devforce-blends.html' title='DevForce “Blends”'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-3194420151454487522</id><published>2010-08-09T18:46:00.001-07:00</published><updated>2010-08-09T18:46:34.353-07:00</updated><title type='text'>DevForce in the Cloud: Prism Explorer</title><content type='html'>&lt;p&gt;On our second flight to Azure, we deployed our “Prism Explorer” sample application. The address is the same as before: &lt;a href="http://dftest003.cloudapp.net/"&gt;http://dftest003.cloudapp.net/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TGCvazetjSI/AAAAAAAAADI/X4cp54RYlYs/s1600-h/PEInAzure-CloudAddress%5B12%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="PEInAzure-CloudAddress" border="0" alt="PEInAzure-CloudAddress" src="http://lh6.ggpht.com/_iOCgrkgC3Tk/TGCvbcAwIuI/AAAAAAAAADM/62p3UBEXsB0/PEInAzure-CloudAddress_thumb%5B10%5D.png?imgmax=800" width="425" height="29" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;The UI dates from Silverlight 2 (our first Silverlight release). We’ve ported it forward to DevForce 2010 and Silverlight 4 but haven’t touched the XAML. Pretty ugly but it gets the point across. Some day, some day …&lt;/p&gt;  &lt;p&gt;Prism Explorer, aside from showing that DevForce and Prism play nice, demonstrates a variety of DevForce features such as:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Arbitrarily complex queries, including anonymous projections &lt;/li&gt;    &lt;li&gt;Add, delete (enabled for Customer only in this case), and save&lt;/li&gt;    &lt;li&gt;Integrated validation (e.g., Customer requires a city) &lt;/li&gt;    &lt;li&gt;Lazy and eager load of related entities &lt;/li&gt;    &lt;li&gt;Online and offline (toggle “Connect” button) &lt;/li&gt;    &lt;li&gt;Save and restore entities to isolated storage file &lt;/li&gt;    &lt;li&gt;Out of browser &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Here it is, running Out-of-Browser, after querying for “Customers (and their orders) starting with C”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TGCvb_u5FZI/AAAAAAAAADQ/3pZ8pXPd-fk/s1600-h/PEInAzure_CustWithC%5B12%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="PEInAzure_CustWithC" border="0" alt="PEInAzure_CustWithC" src="http://lh5.ggpht.com/_iOCgrkgC3Tk/TGCvciwKh6I/AAAAAAAAADU/xnjeiLzCZvY/PEInAzure_CustWithC_thumb%5B8%5D.png?imgmax=800" width="557" height="286" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here’s another moment in the life of the UI – queried for all Employees and clicked Edit button on good ole Nancy Davolio:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_iOCgrkgC3Tk/TGCvdYk9-kI/AAAAAAAAADY/3fX99WU8qUg/s1600-h/PEInAzure_EmployeeEdit%5B10%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="PEInAzure_EmployeeEdit" border="0" alt="PEInAzure_EmployeeEdit" src="http://lh6.ggpht.com/_iOCgrkgC3Tk/TGCvedGYxSI/AAAAAAAAADc/2BldNkCrodg/PEInAzure_EmployeeEdit_thumb%5B8%5D.png?imgmax=800" width="504" height="319" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I shot video of Kim and me deploying it. Raw footage is 40 minutes, much of that watching it build on my stressed-out notebook (Camtasia and VS competing for cycles). Hope to get it to 20 minutes after cutting out the dross.&lt;/p&gt;  &lt;p&gt;Still, I was amazed to get this done in 50 minutes of clock time (paused video 10 minutes while publishing to Azure staging ). That includes commentary, fumbling, and miscues.&lt;/p&gt;  &lt;p&gt;More on all of that in my next post.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-3194420151454487522?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/3194420151454487522/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=3194420151454487522' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/3194420151454487522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/3194420151454487522'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/08/devforce-in-cloud-prism-explorer.html' title='DevForce in the Cloud: Prism Explorer'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_iOCgrkgC3Tk/TGCvbcAwIuI/AAAAAAAAADM/62p3UBEXsB0/s72-c/PEInAzure-CloudAddress_thumb%5B10%5D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-499054568849775572</id><published>2010-08-06T21:27:00.001-07:00</published><updated>2010-08-06T21:28:47.328-07:00</updated><title type='text'>DevForce in the Cloud: 1st Flight</title><content type='html'>&lt;p&gt;Our first Azure DevForce “application” debuted today. &lt;/p&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_iOCgrkgC3Tk/TFzgkoTa-LI/AAAAAAAAADA/1dWqvAuocis/s1600-h/DevForceInAzure-1st_Flight%5B4%5D.png"&gt;&lt;img style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title="DevForceInAzure-1st_Flight" border="0" alt="DevForceInAzure-1st_Flight" src="http://lh5.ggpht.com/_iOCgrkgC3Tk/TFzgk9uBGbI/AAAAAAAAADE/ng6uG_gzTJI/DevForceInAzure-1st_Flight_thumb%5B2%5D.png?imgmax=800" width="384" height="258" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Sure it’s just Northwind customers in an un-styled, read-only Silverlight DataGrid. Kind of like putting a monkey in orbit. But it’s an important step for IdeaBlade and DevForce … and I’m feeling a wee bit proud.&lt;/p&gt;&lt;p&gt;Behind that simple (simplistic?) exterior are DevForce 2010, SQL Azure, Windows Azure, Silverlight 4, Entity Framework v.4, and .NET 4.  That really is EF 4 running in the cloud, not on the client as it is in most Azure demonstrations. That really is the DevForce middle tier “BOS” in the cloud and a DevForce Silverlight client executing in your browser.&lt;/p&gt;&lt;p&gt;We’ll probably have taken this sample down by the time you read this post. But who knows; if you’re quick, you may still be able to catch it at &lt;a title="http://dftest003.cloudapp.net/" href="http://dftest003.cloudapp.net/"&gt;http://dftest003.cloudapp.net/&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Kudos to Kim Johnson, our ace senior architect / developer who made it happen. Thanks to Microsoft’s Developer Evangelist Bruno Terkaly who first showed us EF 4 in Azure when there were no other published examples.&lt;/p&gt;&lt;p&gt;I’ll be talking about DevForce and Azure much more as our “DevForce in the Cloud” initiative evolves. It’s clearly past the “pipe dream” phase and I anticipate acceleration in the weeks ahead.&lt;/p&gt;&lt;p&gt;Those of you who’ve been wondering if we’d get there (Hi Phil!) or whether to "play it safe"  and build your own datacenter (really?) … wonder no more!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-499054568849775572?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/499054568849775572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=499054568849775572' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/499054568849775572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/499054568849775572'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/08/devforce-in-cloud-1st-flight.html' title='DevForce in the Cloud: 1st Flight'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_iOCgrkgC3Tk/TFzgk9uBGbI/AAAAAAAAADE/ng6uG_gzTJI/s72-c/DevForceInAzure-1st_Flight_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-8216178550158286278</id><published>2010-08-06T16:10:00.001-07:00</published><updated>2010-08-07T01:13:07.249-07:00</updated><title type='text'>ObservableCollection / DataGrid Memory Leaks</title><content type='html'>&lt;p&gt;Ran into a BEAR of a memory leak today. Or, rather, one of our customer’s did … while investigating our PrismExplorer sample that demonstrates DevForce 2010 and Prism v.2.2 playing well together.&lt;/p&gt;&lt;p&gt;This post is a re-post of &lt;a href="http://www.ideablade.com/forum/forum_posts.asp?TID=2055&amp;amp;PID=8023#8023"&gt;my exchange on our IdeaBlade Forum&lt;/a&gt;. I figure it’s worth repeating here should you run into it and not think to look on our forum.&lt;/p&gt;&lt;p&gt;The lesson, I hasten to add, is for all Silverlight developers. DevForce entities are not the cause. If you bind a Silverlight DataGrid to objects that implement INotifyPropertyChanged, this post is for you.&lt;/p&gt;&lt;p&gt;The takeaway is this: &lt;strong&gt;Don't reassign the ObservableCollection&amp;lt;T&amp;gt; bound to an ItemsSource; repopulate it!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;An now … the story. First, the customer reports a problem&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;When ever I bind a datagrid or listbox via a ViewModel to an ObservableCollection(results) in a Callback method from a simple query  … I end up consuming memory which will never be released, … not after disposing of the EntityManger, View, Viewmodel, etc. This behavior can be reproduced in your Prism Explorer when querying Customers, Orders, and back a few times. You can see this in Performance Monitor (perfmon) under process-&amp;gt;private bytes  where the count keeps climbing up.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Here is my response:&lt;br /&gt;-------------------------------------------------------&lt;/p&gt;&lt;p&gt;You are (mostly) correct and oh ... how awful! &lt;/p&gt;&lt;p&gt;As I demonstrate below, memory is recovered when you clear the EntityManager. It would be recovered if you disposed of the EntityManager itself.  I'm not sure why you didn't see these effects. &lt;/p&gt;&lt;p&gt;However, you are absolutely right that something horrible is happening. I spent much of the day researching it.&lt;/p&gt;&lt;p&gt;The only good part of the story is that it has nothing to do with DevForce. The cause is something in Silverlight, probably in the Silverlight DataGrid.&lt;/p&gt;&lt;p&gt;I will explain but it will be a bit of a journey leading ... ultimately ... to a sad-but-necessary workaround.&lt;/p&gt;&lt;p&gt;If you want to skip the journey and go right to the destination, the lesson for your code is:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Don't reassign the ObservableCollection&amp;lt;T&amp;gt; bound to an ItemsSource; repopulate it!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;And now ... my sad tale ...&lt;/p&gt;&lt;p&gt;The main "ModelExplorer" view binds a Silverlight DataGrid.ItemsSource to the QueryResults property of the supporting ModelExplorerViewModel (the VM).&lt;/p&gt;&lt;p&gt;"QueryResults" is defined as IList but is always an ObservableCollection&amp;lt;T&amp;gt; in practice (henceforth written as "OC&amp;lt;T&amp;gt;").&lt;/p&gt;&lt;p&gt;The problem starts with the repeated resetting of the QueryResults in the ModelExplorerViewModel after every query. &lt;/p&gt;&lt;p&gt;A peculiarity of PrismExplorer (PE) is that the main "ModelExplorer" view could be asked to display objects of any type in the DataGrid. That's its purpose as a demo screen. Your grids typically only show one kind of object. But PE must work with arbitrary query result types.&lt;/p&gt;&lt;p&gt;Because those types change, the OC&amp;lt;T&amp;gt; must change to match type.&lt;/p&gt;&lt;p&gt;The obvious thing to do was craft a new OC&amp;lt;T&amp;gt; after every query ... one designed for the query results type, assign that new OC to the QueryResults, and raise PropertyChanged on "QueryResults". The DataGrid dutifully hears the call and refreshes its display.&lt;/p&gt;&lt;p&gt;Unfortunately, it consumes &lt;strong&gt;an extra 300K every single time&lt;/strong&gt;. "300K" is not a misprint. &lt;/p&gt;&lt;p&gt;Here's the code with the garbage collection call and logging (&lt;em&gt;aside: we now inject ILoggerFacade into the VM now so that we can write to the Visual Studio Output window&lt;/em&gt;).&lt;/p&gt;&lt;pre&gt;    public IList QueryResults {&lt;br /&gt;      get { return _queryResults; }&lt;br /&gt;      set {&lt;br /&gt;        _queryResults = value;&lt;br /&gt;&lt;br /&gt;        &lt;strong&gt;&lt;u&gt;Log("=== Total Memory = " + GC.GetTotalMemory(true));&lt;/u&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;        RaisePropertyChanged("QueryResults", "QueryResultsCount");&lt;br /&gt;        SelectFirstQueryResultsItem();&lt;br /&gt;      }&lt;br /&gt;    }&lt;/pre&gt;&lt;p&gt;If you add this instrumentation, query for "All Customers", and click the "Query" button repeatedly, the Output window will show that your memory consumption is climbing ~300K each time.  Here are actual measurement.&lt;/p&gt;&lt;p&gt;  Prism Explorer: "=== Total Memory = 3406212";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 3914916";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 4336668";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 4756884";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 5177356";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 5782900";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 6202860";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 6616220";&lt;br /&gt;// Cleared the EntityManager&lt;br /&gt;  Prism Explorer: "=== Total Memory = 3655320";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 4076292";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 4498300";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 4918260";&lt;br /&gt;  Prism Explorer: "=== Total Memory = 5358912";&lt;br /&gt;// Cleared the EntityManager&lt;br /&gt;  Prism Explorer: "=== Total Memory = 3655384";&lt;/p&gt;&lt;p&gt;Note that DevForce isn't going anywhere. You are issuing the same query repeatedly and DevForce satisfies it from the EntityManager cache. However, the PE ViewModel is building a new OC&amp;lt;Customer&amp;gt; each time and reassigning QueryResults. The DataGrid is rebinding the ItemsSource to the new OC&amp;lt;Customer&amp;gt; each time ... and chewing up memory each time.&lt;/p&gt;&lt;p&gt;If we comment out "_queryResult = value", DevForce and PE will continue to do their things ...  DevForce may query the database or satisfy from cache if it can. PE will always build a new OC&amp;lt;T&amp;gt;, assign QueryResults with that OC&amp;lt;T&amp;gt;, raise PropertyChanged, stimulate the DataGrid to rebind to the QueryResults. Exactly the same code paths.&lt;/p&gt;&lt;p&gt;The only programmatic difference is that QueryResults always returns the exact same (empty) object.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;The memory consumption goes flat&lt;/strong&gt; ... as it should. &lt;/p&gt;&lt;p&gt;Of course it climbs modestly when you issue a query that fetches &lt;strong&gt;&lt;em&gt;new&lt;/em&gt;&lt;/strong&gt; data; that is to be expected. Press "Clear" to clear the EntityManager cache and memory is recovered.&lt;/p&gt;&lt;p&gt;This is proof enough for me that the memory leak is in Silverlight ... perhaps in the Silverlight DataGrid. Our entities are involved in some way ... that's why clearing the EntityManager cache allows the GC to recover memory. But the DataGrid is clearly chewing up memory at a fast clip without our adding any new entities to memory.&lt;/p&gt;&lt;p&gt;What could possibly take 300k? The entity data involved are miniscule (it's Northwind!  7 Employees ~90 customers). All entities combined do not weigh 300K. &lt;/p&gt;&lt;p&gt;The memory consumption grows by 300K when there are no new entities. Evidently Silverlight or OC is in a deadly embrace with the entities that prevents garbage collection (there are events involved). But even if so ... the numbers are staggering. We aren't adding 300K of new data each time we click the button. You can't write enough event handlers to consume 300K. The cost of an OC isn't 300K. &lt;/p&gt;&lt;p&gt;In my research, I tripped over an old WPF blog post (can't find it now) that said something about WPF creating completely new data and control templates for each OC. Now THAT is a fast way to burn memory. I'm betting that Silverlight is creating and caching a complete visual representation of the DataGrid and the associated entities each time I reset the ItemsSource with a new OC&amp;lt;T&amp;gt;!&lt;/p&gt;&lt;p&gt;I tried a number of things to shake up the binding ... anything to make it let go of whatever it was holding:&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;clear the _queryResults ( _queryResults.Clear() ) before re-assigning it with the new OC &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;clear the _queryResults and set it null before re-assigning it with the new OC &lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;clear the _queryResults, set it null, raise PropertyChanged ... then assign with new OC&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;None of these attempts worked.  Only pressing "Clear" worked.&lt;/p&gt;&lt;p&gt;What to do? The obvious answer is reuse the OC ... and that is the lesson for your application: &lt;strong&gt;Don't reassign the ItemsSource; repopulate it!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Of course OC&amp;lt;T&amp;gt; requires strongly typed contents. I tried OC&amp;lt;object&amp;gt; with the intention of simply clearing and refilling it with new results after each query. That executes without error. But it doesn't show anything on screen either ... pretty useless :-).&lt;/p&gt;&lt;p&gt;It actually worked if I use List&amp;lt;T&amp;gt; instead of OC&amp;lt;T&amp;gt;. But then I wouldn't have the benefits of ICollectionPropertyChanged and I'd have to manage adds, removals, clears by hand. Yuck.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;The WorkAround&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;As a last resort, on each pass I check to see if the type of the fresh results matches the element type of the OC. If it does, I can re-populate the OC. If it does not match, I have to replace the ItemsSource with the new OC ... and pay the 300K tax.&lt;/p&gt;&lt;p&gt;If you always query for the same type, you'll be fine. You can change the query itself - there are numerous Customer and Employee queries in PE - without paying the tax. It's changing the result type that incurs the tax.&lt;/p&gt;&lt;p&gt;I tried to be clever and keep a dictionary of previously used OC types. If I was querying customers, I'd pull out the OC&amp;lt;Customer&amp;gt;; if I was querying employees, I'd pull out the OC&amp;lt;Employee&amp;gt;.  That didn't help. The DataGrid doesn't remember OCs that it has seen before. Re-using old OCs didn't change its penchant for devouring another 300K &lt;/p&gt;&lt;p&gt;So all I can do is slow it down. If PE starts to blow, you can "Clear" the EntityManager and it will recover.&lt;/p&gt;&lt;p&gt;Here's the revised code (which will appear in the next PE release, minus the GC &amp;amp; Log calls)&lt;/p&gt;&lt;pre&gt;&lt;pre&gt;    public IList QueryResults {&lt;br /&gt;      get { return _queryResults; }&lt;br /&gt;      set {&lt;br /&gt;&lt;br /&gt;        ResetQueryResults(value);&lt;br /&gt;&lt;br /&gt;        Log("=== Total Memory = " + GC.GetTotalMemory(true));&lt;br /&gt;&lt;br /&gt;        RaisePropertyChanged("QueryResults", "QueryResultsCount");&lt;br /&gt;        SelectFirstQueryResultsItem();&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    private void ResetQueryResults(IList results) {&lt;br /&gt;&lt;br /&gt;      if (null != _queryResults) _queryResults.Clear();&lt;br /&gt;      if (null == results  0 == results.Count) return;&lt;br /&gt;&lt;br /&gt;      var resultsType = TypeHelper.GetItemType(results);&lt;br /&gt;&lt;br /&gt;      if (_queryResultsElementType == resultsType) {&lt;br /&gt;        // Same results collection type; can refill it&lt;br /&gt;        foreach (var item in results) {&lt;br /&gt;          _queryResults.Add(item);&lt;br /&gt;        }&lt;br /&gt;      } else {&lt;br /&gt;        _queryResults = results;&lt;br /&gt;        _queryResultsElementType = resultsType;&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private Type _queryResultsElementType;&lt;/pre&gt;&lt;/pre&gt;&lt;p&gt;Here are memory reports:&lt;/p&gt;&lt;p&gt;// Query for All Customers&lt;br /&gt;&lt;br /&gt;Prism Explorer: "=== Total Memory = 3411896"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3425356"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3416064"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3416076"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3416076"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3429460"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3416076"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3415020"&lt;br /&gt;// All Employees&lt;br /&gt;Prism Explorer: "=== Total Memory = 4203344"&lt;br /&gt;Prism Explorer: "=== Total Memory = 4212964"&lt;br /&gt;Prism Explorer: "=== Total Memory = 4213000"&lt;br /&gt;Prism Explorer: "=== Total Memory = 4213000"&lt;br /&gt;Prism Explorer: "=== Total Memory = 4213000"&lt;br /&gt;// Clear Entity Cache ... followed by All Employees&lt;br /&gt;Prism Explorer: "=== Total Memory = 3706416"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3588660"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3593996"&lt;br /&gt;// First Employee&lt;br /&gt;Prism Explorer: "=== Total Memory = 3590928"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3604372"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3589676"&lt;br /&gt;// Employees named Smith (there are none)&lt;br /&gt;Prism Explorer: "=== Total Memory = 3605584"&lt;/p&gt;&lt;p&gt;// All Employees (again)&lt;/p&gt;&lt;p&gt;Prism Explorer: "=== Total Memory = 3757472"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3762120"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3770336"&lt;br /&gt;Prism Explorer: "=== Total Memory = 3762144"&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-8216178550158286278?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/8216178550158286278/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=8216178550158286278' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8216178550158286278'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8216178550158286278'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/08/observablecollection-datagrid-memory.html' title='ObservableCollection / DataGrid Memory Leaks'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-2830492617499727157</id><published>2010-04-30T13:25:00.001-07:00</published><updated>2010-04-30T13:51:23.832-07:00</updated><title type='text'>Context for Comparing DevForce, CSLA, and RIA Services</title><content type='html'>&lt;p&gt;I recently posted on some important differences between DevForce and RIA Services. Someone posted a comment to the effect that DevForce and CSLA seem to be the same and invited me to comment.&lt;/p&gt;  &lt;p&gt;I see the similarities between DevForce and RIA Services. I don’t think DevForce and CSLA are alike at all. Why would someone suggest that they are?&lt;/p&gt;  &lt;p&gt;That got me thinking and lead to this post which reframes the question.&lt;/p&gt;  &lt;p&gt;It first establishes what we have in common … and how to decide quickly if you should consider any of us … or none of us … for your application project.&lt;/p&gt;  &lt;p&gt;Then it articulates fundamental criteria for comparing the three.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: These criteria are not evaluative. They are as neutral as I can make them. I feel pretty confident in that neutrality because, as I apply them to the three products, I can not tell which one of them is “better”. They help me organize my thoughts, not decide which one is “right.”&lt;/p&gt;  &lt;p&gt;Let's start with the what we have in common. &lt;/p&gt;  &lt;p&gt;DevForce, CSLA, and RIA Services target the same problem: building distributed business applications from end to end, server to client. &lt;/p&gt;  &lt;p&gt;If you don't think you have this problem, none of us are right for you. &lt;/p&gt;  &lt;p&gt;We offer .NET-only products. RIA Services is limited today to Silverlight applications; DevForce and CSLA support most .NET client technologies (I don't think any of us are ready for WP7 .. yet. CSLA may work on the CE; we do not). Your required server and client operating environments may make the choice for you. &lt;/p&gt;  &lt;p&gt;We all have the same presumption of a relational database as the primary backing store. Sure we can also persist to other backing stores. But these alternatives appear in supporting roles if they appear at all. None of us are your best choice for building applications that primarily access data through messaging services or persist to one of the NoSql schema-less data stores. &lt;/p&gt;  &lt;p&gt;We all attempt to solve your application problem within some flavor of &amp;quot;mobile business objects&amp;quot; paradigm. If you summarily reject a &amp;quot;mobile business object&amp;quot; solution on principle, none of us are right for you.&lt;/p&gt;  &lt;p&gt;Finally, we are all framework products. We're not application generators. If you want to drag-and-drop your way to a finished product, we're not for you. If you reject 3rd party frameworks, we are not right for you either. &lt;/p&gt;  &lt;p&gt;With me still? Because now we are ready to differentiate the three products. &lt;/p&gt;  &lt;p&gt;You have looked at the problem and you've chosen to solve it by allocating some responsibilities to a framework, reserving others for yourself in the expectation that you will be writing custom application code. &lt;/p&gt;  &lt;p&gt;Every framework is opinionated. Each says: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;We will be responsible for these tasks (the A-list).      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;You will write custom code for these other tasks (the B-list).      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Our architecture and recommend development practices pretty much prescribe that you will write your custom code in manner C. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You look at these opinions and ask yourself &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Do I want the framework to do the things on the A-list?      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Do I want to write code for the things on the B-list?      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Do I want to develop in manner C?      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;How productive will I be if I adopt this framework?&amp;#160; How quickly can I write quality B-list code when I adopt manner C?      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;What items on the A-list do I &lt;em&gt;&lt;strong&gt;really have to do myself&lt;/strong&gt;&lt;/em&gt;? Can I take these particular tasks away from the framework with acceptable ease and still, in the main, be using the framework the way it was intended?       &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;I wish some of the items on the B-list were handled by the framework. What will it take for me to write them myself or acquire them from someone else?      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;I don't care about some of the items on the A-list; do these items get in my way and if so, will that be a serious problem?      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;Do we have the skills and development culture to use this framework effectively? If not, can we and should we acquire those skills?      &lt;br /&gt;      &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;How do these factors collectively influence my development timeline? Do I have a deadline? If so can I reasonably expect to hit the deadline with the resources I have using this framework? &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You will also consider some “non-functional” factors&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Product quality and maturity&lt;/li&gt;    &lt;li&gt;Access to source code &lt;/li&gt;    &lt;li&gt;Support&lt;/li&gt;    &lt;li&gt;Influence on roadmap and repairs&lt;/li&gt;    &lt;li&gt;Product release schedule&lt;/li&gt;    &lt;li&gt;Community (resources, training, etc.)&lt;/li&gt;    &lt;li&gt;Company stability &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I have conspicuously omitted one factor: &lt;strong&gt;license costs&lt;/strong&gt;. CSLA and RIA Services have no license costs. DevForce does. Why doesn’t that matter?&lt;/p&gt;  &lt;p&gt;It doesn’t matter because you’re building a custom application that you’ll be living with for years. A few thousand dollars of licensing fees are irrelevant … they are rounding error … compared to the application investment you’re about to make and the risks you are about to assume. &lt;/p&gt;  &lt;p&gt;If this is not blindingly obvious to you, you shouldn’t be making this decision. You simply don’t have the requisite business acumen to make the right choice.&lt;/p&gt;  &lt;p&gt;When you dissect the products according to these criteria – which you’ve refined and weighted to suit your business environment&amp;#160; and requirements – the differences among CSLA, DevForce, and RIA Services will stand out in sharp relief.&amp;#160; You will have a foundation for choosing among them. &lt;/p&gt;  &lt;p&gt;I said the differences will be stark; I didn’t say that the choice will be easy. Even within the same organization people will weigh some differences more heavily than others. &lt;/p&gt;  &lt;p&gt;You will at least have arranged matters so you can see more clearly what you’re arguing about.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-2830492617499727157?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/2830492617499727157/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=2830492617499727157' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2830492617499727157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2830492617499727157'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/04/context-for-comparing-devforce-csla-and.html' title='Context for Comparing DevForce, CSLA, and RIA Services'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-6380540319681441009</id><published>2010-04-28T21:48:00.001-07:00</published><updated>2010-04-28T21:48:09.934-07:00</updated><title type='text'>DevForce Or RIA Services?</title><content type='html'>&lt;p&gt;I’m thrilled RIA Services is out at last. &lt;/p&gt;  &lt;p&gt;Developers who are familiar with Forms-over-Data, end-to-end, business application development at last have a Microsoft-sanctioned approach to building such applications in Silverlight.&lt;/p&gt;  &lt;p&gt;They’re less inclined to roll-their own data management solution and more inclined to let someone else handle the plumbing.&lt;/p&gt;  &lt;p&gt;That choice is not without problems. It’s unnerving to hand the keys over to a framework and say “you drive.” But let’s face it, your home-brew solution is just another framework too. It may be yours … which makes you feel all gnarly and in control. But it’s still a framework that someone is going to have to document, train, maintain, support, and grow … at the probable expense of delivering the end product demanded by the customer.&lt;/p&gt;  &lt;p&gt;RIA Services has made it OK to delegate these challenging and time-wasting aspects of the application to a third party.&lt;/p&gt;  &lt;p&gt;For me, the usual conversation has shifted from “Why do I need something like DevForce?” to “Why DevForce instead of&amp;#160; RIA Services?”&lt;/p&gt;  &lt;p&gt;Here’s how someone put that question on the &lt;a href="http://forums.silverlight.net/forums/t/178991.aspx"&gt;RIA Services Forum&lt;/a&gt;.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;DevForce or WCF RIA Services? Both seem to do more or less the same data abstraction for Silverlight, but which would be the better route to go in the end? The price tag for me is the winner with WCF RIA services, but this is not always the right choice. Any thoughts?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;a href="http://forums.silverlight.net/members/ColinBlair.aspx"&gt;Colin Blair&lt;/a&gt;, MVP and RIA Services aficionado, invited me to respond to that forum post. Which I was happy to do :-).&lt;/p&gt;  &lt;p&gt;You could read it there. But I’ll spare you the trip and re-post my response here.&lt;/p&gt;  &lt;p&gt;I have much more to add… and I’ll elaborate in the coming weeks and months. Meanwhile, it’s a start.&lt;/p&gt;  &lt;p&gt;--------------&lt;/p&gt;  &lt;p&gt;Yes, RIA Services and DevForce share a common perspective: end-to-end application development, programming against a rich entity model backed (typically) by relational data with validation, concurrency, security, change management, unit-of-work rolled in.&lt;/p&gt;  &lt;p&gt;DevForce has been in commercial release since 2002 (long before Silverlight) so it's been dipped rather thoroughly in the acid bath of real world experience.&lt;/p&gt;  &lt;p&gt;It supports both 2-tier and n-tier applications (a config change) and all the typical .NET client technologies: Windows Forms, WPF, Silverlight, ASP Web Forms, ASP MVC. You can write one code base and use it across all of them ... not that that is always a great idea. We have versions for .NET 2.0, 3.5 and 4.0.&lt;/p&gt;  &lt;p&gt;Let's assume, however, that you are only interested in Silverlight and you don't care about product maturity, track record, or any of that. &lt;/p&gt;  &lt;p&gt;If it seems that DevForce and RIA Services are similar ... that's intentional. We have a common perspective and we want DevForce to align with RIA Services APIs and techniques as much as possible ... so that it's easy to move between the two communities.&lt;/p&gt;  &lt;p&gt;But DevForce and RIA Services are not clones. We do many things differently and offer capabilities beyond the RIA Services baseline.&lt;/p&gt;  &lt;p&gt;Our customers often cite some of the following dozen DevForce differences as their reasons for choosing DevForce:&lt;/p&gt;  &lt;p&gt;1) Same model on server and client. The code you write on the server is the same as the code on the client (unless and except where you don't want it to be). Open the Employee class on either side ... it's identical. The physical class file resides on one side (typically a server, full .NET project) and you have a Silverlight model assembly that links to that file. Compilation produces different assemblies (.NET and Silverlight) whose class names, structures, and logic are effectively the same.&lt;/p&gt;  &lt;p&gt;2) No code generation magic.&amp;#160; We don't touch your code. We don't generate client code. No surprises.&lt;/p&gt;  &lt;p&gt;3) Most DevForce applications use Entity Framework for Object Relational Mapping (ORM) and persistence operation (query, insert, update, delete). &lt;/p&gt;  &lt;p&gt;DevForce generates its own (partial) classes from EF's EDMX using T4 templates; we don't need, use, or generate EF's own classes.&lt;/p&gt;  &lt;p&gt;Our classes are serializable and designed to support RIA scenarios. We inscribe the UI-hint attributes (e.g., Display) and the obvious validation attributes (e.g., Required) into the generated classes. No separate metadata class files needed (keep reading)&lt;/p&gt;  &lt;p&gt;4) You can override our code generation to introduce your own behaviors. You could take over the entire template but it's much easier to override one of the many code generation methods that target the moment of interest to you (e.g., property generation).&lt;/p&gt;  &lt;p&gt;5) No service method pollution.&amp;#160; In RIA Services you have CRUD methods for each type in your model. There could be 400 methods in a 100 entity model. We don't generate CRUD methods; like WCF Data Services, we manage CRUD operations dynamically. Of course you CAN write arbitrary service methods if you wish. You can intercept any Query to inspect, limit, adjust the query. You can intercept any Save to inspect, reject, add/subtract/modify the entities in the change set, or perform arbitrary operations (custom logging and auditing).&lt;/p&gt;  &lt;p&gt;6) Iterative Development: In demos, you build your model and you're done. In reality, you will add, remove, and rename your properties, entities, and the relationships among them. over the long course of your application's lifespan. Such adjustments are trivial with EF-backed models; update the EF model, compile, and run. &lt;/p&gt;  &lt;p&gt;Ok ... maybe you should test too and you made these changes because you wanted to introduce new capabilities. The point is that you'll program to those business concerns; you won't be updating a domain service file and fixing up satellite, entity-related class files.&lt;/p&gt;  &lt;p&gt;7) Client-side LINQ. DevForce supports client-side composition of any LINQ to Entities query, including projections of all kinds, projections into anonymous types, aggregations, grouping and ordering, includes, polymorphic queries (query on a base type). There is NO query you have to compose on the server in a &amp;quot;domain service&amp;quot; method. You don't add OrderBy clauses on server query methods. It is almost unheard of for a DevForce application to have a server-side query method.&lt;/p&gt;  &lt;p&gt;8) Client-side caching. Query results are cached as are entities you create, modify, delete ... and have not yet saved. RIA Services does this too. &lt;/p&gt;  &lt;p&gt;But DevForce applies your LINQ queries BOTH to the server store and to the cache. Suppose you have queried for all Northwind employees; you change &amp;quot;Nancy Davolio&amp;quot; to &amp;quot;Sally Davolio&amp;quot; and you add a new employee named &amp;quot;Sam&amp;quot;. Meanwhile, another user has saved a new employee named &amp;quot;Sherry&amp;quot;. What is the result of a query for employees with first name beginning &amp;quot;S&amp;quot;? The DevForce answer includes &amp;quot;Sally (formerly Nancy)&amp;quot;, &amp;quot;Sam&amp;quot; and &amp;quot;Sherry&amp;quot;. &lt;/p&gt;  &lt;p&gt;You can tell DevForce to query ONLY the cache or ONLY the server ... as appropriate.&lt;/p&gt;  &lt;p&gt;It's trivial (and recommended) in DevForce for your Silverlight application to prepare the cache with entities you need for a particular user scenario as you enter that workflow. You then would default subsequent query execution to &amp;quot;CacheOnly&amp;quot;, and &amp;quot;party on&amp;quot; as if you had an in-memory database. Yes, you can still make remote queries and asynchronously refresh all or part of the cache at will.&lt;/p&gt;  &lt;p&gt;The key benefit: you can easily program the user experience in the synchronous style familiar to most business application developers and still exploit the responsiveness of asynchronous data access ... using the same queries.&lt;/p&gt;  &lt;p&gt;9) Productivity and Testability. You don't need a database or server to build and test your application. You can populate the DevForce entity cache with test entities - entire object graphs - and run disconnected. You can serialize the cache to file (e.g., Isolated Storage) - in a single method - and restore that cache at will. I often build a development data cache file, include it as a resource, and launch my application &amp;quot;in test mode&amp;quot;; the cache fills with the dev data rather than having to hit the server, and I'm running with no web server at all. I can make and explore UI changes in a fraction of the time it would take if I had to spin up Entity Framework and a server. I can work with colleagues far away who don't have Entity Framework or the database ... because there is no dependence at all.&lt;/p&gt;  &lt;p&gt;10) DevForce entity properties are implemented with &amp;quot;property interceptors&amp;quot; that enable you to inject custom behavior into the getters and setter. Without touching the Employee class I can add logic to automatically mask the Social Security number&amp;#160; ... unless the employee is the current user or the user is an HR admin. I could inject logic into a setter to force values to upper case. I have complete, fine-grained control of the DevForce generated properties before and after the actual value access or mutation.&lt;/p&gt;  &lt;p&gt;11) DevForce validation supports the same DataAnnotation validation attributes as RIA Services in addition to our own (richer) validation attributes. But you're not limited to attributes. You can add validation rules programmatically to the class and we'll discover them. You can access the list of validation rules for any type and manipulate that list, removing existing rules and adding other rules ... perhaps customer-specific rules determined by metadata. You can do this with logic entirely outside the entity class. And DevForce validation can be applied to any object, not just entities.&lt;/p&gt;  &lt;p&gt;12) Navigation properties (Order.OrderDetails, Order.Customer) to related entities work even if the related entities are not in cache. DevForce fetches them asynchronously ... and can notify you when the data arrive. I would be wary of multiple, hidden trips to the database (the N+1 problem with lazy loading); you should consider eagerly loading these entities instead. But lazy loading has its place. Of course you can disable lazy loading of any property at any time.&lt;/p&gt;  &lt;p&gt;You can find out more for yourself by visiting our web site, &lt;a href="http://www.ideablade.com/"&gt;http://www.ideablade.com&lt;/a&gt; or write to me at &lt;a href="mailto:AskWard@ideablade.com"&gt;AskWard@ideablade.com&lt;/a&gt;. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-6380540319681441009?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/6380540319681441009/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=6380540319681441009' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6380540319681441009'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6380540319681441009'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/04/devforce-or-ria-services.html' title='DevForce Or RIA Services?'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-6323742159422183231</id><published>2010-04-02T19:23:00.001-07:00</published><updated>2010-04-02T23:07:43.182-07:00</updated><title type='text'>DevForce Extensibility With MEF InheritedExport</title><content type='html'>&lt;p&gt;We’ve offered extensibility points in Our DevForce product since the beginning of the century.&lt;/p&gt;&lt;p&gt;Our customers wrote classes that implemented certain of our interfaces. We discovered those classes by examining assemblies named in a configuration file (app.config or web.config). We had our own probing and injection logic because market forces precluded use of a 3rd party IoC.&lt;/p&gt;&lt;p&gt;In DevForce 2010 we’ve switched to the Microsoft Managed Extensibility Framework (MEF) which is baked into the .NET 4 platform.&lt;/p&gt;&lt;p&gt;How hard was that? It wasn’t a big deal. Mostly we had to figure out how it worked and find the best approach for us. Which is the point of this post.&lt;/p&gt;&lt;p&gt;Because we almost made a mistake. We didn’t know about MEF’s &lt;strong&gt;InheritedExportAttribute&lt;/strong&gt;.&lt;/p&gt;&lt;h3&gt;DevForce Extensibility&lt;/h3&gt;&lt;p&gt;Let me set the stage.&lt;/p&gt;&lt;p&gt;Suppose you want to alter DevForce default behavior by supplying your own way of doing something. Maybe you want to supply a custom “LoginManager” to authenticate users. Maybe you want to supply a class that intercepts all attempts to save data to the database … so you can confirm the user’s right to save or impose some extra server-side validation or add audit records … whatever.&lt;/p&gt;&lt;p&gt;Heretofore, you wrote a MyLoginManager that inherited from IEntityLoginManager and stuffed it in a server-deployed assembly; call it "MyServerStuff". You next identified “MyServerStuff.dll” as a probe assembly in your web.config. We’d look there for a class implementing IEntityLoginManager and, upon finding yours, would instantiate and use your class instead of our default class. Similarly, you wrote a MyEntityServerSaving class that inherited from IEntityServerSaving and we’d find it too.&lt;/p&gt;&lt;p&gt;In MEF, MyLoginManager and MyEntityServerSaving are “&lt;strong&gt;parts&lt;/strong&gt;”. They are parts that you “&lt;strong&gt;export&lt;/strong&gt;” for DevForce to “&lt;strong&gt;import&lt;/strong&gt;”. &lt;/p&gt;&lt;p&gt;The DevForce 2010 difference: we let MEF do the finding and creation of your types instead of doing that ourselves.&lt;/p&gt;&lt;h3&gt;Our Initial Mistake&lt;/h3&gt;&lt;p&gt;In a beautiful world, you – the developer of MyLoginManager and MyEntityServerSaving – don’t change a thing. Your classes just work.&lt;/p&gt;&lt;p&gt;Actually, it’s better than that. You can throw away the &amp;lt;probeAssembly&amp;gt; tags in the web.config and the app.config. That kruft was a repeated source of confusion and heartache for our customers. It’s gone. No &amp;lt;probeAssembly&amp;gt; needed if you drop your assembly on the server in the \bin directory.&lt;/p&gt;&lt;p&gt;We should have done that long ago. MEF made it obvious.&lt;/p&gt;&lt;p&gt;BUT … it looked like it wouldn’t be quite this easy. How would MEF know to import your MyLoginManager and MyEntityServerSaving? &lt;/p&gt;&lt;p&gt;We couldn’t figure that out. In vanilla MEF, you attach an Export attribute to a component that you want others to import. It seemed you’d have to decorate your custom classes with these attributes like this.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;[Export(typeof(IEntityLoginManager))]&lt;/strong&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;public class MyLoginManager : IEntityLoginManager { // your code }&lt;/p&gt;&lt;p&gt;Ugh. Why impose this burden on the poor developer? How many support calls would we field that ran something like this? &lt;/p&gt;&lt;p&gt;“Sir? DevForce didn’t find your class? Please open Visual Studio … now look at the class definition. Does it have an Export attribute? Yes an “Export” attribute. What? Oh yeah you’ll need an assembly reference and a using clause too. Sure, I’ll hold why you build, redeploy and run it …”&lt;/p&gt;&lt;h3&gt;InheritedExportAttribute&lt;/h3&gt;&lt;p&gt;Fortunately, I know how to complain. I wrote a “WTF” email to Glenn who graciously replied as follows:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;You might want to look into InheritedExports. If you are not using metadata you can put an [InheritedExport] on an interface which will automatically apply to the exporter.&lt;/p&gt;&lt;p&gt;In other words….&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;[&lt;strong&gt;InheritedExport&lt;/strong&gt;]&lt;br /&gt;&amp;nbsp;&amp;nbsp;public interface IFoo {}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;public class Foo : IFoo { ...}&lt;/p&gt;&lt;p&gt;Foo above automatically exports IFoo since the decoration is on the interface. There are some issues if you are doing this combined with metadata.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;How about that! &lt;/p&gt;&lt;p&gt;We added “[InheritedExport]” to all of our extensibility interfaces. Now our customer’s existing custom classes are discovered and work as they did before without modification. No attribute needed.&lt;/p&gt;&lt;p&gt;What if the extensibility point is a &lt;strong&gt;base class&lt;/strong&gt; instead of an interface? That works too. Check this out. In DevForce, we have an EntityServerSaveInterceptor class that intercepts server side saves. It does some work by default … work that you can extend.&lt;/p&gt;&lt;p&gt;Here’s its new MEF’ed signature in DevForce 2010:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;strong&gt;InheritedExport&lt;/strong&gt;( typeof(EntityServerSaveInterceptor) )]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;strong&gt;DefaultExport&lt;/strong&gt;( typeof(EntityServerSaveInterceptor) )]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public class EntityServerSaveInterceptor {&lt;/p&gt;&lt;p&gt;Note the “DefaultExport”. That tells MEF to import an instance of this class if you don’t supply your own.&lt;/p&gt;&lt;p&gt;Customers can subclass our default version just as they did before:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public class MyEntityServerSaveInterceptor : EntityServerSaveInterceptor { &lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected override bool ClientCanSave(Type type) { … }&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/p&gt;&lt;p&gt;They can’t MEF up.&lt;/p&gt;&lt;h3&gt;Is MEF Legal?&lt;/h3&gt;&lt;p&gt;You don’t know about MEF? Where have you been? How could you have missed &lt;a href="http://blogs.msdn.com/gblock/" target="_blank"&gt;Glenn “Mr. MEF” Block&lt;/a&gt;; the man is &lt;strong&gt;&lt;em&gt;everywhere&lt;/em&gt;&lt;/strong&gt; – print, stage, and screen – talking up the MEF magic.&lt;/p&gt;&lt;p&gt;You can read about MEF &lt;a href="http://msdn.microsoft.com/en-us/library/dd460648(VS.100).aspx" target="_blank"&gt;here&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/kcwalina/archive/2008/04/25/MEF.aspx" target="_blank"&gt;here&lt;/a&gt; and &lt;a href="http://social.msdn.microsoft.com/forums/en-US/MEFramework/threads" target="_blank"&gt;here&lt;/a&gt; and all over the place. &lt;a href="http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/default.aspx" target="_blank"&gt;Mike Taulty&lt;/a&gt;, who is excellent on any subject, produced some superb &lt;a href="http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2009/12/31/silverlight-4-screencasts-the-managed-extensibility-framework-mef.aspx" target="_blank"&gt;MEF screen casts&lt;/a&gt;. The once-obscure &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection" target="_blank"&gt;Dependency Injection&lt;/a&gt; technique has gone mainstream with MEF and will be arriving soon in a code base near you. You’ve probably been doing something like it for years and didn’t know it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-6323742159422183231?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/6323742159422183231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=6323742159422183231' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6323742159422183231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6323742159422183231'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/04/devforce-extensibility-with-mef.html' title='DevForce Extensibility With MEF InheritedExport'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-1940328701722178994</id><published>2010-04-01T13:16:00.001-07:00</published><updated>2010-04-01T13:16:48.306-07:00</updated><title type='text'>DevForce / UFC Gym Bling On Silverlight TV</title><content type='html'>&lt;p&gt;We had way too much fun at MIX 2010 in Las Vegas last month. John Papa captured the flavor in a &lt;a href="http://johnpapa.net/silverlight/silverlight-tv-19-hidden-gems-from-mix10-ufc-s-multi-touch-app/"&gt;Silverlight TV interview with me&lt;/a&gt; featuring the UFC Gym Kiosk.&lt;/p&gt;  &lt;p&gt;Watch the episode online by &lt;a href="http://channel9.msdn.com/shows/SilverlightTV/Silverlight-TV-19-Hidden-Gems-from-MIX10-UFCs-Multi-Touch-App/"&gt;clicking this link&lt;/a&gt; or clicking the mage below:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://channel9.msdn.com/shows/SilverlightTV/Silverlight-TV-19-Hidden-Gems-from-MIX10-UFCs-Multi-Touch-App/"&gt;&lt;img title="3-31-2010 11-51-04 PM" border="0" alt="3-31-2010 11-51-04 PM" src="http://johnpapa.net/files/media/image/WindowsLiveWriter/SilverlightTV19HiddenGemsfromMIX10UFCsMu_14F2D/3-31-2010%2011-51-04%20PM_3.png" width="487" height="278" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;My buds channeled their inner Elvis (mosaic courtesy John Papa):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://johnpapa.net/silverlight/star-sightings-at-mix-10/"&gt;&lt;img border="0" src="http://johnpapa.net/files/media/image/WindowsLiveWriter/StarSightingsatMIX10_133BF/image_2.png" width="471" height="351" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Clockwise from top: &lt;a href="http://blogs.msdn.com/BradA/"&gt;Brad Abrams&lt;/a&gt;, &lt;a href="http://www.neverindoubtnet.blogspot.com/"&gt;moi&lt;/a&gt;, &lt;a href="http://scorbs.com/"&gt;Karen Corby&lt;/a&gt;, &lt;a href="http://weblogs.asp.net/dwahlin/"&gt;Dan Wahlin&lt;/a&gt;, &lt;a href="http://johnpapa.net/"&gt;John Papa&lt;/a&gt;, &lt;a href="http://timheuer.com/blog/"&gt;Tim Heuer&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This being April 1st and the garb verging on outrageous, you’re excused for doubting the seriousness of the interview.&lt;/p&gt;  &lt;p&gt;In fact, we explored many substantive issues:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;What we do at &lt;a href="http://www.ideablade.com/"&gt;IdeaBlade&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Why &lt;a href="http://www.silverlight.net/getstarted/riaservices/"&gt;WCF RIA Services&lt;/a&gt; … Why &lt;a href="http://www.ideablade.com/"&gt;DevForce&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Iterative development with high velocity and no database drag &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.silverlight.net/"&gt;Silverlight 4&lt;/a&gt;, multi-touch, out-of-browser, Windows 7 &lt;/li&gt;    &lt;li&gt;Kiosk design – the hard work of keeping it simple and obvious &lt;/li&gt;    &lt;li&gt;&lt;a href="http://devlicious.com/blogs/christopher_bennage/"&gt;Christopher Bennage&lt;/a&gt;, his consulting firm &lt;a href="http://www.bluespire.com/"&gt;BlueSpire&lt;/a&gt;, and &lt;a href="http://caliburn.codeplex.com/"&gt;Caliburn&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Feeling like a first class citizen of the Microsoft eco-system &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;And I think the demo showed well what you can do in two weeks by concentrating on the User Experience (UX) and leaving the plumbing to us.&lt;/p&gt;  &lt;p&gt;Who says business can’t be fun?&amp;#160;&amp;#160; We had a blast!&amp;#160;&amp;#160; Enjoy.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-1940328701722178994?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/1940328701722178994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=1940328701722178994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1940328701722178994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1940328701722178994'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/04/devforce-ufc-gym-bling-on-silverlight.html' title='DevForce / UFC Gym Bling On Silverlight TV'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-7681127830402357147</id><published>2010-03-31T13:58:00.001-07:00</published><updated>2010-03-31T13:58:42.932-07:00</updated><title type='text'>Of Tailors and Tooling (rant)</title><content type='html'>&lt;p&gt;Daniel asks a tailor to make him a suit. The tailor measures him and says “come back in three days.” &lt;/p&gt;  &lt;p&gt;Daniel returns to try on the suit. “&lt;em&gt;The left sleeve is too short&lt;/em&gt;” he complains. The tailor says “&lt;em&gt;Raise your right shoulder and drop the left shoulder and you’ll look great.&lt;/em&gt;” Daniel does and, sure enough, the two sleeves meet properly at the wrist.&lt;/p&gt;  &lt;p&gt;“&lt;em&gt;The left pant leg is too long&lt;/em&gt;” cries Daniel. “&lt;em&gt;No problem&lt;/em&gt;” says the tailor. “&lt;em&gt;Lift your left hip and walk on your toes.&lt;/em&gt;” Sure enough, both pant legs break beautifully just above the ankles. &lt;/p&gt;  &lt;p&gt;Daniel pays the tailor and ambles out to the street wearing his new suit. Another man approaches him and exclaims “&lt;em&gt;Wow, great suit! Who’s your tailor?&lt;/em&gt;”. Daniel beams and points to the tailor shop. “&lt;em&gt;He must be a terrific tailor&lt;/em&gt;,” says the man, “&lt;em&gt;to be able to fit a cripple like you!&lt;/em&gt;”&lt;/p&gt;  &lt;p&gt;I’m feeling like Daniel a lot lately. A number of us have been exploring implementation patterns for MVVM in complex, composite business applications. Just as we start getting somewhere promising … someone stops us short and says:&lt;/p&gt;  &lt;p&gt;“&lt;strong&gt;&lt;font color="#0000ff"&gt;&lt;em&gt;You can’t do that because it doesn’t work in Blend.&lt;/em&gt;&lt;/font&gt;&lt;/strong&gt;”&lt;/p&gt;  &lt;p&gt;Let me be clear. I think Blend is grand and am learning to appreciate its power. I desperately want to facilitate the best possible UX. I know I can’t design the visuals worth a damn. I realize the people who can are not programmers and shouldn’t be asked to become programmers. I get it. I will do what it takes to make Blendable Views … including adjusting my posture.&lt;/p&gt;  &lt;p&gt;But I’m not happy with show-stopper arguments like “&lt;em&gt;It won’t work in Blend.&lt;/em&gt;” That may be the reality today but it need not be my future. &lt;/p&gt;  &lt;p&gt;We should be honest about the consequences of saying “&lt;em&gt;it won’t work in Blend&lt;/em&gt;”. Make no mistake, we’re twisting and contorting our architectures to satisfy the present state of the tooling. &lt;/p&gt;  &lt;p&gt;Worse, we’re encouraging the tailor! &lt;/p&gt;  &lt;p&gt;Sometimes I believe he thinks it’s a good thing for us to slouch and droop uncomfortably down the street. He actually thinks it’s a good thing to build View first, to inscribe code in the XAML, to block access to design-time APIs, to resort to Behaviors for simple programming tasks. He can’t believe I need to inject dependencies in the ViewModel … perhaps because that means he’d have to confront his own inadequacies. &lt;/p&gt;  &lt;p&gt;I should get over it. Yet my hackles go up when I detect that smug, dismissive tone. &lt;/p&gt;  &lt;p&gt;Hey, if you have to say “&lt;em&gt;it won’t Blend&lt;/em&gt;” that’s an admission of failure. It means you’re not where you should be. I can deal with that. But stop sounding triumphant … as if what I want to do is stupid because it won’t Blend.&lt;/p&gt;  &lt;p&gt;Yes, please make the tooling great for the designer. But the developer is the customer too … never forget that. The tooling should change to suit me … not the other way around.&lt;/p&gt;  &lt;p&gt;Signed,&lt;/p&gt;  &lt;p&gt;Frustrated-in-CA &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-7681127830402357147?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/7681127830402357147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=7681127830402357147' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7681127830402357147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7681127830402357147'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/03/of-tailors-and-tooling-rant.html' title='Of Tailors and Tooling (rant)'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-4336212373005314384</id><published>2010-03-21T21:41:00.001-07:00</published><updated>2010-03-21T21:43:24.229-07:00</updated><title type='text'>Commands as XAML Resources</title><content type='html'>&lt;p&gt;I’m watching &lt;a href="http://live.visitmix.com/MIX10/Sessions/CL09" target="_blank"&gt;Nikhil Kothari’s talk at MIX 2010&lt;/a&gt; while I write. As with all things Nikhil, you owe it to yourself to take a look.&lt;/p&gt;  &lt;p&gt;The talk is nominally about developing with WCF RIA Services. It’s really about programming style. Most RIA Services demos are 100% drag-and-drop. You might think that’s the only way or the preferred way to write a RIA Services application.&lt;/p&gt;  &lt;p&gt;Not so!&amp;#160; … and Nikhil is determined to show a different path. A standing ovation from me for bucking that trend … while keeping it all accessible to a general development audience.&lt;/p&gt;  &lt;p&gt;I particularly liked the moment around the 31st minute when he uses SketchFlow to show how the View relates to a ViewModel.&lt;/p&gt;  &lt;p&gt;Scoot ahead to 35:40 and you’ll find Nikhil wiring ViewModel actions to View buttons via Commands that he’s instantiated as resources in the View. &lt;/p&gt;  &lt;p&gt;I’m intrigued by this approach even if I’m not completely sold on it. &lt;/p&gt;  &lt;h3&gt;The Problem&lt;/h3&gt;  &lt;p&gt;Silverlight lacks the means to directly bind view events (e.g., button clicks) to ViewModel actions (e.g., “Load Books”). That omission has spurred a variety of solutions: event handlers in code-behind, ViewModel commands wired by attached behaviors, and auto-wire-by-convention (Caliburn-style) to name a few.&lt;/p&gt;  &lt;p&gt;Nikhil has found another way to do it. We can leverage data binding and declare the hook-up in XAML using a simple resource rather than the more obscure behavior. It is quite seductive. Let me elaborate.&lt;/p&gt;  &lt;h3&gt;Button Binding&lt;/h3&gt;  &lt;p&gt;The button has a Command property which can be bound to an implementation of ICommand. &lt;/p&gt;  &lt;p&gt;In MVVM we strive to bind the View to members of the ViewModel. It seems natural for the ViewModel to expose ICommand implementations that we can bind to buttons in the View. I’ve done this myself … I hate to admit.&lt;/p&gt;  &lt;p&gt;Picking up on Nikhil’s example, our BookViewModel could present a “LoadBooksCommand” property that delivers an ICommand wrapper around the VM’s private “CanLoadBooks” and “LoadBooks” methods. &lt;/p&gt;  &lt;p&gt;To support this we write code in the ViewModel like so:&lt;/p&gt;  &lt;pre&gt;    private ICommand _loadBooksCommand = new Command(LoadBooks, CanLoadBooks);&lt;br /&gt;    public ICommand LoadBooksCommand { get { return _loadBooksCommand; } } &lt;/pre&gt;&lt;p&gt;Yuck. The ViewModel author is interested in “LoadBooks” and “CanLoadBooks”. These are the meat of the matter.&lt;/p&gt;&lt;p&gt;The ICommand is a View artifact that has crept into the ViewModel. The Command(…) isn’t even an instance of a .NET class; we have to get it as a helper from some framework ... Prism perhaps. The whole business is distracting kruft and a PITA. &lt;/p&gt;&lt;p&gt;Many of us just put up with it, writing those command pairs over and over.&lt;/p&gt;&lt;p&gt;Nikhil says “Let’s not pollute the ViewModel this way. Let’s refactor the Command back to the view where it belongs”. Our ViewModel will expose “CanLoadBooks” and “LoadBook”s publically just as we would any bindable property. No more ICommand nonsense. &lt;/p&gt;&lt;h3&gt;Command Resources&lt;/h3&gt;&lt;p&gt;In his SilverlightFx framework he’s defined a “Command” class that we can instantiate in XAML.&lt;/p&gt;&lt;p&gt;We create Command instances as resources in our view as follows:&lt;/p&gt;&lt;pre&gt;    &amp;lt;fx:Command x:Key=”loadCommand” Target=”{Binding}” Method=”LoadBooks” /&amp;gt;&lt;/pre&gt;&lt;p&gt;Notice that the target is the default binding which will be the ViewModel and the Method name corresponds to the method of that name in the ViewModel (I’m guessing he can infer the CanLoadBooks method as well).&lt;/p&gt;&lt;p&gt;Finally, we bind the “loadButton” Command property to the “loadCommand” resource. In the video, Nikhil uses the Cider designer for this purpose (so much for “no drag-and-drop”). You might prefer to tweak the XAML yourself:&lt;/p&gt;&lt;pre&gt;    &amp;lt;Button x:Name=”loadButton” Command=”{StaticResource loadCommand}&amp;quot; ...  /&amp;gt;&lt;/pre&gt;&lt;h3&gt;What’s Not To Like?&lt;/h3&gt;&lt;p&gt;I guess it’s ok. Nikhil is making the better of a bad situation, namely, that we cannot yet bind View events to ViewModel methods.&lt;/p&gt;&lt;p&gt;We require a trick shot. We bank the binding cue ball from the button’s Command property off of a static resource at the top of the XAML file and into the ViewModel “LoadBooks” hole. I am not happy about that. I’d prefer to bind the button directly to my ViewModel. On the other hand, I dislike the ICommand crap in my ViewModel. If I must choose between the two, I’m reluctantly inclined toward Nikhil’s approach.&lt;/p&gt;&lt;p&gt;Of course they both breakdown when you need to wire a ViewModel method to anything other than a button Command property. What do you do for the SelectionChanged event of a ComboBox? You can’t bind to that as you can “Button.Command”. You’ll have to reach for a different trick – an attached property perhaps – to do what is essentially the same thing.&lt;/p&gt;&lt;h3&gt;Bind By Convention&lt;/h3&gt;&lt;p&gt;That’s why I’m increasingly enamored of Rob Eisenberg’s “bind-by-convention” approach which he &lt;a href="http://live.visitmix.com/MIX10/Sessions/EX15" target="_blank"&gt;showed at MIX&lt;/a&gt;. I can write&lt;/p&gt;&lt;pre&gt;  &amp;lt;Button x:Name=”LoadBooks” /&amp;gt;&lt;/pre&gt;&lt;p&gt;and Rob’s little framework will both find and wire up my ViewModel’s “LoadBooks” and “CanLoadBooks” methods.&lt;/p&gt;&lt;p&gt;If my ComboBox looks like this:&lt;/p&gt;&lt;pre&gt; &amp;lt;ComboBox x:Name=”Books” /&amp;gt;&lt;/pre&gt;&lt;p&gt;and if my ViewModel has &amp;quot;Books&amp;quot;, &amp;quot;SelectedBook&amp;quot; and &amp;quot;BooksChanged&amp;quot; methods, he'll bind the ComboBox's ItemsSource, SelectedItem and SelectionChanged events for me. &lt;/p&gt;&lt;p&gt;There’s no fuss, no muss whether I’m binding Buttons, ListBoxes, TextBoxes, whatever. And I can always go old-school when the naming conventions fail me. Pretty sweet.&lt;/p&gt;&lt;p&gt;A minor downside with Rob’s approach is the lack of tooling support. Intellisense doesn’t kick in when I’m setting a control’s Name property. I can live with that … especially because his full framework comes with diagnostics that tell me which expected bindings are missing at runtime.&lt;/p&gt;&lt;h3&gt;Summing Up&lt;/h3&gt;&lt;p&gt;I’m all too used to the ICommand-in-ViewModel and I know I don’t love that. I have a feeling that Nikhil’s Command Resource is a better way. It’s certainly more elegant.&lt;/p&gt;&lt;p&gt;Bind-by-convention is the most appealing choice. But I’ll withhold final judgment until I have more experience with it.&lt;/p&gt;&lt;p&gt;You’ll want to watch Nikhil’s talk in any case to get a more rounded view of your choices. He ranges over more ground than commanding … commanding is perhaps 10 minutes of a one hour talk. Check it out.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-4336212373005314384?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/4336212373005314384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=4336212373005314384' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4336212373005314384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4336212373005314384'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/03/commands-as-xaml-resources.html' title='Commands as XAML Resources'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-3856085955731925741</id><published>2010-03-19T18:19:00.001-07:00</published><updated>2010-03-19T18:19:40.987-07:00</updated><title type='text'>Rob E’s Mini-MVVM Framework @ MIX10</title><content type='html'>&lt;p&gt;Rob Eisenberg’s MIX 2010 talk, “&lt;a href="http://live.visitmix.com/MIX10/Sessions/EX15" target="_blank"&gt;Build Your Own MVVM Framework&lt;/a&gt;” was terrific. If you feel modestly comfortable with MVVM, run over and get the video and the code.&lt;/p&gt;  &lt;p&gt;Rob may be best known for his &lt;a href="http://caliburn.codeplex.com/" target="_blank"&gt;Caliburn&lt;/a&gt; WPF/Silverlight Presentation Development Framework. That’s a hefty body of work and if the word “framework” sends an unpleasant shiver down your spine … &lt;em&gt;relax yourself&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;The “framework” demonstrated at MIX is roughly 500 lines (says Rob … I haven’t checked yet &amp;lt;grin/&amp;gt;). It’s based on Caliburn but stripped to essentials that Rob covered in an easy-to-follow, leisurely, one hour code-walk.&lt;/p&gt;  &lt;p&gt;Highlights:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Simple MVVM      &lt;ul&gt;       &lt;li&gt;&amp;quot;VM first&amp;quot; in the sense that VM is in the driver's seat. &lt;/li&gt;        &lt;li&gt;No impediment to &amp;quot;View first&amp;quot; in the sense of view-design drives VM-design. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Simple naming conventions eliminate tedious code and XAML&lt;/li&gt;    &lt;li&gt;Configuration at-the-ready when conventions fail &lt;/li&gt;    &lt;li&gt;No code-behind … and didn’t miss it &lt;/li&gt;    &lt;li&gt;No behaviors … and didn’t miss them (not that they’d be bad) &lt;/li&gt;    &lt;li&gt;No XAML data binding; debuggable bindings created at runtime&lt;/li&gt;    &lt;li&gt;No drag-and-drop binding … and didn’t miss it&lt;/li&gt;    &lt;li&gt;No ICommand implementations and no event handlers &lt;/li&gt;    &lt;li&gt;No files over 150 lines (as I remember)&lt;/li&gt;    &lt;li&gt;Cool co-routines for programming a sequence of sync and async tasks; no call backs in the ViewModel &lt;/li&gt;    &lt;li&gt;Screen Conductor pattern in play&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;All that in one hour.&lt;/p&gt;  &lt;p&gt;The “co-routine” trick alone is worth your time. You almost get F# “bang” syntax in C#.&lt;/p&gt;  &lt;p&gt;It could get more complicated in your app … and you’d have Caliburn. But it might not&amp;#160; … and you’d be living large with dead-simple, DRY code.&lt;/p&gt;  &lt;p&gt;One of the best sessions ever.&lt;/p&gt;  &lt;p&gt;If only we could teach Rob to emote. The guy is passionate on the subject but you might miss it behind that mono-tone voice of his. A &lt;a href="http://movies.msn.com/celebrities/celebrity/jim-carrey/" target="_blank"&gt;Jim Carrey&lt;/a&gt; he is not. You want entertainment? Look elsewhere. You want substance … tune in.&lt;/p&gt;  &lt;p&gt;He got a big ovation, by-the-by, so it ain’t just me who liked it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-3856085955731925741?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/3856085955731925741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=3856085955731925741' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/3856085955731925741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/3856085955731925741'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/03/rob-es-mini-mvvm-framework-mix10.html' title='Rob E’s Mini-MVVM Framework @ MIX10'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-7607573991355234784</id><published>2010-03-19T12:26:00.001-07:00</published><updated>2010-03-19T16:23:05.075-07:00</updated><title type='text'>MVVM, Josh Smith’s Way</title><content type='html'>&lt;p&gt;I’ve long admired &lt;a href="http://joshsmithonwpf.wordpress.com/" target="_blank"&gt;Josh Smith&lt;/a&gt;’s work. He’s one of the best explainers on the web and he – together with Karl Shifflett and Andrew Smith - gave us &lt;a href="http://joshsmithonwpf.wordpress.com/mole/" target="_blank"&gt;Mole&lt;/a&gt;, the superb WPF Visual Studio debugger visualizer.&lt;/p&gt;&lt;p&gt;I heard recently that he’d published an e-book on Model-View-ViewModel (MVVM). I met him for the first time at the Microsoft MVP Summit last week and he graciously handed me a printed copy. I devoured it on the plane home and spent the next day playing with the code and preparing this review. &lt;/p&gt;&lt;p&gt;It’s called “&lt;strong&gt;Advanced MVVM&lt;/strong&gt;” and you can buy a &lt;a href="http://www.lulu.com/content/paperback-book/advanced-mvvm-(hard-copy)/8353355" target="_blank"&gt;printed copy&lt;/a&gt; for $20 or get it for $15 &lt;a href="http://www.amazon.com/Advanced-MVVM-ebook/dp/B0038KX9FW" target="_blank"&gt;on the Kindle&lt;/a&gt;. The companion code is freely available at &lt;a href="http://AdvancedMvvm.com" target="_blank"&gt;AdvancedMvvm.com&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;$15 bucks for a 52 page “book”?&lt;/strong&gt; It’s more of an extended essay to be honest … an essay with code. After spending some pleasurable hours with both book and code I thought “&lt;em&gt;where do you get that kind of entertainment / self-reflection for $15?&lt;/em&gt;” I have a surfeit of 600 page sleepers lounging on my bookshelf at home; paid more then $50 for each and hardly cracked them. Should we pay by the pound? So I’m over it. I don’t mind paying for the hours Josh poured in and the fun I got out. Set your expectations appropriately and you’ll feel fine.&lt;/p&gt;&lt;p&gt;---- 19 March 2010 Note ---&lt;/p&gt;&lt;p&gt;Ok, it’s been a month or so since I wrote this. Life happens while you’re making plans. I intended to be among the first to comment on it. I’m late to that party (although I have deliberately NOT looked at what others may have said) so I’m not sure if it’s still timely. I also shared it with Josh last week to see if I had missed something and get his feedback, particularly in light of my critical remarks.&lt;/p&gt;&lt;p&gt;He encouraged me to publish it even at this late date. I hope he’ll repost here some of his responses to the points I raised.&lt;/p&gt;&lt;p&gt;----------------------------------&lt;/p&gt;&lt;p&gt;MVVM has spooked a lot of developers. There’s more than a whiff of &lt;a href="http://www.joelonsoftware.com/articles/fog0000000018.html" target="_blank"&gt;astronaut architecture&lt;/a&gt; about it. There have to be at least 20 MVVM frameworks and no end of contentious arguments to confound and distress you. No wonder so many are put off.&lt;/p&gt;&lt;h3&gt;MVVM in a Nutshell&lt;/h3&gt;&lt;p&gt;In fact MVVM is fundamentally a simple idea. It starts with the realization that your application is an intractable mess in part because you dumped all of your UI logic into the code-behind … with the help of Microsoft tools. You discover the wisdom of pulling much of that logic out into a companion class (and some helpers) leaving the view class to concentrate on looking pretty and capturing user gestures. The view and its companion must talk; you can structure their conversation according to a variety of familiar patterns. Model-View-ViewModel is one such pattern.&lt;/p&gt;&lt;p&gt;The predominance of automated binding is the hallmark of MVVM. You bind a View’s textbox to a string-providing property of the ViewModel so that a user’s changes in the textbox flow to the property and so that programmatic changes to the ViewModel property flow back to the textbox. You bind View events (e.g., button click) to event handlers in the ViewModel enabling user gestures to be conveyed to the ViewModel.&lt;/p&gt;&lt;p&gt;You could write your own bindings by hand, pushing and pulling data and events with custom code. That’s a lot of work. The XAML-based client technologies (WPF and Silverlight) provide a binding framework that requires little to no custom coding. In most cases you can “connect the dots” declaratively and it just works.&lt;/p&gt;&lt;p&gt;Now the View concentrates on appearance and the ViewModel feeds the view. This separation is both clarifying and liberating. You can start looking at that ViewModel to figure out what it should do and how it should do it without also worrying about the visuals. The subsequent examination of ViewModel’s more limited responsibilities sets you on a more sustainable course. At least this has been my experience … and that of the hundreds (thousands?) of other developers who’ve adopted this pattern.&lt;/p&gt;&lt;p&gt;Now you’ll note that I said it “sets you on course”; I did not say it delivers you to the promised land. There are details to work out. If the View looks to the ViewModel for data, where does the ViewModel get that data? Are we talking about data values alone or the business rules that surround that data, rules about data validity, integrity, security, and persistence?&lt;/p&gt;&lt;p&gt;Many of us draw a circle around these concerns and call that circle “the Model”, the third element in the MVVM triad. Our guiding intuition is this: “the persistent data are definitely in the model and if the rules about data are true for this and every possible UI, the rules belong in the model as well.”&lt;/p&gt;&lt;p&gt;If the last name is required, it is required everywhere; that’s a model rule. If gold customers can select from several thank-you gifts, that sounds like UI logic to me … and belongs in the ViewModel. The specifics have to be worked out.&lt;/p&gt;&lt;h3&gt;Back To Josh&lt;/h3&gt;&lt;p&gt;At this point the discussion risks slipping into theory and theater. We could run to the white board, scribble madly, and count angels on pins without writing a line of code. I love doing that.&lt;/p&gt;&lt;p&gt;Josh has taken another direction which is likely to be both more popular and more effective. He briefly presents his take on MVVM in clear, accessible prose … and then makes it tangible with an extended exploration of a meaty sample application. I’ve read plenty of pattern papers; I don’t remember any that were so thorough … and entertaining … in their examples. &lt;/p&gt;&lt;p&gt;For style and substance this is a remarkable achievement. I truly hope that Josh’s book is widely read because I think it has a better chance of helping WPF and Silverlight developers feel comfortable about MVVM than anything else I’ve seen. &lt;/p&gt;&lt;p&gt;I’m a little worried that some will fear the word “Advanced” in the title. The term “MVVM” is forbidding enough and many folks are still looking for the introduction. I think this book is the introduction they really need. &lt;/p&gt;&lt;p&gt;In what sense is it “advanced”? It’s far from the last word on the subject. It won’t settle any arguments (least of all mine). But it does rise above the introductory level in two important respects. &lt;/p&gt;&lt;p&gt;First, it considers the implications of multiple, cooperating MVVM instances. Most MVVM articles present a single MVVM-triad: a single View and its companion ViewModel and Model. &lt;/p&gt;&lt;p&gt;No application needs a single MVVM triad. If you have a one-screen application, don’t use MVVM; it’s overkill. MVVM is for multi-screen applications consisting of multiple MVVM triads which spring to life somehow and somehow interoperate.&lt;/p&gt;&lt;p&gt;Second, as I noted earlier, Josh doesn’t just talk about the pattern. Most of the pages describe the accompanying game, &lt;strong&gt;BubbleBurst&lt;/strong&gt;, which is implemented in MVVM style. Instead of paeans to principles and their wondrous benefits, you see MVVM in action, warts and all. &lt;/p&gt;&lt;p&gt;BubbleBurst is “advanced” enough to both introduce MVVM and reveal important implementation challenges of multi-MVVM applications. Yet it’s simple enough to be easily understood in the pages of a book or in a few hours spent trolling the code. It’s also fun to play.&lt;/p&gt;&lt;h3&gt;Proceed with Caution&lt;/h3&gt;&lt;p&gt;I’m about to begin my critical remarks. Before I do, I want to reemphasize my enthusiasm for what Josh has accomplished. This book is a wonderful place to begin your MVVM journey and I found it to be an enjoyable and insightful read. So, hell-yes, I’m recommending it.&lt;/p&gt;&lt;p&gt;On the other hand, it would be a shame if developers stopped their education here. Important elements of the story are missing and many recommendations are seriously misguided in my view. Readers should take Josh seriously but, once they are comfortable with the pattern, they should become aware of starkly contrasting perspectives as well.&lt;/p&gt;&lt;h3&gt;Critical Omissions&lt;/h3&gt;&lt;p&gt;Four vital topics are neither covered nor illustrated in the &lt;a href="http://bubbleburst.codeplex.com/" target="_blank"&gt;code&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Testing &lt;/li&gt;&lt;li&gt;Model (the first ‘M’ in MVVM) &lt;/li&gt;&lt;li&gt;Dependency Injection &lt;/li&gt;&lt;li&gt;Event Aggregation &lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Testing&lt;/h4&gt;&lt;p&gt;Josh asks “&lt;em&gt;What is the point of having ViewModels?&lt;/em&gt;” First among his reasons: “&lt;em&gt;the ability to easily write unit and integration tests for the functionality of the user interface without having to get into the messy world of writing tests for live UIs.&lt;/em&gt;”&lt;/p&gt;&lt;p&gt;That’s the last we hear of testing. There is not a single test in the code base. If testing is as important as he says, I’d expect a thorough treatment starting with building a test regimen and showing, by example, how to write good tests. Instead, we get lip service.&lt;/p&gt;&lt;p&gt;I don’t think testability is the only value of MVVM. I couldn’t recommend it for this reason alone. MVVM is a significant architectural investment that introduces complexity. I wouldn’t incur that complexity cost merely to make my UI testable. I’d look for a less onerous route. Fortunately, I think it has other benefits such as clean separation of concerns, improved readability, and easier debugging (try break-pointing XAML!).&lt;/p&gt;&lt;p&gt;But testability is both a motivation for and a by-product of MVVM style and it should have been covered thoroughly in an “advanced” treatise on MVVM.&lt;/p&gt;&lt;p&gt;Moreover, the design would have benefitted greatly from attempts to test it. Many lines of view code-behind are both untestable and harder to follow than they should be. I see early signs of the spaghetti code that afflicts more complex and mature applications … a drum I’ll beat furiously later in this review.&lt;/p&gt;&lt;p&gt;At almost 300 lines, the BubbleMatrixViewModel begs to be tested both for quality and to reveal the expectations latent in its 20+ public and internal members.&lt;/p&gt;&lt;h4&gt;The Missing Model&lt;/h4&gt;&lt;p&gt;The pattern is called &lt;strong&gt;&lt;em&gt;Model&lt;/em&gt;&lt;/strong&gt;-View-ViewModel. Josh’s Model is nowhere to be found. Model and ViewModel are combined and it’s not clear to me how one would disambiguate them.&lt;/p&gt;&lt;p&gt;The absence of Model isn’t blatantly obvious in a simple game like BubbleBurst. The game doesn’t to retrieve or save objects to a persistent store. We aren’t expecting much in the way of business model logic either; there’s nothing of interest to validate or secure. So the lack of a model is not a deep fault of this particular application. Indeed, it’s a convenient way to concentrate our attention on the central issues for most students of MVVM:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;What code belongs in View and what code in ViewModel? &lt;/li&gt;&lt;li&gt;How do View and ViewModel interact? &lt;/li&gt;&lt;li&gt;How do you instantiate Views and ViewModels? &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Nonetheless, we can’t pretend to provide a comprehensive guide to MVVP without talking about the Model and how it interacts with ViewModel and (to a lesser extent) View. A business application will demand a clear delineation of responsibilities and equally clear communication paths.&lt;/p&gt;&lt;p&gt;I’m not letting BubbleBurst off the hook either. I felt on several occasions that some ViewModels were heavier and more complicated than they should be because an inchoate game model was not independently defined.&lt;/p&gt;&lt;h4&gt;Dependency Injection&lt;/h4&gt;&lt;p&gt;I appreciate that Dependency Injection frightens many developers. You can discover MVVM without learning about Dependency Injection. Josh can kind of get away without it as long as he doesn’t test his ViewModels and doesn’t have to think about the services required to manage a persistent model.&lt;/p&gt;&lt;p&gt;But I feel you can’t call this “Advanced MVVM” … or even “Intermediate MVVM” … without introducing DI at some point. In Josh’s application, every View and every ViewModel class is known to and instantiated by some other View or ViewModel class. That won’t fly in real-world applications which have Views and ViewModels that are ignorant of each other.&lt;/p&gt;&lt;p&gt;The constructor of the BubbleMatrixViewModel instantiates three concrete bubble components: BubblesTaskManager, BubbleFactory, and BubbleGroup (twice) before making heavy use of them.  That’s a lot of dependencies that would make this ViewModel brittle and especially difficult to test.&lt;/p&gt;&lt;p&gt;Taking hard dependencies means Josh can freely assume that ViewModels will always have parameterless constructors and can always be instantiated in XAML, as he often does here. Someone new to MVVM might think this is the norm. It is not.&lt;/p&gt;&lt;p&gt;Josh himself alludes to DI as one of the avenues opened by the MVVM pattern: “&lt;em&gt;[MVVM] means that you can use frameworks like MEF to dynamically compose your ViewModels, to easily support plug-in architectures …”.&lt;/em&gt; That’s the last we hear of MEF or dynamic VM composition.&lt;/p&gt;&lt;p&gt;Again, I think we can ignore DI in an introduction to MVVM; we cannot ignore it in an advanced lesson on MVVM.&lt;/p&gt;&lt;h4&gt;Event Aggregation: communicating with the unknown&lt;/h4&gt;&lt;p&gt;All of Josh’s MVVM triads are statically determined. Their relationships to each other are fixed and well known.&lt;/p&gt;&lt;p&gt;I was surprised to see a ViewModel for one view hold a reference to a ViewModel of a subordinate view. That’s not how I do it; my general rule is that MVVM triads do not hold references to each other. I concede that the rule makes it difficult to organize cross-triad communication. Josh’s approach is simple and elegant … when available.&lt;/p&gt;&lt;p&gt;In real-world business applications, the MVVM triads often can’t know about each other. They are often defined in separate modules without mutual references. Views appear and disappear dynamically. Direct communication is frequently impossible.&lt;/p&gt;&lt;p&gt;That’s why so many so-called MVVM frameworks include some kind of messaging or &lt;a href="http://www.martinfowler.com/eaaDev/EventAggregator.html" target="_blank"&gt;Event Aggregation&lt;/a&gt; infrastructure. You don’t need them to understand MVVM triads in isolation. But you never see an application with a single MVVM triad and you rarely find an MVVM application with statically determined, session-permanent views. No “advanced” treatment of MVVM can neglect Event Aggregation.&lt;/p&gt;&lt;h3&gt;View First or ViewModel First?&lt;/h3&gt;&lt;p&gt;Here’s an incendiary topic Josh leaves untouched.&lt;/p&gt;&lt;p&gt;I see two ways to ask this question:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Do I &lt;strong&gt;&lt;em&gt;design&lt;/em&gt;&lt;/strong&gt; the View first or the ViewModel first? &lt;/li&gt;&lt;li&gt;Do I &lt;strong&gt;&lt;em&gt;instantiate&lt;/em&gt;&lt;/strong&gt; the View first or the ViewModel first (or does something else instantiate and wed them)? &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The answer to both questions need not be the same. For example, you could decide to &lt;strong&gt;&lt;em&gt;design&lt;/em&gt;&lt;/strong&gt; the ViewModel first and let the View &lt;strong&gt;&lt;em&gt;instantiate&lt;/em&gt;&lt;/strong&gt; that VM at runtime. This is plausibly the approach advocated in BubbleBurst although Josh never talks about it.&lt;/p&gt;&lt;p&gt;Again, it’s important that readers new to MVVM learn that Josh’s way is not the only way.&lt;/p&gt;&lt;h4&gt;View and ViewModel Design&lt;/h4&gt;&lt;p&gt;In my experience there is a “dialog” between View and ViewModel design. The VM exists to serve a view even as it strives for independence from any particular concrete view. A VM is useless if  there is no view that will work with it; clearly the VM developer must heed the imprecations of the View developer.&lt;/p&gt;&lt;p&gt;On the other hand, in business applications the application’s imperatives – what the view must do to satisfy business requirements – are the province of the programmer and are best articulated through the capabilities of the ViewModel. &lt;/p&gt;&lt;p&gt;Therein lies the necessary tension between View and ViewModel design. As a developer my allegiance is with the ViewModel (“the application should do something worthwhile”) but it would be silly to defend that allegiance at the expense of the View (“a good UX is essential to making an application easy to learn and to use”).&lt;/p&gt;&lt;p&gt;I’d have liked to see this tension at least acknowledged and perhaps explored.&lt;/p&gt;&lt;h4&gt;Who begets Whom?&lt;/h4&gt;&lt;p&gt;Runtime construction is a question apart from the matter of who drives the design. WPF and Silverlight tooling push you toward “View First” construction in which the View instantiates the ViewModel. You’ll often see the View’s DataContext set by a ViewModel instantiated in the XAML as shown here:&lt;/p&gt;&lt;pre&gt;  &amp;lt;UserControl.DataContext&amp;gt;&lt;br /&gt;     &amp;lt;viewModel:&lt;strong&gt;BubbleBurstViewModel&lt;/strong&gt; /&amp;gt;&lt;br /&gt;  &amp;lt;/UserControl.DataContext&amp;gt;&lt;/pre&gt;&lt;p&gt;Contrast this with the ViewModel first, code-based approach (not seen in BubbleBurst) in which the ViewModel is assigned to the View’s DataContext as follows:&lt;/p&gt;&lt;pre&gt; view.DataContext = viewModel;&lt;/pre&gt;&lt;p&gt;The View First approach assumes that the ViewModel can be created via a default, parameterless constructor. That’s fine for BubbleBurst but wholly unrealistic in business applications whose ViewModels have dependencies (e.g., on the domain model).&lt;/p&gt;&lt;p&gt;Neither WPF nor Silverlight XAML support the dependency injection mechanisms that many of us prefer. I wish Josh had talked about this and perhaps discussed the interesting attempts to use MEF dependency injection (via properties rather than constructor arguments)&lt;/p&gt;&lt;p&gt;I’m not trying to settle these questions. I am saying these questions could have been called out in an “advanced” book on MVVM patterns.&lt;/p&gt;&lt;h3&gt;What Belongs In Code-Behind?&lt;/h3&gt;&lt;p&gt;Do we allow or prohibit code-behind? That’s a fist-fight topic. Josh looks for a Goldilocks solution, suggesting the amount of code-behind is just right if confined to “logic scoped to the view”.&lt;/p&gt;&lt;p&gt;Such guidance is far too loose in my opinion. It’s not effective guidance at all.&lt;/p&gt;&lt;p&gt;We choose presentation separation patterns in part because we want to minimize testing of the view. We should test any custom logic we write – no matter how it is scoped. The poverty of our testing tools means that, in practice, we will not test the code in the view. Therefore, any code in the code-behind is suspect.&lt;/p&gt;&lt;p&gt;I am open to some code in the code-behind; the “InitializeComponent” method is inescapable. I’ll accept a minimum of “switch board” code in the code behind; direct wiring to a ViewModel member is ok in small doses.&lt;/p&gt;&lt;p&gt;I draw the line at decision logic. I smell a rat when I see a conditional statement of any kind. That’s where bugs breed. Conditional logic is code we should be testing.&lt;/p&gt;&lt;p&gt;I much prefer this rule: “&lt;strong&gt;No conditional logic in the code-behind&lt;/strong&gt;”.&lt;/p&gt;&lt;p&gt;That’s unambiguous. We don’t have to wonder what “&lt;em&gt;scope of the view&lt;/em&gt;” means. If there’s an “if” or a “switch” statement, something is wrong. You can detect a violation with automation or visual inspection. It’s a rule that’s easy to follow and pretty easy to abide by … when you know how.&lt;/p&gt;&lt;p&gt;What happens when you don’t follow this rule? You’re lured into the kind of dodgy code that … well we see in the innocent seeming BubbleMatrixView.xaml.cs.&lt;/p&gt;&lt;p&gt;In fact, far from being “best practices”, I’d say that the View code in BubbleBurst represents some of the worst practices.&lt;/p&gt;&lt;p&gt;Look at the HandleMatrixDimensionsAvailable method. This event handler is wired to a UI element in the BubbleBurstView. Unfortunately, the UI element happens to be in a different view, the BubbleMatrixView! One view’s code-behind is wired to members of another view; that’s the road to perdition. That would never pass my review.&lt;/p&gt;&lt;p&gt;I wanted to clean it up immediately. I tried to find the intention behind this practice. Usually I look to the name of a method to discover its purpose. Unfortunately the handler is named for the moment when it is called (“Matrix dimensions available”) rather than for what it does. That’s conventional naming for event handlers but not terribly informative. Unless a handler is brain-dead-simple, I have it delegate immediately to methods with meaningful names. The handler tells me when something happens; the inner method tells me what will be done.&lt;/p&gt;&lt;p&gt;Had Josh adopted my suggestion, he’d have realized that his handler has multiple responsibilities:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;wires the outer window’s keydown event&lt;/li&gt;&lt;li&gt;picks up the dimensions of the related view’s grid &lt;/li&gt;&lt;li&gt;starts the game &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That’s too much work for code-behind in my book.&lt;/p&gt;&lt;p&gt;When we strive to apply the “&lt;em&gt;no conditional logic in the code-behind&lt;/em&gt;” rule, we discover other design problems.&lt;/p&gt;&lt;p&gt;It appears that Undo logic is distributed between two ViewModels. One of them, the BubbleBurstViewModel, determines if undo is possible while the second, BubbleMatrixViewModel performs the undo. Probe further and we find that even the BubbleBurstViewModel test for undo-ability is delegated back to the BubbleMatrixViewModel. The ping-ponging among Views and ViewModels is confusing; it doesn’t smell right.&lt;/p&gt;&lt;p&gt;All the signs suggest the real action is in BubbleMatrixView and its ViewModel.&lt;/p&gt;&lt;p&gt;BubbleMatrixView.xaml is short and sweet.The code-behind in BubbleMatrixView.xaml.cs is another story. Five Region tags sound the alarm. You shouldn’t need region tags in code-behind. Here they barely disguise the complexity of 145 lines of code-behind. That can’t be right.&lt;/p&gt;&lt;h3&gt;MicroControllers: BubblesTaskPresenter Example&lt;/h3&gt;&lt;p&gt;I was able to refactor the 53 lines dedicated to animating bubble tasks. Most of them went to a BubblesTaskPresenter class, a component Jeremy Miller calls the “&lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/10/21/build-your-own-cab-15-microcontrollers.aspx" target="_blank"&gt;MicroController&lt;/a&gt;”.&lt;/p&gt;&lt;p&gt;Every MVVM developer should become familiar with the “MicroController” approach.&lt;/p&gt;&lt;p&gt;A “MicroController” performs a narrow UI task on behalf of a view. We usually write one to encapsulate UI logic that is reused across multiple views. That’s not the case here; the application is too small.&lt;/p&gt;&lt;p&gt;We also write MicroControllers to encapsulate UI-specific functionality in a UI-agnostic wrapper. They make it easy for non-UI components, such as ViewModels, to invoke the UI-specific behavior we find in Views. That’s what we need here.&lt;/p&gt;&lt;p&gt;I noticed that the ViewModel holds a TaskManager which raises a PendingTasksAvailable event when there are bubble display tasks. This sets off a sequence of calls between View and ViewModel which collectively “process tasks” queued up by the ViewModel.&lt;/p&gt;&lt;p&gt;Josh’s original code forwarded the event to the View’s code-behind. That code-behind then extracted the VM’s TaskManager and called into it. 53 lines of code-behind are dedicated to this entire process.&lt;/p&gt;&lt;p&gt;After my revision, the view merely provides the ViewModel with a configured MicroController, here called a “BubblesTaskPresenter”:&lt;/p&gt;&lt;pre&gt; _bubbleMatrix.BubblesTaskPresenter = new BubblesTaskPresenter(_bubbleCanvas);&lt;/pre&gt;&lt;p&gt;This is what switchboard code should look like. I’d like to get rid of the instantiation but at least there is a bare minimum of logic and no conditionals.&lt;/p&gt;&lt;p&gt;The ViewModel receives the concrete presenter in the guise of a UI-agnostic interface, IBubblesTaskPresenter and wires itself to the presenter’s events.&lt;/p&gt;&lt;pre&gt;    public IBubblesTaskPresenter BubblesTaskPresenter {&lt;br /&gt;      get { return _bubblesTaskPresenter;}&lt;br /&gt;      set {&lt;br /&gt;        _bubblesTaskPresenter = value;&lt;br /&gt;        _bubblesTaskPresenter.Completed += delegate { ProcessTasks(); };&lt;br /&gt;        TaskManager.PendingTasksAvailable += delegate { ProcessTasks(); };&lt;br /&gt;      }&lt;br /&gt;    }&lt;/pre&gt;&lt;pre&gt;    private void ProcessTasks() {&lt;br /&gt;      var task = TaskManager.GetPendingTask();&lt;br /&gt;      BubblesTaskPresenter.PresentTask(task);&lt;br /&gt;    }&lt;/pre&gt;&lt;p&gt;IBubblesTaskPresenter uses simple .NET types and looks like this:&lt;/p&gt;&lt;pre&gt;  /// &amp;lt;summary&amp;gt;&lt;br /&gt;  /// Interface for a presenter of &amp;lt;see cref="BubblesTask"/&amp;gt;&lt;br /&gt;  /// &amp;lt;/summary&amp;gt;  &lt;br /&gt;  public interface IBubblesTaskPresenter {&lt;br /&gt;     void PresentTask(BubblesTask task);&lt;br /&gt;     event EventHandler Completed;&lt;br /&gt; }&lt;/pre&gt;&lt;p&gt;Where did the 53 lines of code-behind go? Into the BubblesTaskPresenter.&lt;/p&gt;&lt;p&gt;What has been gained? Did I just hide the pea under another untestable cup called a “presenter”? Is this merely an academic exercise?&lt;/p&gt;&lt;p&gt;I don’t think so. True, the presenter is dependent upon WPF and upon BubbleCanvas in particular. But it could be tested with a faked canvas and a faked factory. Testing aside, it’s small and focused; it’s easy to see what it does and how it works. It won’t get lost amidst the other motions of the BubbleMatrixView. We might someday use it in another view that presented BubblesTasks.&lt;/p&gt;&lt;p&gt;The BubbleMatrixViewModel has grown a few lines but remains readable and testable; its imported IBubblesTaskPresenter is easy to fake.&lt;/p&gt;&lt;p&gt;The ViewModel no longer exposes the TaskManager. That’s a good thing because the TaskManager is pretty complex piece of machinery with a rich API. We don’t want the View or BubblesTaskPresenter to know about it.&lt;/p&gt;&lt;p&gt;And the View is 53 lines lighter, reducing the anxiety we might justifiably feel if we handed it over to a non-programming designer for styling.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Homework Assignment&lt;/strong&gt;: if you’re playing along and are looking toward your own application design, you might want to linger over the BubblesTaskPresenter. It is specific to bubbles right now … which is appropriate in the absence of forces that would drive us to generalization. &lt;/p&gt;&lt;p&gt;But you can encapsulate storyboard animations in much this way to both determine state changes within the ViewModel and externalize the animations in “View-space” where they belong. Josh is spot-on when he insists on this separation. The MicroController “presenter” approach is one way to achieve that separation without polluting the code-behind.&lt;/p&gt;&lt;p&gt;Aside: my first presenter was more abstract and general purpose. My generalization was premature. Generalization made the code more complex than it needed to be in this application. I un-factored it to the current version that knows about BubbleCanvas and BubblesTaskStoryboardFactory.&lt;/p&gt;&lt;h3&gt;Views Shouldn’t Talk To Views&lt;/h3&gt;&lt;p&gt;After clearing out the 53 lines, I was able to focus on what’s left.&lt;/p&gt;&lt;p&gt;I was deeply troubled by the properties of BubbleMatrixView that are exposed to and consumed by the BubbleBurstView code-behind. That can’t be right. Views shouldn’t need custom properties. &lt;/p&gt;&lt;p&gt;If you have to expose a custom view member, you should do so through a view interface. We don’t want any code – View or ViewModel – depending upon a concrete view class. That’s asking for trouble and flies in the face of the testability which justifies MVVM.&lt;/p&gt;&lt;p&gt;It’s also completely unnecessary in this application. As noted earlier the event loop from inner BubbleMatrixView to outer BubbleBurstView leads back around to BubbleMatrixView’s ViewModel. We can cut all that nonsense out and simply update the BubbleMatrixViewModel directly in the code-behind … without any conditional logic.&lt;/p&gt;&lt;p&gt;I refactored as follows:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Removed 30 lines from BubbleBurstView code-behind &lt;/li&gt;&lt;li&gt;Added “StartTheGame” to BubbleMatrixViewModel; it combines the functions of setting the dimensions (now private) and starting a new game. &lt;/li&gt;&lt;li&gt;Removed 61 lines from BubbleMatrixView code-behind which now calls StartTheGame when the canvas is loaded. Region tags are gone. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The BubbleMatrixView code-behind is now a trim 30 lines with no conditionals, down from 145 (80% reduction). Of the 30, exactly 5 of them do work.&lt;/p&gt;&lt;p&gt;My cleanup involved eliminating several null checks. They never did anything useful. First, the variables could not be null in practice. Second, even if they were (e.g., someone broke the xaml), the application would not have functioned anyway. I don’t think a blank screen is superior to an exception. The null checks were about as helpful as empty catch blocks.&lt;/p&gt;&lt;h3&gt;Tidy-up BubbleBurstView Code-Behind&lt;/h3&gt;&lt;p&gt;BubbleBurstView’s code-behind had one remaining “if” and some other code that I felt didn’t belong there.&lt;/p&gt;&lt;p&gt;Key monitoring logic contained an “if” statement. At first it seemed like key monitoring was a candidate for another MicroController. But there is only one key to handle, the key for Undo. That wasn’t worth the overhead of another MicroController component. Instead I decided to enrich the BubbleBurstViewModel with an Undo method whose signature is:&lt;/p&gt;&lt;pre&gt;  public bool TryUndo(bool shouldTry) // returns True if undid&lt;/pre&gt;&lt;p&gt;The code-behind calculates whether the key presses amount to an undo request. The call is:&lt;/p&gt;&lt;pre&gt;  e.Handled = _bubbleBurst.TryUndo(isUndoKey);&lt;/pre&gt;&lt;p&gt;I don’t like the isUndoKey calculation but I’ll leave it for another day.&lt;/p&gt;&lt;p&gt;My final bug-a-boo is the LoadBubbleViewResources method which instantiates a ResourceDictionary and plugs it into the application-level resources. &lt;/p&gt;&lt;p&gt;I expected this to be loaded by the App.xaml itself but I suspect Josh wants to simulate the notion that independent assemblies have their own resources. While the “Bubble.View” assembly is not independent – the App.xaml has access to it through its host assembly’s references –, I’ll play along.&lt;/p&gt;&lt;p&gt;In any case, the view’s code-behind shouldn’t know the details of ResourceDictionary construction and App.Resources update. Time for a MicroController: “BubbleViewResourceLoader” which we can invoke from within the code-behind’s constructor for now. It still stinks but it stinks less.&lt;/p&gt;&lt;p&gt;The code-behind now stands at 41 lines, down from the original 86; only 9 of them do work.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Picky, Picky&lt;/h3&gt;&lt;p&gt;I’m a restless complainer. I’ve got a few more bones to pick having nothing to do with MVVM.&lt;/p&gt;&lt;p&gt;Page numbers! You may have noticed that my citations lacked page numbers. That’s because there aren’t any in the printed document I’m reading.&lt;/p&gt;&lt;p&gt;The abundance of Region tags annoys me. Hey, I use them too, especially in pedagogical code where I want to unveil new ideas didactically in the course of a presentation.&lt;/p&gt;&lt;p&gt;I appreciate that they seem to organize the code into nice buckets: “constructors”, “methods”, “fields”. But lately I’ve come to believe that they’re more of a code smell.&lt;/p&gt;&lt;p&gt;If the class is short – as it should be – they interfere with my ability to read and grasp the class at a glance. If the class is long, they suggest that my class implements too many distinct concerns and I’m struggling – vainly – to keep them organized. These concerns would be better delegated to supporting classes. I suspect that automated testing would make this defect more obvious.&lt;/p&gt;&lt;p&gt;I’m not thrilled with the data triggers. Data triggers are not available to Silverlight programmers probably for good reason. The Visual State Manager is the preferred choice for both WPF and Silverlight.&lt;/p&gt;&lt;p&gt;A particularly egregious data trigger can be found in BubbleBurstView.xaml where the GameOverView is collapsed when the BubbleBurstViewModel’s GameOverViewModel is null. Could there be a more obscure way to signal that a modal dialog should be hidden? I suspect a bound IsGameOver property would be both simpler and more obvious.&lt;/p&gt;&lt;h3&gt;Where’s The Code?&lt;/h3&gt;&lt;p&gt;Josh’s original source is at &lt;a href="http://advancedmvvm.com/" target="_blank"&gt;AdvancedMvvm.com&lt;/a&gt; . I’ve temporarily posted my refactored version &lt;a href="http://www.ideablade.com/WardsBlog/JoshSmithBubbleBurst.ward.v2.zip" target="_blank"&gt;on my site&lt;/a&gt;. I’m not promising it will stay there- this &lt;strong&gt;is Josh’s code&lt;/strong&gt; and I’ll do whatever he wants me to do with it (including burn it) – but it’s there now and I’ll let you know if I move it.&lt;/p&gt;&lt;h3&gt;Wrap Up&lt;/h3&gt;&lt;p&gt;I have high hopes for the conversation Josh has started with this book.&lt;/p&gt;&lt;p&gt;I see it as one place to begin your study of MVVM rather than as the definitive work on the subject. Some of the practices I find dubious and there are serious omissions. &lt;/p&gt;&lt;p&gt;But I gave it this much attention because it deserves it. It’s a fine piece of writing, a carefully considered example, and a push in the right direction. Josh speaks to a broad audience with an authentic voice they understand and respect. He has my respect as well.&lt;/p&gt;&lt;p&gt;It’s well worth the $15 bucks &lt;a href="http://www.amazon.com/Advanced-MVVM-ebook/dp/B0038KX9FW" target="_blank"&gt;on the Kindle&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Enjoy!&lt;/p&gt;p.s.: Cross-posted to my other &lt;a href="http://codebetter.com/blogs/wardbell/archive/2010/03/19/mvvm-josh-smith-s-way.aspx" target="_blank"&gt;blog on CodeBetter&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-7607573991355234784?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/7607573991355234784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=7607573991355234784' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7607573991355234784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/7607573991355234784'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/03/mvvm-josh-smiths-way.html' title='MVVM, Josh Smith’s Way'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-1477757477400844179</id><published>2010-01-03T00:02:00.001-08:00</published><updated>2010-01-03T00:02:55.332-08:00</updated><title type='text'>Test Soon Development: a case study</title><content type='html'>&lt;p&gt;I didn’t sleep well after posting about my &lt;a href="http://codebetter.com/blogs/wardbell/archive/2009/12/31/an-ioc-agnostic-prism-bootstrapper.aspx" target="_blank"&gt;IoC-agnostic Prism Bootstrapper&lt;/a&gt;. Bad enough that I’d deleted the original Prism bootstrapper tests. I added insult to injury trying to justify it:&lt;/p&gt;  &lt;blockquote&gt;I really thought this simple task would take maybe a long day at most. Stripping the tests away from the start was supposed to help me stay in the time box. … I didn’t think I could afford [to maintain the tests]. … I wasn’t trying to deliver a product and there is limited value in tests for a version of the Prism RI that is (a) obsolete and (b) irrelevant to your application. &lt;/blockquote&gt;  &lt;p&gt;Except it didn’t stay simple and it didn’t take one day. My pride got the best of me. Ok I’m not proud of the code but I didn’t want to be ashamed of it either. So I kept polishing it. The scope expanded little by little; I added Autofac, Silverlight support, and the Prism RI. Four days flew by. &lt;/p&gt;  &lt;p&gt;Now I’m invested. Now I care if someone uses it. Without tests I fear no one will. I can hear the scolding voice of &lt;a href="http://codebetter.com/blogs/jeremy.miller/"&gt;Jeremy Miller&lt;/a&gt;: “I won’t even look at code that doesn’t have tests.”&lt;/p&gt;  &lt;p&gt;I figured going in that setting up the test environment, converting the tests to run with new bootstrappers, and making it all presentable would take a day. That would have doubled the expected one-day project time. That’s ridiculous. So I deleted the Prism tests instead.&lt;/p&gt;  &lt;p&gt;It seems a false economy now that it’s a four day project. There’s only a 25% cost if I actually can revive the tests in one day.&amp;#160; I can amortize it further if people use it, improve it, and extend it to more IoC containers.&lt;/p&gt;  &lt;p&gt;One more day. How do I justify that? Perhaps, if I document the process and the outcome, I may discover something concrete to say about the utility (or futility) of testing. There’s a blog post in it at the very least.&lt;/p&gt;  &lt;p&gt;...&lt;/p&gt;  &lt;p&gt;I was right about the one day (see chronology below) … sort of. I squeezed it into one day only by taking shortcuts:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;I worked exclusively with the Prism Bootstrapper test fixture. I did not restore tests for other Prism components nor for the Prism RI. &lt;/li&gt;    &lt;li&gt;I revived tests for Desktop only; Silverlight testing would have sunk the budget. &lt;/li&gt;    &lt;li&gt;I didn’t write any &lt;strong&gt;&lt;em&gt;new&lt;/em&gt;&lt;/strong&gt; tests. This being a refactor, the goal was to make all bootstrappers pass the existing tests … and prepare the ground for future tests. &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Was It Worthwhile?&lt;/h3&gt;  &lt;p&gt;Automated testing, they say, confers specific benefits. Did I see them? Let’s review.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Find bugs&lt;/strong&gt;: “No”. Ok, it revealed one minor omission, insufficient payoff for a day’s work.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Clarify intent&lt;/strong&gt;: Yes. The tests give me a better understanding of what the Prism authors expected the bootstrapper to do. For example, they prescribed a particular launch sequence and wrote a test to verify that sequence. I may not know why the sequence is important. But were I tempted to write my own bootstrapper from scratch, I’d know to pay attention to this point.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Improve design&lt;/strong&gt;: No. It did not stimulate design changes to the Systems Under Test (SUT). I still believe that writing automated tests fosters improves design. But I wasn’t writing tests. I was reviving them and, because my ContainerAdapter is supposed to match the UnityBootstrapper API, existing tests were unlikely to provoke change.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Increase confidence&lt;/strong&gt;: Yes. While tests don’t prove that code works, they do provide strong evidence that certain things work “as intended”. Any evidence beats no evidence. The relief of seeing tests pass, especially tests someone else wrote, is undeniable. I’m hopeful that they improve your confidence in the product.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Speed testing&lt;/strong&gt;: Yes. Before, if I made any change to the bootstrapping code, I had to run manual smoke tests for each bootstrapper variant. That entailed changing a compiler directive, recompiling, and running the app for each of five bootstrappers; the cycle took 15 minutes minimum. &lt;/p&gt;  &lt;p&gt;The automated tests uncovered one bug. With their help, I fixed the bug and confirmed the fix for all bootstrappers in a couple of minutes. That’s a big improvement, for sure, but one speedier repair hardly makes up for the day I put into this. I’m twenty or so cycles away from break even. If someone finds more bugs, or decides to refactor the code to make it more readable or more capable, the payback will come.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Prepare for future&amp;#160; change&lt;/strong&gt;: Yes. With a test regime and a body of tests, anyone can quickly verify that changes to the CalBootstrapper, changes to any ContainerAdapter, or the addition of new ContainerAdapters preserve certain constraints on how all of the bootstrappers work. Far from perfect to be sure – there are only ~25 test methods per bootstrapper – but we have a foundation in place.&lt;/p&gt;  &lt;h3&gt;Conclusion&lt;/h3&gt;  &lt;p&gt;The IoC-agnostic Prism Bootstrapper is better for having automated tests. &lt;/p&gt;  &lt;p&gt;That said, the test development effort will be a total&amp;#160; loss if no one uses it. That’s a loss on top of the four days I’d have blown on it in the first place.&lt;/p&gt;  &lt;p&gt;It’s a real risk. I am unlikely to use it myself, odd as that seems; Unity is working fine for my existing clients.&lt;/p&gt;  &lt;p&gt;On the other hand, I suspect that the mere existence of tests improves the chances that someone will adopt it. &lt;/p&gt;  &lt;p&gt;You’d think the IoC product authors might show some interest; their customers want to use Prism. As they improve their containers or come up with new versions, the test-backed CalBootstrapper should make it easer to demonstrate that their enhancements are Prism-friendly.&lt;/p&gt;  &lt;p&gt;Patterns and Practices has a stake in promoting a Prism that is open to any container … and they are welcome to take this code and run with it.&lt;/p&gt;  &lt;p&gt;Meanwhile, the payback remains uncertain. We’ll have to wait and see.&lt;/p&gt;  &lt;p&gt;---&lt;/p&gt;  &lt;h3&gt;Chronology of Bootstrapper Test Resuscitation&lt;/h3&gt;  &lt;div style="margin-left: 10px"&gt;   &lt;table border="0" cellspacing="0" cellpadding="2"&gt;&lt;tbody&gt;       &lt;tr&gt;         &lt;td valign="top" width="76"&gt;5 minutes&lt;/td&gt;          &lt;td width="10"&gt;&amp;#160;&lt;/td&gt;          &lt;td valign="top" width="563"&gt;Restore original Prism bootstrapper tests for the UnityBootstrapper; they pass.&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="76"&gt;1 hour&lt;/td&gt;          &lt;td width="10"&gt;&amp;#160;&lt;/td&gt;          &lt;td valign="top" width="563"&gt;Refactor test fixtures so not dependent on Unity or UnityBootstrapper; they pass.&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="76"&gt;30 minutes&lt;/td&gt;          &lt;td width="10"&gt;&amp;#160;&lt;/td&gt;          &lt;td valign="top" width="563"&gt;Extract Prism’s ancillary mocks (hand coded mocks) into their own assembly; tests pass.&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="76"&gt;1 hour&lt;/td&gt;          &lt;td width="10"&gt;&amp;#160;&lt;/td&gt;          &lt;td valign="top" width="563"&gt;Get the tests passing on the “RefinedUnityBootstrapper”. No bugs found; one test failed on a log message change leading to a change in the test. Established a pattern for automated testing of multiple UnityBootstrappers. &lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="76"&gt;2.5 hours&lt;/td&gt;          &lt;td width="10"&gt;&amp;#160;&lt;/td&gt;          &lt;td valign="top" width="563"&gt;Tests finally pass on the first version of the IoC-agnostic ContainerAdapter. Almost all of the work involves decoupling the tests and mocks from IUnityContainer. Found one bug in my code! I had omitted a Region Behavior mapping. Now can automate testing of multiple Bootstrappers … as long as they require Unity.&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="76"&gt;30 minutes&lt;/td&gt;          &lt;td width="10"&gt;&amp;#160;&lt;/td&gt;          &lt;td valign="top" width="563"&gt;StructureMap, the first non-Unity bootstrapper, is using my ContainerAdapter and passing the tests. There was no issue with the SUT. The trouble again was getting the tests to work. &lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="76"&gt;7 minutes&lt;/td&gt;          &lt;td width="10"&gt;&amp;#160;&lt;/td&gt;          &lt;td valign="top" width="563"&gt;AutofacContainerAdapter test project created, ran green, and checked in. That 7 minute pace augers well for extending the reach of the tests to forthcoming versions of SM and Autofac and to other IoC products. &lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td valign="top" width="76"&gt;30 minutes&lt;/td&gt;          &lt;td width="10"&gt;&amp;#160;&lt;/td&gt;          &lt;td valign="top" width="563"&gt;Package, deploy, download, re-test both the bootstrappers and the Prism RI&lt;/td&gt;       &lt;/tr&gt;        &lt;tr&gt;         &lt;td style="border-top: black 1px solid" valign="top" width="76"&gt;~6 hours&lt;/td&gt;          &lt;td width="10"&gt;&amp;#160;&lt;/td&gt;          &lt;td style="border-top: black 1px solid" valign="top" width="563"&gt;Total&lt;/td&gt;       &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt; &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-1477757477400844179?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/1477757477400844179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=1477757477400844179' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1477757477400844179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/1477757477400844179'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2010/01/test-soon-development-case-study.html' title='Test Soon Development: a case study'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-6362853400843997045</id><published>2009-12-31T20:32:00.001-08:00</published><updated>2009-12-31T20:32:26.043-08:00</updated><title type='text'>An IoC-Agnostic Prism Bootstrapper</title><content type='html'>&lt;p&gt;&lt;a href="http://www.codeplex.com/prism"&gt;Prism&lt;/a&gt; from Microsoft Patterns &amp;amp; Practices leans on an &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;Inversion of Control (IoC)&lt;/a&gt; container. While nominally indifferent to your choice of container, you have to work a bit to extricate yourself from its default choice which is &lt;a href="http://www.codeplex.com/unity"&gt;Microsoft Unity&lt;/a&gt;. More so with some containers than others.&lt;/p&gt;  &lt;p&gt;The sweat and tears flow in the “Bootstrapper” class with which you launch your application. Most Prism samples feature a Bootstrapper that inherits from “UnityBootstrapper”. “UnityBootstrapper” busies itself with registering and configuring a dozen or so Prism components in a manner characteristic of Unity and it unapologetically takes a hard dependence on Unity itself. You are welcome to write your own Bootstrapper base class from scratch; of course this entails reading and understanding what “UnityBootstrapper” does so you can reassure yourself that your replacement achieves the same effects. Who has time for that?&lt;/p&gt;  &lt;p&gt;Almost a year ago I found myself writing a single application with three different client technologies, each dependent upon its own container. The three diverged in minor details – each was a different incarnation of a Container + ObjectBuilder – but the differences were sufficiently great that I felt compelled to unleash the Prism base bootstrapper class from its Unity chains.&lt;/p&gt;  &lt;p&gt;Preoccupied with more important business, I took the most expeditious route. I salvaged as much of Prism’s UnityBootstrapper as I could while replacing its direct dependency on Unity library references. &lt;/p&gt;  &lt;p&gt;Prism initialization is not something I want to own. When P&amp;amp;P updates its UnityBootstrapper, I want a quick, no-thought pathway to update my IoC-agnostic version.&lt;/p&gt;  &lt;p&gt;The result was Cal.Bootstrapper (“CAL” is short for “Composite Application Library”, Prism’s official name) and some supporting types. Cal.Bootstrapper looks like a cleaned-up UnityBootstrapper. It goes through the same motions of registering types and configuring instances albeit with reference to a denuded IoC, shorn of all but the most minimal functionality. This, dear reader, will be my gift to you.&lt;/p&gt;  &lt;p&gt;Recently, a few folks have wondered about replacing Unity with a completely different IoC container. The one I hear most often is &lt;a href="http://structuremap.sourceforge.net/Default.htm" target="_blank"&gt;StructureMap&lt;/a&gt;. Its author, &lt;a href="http://codebetter.com/blogs/jeremy.miller/" target="_blank"&gt;Jeremy Miller&lt;/a&gt;, has several times entertained the notion of replacing “UnityBootstrapper” with something that reflects glory on StructureMap. Apparently he has better things to do. I guess I’ll tackle it.&lt;/p&gt;  &lt;h3&gt;The Goods&lt;/h3&gt;  &lt;p&gt;I’ve bundled everything described in this post into a 2 meg zip, &lt;a href="http://www.ideablade.com/WardsBlog/PrismRI-Ioc.zip" target="_blank"&gt;PrismRI-Ioc.zip&lt;/a&gt;, downloadable from my company website. Do with it as you will.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Please note: I have no intention of maintaining this; don’t even ask.&lt;/strong&gt;&lt;/p&gt;  &lt;h3&gt;No, This is Not the Right Way&lt;/h3&gt;  &lt;p&gt;My knowledge of StructureMap is deeply impoverished but, from the little I do know, I’m certain that the “proper” course is to abandon “UnityBootstrapper” altogether. But there’s a reason Jeremy hasn’t tackled this and no one seems to have done so for other IoC products either.&lt;/p&gt;  &lt;p&gt;Nicholas Blumhardt, author of Autofac, took a crack at integrating Prism with his IoC back in August, 2009. He wanted to do it “the right way,” completely rethinking how a Prism app is bootstrapped and how application modules are written. He describes it &lt;a href="http://code.google.com/p/autofac/wiki/PrismIntegration" target="_blank"&gt;here&lt;/a&gt; as a “work-in-progress”. I guess it took a little more work than he thought it would and he must have found something better to do because it doesn’t look like he finished.&lt;/p&gt;  &lt;p&gt;I hoped to avoid this “road to good intentions” by doing it the “the easy way” which may be the “wrong way” but it works … which beats something that doesn’t.&lt;/p&gt;  &lt;p&gt;I decided to change as little of the Unity-oriented Prism app approach as I could. I want to get something done. I want you to be able to convert your running Prism app with minimal effort.&lt;/p&gt;  &lt;p&gt;Accordingly, my “Cal.Bootstrapper” mimics the “UnityBootstrapper” and it wallows in the style and ceremony that other IoC products despise.&lt;/p&gt;  &lt;p&gt;Is it all that bad? Why am I changing my IoC container anyway? I ought to have a clear idea about what I want from an alternative to Unity. I’m wasting my time if I’m only replacing the UnityBootstrapper with something “better”. Frankly, I don’t care how Prism configures its minimal requirements. If I want StructureMap (or AutoFaq, Castle Windsor, Ninject, etc), it is because I prefer that IoC for registering and configuring &lt;strong&gt;&lt;em&gt;my own application components&lt;/em&gt;&lt;/strong&gt;. I may replace the Prism configuration eventually but right now that is neither my motivation nor my first step.&lt;/p&gt;  &lt;p&gt;Therefore, although my Cal.Bootstrapper is ugly as sin, it will serve me for the nonce as I hope it serves you and I shall proceed to describe it without further apology. I will let it configure Prism the ugly way using my IoC container in place of Unity after which I am free in my own code to drive my IoC container as it was meant to be driven.&lt;/p&gt;  &lt;h3&gt;Battle Plan&lt;/h3&gt;  &lt;p&gt;A Prism application has a Bootstrapper class to configure the container, create and configure the main UI view called the “shell”, acquire application modules, and launch the application.&lt;/p&gt;  &lt;p&gt;You are expected to write a custom Bootstrapper that inherits from a base Bootstrapper class provided by Prism (the aforementioned UnityBootstrapper). This base class handles the above inventory of start-up tasks. Your derived Bootstrapper is supposed to extend the base class by overriding certain abstract and virtual methods.&lt;/p&gt;  &lt;p&gt;In other words, the bootstrapper is launch karaoke. You add your voice at predefined moments. It’s great if the music suits you. If you’re singing off key, you’re should stop faking it and write your own song.&lt;/p&gt;  &lt;p&gt;Tempted as I was, I chose not to quarrel with this approach. In fact, I took a deep breath and then embraced it … for the reasons discussed above. &lt;/p&gt;  &lt;p&gt;I decided to replace the UnityBoostrapper with an alternative base class (Cal.Bootstrapper) that does not know about Unity.&lt;/p&gt;  &lt;p&gt;Your derived Bootstrapper will provide an IoC container to this base class, wrapped in a vendor-neutral “ContainerAdapter, and delivered to the base class by overriding its abstract “CreateContainerAdapter” method.&lt;/p&gt;  &lt;p&gt;I have a few additional goals:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;“Improve” the UnityBootstrapper so I can figure out what it does. &lt;/li&gt;    &lt;li&gt;Make it easy to update my base class when (if) Microsoft updates the UnityBootstrapper. &lt;/li&gt;    &lt;li&gt;Minimize the effort to get my existing app bootstrapper deriving fro the IoC-agnostic base class. &lt;/li&gt;    &lt;li&gt;Minimize the changes necessary to convert my existing Unity-based Prism app. &lt;/li&gt;    &lt;li&gt;“Prove it” with an app Prism-aficionados know: the Prism Reference Implementation. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The original UnityBootstrapper is code only a mother could love. Long methods; much repetition; mysterious names. I can’t replace it until I understand what it does. My first step is to refactor it for readability. This is somewhat a matter of taste but I hope you’ll agree that the my revision, called “RefinedUnityBootstrapper”, is an improvement.&lt;/p&gt;  &lt;p&gt;I mustn’t get carried away if I am to satisfy my second subsidiary goal. Too many improvements would hinder re-synchronization with Microsoft’s changes.&lt;/p&gt;  &lt;p&gt;I want to prove that my approach works on an “application” that anyone can examine and that would be familiar to Prism developers. The Prism RI is the obvious candidate; that’s what I tackled.&lt;/p&gt;  &lt;p&gt;I haven’t looked at the RI in a long time. The version on my disk dates from February 2009. That’s pre-Silverlight 3 and, although I had patched it for SL 3, it’s still old and funky. The UI doesn’t work the way it should: stock positions don’t change when you buy and sell, the “Watch List” feature is broken, the Silverlight version throws a recoverable exception when you sell more stock than you own.&lt;/p&gt;  &lt;p&gt;But I didn’t have time to freshen it up, it was good enough for my purposes, and it’s all I’m going to give you.&lt;/p&gt;  &lt;h3&gt;Swappable Versions&lt;/h3&gt;  &lt;p&gt;This is a tutorial. I want you to be able to switch among different container implementations without changing the body of the application. I don’t have the time or the interest to do anything fancy.&amp;#160; In the “real” world, I’d make the change and discard the original. &lt;/p&gt;  &lt;p&gt;The version of the RI you run depends entirely upon the executing version of Prism RI Bootstrapper class. The class is divided into two partial class files. One of them is constant. The other holds just the code that varies from container to container. The file with variations is called StockTraderRIBootstrapper.Ioc.Desktop or StockTraderRIBootstrapper.Ioc.Silverlight.&lt;/p&gt;  &lt;p&gt;The variations are governed by compiler directives at the top. You uncomment ONE of them, recompile, and let ‘er rip. The example below shows the bootstrapper readied for StructureMap.&lt;/p&gt;  &lt;p&gt;//***************************************************************************    &lt;br /&gt;// *** PICK YOUR BOOTSTRAPPER AND IOC CONTAINER WITH _ONE_ OF THESE DEFINES &lt;/p&gt;  &lt;p&gt;//#define ORIGINAL_UNITYBOOTSTRAPPER    &lt;br /&gt;//#define REFINED_UNITYBOOTSTRAPPER     &lt;br /&gt;//#define UNITY_CONTAINER_ADAPTER     &lt;br /&gt;#define STRUCTUREMAP_CONTAINER_ADAPTER     &lt;br /&gt;//#define AUTOFAC_CONTAINER_ADAPTER &lt;/p&gt;  &lt;p&gt;//***************************************************************************&lt;/p&gt;  &lt;p&gt;Each variation takes only a few lines. I set the title text so you can see which version is running on screen (the original three letter “CFI” company name changes to one of “OUB”, “RUB”, “UCA”, “SMA”, or “ACA” to match your selection). For the Ioc-agnostic variations, there is an override of the method that creates the selected Ioc ContainerAdapter. The two versions pinned to the UnityBootstrapper (remember that I “refined” the UnityBootstrapper first simply to understand it better) have a shim method instead.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Incredibly stupid, I know. I’d never ship anything like this. I live with it because it’s a throw away demo and doesn’t merit the effort or complexity of proper decoupling. Or at least it doesn’t merit that attention yet.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The rest of the Prism RI stays constant. It took some work to keep it that way. Not a lot, fortunately; the Patterns and Practices people did a pretty good job of keeping the RI Ioc-neutral.&lt;/p&gt;  &lt;p&gt;I won’t bore you with the details of my journey to this blissful place. They are chronicled in “PrismRIChanges.txt”, located in the PrismRI folder next to the Visual Studio Solution file, “StockTraderRI-IoC.sln”. The gist of it is&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Add the Ioc assemblies in a common directory structure &lt;/li&gt;    &lt;li&gt;Add the PrismBootstrapper solution with its Ioc-agnostic Cal.Bootstrapper and the Ioc-specific ContainerAdapters. &lt;/li&gt;    &lt;li&gt;Revise the start-up project, StockTraderRI, to access the above &lt;/li&gt;    &lt;li&gt;Replace references to “IUnityContainer” with “IContainerAdapter” &lt;/li&gt;    &lt;li&gt;Remove module references to Unity. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You’ll do pretty much the same if you convert your existing Prism application to another Ioc container.&lt;/p&gt;  &lt;h3&gt;ContainerAdapters&lt;/h3&gt;  &lt;p&gt;The fun is in the ContainerAdapters which implement the following interface:&lt;/p&gt;  &lt;p&gt;namespace Cal.Bootstrapper {    &lt;br /&gt;&amp;#160; public interface IContainerAdapter { &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; IContainerAdapter RegisterInstance&amp;lt;T&amp;gt;(T instance);    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; IContainerAdapter RegisterType&amp;lt;TFrom, TTo&amp;gt;(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ContainerRegistrationScope scope) where TTo : TFrom;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; IContainerAdapter RegisterType(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Type fromType, Type toType, ContainerRegistrationScope scope);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; IContainerAdapter RegisterTypeIfMissing&amp;lt;TFrom, TTo&amp;gt;(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ContainerRegistrationScope scope) where TTo : TFrom;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; IContainerAdapter RegisterTypeIfMissing(     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Type fromType, Type toType, ContainerRegistrationScope scope);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; T Resolve&amp;lt;T&amp;gt;() where T : class;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; object Resolve(Type type);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; T TryResolve&amp;lt;T&amp;gt;() where T : class ;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; object TryResolve(Type type);     &lt;br /&gt;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160; public enum ContainerRegistrationScope {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Singleton,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Instance,     &lt;br /&gt;&amp;#160; }     &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;Not so bad if you know your container. Clearly IContainerAdapter must be so dumb that any IoC Container vendor can support it. It needs to be just smart enough for the base Bootstrapper class to configure Prism. Fortunately, this challenge is easily met.&lt;/p&gt;  &lt;p&gt;The code tends to be boilerplate. Autofac took a little more work (see below) but still weighs in at only 180 lines.&lt;/p&gt;  &lt;p&gt;You also have to write an adaptor that implements Microsoft.Practices.ServiceLocation.IServiceLocator; virtually everyone has done this already.&lt;/p&gt;  &lt;h3&gt;IoC Containers Demo’d&lt;/h3&gt;  &lt;p&gt;I’ve tried this approach with three IoC Containers: &lt;a href="http://msdn.microsoft.com/en-us/library/dd203101.aspx" target="_blank"&gt;Unity&lt;/a&gt; (Unity v.1.2.0.0, ObjectBuilder2 v.2.2.2.0), &lt;a href="http://sourceforge.net/projects/structuremap/files/" target="_blank"&gt;StructureMap&lt;/a&gt; (v.2.5.4.0), and &lt;a href="http://code.google.com/p/autofac/downloads/list" target="_blank"&gt;Autofac&lt;/a&gt; (Desktop: v.1.4.5.676, Silverlight: 1.4.4.572).&lt;/p&gt;  &lt;p&gt;You should know that I am not an expert in any of these containers. In fact, I just winged it, especially with StructureMap and Autofaq about which I know squat. I figured I could download them, skim whatever documentation they offered, and get something to work adequately for Shmoes like me.&lt;/p&gt;  &lt;p&gt;It’s not quite that easy and I have low confidence in my use of these containers. Their authors are invited to lend a hand improving matters … after they’re done laughing.&lt;/p&gt;  &lt;p&gt;I wanted to show at least one non-Unity container for both desktop and Silverlight applications. StructureMap doesn’t have a Silverlight version yet (come on, Jeremy). I tried Autofac because it does have a Silverlight version. &lt;/p&gt;  &lt;p&gt;I’m glad I did. The StructureMap implementation was a breeze. Autofac was much harder. I’m not trashing Autofac. It just happened to be harder for me, partly due to my ignorance and mostly because of the position Autofac takes on resolving unregistered types.&lt;/p&gt;  &lt;h3&gt;Major Container “Gotcha”&lt;/h3&gt;  &lt;p&gt;Container differences matter! One pervasive Prism practice in particular relies on a Unity default behavior that other containers do not observe. It’s serious enough to influence your choice of containers or make your conversion substantially more difficult.&lt;/p&gt;  &lt;p&gt;Prism instantiates a lot of its own components with unregistered public concrete classes. For example, somewhere in the bowels of RegionManager initialization, it resolves “DelayedRegionCreationBehavior”. This class is never registered with the container.&lt;/p&gt;  &lt;p&gt;Unity is ok with this. When asked to resolve an unregistered public concrete type, it treats the type as if it had been registered and scoped as an instance (i.e., you get a fresh instance each time). Both TryResolve and Resolve behave this same way.&lt;/p&gt;  &lt;p&gt;Prism components count on this default Unity container behavior. What if you change containers?&lt;/p&gt;  &lt;p&gt;StructureMap has the same default behavior when resolving an unregistered public concrete type. However, it’s TryResolve equivalent, “TryGetInstance”, return null. As I write, I have not detected a consequence of this difference; but I know it’s waiting in the grass somewhere.&lt;/p&gt;  &lt;p&gt;You could argue all day about whether a container should return null or return an instance the way Unity does. You could argue whether it should default to Singleton or Instance scope. &lt;/p&gt;  &lt;p&gt;Autofac punts. If you attempt to Resolve an unregistered type, it throws an Autofac.ComponentNotRegisteredException with a clear message. “TryResolve” returns null, which is the sensible thing to do.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Aside: the three ContainerAdapter files in my sample implement a “ContainerPlay” class that reveals these differences.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;I can’t quarrel with Autofac’s choice but I sure paid the price for purity. I had to hunt down all resolutions of concrete types and manually register them during AutofacContainerAdapter initialization. Unfortunately even that is insufficient. Many class constructors take parameters defined by concrete types. The container will attempt to resolve these and will throw at runtime. There aren’t integration tests to detect these automatically so I have to wander through the app under the debugger. I still haven’t got it to work.&lt;/p&gt;  &lt;p&gt;It was easier to get the Prism RI working with StructureMap. I have assumed that the only critical difference is with explicit “TryResolve” calls. I haven’t encountered any optional constructor parameters so I expect StructureMap and Unity to resolve these in the same way.&lt;/p&gt;  &lt;p&gt;I searched the Prism and RI source code for “TryResolve” calls involving concrete type. There weren’t many of them. I only found one of potential consequence. The base bootstrapper calls “TryResolve&amp;lt;RegionAdapterMappings&amp;gt;”. Fortunately, it also registers RegionAdapterMappings explicitly so resolution is always successful. Perhaps I was luck. Remember to be careful how you use TryResolve in your application.&lt;/p&gt;  &lt;p&gt;The net of it is that containers differ. Prism should not have relied on a Unity-specific type resolution feature. If you have done so in your Unity-based application (as I have), you too are vulnerable.&lt;/p&gt;  &lt;h3&gt;Where Did The Tests Go?&lt;/h3&gt;  &lt;p&gt;I removed the test projects from the Prism RI and the Composite Application Library projects that go with it. Why did I do that? laziness?&lt;/p&gt;  &lt;p&gt;I really thought this simple task would take maybe a long day at most. Stripping the tests away from the start was supposed to help me stay in the time box. It was going to be non-trivial to setup Prism’s test environment, convert the tests, and repackage for distribution to you. I didn’t think I could afford it.&lt;/p&gt;  &lt;p&gt;The point of the exercise was to demonstrate how to liberate your application to use an alternative container. I wasn’t trying to deliver a product and there is limited value in tests for a version of the Prism RI that is (a) obsolete and (b) irrelevant to your application.&lt;/p&gt;  &lt;p&gt;Unfortunately, this “simple” task kept expanding in scope; it took four long days. Geez like that never happens.&lt;/p&gt;  &lt;p&gt;Now that I’m “done” I wish I had those tests back, the UnityBootstrapperFixture in particular. Debugger testing is painful as we all know. Had I committed to automated tests, I would have written something better than the idiotic compiler-directive-based approach to swapping containers. Sure it would have cost me something – a day? – to get it right, a day I didn’t want to spend. But if someone wants to take this further, the tests would accelerate his progress greatly and imbued his efforts with confidence. Mea culpa.&lt;/p&gt;  &lt;p&gt;I wonder if some kind soul will restore them?&lt;/p&gt;  &lt;p&gt;Happy New Year, everyone!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-6362853400843997045?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/6362853400843997045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=6362853400843997045' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6362853400843997045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6362853400843997045'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/12/ioc-agnostic-prism-bootstrapper.html' title='An IoC-Agnostic Prism Bootstrapper'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-2678621790980584320</id><published>2009-11-23T14:26:00.001-08:00</published><updated>2009-11-23T14:45:11.957-08:00</updated><title type='text'>PDC 2009 Session Links</title><content type='html'>&lt;p&gt;I extracted the session titles and links into &lt;a href="http://www.ideablade.com/WardsBlog/pdc09Sessions.pdf" target="_blank"&gt;this PDF&lt;/a&gt; to make it easier for me (and for you) to find and navigate to the PDC 2009 session materials. Hope it works for you.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-2678621790980584320?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/2678621790980584320/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=2678621790980584320' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2678621790980584320'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2678621790980584320'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/11/pdc-2009-session-links.html' title='PDC 2009 Session Links'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-8416019706778362500</id><published>2009-11-03T15:19:00.001-08:00</published><updated>2009-11-03T15:19:04.501-08:00</updated><title type='text'>Easing into Prism</title><content type='html'>&lt;p&gt;I received a familiar email today:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Is it possible to start slowly with this Prism stuff and work my way into it gradually. Can I get something running quickly with &lt;a href="http://www.ideablade.com"&gt;DevForce&lt;/a&gt; as I know it now? My client has seen a prototype and I need to construct it soon. Then can I come back later and modularize the whole thing behind the scenes?&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Here’s my reply:&lt;/p&gt;  &lt;p&gt;You do &lt;u&gt;not&lt;/u&gt; need &lt;a href="http://www.codeplex.com/prism"&gt;Prism&lt;/a&gt; to get started!&amp;#160; You can introduce it into your application as you see opportunities that make sense to you. Prism is not a monolithic framework. It is a small collection of free-standing components that also work well together. You can adopt it a piece at a time; some of it you may comfortably ignore.&lt;/p&gt;  &lt;p&gt;It’s definitely worth reading about. It’s worth looking at the Reference Implementation and the Quick Starts. Get the Composite Application Guidance book from Patterns and Practices, look at what folks are doing with it and saying about it. &lt;/p&gt;  &lt;p&gt;Don’t get hung up on Prism itself. It is guidance first and implementation second. Poke around. See how other people tackle some of the same concerns. You might look at &lt;a href="http://caliburn.codeplex.com/"&gt;Caliburn&lt;/a&gt;, for example.&lt;/p&gt;  &lt;p&gt;In other words, take your time and educate yourself.&amp;#160; You don’t have to dive into the deep end.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;However, I feel strongly&lt;/strong&gt; that you should start wrapping your head around &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;Dependency Injection (DI)&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;Inversion of Control (IoC)&lt;/a&gt; containers as soon as you can.&amp;#160; They will completely transform the way you write your application. They will position you for future modularity and make your code ever so much easier to maintain. &lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Learning IoC is also a great career move&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;When you see yourself writing “new XXX(…)” you will learn to stop and ask yourself, “Do I really want to lock myself into the XXX type or would I be better off if XXX were delivered to me instead?”&amp;#160; In recent years my answer has increasingly been to avoid “new” and let the IoC construct and inject the instance I need.&lt;/p&gt;  &lt;p&gt;Don’t get carried away now. It’s a shiny new toy. Take it easy. But get used to it.&lt;/p&gt;  &lt;p&gt;I know you asked about Prism and here I am waxing on about IoC. I only go on about this because your decision to use or not use DI/IoC is fundamental. Prism (and its ilk) will come along naturally if you use DI; they won’t seem so natural if your application is not DI-ready.&lt;/p&gt;  &lt;p&gt;I promise the effort of learning DI (and it does takes some effort) will pay off quickly … and for the rest of your career. The principles are fundamental to emerging Microsoft technologies (see the &lt;a href="http://www.codeplex.com/MEF"&gt;Managed Extensibility Framework – MEF&lt;/a&gt;). Dependency Injection is the primary vehicle for implementation of most modern application development patterns.&lt;/p&gt;  &lt;p&gt;You have plenty of IoC containers to consider. &lt;a href="http://www.codeplex.com/unity"&gt;Microsoft Unity&lt;/a&gt; is one choice but by no means the only one: AutoFaq, Castle Windsor, Ninject, and StructureMap are popular (apologies to any I omitted). &lt;/p&gt;  &lt;p&gt;Do not be overwhelmed! These alternatives are vying for your affections with tons of features and you may easily become convinced that DI is super-complicated.&lt;/p&gt;  &lt;p&gt;You can ease into DI. Take a look at our “&lt;a href="http://www.ideablade.com/DevForceSilverlight/DevForceSilverlight_PrismExplorer.aspx"&gt;Prism Explorer&lt;/a&gt;” (which uses Unity); you’ll hardly notice IoC but it’s there. I limited myself to the simplest Unity techniques. If I remember correctly, I only use constructor injection, I register very few interface types, and I don’t use any of the attribute markup. You can go amazingly far without any advanced IoC features.&lt;/p&gt;  &lt;p&gt;In sum, get going on your application and do not let these technologies distract you. They are important and valuable but you don’t want to destroy your business relationship by drowning in technologies that you know nothing about.&lt;/p&gt;  &lt;p&gt;Get acquainted with Dependency Injection first and start using it experimentally. Learn about Prism in all that spare time.&lt;/p&gt;  &lt;p&gt;Try partnering with someone who has been down this road before. If that is not possible, find a local users group and latch on to other like-minded developers. It’s much more fun when you play with others.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-8416019706778362500?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/8416019706778362500/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=8416019706778362500' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8416019706778362500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8416019706778362500'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/11/easing-into-prism.html' title='Easing into Prism'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-6929269702013736558</id><published>2009-11-01T10:22:00.001-08:00</published><updated>2009-11-01T10:22:15.931-08:00</updated><title type='text'>Young @ Heart: The (2007) Movie</title><content type='html'>&lt;p&gt;Stumbled into “&lt;a href="http://www.netflix.com/Movie/Young_Heart/70084235?lnkctr=srchrd-sr&amp;amp;strkid=77792419_1_0&amp;amp;strackid=22999aefd34b1d12_1_srl"&gt;Young @ Heart&lt;/a&gt;”, a documentary about a New England choral group performing punk, rock, and R&amp;amp;B covers; the hook is that the members are well over 70 (high of 92).&lt;/p&gt;  &lt;p&gt;Sounds like an opportunity for terminal cuteness … “oh those feisty seniors … isn’t it amazing that they can sort of sing at all at their age? … it’s so inspiring!”.&amp;#160; That’s exactly the sense you get &lt;a href="http://www.youtube.com/watch?v=-3uOOhm8Fj8"&gt;from the trailer&lt;/a&gt; which is delivered with the typical phone-it-in Fox Searchlight style. Exactly the kind of movie I avoid.&lt;/p&gt;  &lt;p&gt;But this one caught me completely by surprise and I’m still roiling with emotions a day later. I’m trying to figure out why. &lt;/p&gt;  &lt;p&gt;It should have been utter treacle like one of those sentimental movies about animals, or kids, or illness, or the mentally infirm. Instead it’s a rich character study in which each member of the cast takes you somewhere you’re likely to go … somewhere you want to go … if you’re lucky enough to live that well.&lt;/p&gt;  &lt;p&gt;Singing is the glue and reason enough to watch. The songs - well-known pop tunes of youthful love, rage, despair, and hope – confess new moods and meanings as sung by performers far from adolescence.&amp;#160; The juxtapositions can be simple fun as in the raucous “I Want to be Sedated”, given literal treatment by a cast for whom the wheelchair is a serious threat. Or it can rip you open as when Bob Knittle’s rich baritone pleads “&lt;a href="http://www.metrolyrics.com/fix-you-lyrics-coldplay.html"&gt;I will try to fix you&lt;/a&gt;” to the barely perceptible beat of his oxygen machine, counting down toward the inevitable. It would be contrived if it didn’t actually happen, inadvertently, before a packed house of loving fans.&lt;/p&gt;  &lt;p&gt;The heart of the movie is the interviews and the lives of the cast as they orbit the rehearsal hall. The authenticity is striking. At a jail house concert the camera lingers on the prisoners’ faces each surrendering a thought of present loss or worrisome future. They are not being entertained (although they think they are); they are transported to the company of someone they miss, of someone they may become.&lt;/p&gt;  &lt;p&gt;Death is a looming presence. Close as he is, the cast are no more ready for him than we are.&lt;/p&gt;  &lt;p&gt;It’s not great filmmaking. It’s great human material triumphing over the pedestrian. It’s people being themselves, striving for meaning and community, just a few feet ahead of us down the road we travel together.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-6929269702013736558?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/6929269702013736558/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=6929269702013736558' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6929269702013736558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6929269702013736558'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/11/young-heart-2007-movie.html' title='Young @ Heart: The (2007) Movie'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-8653504927198835858</id><published>2009-10-16T14:52:00.001-07:00</published><updated>2009-10-17T12:09:51.869-07:00</updated><title type='text'>Patterns and Frameworks</title><content type='html'>&lt;p&gt;I just returned from the Microsoft &lt;a href="http://www.pnpsummit.com/west2009/west2009.aspx"&gt;Patterns and Practices Summit 2009&lt;/a&gt; which may be my favorite Microsoft conference. Great for exposure to customers with real applications and to the wonderful, dedicated Microsoft developers who aspire to serve them. More on this in another post. I have another point to make here, which is …&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Patterns are not Frameworks&lt;/strong&gt;. We should draw a bright line between &lt;strong&gt;Patterns&lt;/strong&gt; and their &lt;strong&gt;Implementations&lt;/strong&gt;. A pattern only becomes a pattern if and when there are multiple implementations. You don't know a pattern well until you've seen more than one implementation. If there is a single, canonical implementation, the thing is not a pattern, it’s a framework.&lt;/p&gt;&lt;p&gt;“Duh” you say. We know this. And yet it eludes us in practice.&lt;/p&gt;&lt;p&gt;I had numerous conversations about this with folks who work in PnP. The conversation goes something like this:&lt;/p&gt;&lt;h3&gt;The Conversation&lt;/h3&gt;&lt;p&gt;“We are not a product group. We don’t want to be a product group. &lt;/p&gt;&lt;p&gt;“We’re trying to provide guidance to consumers of Microsoft development products. We are reluctant even to say ‘best practices’ anymore. It’s just the best guidance we can give today, built with time, and commitment, and our access to experts inside and outside Microsoft.&lt;/p&gt;&lt;p&gt;“We’re answering the customer call for Microsoft to demonstrate how to use its own products in real applications. &lt;/p&gt;&lt;p&gt;“This bleeds inevitably into more general questions about how to build applications and soon (and properly) we investigate and describe general design and implementation patterns that go beyond the particulars of Microsoft products.&lt;/p&gt;&lt;p&gt;“It’s not enough to talk about the patterns. We need to demonstrate those patterns … express them in real code that works with Microsoft technology.&lt;/p&gt;&lt;p&gt;“That is when it starts to get away from us. Our guidance, as it becomes code, starts to cover more and more customer cases. It begins to harden and the pattern becomes harder to see behind the bells and whistles. Customers say ‘wow, can I use that in my application?’ and we say ‘sure’. They say ‘it would really help our particular situation if it also did this’ and we say ‘sure’ again.&lt;/p&gt;&lt;p&gt;“Then they want us to give it a name, package it up, support it, develop a roadmap. They want us to productize it … and we start to do that because serving customers is also our mission. And, in our (not so) secret hearts, we all want to ship products … we’re wired that way.&lt;/p&gt;&lt;p&gt;“Then we start worrying about backward compatibility … because customers get angry at us if we change anything&lt;/p&gt;&lt;p&gt;“Then others in the community, especially the Open Source community, get on our case for having sucked the oxygen away from alternative implementations that may be better in many scenarios. They say we have imposed, de facto, a particular implementation of the pattern; people can’t tell the difference between the pattern and what Microsoft did to it. And I see their point.&lt;/p&gt;&lt;p&gt;“And now we have old code (e.g., CAB) that no longer represents our current thinking … that, in fact, embodies practices we would counsel &lt;em&gt;against&lt;/em&gt; today … and we cannot walk away from it.&lt;/p&gt;&lt;p&gt;--&lt;/p&gt;&lt;p&gt;I don’t know that there is an easy answer to this one. I’m not willing to place all the blame on PnP either. The customer should know better.&lt;/p&gt;&lt;p&gt;“Best Practices” do not sit still. They evolve, leaving behind a trail of “formerly best practices” to which millions of dollars and entire careers are firmly attached. PnP is pulled in one direction by its responsibility to offer the best current guidance … and by its responsibility to customers who have placed big bets on its past guidance.&lt;/p&gt;&lt;p&gt;Perhaps we need some different rules of engagement.&lt;/p&gt;&lt;h3&gt;Explicit Shelf Life&lt;/h3&gt;&lt;p&gt;What if PnP put a “Sell By” date on their code? What if it had a shelf life and warning label: “Use with caution. Do not expect support beyond 3 years”. Stamp this at the top of every piece of code and every web page.&lt;/p&gt;&lt;p&gt;Then mean it. If you need to break, you break. Customers need to know that you are serious about your commitment to giving them the best advice you can and you do them no favors by clinging to outdated code.&lt;/p&gt;&lt;p&gt;This happens in OSS all of the time. Dead bodies are strewn everywhere.&lt;/p&gt;&lt;p&gt;You can do this. Microsoft can’t but you can. I think you can wean your customers away from thinking of you as a product group. If that means fewer customers served … that may be for the best … for everyone: your customers, you, and Microsoft itself.&lt;/p&gt;&lt;h3&gt;Play Well With Others&lt;/h3&gt;&lt;p&gt;My thesis again: a pattern is independent of any one implementation. You don't know a pattern well until you've seen at least two implementations.&lt;/p&gt;&lt;p&gt;What if PnP routinely called out the other implementations of the patterns they describe? Front and center, not as an afterthought. Openly encourage customers to look at these alternatives … if only to gain a contrasting perspective on the PnP guidance.&lt;/p&gt;&lt;p&gt;One of the best ways to learn about the Composite Application Block (CAB), for example, was Jeremy Miller’s “&lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/05/21/build-your-own-cab-part-1-the-preamble.aspx"&gt;Build your own CAB&lt;/a&gt;” series. I assure you I had no intention of following Jeremy’s advice and building my own CAB. It didn’t even occur to me. But that series was the best (unintentional) documentation of CAB I ever found, It introduced me to different ways of thinking about each issue (e.g., Event Aggregation and Dependency Injection). I learned indirectly what CAB was doing and the consequences of my choice. I’m not saying the consequences were all bad either; but there were consequences and I only recognized them in the oblique light cast by Jeremy’s series.&lt;/p&gt;&lt;p&gt;PnP might do more to highlight these alternatives and to encourage discussion about the contrasting choices. People who come to Prism should learn … right there on the home page … that a &lt;a href="http://www.codeplex.com/caliburn"&gt;Caliburn&lt;/a&gt; exists. When they come to the &lt;a href="http://www.codeplex.com/unity"&gt;Unity home page&lt;/a&gt;, they could learn that there are 5 to 10 other popular IoC containers to choose from and find links to learning more about IoC practices.&lt;/p&gt;&lt;p&gt;[I was just on the Unity page. It’s a fine product home page; it is not fine for guidance about Dependency Injection and IoC in general.]&lt;/p&gt;&lt;p&gt;I don’t think that PnP should endorse Caliburn or anything else for that matter. I’m not suggesting that PnP’s output is inferior or that PnP should express less than abundant enthusiasm for its own work.&lt;/p&gt;&lt;p&gt;I am saying that PnP is presenting itself as a product purveyor in a manner that conflicts with its role as a trusted source of guidance. This ensures that it will be trapped into long term support commitments, the kinds of commitments that some people there tell me they do not want.&lt;/p&gt;&lt;p&gt;PnP could say in some unambiguous fashion, “my dear customer, we offer a wonderful implementation of this pattern. HOWEVER … you ought to look at some alternatives, not only when first choosing your approach but also throughout your application development; there’s gold in seeing how others approach these same problems.”&lt;/p&gt;&lt;h3&gt;True Open Source&lt;/h3&gt;&lt;p&gt;What if PnP could accept contributions from the field? I don’t mean through “Contrib”; I mean directly into the guidance itself.&lt;/p&gt;&lt;p&gt;What if PnP developers actually read some of the Open Source code out there?&lt;/p&gt;&lt;p&gt;I’m pretty sure the legal guardians won’t permit it … in which case “Contrib” is the best they can do.&lt;/p&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;They call it "Microsoft Patterns and Practices", not "Microsoft Tool and Die".&lt;/p&gt;&lt;p&gt;It is time for customers to pull back from unrealistic expectations of Patterns and Practices. They are not your application infrastructure outsourcer. They are a trusted source of guidance. Rejoice if they provide more but do not expect or demand it.&lt;/p&gt;&lt;p&gt;Patterns and Practice doesn’t need to change what they build. I do think PnP can rethink its commitments to prior output. It can do a much better job of promoting the spirit of exploration and directing its community to external resources that offer contrasting implementations and points of view.&lt;/p&gt;&lt;p&gt;And now I descend from this soap box … in search of another.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-8653504927198835858?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/8653504927198835858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=8653504927198835858' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8653504927198835858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8653504927198835858'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/10/patterns-and-frameworks.html' title='Patterns and Frameworks'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-8772035762539638224</id><published>2009-09-16T12:40:00.001-07:00</published><updated>2009-09-16T12:40:04.316-07:00</updated><title type='text'>Man and Superman</title><content type='html'>&lt;p&gt;I was reading Jeremy Miller’s musings on “&lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2009/09/09/there-are-two-types-of-developers.aspx"&gt;Two Types of Developers&lt;/a&gt;”. &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Developers fall into two different extremes … Some developers can jump right into any technology and find out how best to use it and new ways to twist it and apply it without really questioning the “goodness” of that technology.&amp;#160; Others look at a technology with preconceived notions of how it should work and are quick to drop a technology when it doesn’t fit their vision of “good.”&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I am reminded that there are two kinds of people in this world: the people who divide the world into two kinds of people and the people who don’t. I am one of those two kinds of people.&lt;/p&gt;  &lt;p&gt;What Jeremy really means it that there are two developer &lt;strong&gt;&lt;em&gt;mindsets&lt;/em&gt;&lt;/strong&gt;. Actually-existing developers indulge both modalities as he also observes in this second paragraph. Still, the thrust of his argument is that developers habituate to one or the other extreme.&lt;/p&gt;  &lt;p&gt;Jeremy aligns himself mostly with the second. He describes an encounter with someone who, as Jeremy would have it, is inclined to the first. &lt;/p&gt;  &lt;p&gt;I happen to have read the blog post on exhibit, know both parties (call the other “B”), and participated in some of the exchange that ensued. It got me wondering whether I buy Jeremy’s dichotomy.&lt;/p&gt;  &lt;p&gt;Jeremy strives to be non-judgmental, averring potential advantages on both sides. I suggest that his phrase “&lt;em&gt;&lt;strong&gt;without really questioning the ‘goodness’ of that technology&lt;/strong&gt;&lt;/em&gt;” gives the game away.&lt;/p&gt;  &lt;p&gt;I know “B” and he is a curious fellow (double entendre intended). His curiosity is evident in the post and manifold in conversation. “B” never takes a technology on face value, certainly not “Prism” which was the technology at issue in this example.&lt;/p&gt;  &lt;p&gt;It may be relevant to note that “B” was deeply involved in Prism development. He is obviously comfortable with it. But “B” was as deeply involved in the debates, disappointments, and compromises that are inevitable when one works collaboratively on a framework. He may be blind to some of its faults but he can’t be accused of being uncritical by nature.&lt;/p&gt;  &lt;p&gt;What happened here is that “B” chose to implement a solution to a problem using technology that Jeremy dislikes. One may say so. One may ponder the reasons. But to leap to the conclusion that “B” (or anyone who chooses similarly) is simply “unquestioning” …&amp;#160; that is unjust.&lt;/p&gt;  &lt;p&gt;Worse, it is lazy.&lt;/p&gt;  &lt;p&gt;It forecloses a genuine attempt to investigate how developers actually make choices in the real world of customers and deadlines. &lt;/p&gt;  &lt;p&gt;Are there drudge journeyman programmers who paint by numbers? Sure … but they aren’t relevant to this discussion and that is not what Jeremy thinks of “B”.&lt;/p&gt;  &lt;p&gt;Do we often cheerily follow the easy, well-trod path? Of course. Do we challenge our every decision to be the best possible in the abstract. No. None of us do. Could “B” have made a better choice than Prism… even in his particular circumstances? Maybe … which makes it worth pursuing with “B” .&lt;/p&gt;  &lt;p&gt;But Jeremy’s point isn’t that we are prone to be the willing captives of our familiar tools. No, he claims we are by nature either slaves or freeman, the “last man” or the “Übermensch”. That is the true import of his “&lt;em&gt;interesting taxonomy of developers that I’ve observed for years&lt;/em&gt;”.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;The earth has become small, and on it hops the last man, who makes everything small. … One still works, for work is a form of entertainment. But one is careful lest the entertainment be too harrowing. One no longer becomes poor or rich: both require too much exertion. … 'We have invented happiness,' say the last men, and they blink.&lt;/p&gt;    &lt;p&gt;Behold, I teach you the overman. The overman is the meaning of the earth.Let your will say: the overman &lt;i&gt;shall be&lt;/i&gt; the meaning of the earth! I beseech you, my brothers, &lt;i&gt;remain faithful to the earth,&lt;/i&gt; and do not believe those who speak to you of otherworldly hopes!&amp;quot; &lt;/p&gt;    &lt;p&gt;- Nietzsche's &lt;i&gt;Thus spoke Zarathustra&lt;/i&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;It’s thrilling to hear … but I am not buying it.&lt;/p&gt;  &lt;p&gt;I’m a huge Jeremy Miller fan; this was not his best day.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-8772035762539638224?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/8772035762539638224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=8772035762539638224' title='122 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8772035762539638224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8772035762539638224'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/09/man-and-superman.html' title='Man and Superman'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>122</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-8215818255175218030</id><published>2009-09-12T12:36:00.001-07:00</published><updated>2009-09-12T19:41:19.785-07:00</updated><title type='text'>Silverlight Spy 3 – First Look</title><content type='html'>&lt;p&gt;&lt;a href="http://silverlightspy.com/silverlightspy/" target="_blank"&gt;Silverlight Spy 3&lt;/a&gt; was just released. I think you’ll want this in your tool bag right away. Why? Because it is a great way of seeing what’s going on in your Silverlight application … and twiddling its appearance … &lt;em&gt;at runtime&lt;/em&gt;. &lt;/p&gt;&lt;p&gt;It is especially helpful if you’re building a compositional application of many, independently-designed views; you want to see them playing together and understand what’s happening.&lt;/p&gt;&lt;h3&gt;Quick Tour&lt;/h3&gt;&lt;p&gt;I’m looking at my Prism Explorer demonstration app right now. This demo shows our &lt;a href="http://www.ideablade.com/DevForceSilverlight/DevForceSilverlight_overview.aspx" target="_blank"&gt;DevForce Silverlight&lt;/a&gt; Data Services product working with &lt;a href="http://www.codeplex.com/prism" target="_blank"&gt;Prism&lt;/a&gt;.&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv4rlpBzSI/AAAAAAAAABo/x1Lk-7MEWqs/s1600-h/01_PEatLaunch.PNG"&gt;&lt;img style="WIDTH: 320px; HEIGHT: 193px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380667607546449186" border="0" alt="" src="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv4rlpBzSI/AAAAAAAAABo/x1Lk-7MEWqs/s320/01_PEatLaunch.PNG" /&gt;&lt;/a&gt; &lt;p&gt;Fired it up in Visual Studio (to get the Cassini server side going), then pasted the URL (http: //localhost:9006/) into Spy’s address bar. Spy fires up the client in its browser just fine.&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv4w6IEKzI/AAAAAAAAABw/sREcMtlE-Ik/s1600-h/02_PEinSpyAtLaunch.PNG"&gt;&lt;img style="WIDTH: 320px; HEIGHT: 258px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380667698944682802" border="0" alt="" src="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv4w6IEKzI/AAAAAAAAABw/sREcMtlE-Ik/s320/02_PEinSpyAtLaunch.PNG" /&gt;&lt;/a&gt; &lt;p&gt;Spy drew the red highlight box, not me. I held down the ctrl + shift keys and moved my mouse around the browsed page; as I did, Spy highlighted each element in this manner; and then I clicked on the address to set the focus as you see it.&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/_iOCgrkgC3Tk/Sqv4423xv0I/AAAAAAAAAB4/YtJqcw8RN_A/s1600-h/03_AddressInExplorer.PNG"&gt;&lt;img style="WIDTH: 314px; HEIGHT: 212px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380667835510013762" border="0" alt="" src="http://2.bp.blogspot.com/_iOCgrkgC3Tk/Sqv4423xv0I/AAAAAAAAAB4/YtJqcw8RN_A/s320/03_AddressInExplorer.PNG" /&gt;&lt;/a&gt; &lt;p&gt;Now I swing over to the Explorer view and I see that the address is a TextBlock in the middle of a DataGridCell … deep in the visual (or logical) tree that begins with my Prism shell. I love being able to start from something I see on the page right to the element in the object tree.&lt;/p&gt;&lt;p&gt;I get the same effect in the other direction by navigating from the tree: select a node and watch Spy highlight the corresponding visual real estate in its browser.&lt;/p&gt;&lt;p&gt;I can see the XAML for this TextBlock in Spy’s View window:&lt;/p&gt;&lt;a href="http://3.bp.blogspot.com/_iOCgrkgC3Tk/Sqv48VXgidI/AAAAAAAAACA/0oRZgckLt0k/s1600-h/04_AddressXamlView.PNG"&gt;&lt;img style="WIDTH: 320px; HEIGHT: 58px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380667895235774930" border="0" alt="" src="http://3.bp.blogspot.com/_iOCgrkgC3Tk/Sqv48VXgidI/AAAAAAAAACA/0oRZgckLt0k/s320/04_AddressXamlView.PNG" /&gt;&lt;/a&gt; &lt;p&gt;Suppose I want to see what would happen if I gave the address a little more air. I open Spy’s Properties window, locate the Padding property and try “20” all around. I see the effect immediately:&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5Aad2EuI/AAAAAAAAACI/DdRi-nCtTlc/s1600-h/05_AddressPropertyChange.PNG"&gt;&lt;img style="WIDTH: 320px; HEIGHT: 261px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380667965324006114" border="0" alt="" src="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5Aad2EuI/AAAAAAAAACI/DdRi-nCtTlc/s320/05_AddressPropertyChange.PNG" /&gt;&lt;/a&gt; &lt;p&gt;&lt;strong&gt;&lt;em&gt;Peeking and tweaking the look on the fly is value that can hardly be overstated &lt;/em&gt;&lt;/strong&gt;especially in a composite app. Sometimes you just have to see the app run in a production context with real data behind it to understand what is going on. Adjusting some values to visualize how it might look after correction … that’s worth something to me.&lt;/p&gt;&lt;p&gt;Spy integrates seamlessly with &lt;a href="http://www.red-gate.com/products/reflector/" target="_blank"&gt;Reflector&lt;/a&gt; so I can poke around in the client-side source code while in Spy. First, I tell Spy where to find Reflector through Tools / Options / Reflector. Then, in the Explorer window, “Object Browser” node, I navigate the assemblies in the XAP:&lt;/p&gt;&lt;a href="http://3.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5RV34jJI/AAAAAAAAACo/JAXf1hV-7ME/s1600-h/09_ObjectBrowser.png"&gt;&lt;img style="WIDTH: 175px; HEIGHT: 320px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380668256148819090" border="0" alt="" src="http://3.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5RV34jJI/AAAAAAAAACo/JAXf1hV-7ME/s320/09_ObjectBrowser.png" /&gt;&lt;/a&gt; &lt;p&gt;The View window exposes the disassembled code using Reflector:&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5VbvuxoI/AAAAAAAAACw/oB_84eYw5Cg/s1600-h/10_BootstrapReflected.PNG"&gt;&lt;img style="WIDTH: 320px; HEIGHT: 223px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380668326444713602" border="0" alt="" src="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5VbvuxoI/AAAAAAAAACw/oB_84eYw5Cg/s320/10_BootstrapReflected.PNG" /&gt;&lt;/a&gt; &lt;p&gt;I can also spy on other people’s applications. Now, when I see an effect I like, I’ll have a fighting chance to figure out how it’s done. Nothing evil in that.&lt;/p&gt;&lt;p&gt;Perhaps more productively, Spy can help me better support my customers. I don’t have their code. I don’t want their code! Now I can fire up their app in Spy from out here in Stinson Beach (yes, kicking back with the blog) and gain immediate insight. Having reflector baked in makes it easy to walk their code too.&lt;/p&gt;&lt;h3&gt;Helpful Touches&lt;/h3&gt;&lt;p&gt;Spy let’s me monitor mouse and key events which I can filter. In this snapshot, clicking on the event also takes me to the associated visual element.&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5EX6ji2I/AAAAAAAAACQ/tvgBVEHFBtE/s1600-h/06_EventMonitor.png"&gt;&lt;img style="WIDTH: 320px; HEIGHT: 135px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380668033358596962" border="0" alt="" src="http://2.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5EX6ji2I/AAAAAAAAACQ/tvgBVEHFBtE/s320/06_EventMonitor.png" /&gt;&lt;/a&gt; &lt;p&gt;I like to know when my app is visiting the server. Fiddler, Firebug (FireFox), and Web Development Helper (IE) are superior tools for the in-depth analysis. But if I just need to know that something went over the wire and peek at the headers, Spy does nicely. In this snap I just asked for a projection over all customers and their orders:&lt;/p&gt;&lt;a href="http://2.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5JVOfqWI/AAAAAAAAACY/lCGAKjStL0I/s1600-h/07_NetworkMonitor.png"&gt;&lt;img style="WIDTH: 320px; HEIGHT: 151px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380668118536268130" border="0" alt="" src="http://2.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5JVOfqWI/AAAAAAAAACY/lCGAKjStL0I/s320/07_NetworkMonitor.png" /&gt;&lt;/a&gt; &lt;p&gt;The top window is a grid of the traffic; double clicking a row reveals the headers panels in the lower half.&lt;/p&gt;&lt;p&gt;There’s a Performance Monitor with the visual familiarity of the one in Windows Task Manager.&lt;/p&gt;&lt;a href="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5NygYRPI/AAAAAAAAACg/-0mrWzYv9H8/s1600-h/08_PerfMonitor.png"&gt;&lt;img style="WIDTH: 279px; HEIGHT: 320px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5380668195115386098" border="0" alt="" src="http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv5NygYRPI/AAAAAAAAACg/-0mrWzYv9H8/s320/08_PerfMonitor.png" /&gt;&lt;/a&gt; &lt;p&gt;The processor metric seems parallel to the Task Manager’s. The memory metric probably tracks just your app’s usage although how and how precisely I can’t tell. I noticed unpredictable figures simply by refreshing the application address to restart the app. I think of it as a rough gauge of relative behavior. You’ll get a general feel and you might be able to detect some memory leaks this way.&lt;/p&gt;&lt;p&gt;There are other goodies. These are just the features that attracted my immediate attention and made me want to buy.&lt;/p&gt;&lt;h3&gt;Price&lt;/h3&gt;&lt;p&gt;Spy was free in earlier incarnations. It now sells for roughly US$100 for a personal copy. You can download an evaluation copy that’s good for 27 days.&lt;/p&gt;&lt;p&gt;Frankly, I’m glad to see a price. I love “free” as much as the next guy but nothing is truly free. I want Spy’s author to keep improving this tool and he has to make a living at it to do it well. I’m bummed when a great free tool comes along and then it just sits there, waiting upon the author’s free time to answer questions, fix bugs, and take the next giant leap.&lt;/p&gt;&lt;p&gt;The biggest shortfall (as I will repeat) is the utter absence of documentation. With a little dough, Koen Zwikstra - the man behind spy - can afford to hire a tech writer and cut some videos.&lt;/p&gt;&lt;p&gt;Full disclosure: I got a free copy as an MVP. This review, however, is entirely my idea with no promise of reward.&lt;/p&gt;&lt;h3&gt;Wrap Up&lt;/h3&gt;&lt;p&gt;Silverlight Spy 3 is a super tool and a fine piece of work. Runs like a top. No install issues, no runtime glitches so far.&lt;/p&gt;&lt;p&gt;No documentation! None that I could find. This is a huge weakness. Thank goodness for &lt;a href="http://channel9.msdn.com/shows/Continuum/SilverlightSpy/" target="_blank"&gt;Koen’s Channel 9 video with Adam Kinney&lt;/a&gt; recorded at MIX in March 2009; it opened my eyes to the potential and gave me valuable operating clues. How else would I discover “Ctrl+Shift+Mouse+Click”? Web search revealed nothing else (there is material on Spy &lt;u&gt;2&lt;/u&gt;). &lt;/p&gt;&lt;p&gt;Fortunately, it is pretty intuitive. Just bang around on it awhile and it starts to make sense. But some kind of guide needs to come out soon.&lt;/p&gt;&lt;p&gt;I’m hopeful this introduction piques your interest and gets you started.&lt;/p&gt;&lt;p&gt;A few minutes with Spy and you remember in a hurry never to put anything secret in your Silverlight client; that’s the wrong place for the Coca Cola recipe. Sure other tools can do it …. but Spy makes it so easy.&lt;/p&gt;&lt;p&gt;Go Spy! &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-8215818255175218030?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/8215818255175218030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=8215818255175218030' title='37 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8215818255175218030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/8215818255175218030'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/09/silverlight-spy-3-first-look.html' title='Silverlight Spy 3 – First Look'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_iOCgrkgC3Tk/Sqv4rlpBzSI/AAAAAAAAABo/x1Lk-7MEWqs/s72-c/01_PEatLaunch.PNG' height='72' width='72'/><thr:total>37</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-4667178818051840434</id><published>2009-09-08T14:59:00.001-07:00</published><updated>2009-09-08T15:41:39.427-07:00</updated><title type='text'>AdventureWorks 2000 tinyint nightmare</title><content type='html'>&lt;p&gt;You’re going to love this one!&lt;/p&gt;  &lt;p&gt;Some of our integrations tests use AdventureWorks 2000. One developer’s test updated a Sales.SalesOrderDetail. The test suddenly blew up with a SQL Server 2005 error that complained about exceeding the size limit of a TinyInt. &lt;/p&gt;  &lt;p&gt;The error didn’t say where this TinyInt lived or what the column was called. The best we could tell was that the exception occurred while updating Sales.SalesOrderDetail.&lt;/p&gt;  &lt;p&gt;SalesOrderDetail has a TinyInt column, “LineNumber”, which was not jeopardized by the update. &lt;/p&gt;  &lt;p style="margin-left: 16px"&gt;&lt;em&gt;Aside: I have a different AdventureWorks db on my machine that doesn’t have “LineNumber” or a TinyInt but it does have, “OrderQty”, which is a SmallInt. I would have suspected that (“SmallInt, TinyInt, what’s the difference?”); there would be no problem there either.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;No other developer could reproduce the SQL exception.&lt;/p&gt;  &lt;p&gt;After hours of hair-pulling, the developer found that there is an update trigger on SalesOrderDetail that updates the parent Sales.SalesOrderHeader. SalesOrderHeader has an update trigger that increments SalesOrderHeader.RevisionNumber … which is a TinyInt.&lt;/p&gt;  &lt;p&gt;Over the course of many tests, that RevisionNumber kept creeping up … until it hit 255. Each developer has his own AdventureWorks copy so no surprise no one else could reproduce it.&lt;/p&gt;  &lt;p&gt;You can blame the victim if you wish; should have had adequate rollback logic all along.&lt;/p&gt;  &lt;p&gt;But I have to admire the genius who decided that you’d never exceed 255 updates of a SalesOrderHeader in a test database.&lt;/p&gt;  &lt;p&gt;Let’s thank SQL Server for throwing an exception on exceeding the max for a TinyInt without telling us the name of the column or table involved.&lt;/p&gt;  &lt;p&gt;Kudos also to the other evil genius in this mess who wrote a trigger on one table that fires a trigger on another table to update the RevisionNumber … and didn’t bother to check the type or implement exception logic that would help clarify the problem.&lt;/p&gt;  &lt;p&gt;There must be an award for this kind of thing.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Lesson #1&lt;/strong&gt;: If you are using AdventureWorks 2000, be sure to reset all SalesOrderHeader.RevisionNumber values to 0. It’s too late to mess with the schema.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Lesson #2&lt;/strong&gt;: Hey, SQL Server folks, how about a little more help in exception messages?&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Lesson #3&lt;/strong&gt;: Please write good exception messages yourself … messages that would give the poor sod who received it a fighting chance of understanding the problem. Extra credit if you suggest how to fix it.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Lesson #4&lt;/strong&gt;: Business logic in the database is killing us out here. You DBAs have got to be more helpful.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Lesson #5&lt;/strong&gt;: Stop trying to squeeze every last byte out of the schema. TinyInt should be used only in the most extreme circumstances and never where it could be incremented.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-4667178818051840434?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/4667178818051840434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=4667178818051840434' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4667178818051840434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/4667178818051840434'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/09/adventureworks-2000-tinyint-nightmare.html' title='AdventureWorks 2000 tinyint nightmare'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-5772705259889626118</id><published>2009-09-04T16:33:00.001-07:00</published><updated>2009-09-04T16:33:45.521-07:00</updated><title type='text'>On Software Warning Labels</title><content type='html'>&lt;blockquote&gt;   &lt;p&gt;&amp;quot;The only demand I make of my reader is that he should devote his whole life to reading my works.&amp;quot; – James Joyce to an interviewer.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I’ve been weighing in &lt;a href="http://www.riaservicesblog.com/Blog/post/The-Problem-with-the-DomainDataSource.aspx"&gt;on Colin Blair’s blog&lt;/a&gt; recently about concerns I have about the RIA Services DomainDataSource (DDS) … concerns that apply equally to our own DevForce ObjectDataSource. &lt;/p&gt;  &lt;p&gt;Colin’s &lt;a href="http://www.riaservicesblog.com/Blog"&gt;blog on RIA Services&lt;/a&gt; is worth watching as Colin’s is a thoughtful voice. He likes RIA Services a lot … but not uncritically. &lt;/p&gt;  &lt;p&gt;His post is a response to &lt;a href="http://silverlightfeeds.com/Feed/6/Jeff_Handley/"&gt;Jeff Handley&lt;/a&gt;’s &lt;a href="http://twtpoll.com/3qu35y"&gt;twitter poll&lt;/a&gt;: “&lt;strong&gt;&lt;em&gt;Do you consider the .NET RIA Services DomainDataSource to be ‘Data Access Logic’ in the UI?&lt;/em&gt;&lt;/strong&gt;”. &lt;/p&gt;  &lt;p&gt;Collin said “Yes”, then did the responsible thing and posted his reasons. That set in motion a small to-and-fro with Jeff who is maintaining and evolving the DDS for Microsoft.&lt;/p&gt;  &lt;p&gt;What is going on there is some sensible thinking. There is no Microsoft bashing. I suppose some posturing is inevitable (at least where I am involved) but I believe that matters of real substance are poking through. We’re not just talking about “good design”; we’re talking about consequences.&lt;/p&gt;  &lt;p&gt;Which brings me to something that has been gnawing at me since I fulminated against &lt;a href="http://neverindoubtnet.blogspot.com/2009/08/drag-drop-debate-on-herding-code.html"&gt;Drag-and-Drop&lt;/a&gt; back in August. &lt;/p&gt;  &lt;p&gt;I received feedback, not only from Microsoft friends, that I had been uncharacteristically caustic and univocal in my opinion. I seemed to be sliding into the camp that would “shun” people who might use a DDS control; the camp that would “think those people are stupid.”&lt;/p&gt;  &lt;p&gt;I recall too well my Berkeley days of smug “Us versus Them”-dom. Appears my capacity for self-righteousness is undiminished.&lt;/p&gt;  &lt;p&gt;Timeout! I do not believe that the people who use the DDS are stupid. On the other hand, I do meet a great number of developers who are overworked, undertrained, and uncurious. They constitute the majority of developers … as they do in every profession. &lt;/p&gt;  &lt;p&gt;I look in the mirror and can say the same of myself with respect to many topics. There isn’t time to understand the implications and nuances of everything I do. I can muster little interest in certain areas of software development. I simply trust that the technologies work and are appropriate … and I move on with my busy day. Our love of our craft is not equally distributed over the entirety of our domain.&lt;/p&gt;  &lt;p&gt;So when I … or anyone … get amped up on a topic like DDS or drag-and-drop or ViewModel … what should I expect? Is this stuff really that bad for you? Are they clubbing baby seals? &lt;/p&gt;  &lt;p&gt;No. It’s only software. We are not geniuses. We are not James Joyce and we certainly don’t deserve that kind of devotion.&lt;/p&gt;  &lt;p&gt;I’m not backing off my “concern” about drag-and-drop. I’m not recanting my critique of the DDS (and our own ObjectDataSource). I just want to position myself differently … a bit more sympathetically … perhaps suggest an approach that may benefit the developer community and lower the temperature.&lt;/p&gt;  &lt;p&gt;What if Microsoft (and IdeaBlade) were &lt;strong&gt;more upfront&lt;/strong&gt; about the consequences and alternatives of some of these dubious controls and practices? &lt;/p&gt;  &lt;p&gt;There is the sense among many that Microsoft doesn’t talk as openly as it should about &lt;a href="http://en.wikipedia.org/wiki/Technical_debt"&gt;technical debt&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Taking on technical debt can be a wise investment. I use the DataForm with auto-generation in my demos. Incredibly convenient. Could probably get away with it for some production screens that have only a few fields and don’t need much management; it will save tons of time that would be utterly wasted if I did a better job of customizing the user interaction … because nobody wants or needs “a better job”.&lt;/p&gt;  &lt;p&gt;I incur that technical debt with gratitude. I choose what I’m doing.&lt;/p&gt;  &lt;p&gt;There is no problem with the DataForm, or the DDS, or drag-and-drop. The problem is that many developers are insufficiently aware of the debt they are incurring. I use my credit card knowing that I’ve got it covered; too many developers are using the “credit card” thinking it’s free money.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;a href="http://netcave.org/"&gt;Alan Stevens&lt;/a&gt; &lt;/b&gt;suggested something like the following in the &lt;a href="http://neverindoubtnet.blogspot.com/2009/08/drag-drop-debate-on-herding-code.html"&gt;Herding Code podcast I wrote about&lt;/a&gt;. He said it would be ok to do demos with drag-and-drop if the presenter stopped for a moment and said:&lt;/p&gt;  &lt;p&gt;“This approach has utility under specific circumstances … but watch-out because it has costs too. I strongly recommend that you read up on it over here … to appreciate the limits of what I’m showing you … and to learn about alternative paths that may be more appropriate now or in the future.”&lt;/p&gt;  &lt;p&gt;That speech is a responsibility we have as presenters at conferences.&lt;/p&gt;  &lt;p&gt;Those of us who make and sell a product bear an additional responsibility, especially when we target the broad market of developers who, let’s face it, don’t try very hard to master the craft.&lt;/p&gt;  &lt;p&gt;It isn’t enough to squirrel the discussion away in the corner of some blog. That’s the equivalent of hiding in the small print.&lt;/p&gt;  &lt;p&gt;I think we (IdeaBlade, Microsoft) should put a warning sticker right on the control itself. Put it in the XAML doc. Teach Intellisense to show the “warning” hyperlink.&lt;/p&gt;  &lt;p&gt;Smack me as a hypocrite if we neglect to put a warning on our own ObjectDataSource when we ship it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-5772705259889626118?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/5772705259889626118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=5772705259889626118' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5772705259889626118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5772705259889626118'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/09/on-software-warning-labels.html' title='On Software Warning Labels'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-5117385275651017921</id><published>2009-08-29T17:02:00.001-07:00</published><updated>2009-08-29T17:02:03.142-07:00</updated><title type='text'>Fiddler + WCF SOAP+ Cassini = Ooof!</title><content type='html'>&lt;p&gt;What a PITA trying to observe my DevForce Silverlight application running in Cassini using Fiddler2. Thanks to &lt;a href="http://johnpapa.net/"&gt;John Papa&lt;/a&gt; I’ve got that working now.&lt;/p&gt;  &lt;p&gt;Here’s the situation:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;DevForce communicates using WCF SOAP service &lt;/li&gt;    &lt;li&gt;I’m running both the client and the service in Cassini, not IIS &lt;/li&gt;    &lt;li&gt;Tried all the recommended configurations (see below) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The problem is the WCF SOAP service. There is no issue with REST.&lt;/p&gt;  &lt;h3&gt;What Finally Worked&lt;/h3&gt;  &lt;p&gt;Can’t make it work with IE at all. Haven’t found anyone who knows how.&lt;/p&gt;  &lt;p&gt;But I can make it work with &lt;strong&gt;FireFox&lt;/strong&gt; … and I am fine with running in Firefox. Here ya go:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Install &lt;a href="http://www.mozilla.com/"&gt;Firefox&lt;/a&gt; (duh) &lt;/li&gt;    &lt;li&gt;In fiddler: Tools / Fiddler Options / General / disable IPv6 [may not be necessary] &lt;/li&gt;    &lt;li&gt;In fiddler: Tools / Fiddler Options / Connections. Click “Copy Browser Proxy Configuration URL” … which puts the right phrase in your clipboard &lt;/li&gt;    &lt;li&gt;In Firefox: Tools / Options / Network / Settings. Click “Automatic proxy” radio button which enables the text box. Paste script address from your clipboard.      &lt;br /&gt;On Vista/Win 7, the address looks like       &lt;br /&gt;“file:///C:/Users/YOUR_LOGIN_NAME/Documents/Fiddler2/Scripts/BrowserPAC.js” &lt;/li&gt;    &lt;li&gt;Remember to “OK” your way out of the dialogs (yes, I forgot this and hit cancel) &lt;/li&gt;    &lt;li&gt;Close Firefox &lt;/li&gt;    &lt;li&gt;Re-launch Firefox &lt;/li&gt;    &lt;li&gt;Re-launch Fiddler &lt;/li&gt;    &lt;li&gt;Confirm Firefox browser actions show up in Fiddler &lt;/li&gt;    &lt;li&gt;Launch your app &lt;/li&gt;    &lt;li&gt;Paste app address into Firefox &lt;/li&gt; &lt;/ol&gt;  &lt;h3&gt;What Works If I Change Requirements&lt;/h3&gt;  &lt;p&gt;You can deploy the server to IIS and point the Silverlight Client at it. That’s fine … but I didn’t want to bother with that. Just want Cassini to do it all.&lt;/p&gt;  &lt;p&gt;You can use Nikhil’s excellent IE plug-in, &lt;a href="http://projects.nikhilk.net/WebDevHelper"&gt;Web Development Helper&lt;/a&gt;. This works too. You enable it from the IE menu: View / Explorer Bars / Web Development Helper.&amp;#160; But I was looking for a Fiddler solution.&lt;/p&gt;  &lt;h3&gt;What Doesn’t Work&lt;/h3&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;Don’t have VPN running&lt;/em&gt;&lt;/strong&gt;. The minute I’m running my VPN, Fiddler stops listening to all IE traffic, even regular browser traffic (no problem for Firefox though). I’m sure there is a way around this. I don’t know what it is … and at the moment it is just easier to shut down my VPN.&lt;/p&gt;  &lt;p&gt;Many kind people offered suggestions … all of which failed me one way or another:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;localHost.:&lt;em&gt;port&lt;/em&gt;/myapp (that’s with a period between “localhost” and colon) - app crashes, unspecified service security exception &lt;/li&gt;    &lt;li&gt;127.0.0.1:&lt;em&gt;port&lt;/em&gt;/myapp instead of localhost - app crashes, unspecified service security exception &lt;/li&gt;    &lt;li&gt;ipv4.fiddler:&lt;em&gt;port&lt;/em&gt;/myapp instead of localhost - app crashes, unspecified service security exception (because translates to 127.0.0.1) &lt;/li&gt;    &lt;li&gt;myMachineName:&lt;em&gt;port&lt;/em&gt;/myapp instead of localhost – “[Fiddler] Connection to ward-xps failed.       &lt;br /&gt;Exception Text: No connection could be made because the target machine actively refused it” &lt;/li&gt;    &lt;li&gt;Fiddler proxy setting: Tools / Fiddler Options / General / uncheck “Enable IPv6” – no help &lt;/li&gt;    &lt;li&gt;Fiddler Tools / WinINET Options / LAN Settings. “Use a proxy server” checked. Click Advanced button … proxy addresses are set to 127.0.0.1 – no help &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Many of these suggestions are variations on the cryptic paragraphs in the configuration FAQ on the Fiddler site: &lt;a title="http://www.fiddlertool.com/Fiddler/help/hookup.asp#Q-LocalTraffic" href="http://www.fiddlertool.com/Fiddler/help/hookup.asp#Q-LocalTraffic"&gt;http://www.fiddlertool.com/Fiddler/help/hookup.asp#Q-LocalTraffic&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-5117385275651017921?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/5117385275651017921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=5117385275651017921' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5117385275651017921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/5117385275651017921'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/08/fiddler-wcf-soap-cassini-ooof.html' title='Fiddler + WCF SOAP+ Cassini = Ooof!'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-6755898249243835525</id><published>2009-08-22T12:52:00.001-07:00</published><updated>2009-08-22T12:52:15.526-07:00</updated><title type='text'>Discover Silverlight with “Silverlight 3 Jumpstart”</title><content type='html'>&lt;p&gt;Maybe you’ve heard of this Silverlight thing. There’ve been 2,300 new Microsoft technologies introduced this year but Silverlight seems like it might be important. You are a busy, experienced business application developer with limited time. You demand substance but there’s no way you’re going to wade through 800 pages of how to build custom flashy controls. You won’t tolerate marketecture; you don’t want the “Silverlight Programmers Bible” either.&lt;/p&gt;  &lt;p&gt;You should snag a copy of “&lt;a href="http://silverlightjumpstart.com/Default.aspx"&gt;Silverlight 3 Jumpstart&lt;/a&gt;” by Microsoft MVP and Regional Director &lt;a href="http://blog.davidyack.com/"&gt;David Yack&lt;/a&gt;. At a slim 209 pages you can blaze through it on a roundtrip flight to Redmond just like I did. You won’t learn Silverlight in depth. But you will get a soup-to-nuts view of what building a business application in Silverlight is really like. All of the essential mechanics are there.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;How Silverlight compares to alternative client technologies (ASP, WinForms, WPF, Flash/Flex/Air) &lt;/li&gt;    &lt;li&gt;Development tools – got Visual Studio? not much more is absolutely required &lt;/li&gt;    &lt;li&gt;“Hello, Silverlight” – of course &lt;/li&gt;    &lt;li&gt;Hosting a Silverlight app – pretty easy stuff &lt;/li&gt;    &lt;li&gt;Basic screen layout with XAML and visual controls &lt;/li&gt;    &lt;li&gt;Data binding controls to data – because that’s our bread and butter &lt;/li&gt;    &lt;li&gt;Debugging – about time someone talked about that &lt;/li&gt;    &lt;li&gt;Making it look decent with styling - think CSS&lt;/li&gt;    &lt;li&gt;SketchFlow intro – executable sketches to win your client’s confidence &lt;/li&gt;    &lt;li&gt;Plumbing (aka, Application Architecture) – so you don’t reinvent every wheel &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;David is steadfast and clear about his purpose: to give you a firm grasp of what is involved in Silverlight development. &lt;/p&gt;  &lt;p&gt;He shoves to the side everything that would get in the way. You already know it gets more complicated than “that” … whatever “that” happens to be. “Rough road ahead” signs are sufficient for the nonce; no need for the bumpy ride right now.&lt;/p&gt;  &lt;p&gt;When it comes to getting data into and out of your application, I’m personally thrilled to report that David devotes pages [181 - 184] to our &lt;a href="http://www.ideablade.com/DevForceSilverlight/DevForceSilverlight_overview.aspx"&gt;DevForce Silverlight&lt;/a&gt; product; full disclosure: I helped him with those four pages. Nearby you can read about the other “Business Application Frameworks”: CSLA, RIA Services, and roll-your-own. &lt;/p&gt;  &lt;p&gt;Do yourself a huge favor: don’t roll-your-own; I hope you see why when you look at all the challenging ground these “frameworks” cover.&lt;/p&gt;  &lt;p&gt;The very nature of this book requires that it be early to market. It’s not going to be a “timeless classic” nor is that its intention. This is one of the first … if not &lt;strong&gt;&lt;em&gt;the&lt;/em&gt;&lt;/strong&gt; first … Silverlight 3 books out there. &lt;/p&gt;  &lt;p&gt;The haste shows. There are grammar and spelling mistakes. Chapter 10 was clearly intended to be Chapter 1 as it makes forward references to chapters that you’ve already read. That’s mildly disappointing. Don’t let this undermine your faith in the material; the book is accurate in all important respects relevant to your purpose: to learn what Silverlight development is like and whether it might be for you.&lt;/p&gt;  &lt;p&gt;The book is affordably priced at $30 for print, $20 as an e-book; if you use the discount code for my blog (“WardBlog”), the e-book is only $15. The e-book arrives as a PDF and (unlike many technical books) is perfectly readable on your laptop or Kindle or other e-book reader.&lt;/p&gt;  &lt;p&gt;Silverlight is a tremendous business application delivery vehicle and a heck of a lot more productive than any other web technology out there. Silverlight Jumpstart will show you why.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-6755898249243835525?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/6755898249243835525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=6755898249243835525' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6755898249243835525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/6755898249243835525'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/08/discover-silverlight-with-silverlight-3.html' title='Discover Silverlight with “Silverlight 3 Jumpstart”'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-2564785572353724605</id><published>2009-08-20T18:26:00.001-07:00</published><updated>2009-08-20T18:26:32.193-07:00</updated><title type='text'>Presentation Patterns Podcast</title><content type='html'>&lt;p&gt;&lt;a href="http://herdingcode.com/?p=208"&gt;Jeremy Miller, Glenn Block, Rob Eisenberg &amp;amp; I&lt;/a&gt; held a lively, civilized two hour conversation about presentation patterns, courtesy of the good fellas at &lt;a href="http://herdingcode.com"&gt;Herding Code&lt;/a&gt;. Part One of the podcast was just &lt;a href="http://herdingcode.com/?p=208"&gt;released&lt;/a&gt;; the hosting page provides a synopsis so you can read quickly to discover if it’s for you. &lt;/p&gt;  &lt;p&gt;You always feel a tinge of regret after doing these things … like you’re not sure what you did last night after a serious bender … but having replayed it, I’m thinking there are some useful hints tucked in there. Check it out.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-2564785572353724605?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/2564785572353724605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=2564785572353724605' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2564785572353724605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/2564785572353724605'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/08/presentation-patterns-podcast.html' title='Presentation Patterns Podcast'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-3803525430074353393</id><published>2009-08-15T22:34:00.001-07:00</published><updated>2009-08-15T22:34:53.247-07:00</updated><title type='text'>Do Not Make Every Method Virtual</title><content type='html'>&lt;p&gt;I’m reacting to Roy Osherove’s recommendation, “m&lt;em&gt;ake methods virtual by default&lt;/em&gt;”, in his excellent &lt;a href="http://manning.com/osherove/"&gt;The Art of Unit Testing&lt;/a&gt; which I &lt;a href="http://neverindoubtnet.blogspot.com/2009/08/art-of-unit-testing.html"&gt;reviewed a few days ago&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I’ve heard my friend &lt;a href="http://codebetter.com/blogs/jeremy.miller/default.aspx"&gt;Jeremy Miller&lt;/a&gt; wish that .NET methods were virtual by default as they are in Java. I respect these guys immensely but I strenuously disagree. You should make each member virtual reluctantly and in the full knowledge of the risk you are taking. I hope you’ll at least appreciate my concerns even if you are not convinced.&lt;/p&gt;  &lt;h3&gt;Why Virtualize All Members By Default&lt;/h3&gt;  &lt;p&gt;It’s Roy’s first suggestion in his “Design for Testability” appendix [258]. He calls it “handy” and it is handy indeed. The easiest way to stub or hand-mock a class is the “extract and override” approach in which you override a production class to gain access to its innards during testing.&lt;/p&gt;  &lt;p&gt;In one such example [71], a TestableProductionClass derives from a ProductionClass so that the implementation of the latter’s GetConcreteDependency() can be replaced with an alternative that returns a stub class instead of the concrete class.&lt;/p&gt;  &lt;div style="margin-left: 10pt"&gt;&lt;font face="Courier New"&gt;// ProductionClass      &lt;br /&gt;protected virtual ILogger GetLogger() { return new ProductionLogger();}&lt;/font&gt;     &lt;br /&gt;    &lt;br /&gt;&lt;font face="Courier New"&gt;// TestableProductionClass : ProductionClass      &lt;br /&gt;protected override GetLogger() { return new TestLogger(); }&lt;/font&gt;&lt;/div&gt;  &lt;p&gt;What an easy way to swap out the dependency on the production logger … and I don’t need any of that messy IoC machinery.&lt;/p&gt;  &lt;p&gt;If every method were virtual, any member could be replaced in this fashion within the test environment.&lt;/p&gt;  &lt;p&gt;Making every method virtual makes life easier for the mocking frameworks too. Most do well at fabricating mocks either for interfaces or for unsealed classes with protected virtual methods. I believe it is fair to say that most have a tougher time mocking closed concrete classes.&lt;/p&gt;  &lt;p&gt;A class with all virtual methods is easier to proxy too, lending itself to injection techniques such as Ayende demonstrates in his &lt;a href="http://ayende.com/Blog/archive/2009/08/07/nhibernate-amp-inotifypropertychanged.aspx"&gt;post about injecting INotifyPropertyChanged into POCO objects&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;What could possibly be wrong with this?&lt;/p&gt;  &lt;h3&gt;Invites Violation of Liskov Substitution Principle&lt;/h3&gt;  &lt;p&gt;The “&lt;a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle"&gt;Liskov Substitution Principle (LSP)&lt;/a&gt;” is the “L” in Robert “Uncle Bob” Martin’s &lt;a href="http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod"&gt;SOLID design principles&lt;/a&gt;. Formally this principle states that the derived class can’t make a method’s pre-conditions stronger nor post-conditions weaker. In colloquial English, the derived method can’t change the fundamental guarantees of the base method. It may do things differently but it shouldn’t violate our expectations of what goes in, what comes out, or what the method does.&lt;/p&gt;  &lt;p&gt;Uncle Bob, in his &lt;a href="http://www.amazon.com/Principles-Patterns-Practices-Robert-Martin/dp/0131857258"&gt;Agile Principles, Patterns, and Practices in C#&lt;/a&gt; , describes LSP as a “prime enabler of the &lt;a href="Open Closed Principle "&gt;Open Closed Principle&lt;/a&gt; (OCP)” [151]. It follows that a violation of LSP is effectively a violation of the more familiar OCP.&lt;/p&gt;  &lt;p&gt;Now I have no problme with deliberately making some methods virtual. That is one of the favored techniques for facilitating OCP; it is a mechanism for identifying an opening for extension.&lt;/p&gt;  &lt;p&gt;My argument is with opening up the class blindly and totally by making everything virtual. Suddenly nothing in the class is truly “closed for modification.” The “virtual” keyword announces to the world “here is my extension point.” When every method is virtual, the world is invited to change every method.&lt;/p&gt;  &lt;p&gt;The lesson of Martin’s LSP chapter is that extending a class by overriding a virtual method is tricky business. The innocent seeming Rectangle is his famous example. What could go wrong in deriving Square from Rectangle and overriding its Length and Width properties? It turns out that plenty can go wrong [140] and that it’s almost impossible for the author of the class to anticipate and guard against the abuse of his class.&lt;/p&gt;  &lt;p&gt;Martin is pragmatic. “Accepting compromise instead of pursuing perfection is an engineering trade-off. … However, conformance to LSP &lt;em&gt;should not be surrendered lightly&lt;/em&gt;.” [his emphasis, 149] . He continues:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;The guarantee that a subclass will always work where its base classes are used is a powerful way to manage complexity. Once it is forsaken, we must consider each subclass individually.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;I’m going to come back to this point. Because we give up the guarantee … and open wide the door to big trouble … when we make every member virtual.&lt;/p&gt;  &lt;p&gt;Let back up a second and elaborate on the danger.&lt;/p&gt;  &lt;h3&gt;The Wayward Elevator&lt;/h3&gt;  &lt;p&gt;I am the maker of Elevator software that runs elevators around the globe. My Elevator class has an Up method. Suppose I make it virtual. How might value-added elevator developers implement an override of a virtual Up in their derived BetterElevator class? They could&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;replace it completely; base.Up() not called &lt;/li&gt;    &lt;li&gt;call base.Up(), then invoke custom logic &lt;/li&gt;    &lt;li&gt;invoke custom logic, then call base.Up() &lt;/li&gt;    &lt;li&gt;wrap base.Up() in pre- and post-logic &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It’s not an issue when &lt;em&gt;I am doing the deriving&lt;/em&gt;. I almost never call base when I derive a test class (TestElevator). If I support construction of a dynamic proxy to address cross-cutting concerns, I expect the proxy to wrap the base method. These scenarios are not worrisome to me. Why?&lt;/p&gt;  &lt;p&gt;When writing tests, I have intimate knowledge of Elevator. Elevator’s details are open to me. I wrote it. I know what I’m doing.&lt;/p&gt;  &lt;p&gt;If I make Up() accessible to a proxy, I again know what I’m doing … and more importantly, I know how the proxy will manipulate my method. The proxy may behave blindly but it operates automatically and predictably. Whether I decorate the method with attributes or map it or rely on some conventions, I, the author of the class, am choosing precisely how it will be extended.&lt;/p&gt;  &lt;p&gt;Unfortunately, I can’t declare Up() to be “virtual for testing” or “virtual for proxying”. It is simply “virtual”, an invitation to extension by unknown developers in unknown ways. I have lost control of my class.&lt;/p&gt;  &lt;p&gt;I knew that Up() sent the elevator ascending. But I can’t stop someone from re-implementing Up() so that it descends instead. Maybe base.Up() triggers the doors to close. The developer might call base.Up() too late, sending the elevator in motion before the doors have closed. The developer could replace my base.Up with something that juggled the sequence of door closing and elevator motion methods, interleaving custom behaviors, yielding upward motion that failed to satisfy some other elevator guarantees.&lt;/p&gt;  &lt;p&gt;Any of these or a hundred other implementations of Up() could alter Up-ness in ways that are subtly incorrect or catastrophically wrong. Everyone one of those implementations requires that the developer understand intimate details of the Elevator class, details that he would not have to know if the method were sealed. &lt;/p&gt;  &lt;p&gt;“Up” is definitely not closed to modification. It is dangerously open. As an Elevator man, I should work hard … perhaps writing a lot of Elevator.Up certification tests … to ensure that essential pre-conditions, post-conditions, and possible side-effects are all correct even for derived classes.&lt;/p&gt;  &lt;p&gt;The burden on my development has gone up as well, not through conscious design but by default. This is unthinking design, fiat design. My code fails “open” instead of “failing” closed. I better be very good and very conscientious about manually sealing what the language would make virtual on its own.&lt;/p&gt;  &lt;p&gt;I’m not that good and I’m definitely not conscientious.&lt;/p&gt;  &lt;h3&gt;Is This Paternalism?&lt;/h3&gt;  &lt;p&gt;Am I being absurdly protective. Sure there are risks. Programmers are adults and we should treat them as such. &lt;/p&gt;  &lt;p&gt;I hear this a lot. I hear about how Microsoft tends to infantilize the developer, tries to shield them from the bumps and bruises that are essential to mastering the profession. There comes a time when you let the kid have sharp scissors and run around with them if he must. A few blind kids is a price worth paying.&lt;/p&gt;  &lt;p&gt;I agree … as long as I’m not paying the medical bills.&lt;/p&gt;  &lt;h3&gt;I Write Frameworks, You Write Applications&lt;/h3&gt;  &lt;p&gt;I can’t tell you how to build your applications. When you own the class … and you do as an application developer … your team is answerable to you. You don’t come to me with your medical bills.&lt;/p&gt;  &lt;p&gt;But I write frameworks for you to use. You’ve licensed my product and you’re paying me for support. When the elevator goes down instead of up; when the doors close suddenly and injure a rider; when the elevator simply stops … you don’t say “I wonder what I did?” You say “that elevator we bought is a piece of crap.” &lt;/p&gt;  &lt;p&gt;You paid for support. You call me. And I am pleased to give it.&lt;/p&gt;  &lt;p&gt;It’s not free to you. It’s not free to me either. I have to find what’s wrong as quickly as possible and get your elevator moving safely again. Unfortunately, if you’ve written BetterElevator (as you are supposed to do … it’s a framework remember) and you can change everything about my Elevator, I face an extremely challenging support call.&lt;/p&gt;  &lt;p&gt;I have no idea what you’ve done. I don’t know what you’ve done to elevator and I can’t guess. You can tell me … you will tell me … that you haven’t touched “Up”. Perhaps you didn’t. Instead you’ve overridden another method on another of my classes that Up requires.&lt;/p&gt;  &lt;p&gt;Maybe you don’t write applications. Maybe you write an open source framework. Fantastic. You don’t have true customers. If someone has a problem, you diagnose it and maybe you fix it … at your leisure. That someone has no recourse … and knows that going in. &lt;/p&gt;  &lt;p&gt;That’s often why businesses won’t use open source. As more than one manager has told me, “I want a neck to wring.”&lt;/p&gt;  &lt;p&gt;I think I’m entitled to fear for my throat. But that’s not my real motivation. I’m in the business of providing good service for a product that makes certain behavioral guarantees. I can’t deliver good service if I can’t make those guarantees and I can’t make those guarantees if every method of every class is up for grabs.&lt;/p&gt;  &lt;p&gt;I’m not sure you can either.&lt;/p&gt;  &lt;h3&gt;.NET Framework Design Guidelines&lt;/h3&gt;  &lt;p&gt;I’m not the only guy with a healthy suspicion of virtual methods. I admit my degree of suspicion is higher than the that of the application architect’s. The application architect probably knows and controls the developer who derives from his class. The unknown developer who derives from my class controls me.&lt;/p&gt;  &lt;p&gt;The designers of .NET understand this too well. That’s why in the &lt;a href="http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321246756"&gt;.NET Framework Design Guidelines&lt;/a&gt;, Krzysztof Cwalina and Brad Abrams write&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Virtual members … are costly to design, test, and maintain because any call to a virtual member can be overridden in unpredictable ways and can execute arbitrary code. .. [M]uch more effort is usually required to clearly define the contract of virtual members, so the cost of designing and documenting them is higher.&amp;#160; [201]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If all members are virtual by default,&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;I waste effort manually sealing most of them, &lt;/li&gt;    &lt;li&gt;I test and document and support more methods than I have resources to support &lt;/li&gt;    &lt;li&gt;I add unwanted complexity &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;and what do I gain for my pains?&lt;/p&gt;  &lt;h3&gt;What Should We Do?&lt;/h3&gt;  &lt;p&gt;I want to blame someone. I’m going to blame the language authors. Maybe methods are automatically virtual only in test environments. We should be able to mark methods for proxying and compile time injection (as in static Aspect Oriented Programming). Otherwise, members are closed unless explicitly made virtual through the conscious effort of a conscientious programmer.&lt;/p&gt;  &lt;p&gt;Meanwhile, I’m prepared to be pragmatic. I like Roy’s recommendation [260] that dependencies should be defined in virtual properties (or methods) without logic.&amp;#160; Auto-properties and similar logic-less methods are safer to make virtual. The &lt;a href="http://en.wikipedia.org/wiki/Template_method_pattern"&gt;Template Design Pattern&lt;/a&gt; is a controlled approach to extensibility that may assist testability as well. Interface-based designs help too.&lt;/p&gt;  &lt;p&gt;That’s as far as I dare go as a framework developer. Application developers may have more rope to hang … er … more latitude.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/393540894130950585-3803525430074353393?l=neverindoubtnet.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://neverindoubtnet.blogspot.com/feeds/3803525430074353393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=393540894130950585&amp;postID=3803525430074353393' title='26 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/3803525430074353393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/393540894130950585/posts/default/3803525430074353393'/><link rel='alternate' type='text/html' href='http://neverindoubtnet.blogspot.com/2009/08/do-not-make-every-method-virtual.html' title='Do Not Make Every Method Virtual'/><author><name>Ward Bell</name><uri>http://www.blogger.com/profile/10977457957771020146</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-_KfbYBXqYak/Tnkw9N4CS3I/AAAAAAAAAJk/ICDGqMG-7ps/s220/Ward.jpg'/></author><thr:total>26</thr:total></entry><entry><id>tag:blogger.com,1999:blog-393540894130950585.post-9026296259353256240</id><published>2009-08-14T14:50:00.001-07:00</published><updated>2009-08-15T22:37:46.021-07:00</updated><title type='text'>The Art of Unit Testing</title><content type='html'>&lt;p&gt;After I read &lt;a href="http://devlicio.us/blogs/tim_barcz/archive/2009/07/23/book-review-the-art-of-unit-testing.aspx"&gt;Tim Barcz’s review&lt;/a&gt; of Roy Osherove’s “&lt;a href="http://manning.com/osherove/"&gt;The Art of Unit Testing&lt;/a&gt;” and I knew I had to get a copy right away. It just arrived and I read it in one sitting.&amp;#160; I am so pleased that I did. I’ll quarrel with it … but do not let that deter you from rushing to buy your own copy.&lt;/p&gt;  &lt;p&gt;Let me say that again. I highly recommend this book – five stars -, especially to folks like me who are not deep into unit testing. This review is full of my grumpy disagreements. That’s how I engage with a good book. Don’t be dissuaded.&lt;/p&gt;  &lt;p&gt;&lt;font color="#808000"&gt;&lt;strong&gt;&lt;em&gt;Warning: Long post ahead. The short of it: buy the book. Everything else is commentary.&lt;/em&gt;&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;There is no point in recapping the book’s main points as &lt;a href="http://devlicio.us/blogs/tim_barcz/archive/2009/07/23/book-review-the-art-of-unit-testing.aspx"&gt;Tim Barcz&lt;/a&gt; did that for us. I’m coming at it from a different angle. I’m coming at it from the angle of a guy who wishes he wrote more tests, wishes he was good at testing, even wishes he practiced (or at least gave a serious, sustained effort at trying) TDD. A guy who doesn’t.&lt;/p&gt;  &lt;p&gt;A guy much like the vast multitude of developers out there … who is embarrassed by being “old school”, is looking for an opportunity to catch up, but isn’t going to take crap from an obnoxious TDD fan-boy. &lt;/p&gt;  &lt;p&gt;I’ve had plenty of success over the years, thank you very much. I’ve written good programs (and bad) that still work. And I can mop the floor with legions of developers who think TDD/BDD/WTF experience yields greatness. They remind me of newly minted MBAs who believe with unshakeable certainty that they’re entitled to a management position. Think again.&lt;/p&gt;  &lt;p&gt;Do I sound defensive? Yup. Enough already. My point is this ... &lt;/p&gt;  &lt;p&gt;One of Roy’s goals is to reach people like me. We’re experienced developers who may have mucked around with unit testing but aren’t doing it regularly and may have had some rough experiences. We believe … but we don’t practice. Can he do something for us that makes us want to try again or try harder. Can he keep it simple and approachable and be respectful and non-dogmatic.&lt;/p&gt;  &lt;p&gt;Yes he can. &lt;/p&gt;  &lt;p&gt;He extends olive branches aplenty throughout. Out the gate he writes: “One of the biggest failed projects I worked on had unit tests. … The project was a miserable failure because we let the tests we wrote do more harm than good.”&amp;#160; &lt;/p&gt;  &lt;p&gt;Thank you. I don’t believe it for a second. Oh I believe the tests were every bit as unmaintainable. I’m just not buying that the project failed because of the tests. They contributed perhaps, but in my experience, projects fail for other deeper reasons. That, however, is another post.&lt;/p&gt;  &lt;p&gt;What I applaud is that he opens empathetically. He goes straight to the dark heart of our limited test-mania experience: when brittle, inscrutable tests became so onerous that they had to be abandoned. Been there. Seen it several times. &lt;/p&gt;  &lt;p&gt;I appreciate that a similarly open and self-critical sensibility shines throughout. I’m particularly fond of the section on alternatives to “Design for Testability” in appendix A. There he notes that the uncomfortable coding-style changes required to support testing are an artifact of the statically typed languages we use today.&amp;#160; “The main problems with non-testable designs is their inability to replace dependencies at runtime. That’s why we need to create interfaces, make methods, virtual, and do many other related things. [266]”&lt;/p&gt;  &lt;p&gt;Dynamic languages, for example, don’t require such gymnastics. Perhaps with better tools and language extensions (Aspect Oriented Programming comes to mind) we can make testing easier for the statically typed languages.&lt;/p&gt;  &lt;p&gt;Here he acknowledges that testing is just too darned hard, harder than it should be, and this difficulty – not resistance to new-ish ideas by crusty old farts like me – is a genuine obstacle.&lt;/p&gt;  &lt;p&gt;Until then, we have to accept that incorporating unit testing in our practice requires more than an act of will. You will need hard won skills and experience and you will have to contort your code to get the benefits of unit testing. This is not your fault. You will pay a bigger price than you should have to pay. It may be rational to say “I can’t pay that price today, on this project.”&lt;/p&gt;  &lt;p&gt;It may be rational. It may also be wrong. In any case, Roy’s goal is to reduce that price as best he can (a) with a progressive curriculum yielding skills you can use at each step and (b) by introducing you to tools that cover for language deficiencies.&lt;/p&gt;  &lt;p&gt;Roy succeeds for me on both fronts. Each step was a small enough to grasp and big enough to be useful. The tools survey was thin … but at least he has one – with opinions – that gives you places to look and an appreciation of their place in a complete testing regime.&lt;/p&gt;  &lt;h3&gt;Part 1 - Basics&lt;/h3&gt;  &lt;p&gt;This part is so important for readers like me. Overall, I thought it was grand. I’m about to freak out about a few of Roy’s choices but before I do I want to say “(mostly) well done!”&lt;/p&gt;  &lt;p&gt;My biggest disappointment is Roy’s scant mention of IoC. There is brief treatment of Dependency Injection [62-64] and a listing of IoC offerings in the appendix. That’s it. There is not a single example of IoC usage.&lt;/p&gt;  &lt;p&gt;Testing is one of the primary justifications for using IoC. Such short shrift could leave the reader wondering what all the fuss is about. Wrongly, in my opinion. I was really looking forward to guidance on proper use of IoC in unit testing.&lt;/p&gt;  &lt;p&gt;The omission felt consequential in Roy’s discussion of test super classes [152ff] where he takes a couple of classes that do logging and refactors their test classe to derive from a BaseTestClass [155] whose only contribution derived classes is its StubLogger. What a waste of inheritance. Injecting a logger is the IoC equivalent of “Hello, World”. What am I missing? &lt;/p&gt;  &lt;p&gt;I realize (from painful experience) that it’s easy to create an IoC configuration rat’s nest in your test environment. That’s why I was hoping Roy would propose some best practices. Instead, I believe we are served an anti-pattern.&lt;/p&gt;  &lt;p&gt;I must also say I was shocked to see favorable mention of using compiler directives [79 
