Tuesday, May 24, 2011

Use wildcards to include resource files in a project

Just discovered from Keith Rome’s blog post that you can use wildcards to include files in a project. This is occasionally useful as when you have lots of resources.

For example, in the IdeaBlade Bookshelf sample application (based on John Papa’s BookClub sample) there is a folder of 58 images:

clip_image001

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.

Alternatively you can edit the project file once to pick up all of the jpgs and never worry about it again.

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).

Each of the image files is mentioned by name in an <ItemGroup/> as shown here.

clip_image002

Replace the entire <ItemGroup/> block with the following:

  <ItemGroup>
    <Content Include="Assets\Images\*.jpg">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content> 
  </ItemGroup>

Save and reload the project. Henceforth, the images will be self-included.

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.

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.

Who knew?

Monday, May 23, 2011

MVVM Backlash

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.

In the end, I am unrepentant: I continue to practice MVVM and recommend it to others.

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.

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.

Disquieting conversations

I have had a long running conversation with sage and MVVM skeptic, Billy Hollis 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:

  1. MVVM is a way for code-addicted developers to deflect attention from the horrible designs they inflict on users,
  2. MVVM complicates development with little or no compensating benefit,
  3. there is too much strident, jargon-filled, punishing MVVM rhetoric that alienates the mass of developers.

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.

I ruefully acknowledge his 3rd objection although I believe we’ve largely outgrown it.

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.

John Papa 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.

But why bother with MVVM in the first place?  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 

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.

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?

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.

The usual arguments for MVVM

Here are bullets from a hypothetical MVVM benefits slide; I’ve drawn them from several presentations, blogs, and discussions.

  • Separation of concerns (SoC)
  • Loose coupling
  • Data Binding
  • Designer / developer symbiosis
  • Reusability
  • Avoid spaghetti code
  • Consistent, maintainable, scalable
  • Support for design time data
  • Automated view-logic testing
  • Multiple views over the same view logic

John and I kicked these around. It turns out that many of them don’t hold water.

We ruled out “separation of concerns” and “loose coupling” right away because they are just jargon to many people.

[update: "ruled out" was a poor verb choice. What I meant was that we didn't want to chant "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.]

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.

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).

Data binding? 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.

Designer / developer symbiosis” refers to the ability of a designer and a developer to work on the view independently without risk of corrupting the other’s work.  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.

The “spaghetti code” 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?

Design time data support? Check! John and I believe developers and designers are more effective when they design, maintain and evolve 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.  I expand on this point below.

Automated view-logic testing? Check! We agreed that automated testing of code-behind is so difficult as to be impractical. Billy agrees too. Score one for MVVM. Of course if you don’t do automated testing of view logic …   I talk more about this below.

Multiple views over the same view logic? Check! 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.

Definitive benefits

Three claims survive close analysis; ViewModel has a decisive advantage when you care about

  • design time data
  • automated view testing
  • multiple views over the same view logic

Do you really care?

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.

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.

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.

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.”

Actually I’ve done it and I’ve got a BookClub demo that shows how. ViewModel automated testing is the way IdeaBlade professional services rolls.

Please, please, please prove me wrong and tell us all where we can see some ViewModel testing.

I might do it if it’s easy

I fear that the unequivocal 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.

I remind you, pace 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.

I suppose what I am saying (and lot of people are saying ) is “take this MVVM medicine … it’s good for you … even though you may not feel different right away. ”

That means MVVM must be easy to do. 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.

Fortunately, MVVM is easy to do. There’s always someone around to make a good thing harder than it needs to be. Laurent Bugnion’s MVVM Light 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.

I have a good feeling about John’s video series. I think it’s going to help you feel good about MVVM.

Appendix: Observation Details

The remainder of this post explores a few of the earlier observations in a bit more detail. Indulge yourself if you will.

Separation of Concerns

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.

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.  Practical consequences attend. But are they sufficiently compelling? Or can a good developer achieve practical separation with little effort?

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.

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.

I considered a detailed discussion of Robert Martin’s SOLID 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.

Culturally ViewModel is more aligned with SOLID thinking but, as I said, you can get the practical benefits in code-behind without much effort.

Loose Coupling

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.

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?

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.  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 DataContext to this in the constructor. Done. The choice is mine.

Automated Testing

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.

Update: Bill Kempf took up the challenge in a follow-up blog post that shows you can (a) write a code-behind ViewModel and (b) test it. Thus he reminds us that MVVM is a pattern admitting of many implementations ... 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!

ViewModel testability alone should be sufficient reason to adopt MVVM designs. And MVVM proponents dutifully recite MVVM’s testability advantage.

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.

One possible explanation: demo 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.

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.  VM testing can seem a well-intentioned luxury that you never get around to doing.

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 IsBusy 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?

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.

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.

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.

Design time data

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.

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:

  • You can’t re-use the sample data as fakes for developer, QA, and automated testing.
  • 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.
  • Complex object graphs are trickier to maintain in XML sample data
  • You have to update the sample data structures as your model evolves
  • Sample data files tend to be scattered around your projects, complicating maintenance.
  • It’s tedious at best to keep the sample data out of the production builds.

The first objection is a big one for me. I’ve always got fake data around during development and testing.

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.

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.

Designer / developer symbiosis

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.

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.

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 might be 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. 

On the plus side, ViewModel discipline 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.

Caliburn

I am a Caliburn 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 behaviors to the XAML; the developer doesn’t write ICommands. 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.

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 IdeaBlade are doing our part to smooth that road.

Friday, March 11, 2011

EFProf First Look: profiling a DevForce SL app

We are destined to fall into a performance tar pit. It’s bound to happen. The real question is how to get out.

It starts with finding where 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.

Which brings me to EFProf, 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 suspected cause of performance problems.

Well, is it or isn’t it? EF Prof can help settle the question. Oren (better known by his nome-de-blog of Ayende Rahien) is the principal behind EFProf; that’s reason enough to give his tool a look.

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.

Setup

Ridiculously easy.

  1. Download and extract the zip (duh)
  2. Add to the web application project a reference to the EFProf profiler library, HibernatingRhinos.Profiler.Appender.v4.0
  3. Initialize the profiler in the Application_Start method of the Global.asax
    #if DEBUG
    // Engage EF Profiler: http://efprof.com
    HibernatingRhinos.Profiler.Appender.EntityFramework.EntityFrameworkProfiler.Initialize();
    #endif

    The application is now instrumented in a debug build. Time to listen for those profile results …

  4. Run the profiler UI executable, EFProf.exe
  5. Enter your license key (first time only; there’s a 30 day trial)
  6. Launch the Silverlight application.

Now even easier: add it to your solution with Nuget and get updates automatically.

What you get

This is a “First Look”, not a tutorial, so all I’m going to do is tease you with a few screenshots.

Here is the main screen after running a DevForce Silverlight automated test sequence.

e:EFProf-statements1

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 ObjectContext instance created in the DevForce EntityServer query pipeline. The highlighted request is the first query:

EFProf-first-query

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.

EFProf-second-query

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.

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:

EFProf-unbounded-alert

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:

EFProf-all-customers-query-sql

Here’s what an individual update operation looks like:

EFProf-save-cust-update

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.

Analysis

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.

It gets better. Check out the Analysis choices. Three strike me as most useful for a DevForce Silverlight application:

EFProf-analysis-overview

EFProf-analysis-expensive-queries

EFProf-analysis-unique-queries

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.

You can apply filters to scope the analysis:

EFProf-filter-choices

And apply them in combination:

EFProf-filters-applied

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.

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.

Cost and ROI

An EFProf license costs ~$300.

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.

Take a look – it’s got a 30 day trial. You’ll be glad you did.

Thursday, March 10, 2011

VS Designer can’t find Resource

We got bit by this one today.

We asked the App.xaml to create a ViewModelLocator as a resource.

<local:ViewModelLocator x:Key="Locator" />

Blend was fine with that. But the Visual Studio Designer (“Cider”) reported an error along the lines of “Cannot find key ‘Locator’” and “Cannot add type to ResourceDictionary”. Of course the view failed to show in the Cider designer. Not good.

We know ViewModelLocator type is defined in “local”. Blend could find it. Why not Cider? Utterly maddening.

We noticed that ViewModelLocator derived from a base class – call it ViewModelLocatorBase – which happed to be defined in a referenced assembly.

When we redefined the ViewModelLocator without the base class, Cider was happy. When we copied the base class into the same project as the ViewModelLocator and derived from the copy, Cider was happy.

There was nothing wrong with the base class itself.  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.

Adding an xmlns reference to that foreign assembly in the App.xaml didn’t help either.

Solution: Give the referenced assembly an XmlnsDefinition

We stumbled into this workaround on a hunch. We opened the AssemblyInfo.cs of the project in which ViewModelLocatorBase is defined and added an Xmlns definition attribute … such as this one:

[assembly: XmlnsDefinition(http://schemas.ideablade.com/presentation, "IdeaBlade.Presentation")]

We recompiled the project and added this xmlns to the top of App.xaml.

xmlns:ibp="http://schemas.ideablade.com/presentation"

Cider smiled upon us at last.

We don’t know if this is the only way to recover. We just know that it works.

Notes:

  • Learn more about XmlnsDefinition here.
  • Remember to add a separate XmlnsDefinition for each namespace in that project.
  • You only encounter this problem when the resource 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 ViewModelLocator created a Foo and Foo is defined in a separate assembly; Foo isn’t a resource. The problem arose because ViewModelLocator – which is a resource – depends upon the ViewModelLocatorBase class that resides in a separate referenced assembly.

Wednesday, February 23, 2011

Nested sandbox editors?

I received an interesting question in the mail today regarding Sandbox Editors and the advice I offered in a previous post:

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.

I guess what I am asking should I always protect a parent view from changes in a child until the user make the change permanent? Is this what you would do in a real application?

The essence of the question is in this one line: “should I always protect a parent view from changes in a child?”

First of all, I always avoid the word “always”.  But seriously …

The point of the separate repository is to isolate the editing context from the main application context. Within 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.”  I’d be surprised if this is really what the user wants.

Let’s step back a bit. Early in my Sandbox Editor post I stressed that some folks prefer seeing the provisional changes propagated across the UI … as they happen. In my mind that is a perfectly reasonable experience. If the user expects it and the view design supports that expectation, all is well.

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.

However, when the editor hovers on top 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.

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?

Back to your question: should you “sub-sandbox”? Only you know what makes the best user experience for your application. The way you design the screens may influence your decision.

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.

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.

Saturday, January 29, 2011

MVVM Party: Data Service Required

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.

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). 

Are there exceptions? I can’t think of a single one. I wouldn’t break this rule in an MVVM demo.

Now if I’m not using the MVVM pattern, fine. I just mandated a rule for ViewModel, not a rule for all UI architectures.

This really is one of the laws of ViewModel construction, taking a privileged place besides a very few other such laws as “The ViewModel may not have a reference to the View” and “The ViewModel may not refer to a type that requires a running view to construct.”

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.

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.

Who Put The Hot Sauce in Grandpa’s Oatmeal?

I’ll give you backstory and then I’ll repeat here what I said on the WCF RIA Services forum.

I frequently troll the WCF RIA Services forum to find out what RIA developers are thinking and <grin> to learn of the many ways in which IdeaBlade’s DevForce is superior.</grin>

I’m especially fond of Colin Blair’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.

This time he gave bad advice.

A developer identified as “lein4d” posted the following question (amended for grammar and style, highlights added)

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?

In many of the recent MVVM examples I've seen, the classes are separated into ViewModel, IServiceAgent, and ServiceAgent classes, in which only the ServiceAgent Class knows about RIA details.

I've been following this approach for a while, but I found it too cumbersome to create all the boilerplate code each time I create another ViewModel.[???] The application I'm creating doesn't have unit tests, and is not making use of design-time data.[!!!]

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.

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?

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 “Feel free to use the DomainContext directly in your ViewModel.

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.

Although I am shy and generally unwilling to express myself forcefully, I found myself writing this spirited reply.

Why ViewModel Should Delegate Persistence To A Service

@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.

I don't have a lot of hard and fast rules. I do have a few. This is one of them.

"No persistence machinery in the ViewModel"

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).

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.

I ask all of my customers to write ViewModels that concentrate 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 "services". A focused ViewModel is easier to understand and easier to test [oops ... I mentioned those points again]. It is also less vulnerable to changes that have nothing to do with the View.

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.  You wouldn't dream of writing that code in each of your Views or ViewModels. The DC abstracts that for you.

But it's not a sufficient abstraction for the ViewModel. There are still too many mechanics. Let's get concrete.

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 "GetCustomers". Why should it care about how that method is implemented?

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?

These are all important considerations. None of them have anything to do with getting customers onto the screen ... which is the VM's job.

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?

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 "no", then the code belongs in a Data Service, not the ViewModel.

Let's generalize that thought. You should be able to answer the following question for all code in your ViewModel:

Would changing this code alter the appearance of the view or how the user interacts with the view? If "yes", the code can stay. If "no", the code belongs elsewhere, perhaps in a helper class to which the VM delegates.

This is not 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.

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.

Obviously I wasn't always looking at Silverlight code; usually it was Windows Forms where the corresponding collaborator is the "Presenter" 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.

Why those differences?  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.

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.

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.

A final detail. Your question seemed to imply that you were creating a new "ServiceAgent" and interface for each ViewModel. You wrote "I found it too cumbersome to create all these boilerplate codes each time I create another ViewModel."

I would find that too cumbersome as well. I tend to write one "ServiceAgent" (DataService, Repository, whatever) per module. That's not a strict rule. But I do find that I use the same service across multiple VMs.  John Papa's tiny BookClub example has a single "BookService" that does the trick for both the BookViewModel and the CheckoutViewModel. You really don't need a lot of these services in your application.

Colin Replies

After I posted, Colin and I had a spirited exchange which you can read on the forum. I won’t repeat it all here. But I will summarize his objections and my counter arguments.

#1 “The primary purpose of the ViewModel is data binding”.

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.

#2 [Paraphrasing] You don’t need a data service for a “Hello, World” application.

True enough. You don’t need MVVM either. More to the point, you probably shouldn’t be using MVVM in a “Hello, World” application.

#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]”.

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 uncomfortable when we waffle.

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.

On this particular and rare occasion, I harbor no such doubts.

Conclusion

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.

You’ll be glad you did.

Friday, December 17, 2010

“Sandbox” Editors with ClientUI Contacts

We’re developing a full-stack WPF/Silverlight development series in concert with Intersoft Solutions using DevForce and Intersoft’s “ClientUI” technology. You can learn about the series and keep up with the latest developments on our website.

Today I’m announcing the second installment of the series which replaces the “synchronous” editor with a “sandboxed” editor.

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:

image

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.

For example, the unfinished editing session in which we changed “Andre” to “Bob” should look like this:

image

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.

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 walkthrough document that accompanies the second code sample.

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.

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.

Happy holidays!

Update: Checkout the related post in which I answer an email about nested sandbox editors