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.

46 comments:

Anonymous said...

I agree that the "MVVM is the only way" viewpoint seems to be both widespread and held without understanding by most.

However, there are two points I think are missed here

1) What-Not-How. I'm not going to use the jargon here, so let's say "What not How"... In MVVM, I might have want to make the record state "Booked" when a provider is selected. I find this much easier to think of than "when the listbox 'providerList' has 'SelectedItem !=null' set 'StateLabel' to 'Booked'. Sure, you need to do both, but in MVVM the logical state can be thought about entirely on its own. Sure, you hit this a bit in your SoC discussion, but a simple concrete makes it no longer an academic point, and now a real one.

2) People say MVVM makes code more complex, but I'd like to see why they say that. Different, yes. but decoupled doesn't always mean complex- ask a RoR developer, where coupling is often by convention. Often this means the person doesn't actually use it and finds it unfamiliar. I normally have *no* code-behind, and less code in my viewmodel than I did in the codebehind.

G. Andrew Duthie said...

Nice post. Appreciate the 'open kimono' assessment of MVVM. While I've come to appreciate MVVM, I'm still trying to get my head around how to communicate its value to others, and you highlight the reason why many of the usually-touted advantages ring hollow for most devs.

One of the reasons I enjoy talking to Billy about stuff like this is that he's usually right...and he's not shy about calling out what he sees as unnecessary stuff that can get in our way.

Thanks for sharing the observations...it may make MVVM that much less appealing to the general population, but distilling the essential benefits means that you're making a more compelling case to those who care about those specific advantages.

Ward Bell said...

Thanks @G. Andrew Duthie

Ward Bell said...

@Anonymous You are right that there is no SoC if the code-behind has logic that refers to the state of a ListBox.

My point is that the view could be bound to a property in the code-behind ... in which respect it is no different from a binding to a similar property of the VM.

Culturally, code-behind-ers tend to write in the manner you describe. But if we could teach MVVM, we could teach a different way to do code-behind.

I don't think MVVM is "more complex". I must agree that adding a separate VM class adds complexity. Fortunately, it can recover by reducing complexity and pain elsewhere in the system.

Vic Klien said...

Wow, great post. Relating MVVM to politics and religion: This questioning of MVVM is like a "Newt Gingrich" moment. When someone who doesn't understand MVVM tries to critique it, it's not nearly as interesting as when someone really knowledgeable does. For a religious example of that, see the books on the bible by "Bart Ehrman", former believer who is now an "agnostic".

Vic

wekempf said...

Someone once pointed out that the codebehind can be thought of as a ViewModel of sorts. If you treat it as such it might even be possible to unit test it, in which case the only benefit you really get is the ability to have multiple Views.

Someone else (or maybe the same someone) pointed out that the design of "lookless controls" in WPF/XAML is a very strict realization of MVVM, and the only reason for it is to provide the ability to template/style the control, so as easy as it is to think you'll rarely want to have multiple Views for a ViewModel, that does seem to be the biggest architectural reason for the pattern.

Just food for thought.

John Papa said...

I appreciate that you spent the time putting this all down. I also appreciate that you made it clear that you and I discussed this and have similar, though not exact same mindsets on this.

The key to this discussion that you and I had was to find out how to help folks learn MVVM who are "interested" in learning MVVM. You and I both feel (now I'll include you in this statement)that we should not force anyone into any pattern. The difference here is important: we're not stating that everyone should do it or they are evil. Rather, we are saying that if you believe in things like SoC, total cost of ownership, maintainability, blah blah blah then you may want to look at this. But if you don't, that's cool too. We'll still be your friends :)

The learning material I am working on is really intended to help folsk solve problems. I could title it that, but MVVM will sell more :)

Ward Bell said...

@wekempf Thanks for your comments.

Do share if you know a practical, low friction way to test code-behind. I can't think of one.

I'll take this moment to say that I value the cultural and psychological forces attached to MVVM that foster maintainable code. I'm not walking away. I'm cutting through the exaggerations. Cheers!

Vic Klien said...

@John Papa,

As an "evangelist" your goal is rather modest (realistic?). You seem to be saying, you only want to assist the believers who have already joined the church to become more skilled at the incantations. The more ambitious and challenging goal would be to actually persuade the large body (>50%?) of SL-devs who are still skeptical, unwashed, code-behind infidels.

A miracle or two might be helpful.

Vic

Ward Bell said...

@john_papa Agreed!

I just had to write down what I remembered of our search for arguments that resonate with the widest possible developer audience. It was not as easy as I thought it would be.

I appreciate your non-dogmatic approach and I am sure your audience counts on it.

Looking forward to your series.

John Papa said...

Vic ... your assuming what I do always accrues directly to my my role with my employer. I am a developer, have been a consultant, and an architect of maintainable systems for 15+ years. That's my perspective. I'm not an evangelist for a pattern. If folks are ready, I'll help them with the pattern.

I won't and don't try to sway folks to the wrong way. I just wont do it.

Rob Eisenberg said...

Separation Patterns, including MVVM, are just a manifestation of OOD in the UI tier. If you don't value maintainability or extensibility, then there's really no point in learning to write good object oriented code at all. That's why it was invented. But, if you do value those things, it's worth taking the time to learn.

Unknown said...

@wardbell "We at IdeaBlade are doing our part to smooth that road" Is there a reference app available that shows Caliburn and devforce working together ?

Vic Klien said...

@John Papa,

No disrespect was intended. I think you do a great job, and I appreciate your "no-BS" style.

Personally, as a SL-dev, I know a lot of the basic MVVM "incantations", but I'll confess that as I'm doing them I often question my faith. That's why I like Ward's post / discussion, because hopefully it will either build my faith, based on reason, or else make me a less-guilty-feeling agnostic.

Vic

Ward Bell said...

@vic - I didn't hear what you heard in John's comment. I don't think his MVVM series has an evangelical mission.

His series will explain "how" to those who want to know how.

Secondarily, the series introduction will offer reasons why to the curious.

What we were looking for is a way to talk about the "why" without reciting principles. We believe in those principles ourselves - not backing off from that.

But (speaking for both of us) we felt (a) we had to avoid punishing dogmatism and (b) we could learn more and reach more people by skipping the chapter-and-verse and going direct to practical consequences.

Such outreach is a worthy if secondary goal.

Ward Bell said...

@Stephen - Yes there is a sample on codeplex of DevForce and Caliburn working together.

I'll be doing a webinar about it with Rob Eisenberg early next month.

Pragmatect said...

In large (e.g. LOB) projects, code/markup comprehension, navigability, and maintenance are going to trump a lot of the other concerns you have mentioned. One of the ways you can manage those concerns is by paying attention to "Separation of Concerns" or "loose coupling" in your application. So please don't whack those two so cavalierly!! Why do we tend to approach architectures/patterns as a one-size-fits-all? I think we have been too eager to automatically apply MVVM, as if from rote memory, to any SL or WPF project that comes our way. Just as Martin Fowler (and Eric Evans) have said in their various books and publications, you don't automatically apply the Domain Model; sometimes Active Record is more apropos to the problem at hand. There are times when it is valid to use code behind. But I have personally experienced the brutal awfulness (this is the opposite of Ingebretsen's Awesomenss btw) of a large WPF application that should have had some MVVM-like pattern applied to it, but the developers in the beginning were not aware that such architectures could be applied, and just used Markup Subclassing and code-behind like techniques.

Rob

Ward Bell said...

@rob - I'm an unreconstructed fan of MVVM as you know.

But let's be kind. Maintainability and extensibility are widely held values ... even by those who are not sold on MVVM.

What I tried to explore in this essay was the possibility of writing maintainable and extensible code in Code-Behind style. I'm not recommending it. But before I declared it impossible, I wanted to think it through.

The more I thought about it (and John and I talked about this at length), the more I realized that you could create maintainable, extensible applications if you were disciplined in how you wrote the code-behind.

You couldn't write testable code in code-behind. You couldn't get the reusability of design data that I value with the code-behind approach. You couldn't benefit from Caliburn-style convention-based autowiring.

But just because you went the code-behind route didn't mean it was necessarily a big pile of crap either. You can keep it DRY and externalize dependencies and use binding to decouple the code-behind from the GUI controls.

I have to say that every time I've seen significant code in the code-behind, it's been what I would call a big-pile of crap. I just can't be sure that it is always a pile of crap.
To be fair, we've seen some crappy ViewModels too.

I haven't looked at Billy's code. I know he's had years of success in real world application development and delivery. If he's not writing MVVM, I figure he must have found a way to do well without it. I'm kind of curious about that.

In any event, this essay intends to hold the door open, to allow for the possibility of well-written code-behind.

Testability, design data, convention-based wiring ... and the obligatory SoC that MVVM imposes on me, the slacker developer ... these are good enough reasons for me personally to stick with MVVM.

Ward Bell said...

@pragmatech - Well said.

I hope I wasn't perceived as dismissive of SoC or loose coupling. Heaven forfend! They're critical.

I was merely acknowledging that those principle could guide code-behind development ... even if they usually don't.

Teaching MVVM remains as important as ever. We want to make it accessible to everyone, even those unfamiliar with the pattern terminology. We want to reach those folks early, before they've gone too far down the path of a nasty code-behind mess.

If they're good enough to do it all in code-behind and keep it clean, bless them. I've never seen it, but I can't deny the possiblity.

Pragmatect said...

Ward,

maybe we should redefine SoC as "Separating of Concerns" instead of "Separation of Concerns" to focus more on the process, more on the developer's mental model, rather than some magical end result... I think when you put yourself into the state of mind of thinking about the different code layers and programming artifacts more in terms of "Model", you tend to avoid commonly accepted bad practices. What MVVM does for you is put in in a mental state that each contributing entity to the application (Model, ViewModel, View) has a distinct role. What role does code behind play in a Xaml-based application? It some ways it seems like a convenient bucket to dump event-handlers and related code that VS will conveniently put there for you.

Rob

Anonymous said...

Having used MVVM on 4 projects,I agree in general with your points.

I do however agree with another comment above, which refers to the idea that vms can be used nicely for more 'micro' scenarios such as binding to datatemplates. For a simple example, my current wpf project has a datatemplate for capturing email data (to, subject, body...) and I have a corresponding emailMessageVM. The point is, not all vms are necessarily a 1-1 replacement for code-behind.

Another problem with code-behind is the difficulty in inheriting from a base class in the code-behind world. I worked on a project that had 50-100 screens that all had some very common elements (videos, menu items, images, header text, help text...), all of which was maintained in a database via a cms. It was fantastic to be able to create one base screen viewmodel that took care of fetching all that common data. A lot of the screen specific viewmodels did nothing more than inherit from the base class, seeding it with the screenid which fetched the specific data for that screen.

Of course testability is critical in some scenarios and a waste of money in others. If you are writing a CRUD screen and write automated tests, I think in most cases you are wasting your client's money.

Mr Hollis is pretty funny I must admit. I remember a podcast where he said something like if you follow all the dogma going around, you will be pair programming, writing 2 lines of test code per line of prod code, and employing 1 QA person per 2 coders. In that scenario the person paying the bills will be paying 5x as much as just employing 1 sound engineer with a remit to get the job done.

John Papa said...

Vic ... No worries, no insult taken. Just clarifying that the training i am doing is not part of my direct role. I love good code, good patterns, and MVVM falls into that. I see a lot of folks falling down with MVVM and spend a lot of my time helping them. So I figured it was time for me to put it all down. Plus, its just something I enjoy.

Good to hear that you use MVVM and that you question it occasionally. I firmly believe that its good practice to refactor our own thinking occasionally.

Ward and I both are firm beleivers and practioners of MVVM. We both agree there are multiple right ways, too. We spend a lot of time bouncing ideas off each other to see what stinks.

Thanks for the compliment, BTW :)

Anonymous said...

It has always bugged me, too, that proponents of MVVM don't demo unit tests. On the other hand, there is not always enough time to test in a demo. I've done it once, but it only worked because it was part of the topic.

My solution to this problem now is to develop demos in the open using TDD. I'm building one now on my blog at Adventures in Software. That way I can reference the tests during the demo, but still focus on showing the content.

Nair said...

I agree with you totally on all comments. MVVM for starters is very intimidating, but once you get used to it, you will never want to code without it. My 2 cents, I prefer Jounce more than MVVMLite just because of the simplicity for MVVM development.

Anonymous said...

May be I am the only one, but for me MVVM is a natural way of programming with WPF. Why should I use "UpdateControl" from the code behind as in WinForms if there is a binding for that?

I don't quite understand an argument like "it's hard for beginners, it's difficult to grasp". WPF is difficult for beginners, yes, but if you get WPF itself, MVVM comes naturally.

The problems with MVVM start when you extrapolate this pattern (which is only about view and its model) to whole application, from the controls to navigation to screen lifecycle.

Nair said...

To answer why MVVM is difficult, we are moving from class ASP to Silverlight. Most of the developers never even know what is MVC/P so to get them to seperate the code is difficult.

John Gossman said...

A couple of points:

1) It's a pattern, not a religion. I always tell people to use it when they find it useful...that the real value of the pattern is the language it gives you to talk about design.

2) It's not a coincidence that MVVM works well for WPF/SL. We developed the pattern (the specifics with data-binding etc.) and the framework at the same time. Even if you decide not to use MVVM, I believe understanding it helps you understand the platform.

I think one advantage not mentioned is the potential for ViewModels to be shared between form factors and technologies--SL, WP7, WPF and even more generally to not XAML technologies.

Bart Czernicki said...

I actually like the spirit of the article.

I don't agree with the comments because MVVM is hard, you shouldn't do it. However, I do agree that MVVM is overrated...if you aren't RELIGIOUS (strongly capped for a purpose) about unit testing/TDD your benefits of MVVM are going to be a lot more negligible.

lee said...

While MVVM does help in UnitTesting. I dont agree on DesignTimeData Stuff. A lot of times the size of the view is dependent on the runtime Height and width of the plugin.
In my view MVVM is not hard and not a lot to it. In my view, MVVM thing is way overblown. it is just a class which implements INPC. The rest is specific to the application.

I would say it is better to spend time on learning how to write better WPF/Silverlight.

What is the point in UnitTesting code that should not be there in the first place.

unibrow said...

I would be very much interested in hearing if you guys think the same applies to the MVP pattern specifically in the context of Asp.net webforms? If you are not doing automated unit testing (at the presenter level) and you don't have multipe UI's reusing the same logic is there any point? What are your thoughts?

Craig said...

Thanks for the objective article on the pros and cons. Too often articles like this come off as nothing more than the author justifying why he or she already holds a certain view (no pun intended).

John Zabroski said...

Support for design-time data is a function of arranging the scene graph or object graph into a dataflow graph. With a dataflow graph, updates to individual nodes are atomic. Atomic updates to nodes in a graph means that IDEs like Expression Blend have a solid theoretical foundation for IDE actions. It has nothing to do with MVVM. Apple Cocoa developers are confused by this fact, too, since Xcode has special design-time visualizations to show what Controller logic binds to (you have to actually use the IDE to understand what I mean, since I can't draw a picture here). The semantics of the graph determine just how good your IDE can be.

At work, we try to avoid design-time tools like Blend and Visual Studio and instead roll our own. The advantage is that the Composite Application internalizes the Atomic Update operation. As a result, it *understands* what updating nodes means. The disadvantage is that it is poorly suited to third party plug-ins, unless you write a very complex internalized Atomic Update, since now your atomic update must take into account dynamic federation of the UI due to third-party untrusted code.

Likewise, (imperative) data binding has nothing to do with MVVM. Binding is just a generalization of the GoF Observer pattern, where a Subject and Observer are completely decoupled via a Registrar in order to maintain anonymity and allow for distributed, ad-hoc queries.

I hope what I've said here is helpful, but it by no means is authoritative. I constantly shift my understanding on what is possible and what problems I know how to solve. When building IDEs or Composite Applications, we're really pushing the bounds on genericity and to think in such abstract terms generally requires real world examples to guide building the right abstractions. Forget PowerPoint bullets. Use user stories and scenarios of what an idealized Composite App should do. My experience has been that even constantly thinking this way is extraordinarily difficult and brainmelting at times, but very rewarding since it controls class complexity e.g. how classes interact and how many total classes you have in your project.

Cheers,
Z-Bo

Vic Klien said...

There is an opportunity for someone to write a whole series of posts about "what sucks about the sacred-cows of SL/WPF development". Although most of the following "sacred cow" techologies have use-cases where they shine, they all have serious downsides:

MEF: Vast, perf-killing, overkill for connecting views, VMs and services (probably why MVVM-Light incorporates a simpler solution).

Blend: I prefer editing the XAML directly. Blend to me is an annoying XAML-polluter/mangler and glorified gradient builder.

Animation: 90% of the time an annoying gimmick that detracts from my UX. Useful UX design is hard and it's not about cheap tricks like animation.

Unit-testing: The fact it is rarely used (even by UT advocates) with real, paid client projects (pace-makers hopefully excepted) probably does say something about its relative value (as currently practiced).

Vic

Anonymous said...

I think you missed the biggest argument for MVVM (or more specifically avoiding the code behind). What happens when you want to port your application to next greatest UI technology. Our current God awful code behind logic is so coupled with the UI that it's a massive investment of resources just to break the logic out. MVVM forces the view to be completely decoupled from the logic making it instantly mire scalable. Check that one for MVVM.

javin paul said...

Convincing arguments and useful reasons but MVVM is quite popular though misunderstood by many and its difficult task to get it right

Thanks
How HashMap works in Java

Anonymous said...

Well balanced article....

Actually, a lot of people are saying that you should use MVVM, while I say it just depends.

In our project we ported an existing simulation model, so we had a very "fat" model we could perfectly unit test. We just skipped the ViewModel, because it would just be an endless copying exercise of properties.

Also, developers have a tendency to make everything "generic" "decoupled" "flexible" "reusable" "throw-out-GUI-without-single-business-line-of-code-change", because this satisfies our developer DNA implanted in the university of "good" patterns.

But at some point you should just accept that an application has a specific perpuse and that it is tailored for this! And that it occurs very, very rarely that big changes we all "anticipate" need to be implemented in the lifespan of the application.

I must admit that while MVVM satisfies a lot of the tickmarks for the mentioned patterns, so far I have not had the experience that it helped me get things out the door faster.

Unknown said...

:) awesome post Ward. :)

Billy Hollis said...

What? You mean you actually pay attention to that crank Hollis? Jeez, he still writes code in VB, for goodness sake.

Anonymous said...

The best blog post I 've read this year so far!

Although I do hate the code-behind approach, patterns were originally forced at me at work and then later I fell in love with them, it is soo refreshing reading someone who knows and then questions the gospels.

WPF/SL are amazing technologies and having been involved with them for some years now i thoroughly enjoyed your post.

Keep up the great work.
Regards

Anonymous said...

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

But you just have with that statement !

Anonymous said...

Thanks for this. I think the cultural issues shouldn't be overlooked either.

Personally taking the time to learn MVVM also taught me the value of "separation of concerns" and not repeating code. Having learned it using MVVM Light, I can see how I could essentially do the same thing with code-behind as the view model. However I probably wouldn't have and my latest and most complex project would be a spaghetti mess by now.

James Marcos said...

FWIW, I'd take any commentary from that Billy Hollis fella with a huge grain of salt. He laments the "horrible designs" inflicted by developers when his own site just looks like a giant jpeg that people have to scroll around. In fact I tried scrolling around a bit before realizing that it was enlarging the page! I guess I should have noticed the tiny text at the bottom warning me that this website would override my mouse's normal behavior. *facepalm*

To top it off, it runs slow as shit. He could have built that entire page in pure HTML and it would be more performant with the same amount of (useful) features. What a horrible misuse of technology!

To be completely honest, the sheer pants-on-head insanity of that site makes me want to disregard everything the man says and run into the embrace of MVVM, lest I suffer his fate.

Ward Bell said...

James - I wish I could disagree with your assessment of Billy's web site. I can't. I can't defend the design. I can't defend the implementation.

But I don't think that is reason enough to dismiss Billy or his observations.

First, he isn't a web site designer and web apps are not his business. We all have to BE on the web even if web development isn't our thing. As far as I can tell, he used the necessity of having a web site to explore some ideas - most of them unfinished. I am reminded of the old chestnut about the terribly shod children of the cobbler.

Second, he's talking about MVVM as it relates to XAML application design and implementation. That is Billy's business - his areas of strength and experience.

I suggest we ignore his website and focus on the issues.

Of course, as you know, I still come down on the side of MVVM ... as a practical pattern for XAML application implementation ... even as I acknowledge that it is possible to do good work without it.

Anonymous said...

Here are real world issues I've had with implementation of MVVM in SL5 Applications:
1. Code bloat, it's never a good thing at any point of development
2. Slower code
3. Unit Testing ... haven't seen a company yet that does UT ... who's gonna pay for that?
4. Can accomplish a good design via code-behind without yet another "pattern" layer
5. It is a religion, and religions are open to "interpretation" and that's exactly the problem
6. ROI is worse, not better

I could list more problems with MVVM pattern, but don't have time because I got real work to do.

Michael said...

The main tangible benefit I have had from MVVM is design-time data. So much easier to see what the complex items in the ListBox are actually going to look like without having to run and rerun.

However, the more I use MVVM the more I like its 'tidiness', but dislike the lack of language support. I should be able to say my ViewModel class 'models' a given model, which should automatically then surface its public interface. Anything I don't specifically override automatically just gets passed through to the model (and properly supports INotifyPropertyChanged on the ViewModel).

Anonymous said...

I think you are absolutely correct. I also practice MVVM few years now and finding that the fact that MVVM requires me to maintain a 2nd hierarchy of my model.. aka View Model is simply source to many problems.
it actually works against any principal which involves separation of concerns. I find myself being very concerned every time I change my model during my work due to MVVM.