8 ms·
MVVM is Exceptionally OK
- interlocutor 11y agoI find MVVM very confused. In MVVM you have the Model and View layers, which I get, and also the View Model layer, which I don't. The View Model is supposed to be UI independent, and that I don't get. The Model layer is already UI independent. There is no need for a second UI independent layer. In practice the View Model layer is written specifically to support the UI, so there is no point in making it UI independent. Some argue this is for testability. But you can already test the Model layer without the UI. Additional testing should include the UI, and should be through the UI. The motivation behind MVVM appears to be to update the UI automatically when data changes. Modern frameworks are moving away from two-way data binding (React, Angular 2.0, Ember, etc.) Also, data binding is best done in code (the jQuery way) as opposed to declaratively (the WPF way).
- Aleman360 11y agoFrom a XAML perspective: The ViewModel just adapts various Models/Services for a particular View. It converts types provided by the Model as needed, formats strings, computes progress, etc. "UI independent" just means that it should be a logical model of the View, rather than a visual model (e.g., don't expose Color or Brush properties, instead expose properties like IsSelected). So think of the View model like logical code-behind. > Modern frameworks are moving away from two-way data binding (React, Angular 2.0, Ember, etc.) On the web, maybe. But Windows apps (UWP) are still based on data binding.
- jsmeaton 11y agoI've only ever done MVVM development with WPF/XAML and it makes a whole lot of sense for me. Viewing it as a logical code-behind is exactly the right way to see view models in my experience. I've not done iOS development, and the term View Controller in the article was very confusing. Other than XAML being somewhat confusing and having relatively poor IDE support, I've found the WPF MVVM model to be the most intuitive and nice UI design pattern that I've used.
- interlocutor 11y ago> don't expose Color or Brush properties Why not? The ViewModel is written specifically for the View, and it does not serve any purpose to make it UI independent. By avoiding Color etc. in this layer you end with two UI independent layers (Model and ViewModel) and that makes no sense. One UI-independent layer is enough. In MVVM the View knows about the ViewModel but supposedly the ViewModel does not know about the View. But in reality the ViewModel is written specifically for the View, so it might as well know the View.
- Aleman360 11y agoUI frameworks usually have DSL's that are much better at dealing with visual state (e.g., XAML, CSS) and provide mechanisms for sharing styles and resources between multiple views. And do things like swap colors out automatically based on system accessibility settings. Or adjust font sizes for localization.
- interlocutor 11y ago> But Windows apps (UWP) are still based on data binding. Yes, I understand that Windows APIs still use two-way data binding. But by and large the developer community is realizing that two-way data binding is gimmicky and that in large applications two-way data binding is a liability. On the Web most JavaScript frameworks are moving away from two-way data binding (React, Angular 2, Ember, etc.) The reason for that has nothing to do with the Web or with JavaScript. The underlying reason is applicable to application development in general, regardless of platform. Here's Tom Dale and Yehuda Katz, developers of Ember, explaining their decision to move away from two-way data binding: https://changelog.com/131/ https://changelog.com/131/ (skip to 0:42) Excerpts:-------------------- "Why do people still prefer to write server-rendered apps? The programming model is just so easy. If you think about how people build sever-rendered apps.. the request comes in, you get your model data out of the database, you hand it to your view layer to render, you return that output and that's it. Every time you handle a new request, because HTTP is stateless, you start from scratch. "Conversely, things like Angular and Ember have two-way data bindings, right? And it really easy to end up in -- especially in a large or sophisticated application which is stateful. As the user is looking at it, it's not like the state is getting reset, you are constantly having to keep everything in sync yourself. It is easy to end up in a state where you can't yourself explain how data flows through it. "The brilliance in react is bringing back a programming model that is as simple as server-rendered apps. "Even though both Angular and Ember have the notion of events and data bindings, data bindings feels so cool that people started tunneling events through data bindings. "Honestly when I look at the critiques React people have about Ember and trying to understand, OK, you were an ember developer, you were reasonably productive, but you find yourself way more productive in React. What is happening? What we are finding -- and this played into the Ember 2.0 plan -- is that people are abusing two way data bindings to express something that is fundamentally an event. A big focus of Ember 2.0 is moving away from two way data bindings as the primary method of communication to events. We added too much sugar around two-way data bindings and that led people to use two-way data bindings as an event bus.
- Lazare 11y agoI wrote a (very) large SPA in Knockout, which is nominally a MVVM framework, and I definitely see your points. In Knockout, you have HTML templates, which are the view, but the distinction between the Models, the View Models, and every other bit of code in your application is pretty much lost. Not sure if it was my lack of knowledge of MVVM best practices (likely), Knockout (possible), or something inherent to MVVM, but if ever there was an architecture that lent itself to turning into Big Balls Of Mud... Edit: Digging into the links, it seems the article is talking specifically about native mobile applications, so maybe there's context I'm missing.
- dewiz 11y ago>>Modern frameworks are moving away from two-way data binding (React, Angular 2.0, Ember, etc.) Do you have any reference about this? I thought the opposite was true. My main interest being Ember, I'd like to know more about what you said.
- edgyswingset 11y agoTake this as a grain of salt, but my experience with React so far as been one where it's easiest to set up your UI as one-way "data pipelines".
- petilon 11y agoHere it is: Creators of Ember talking about moving away from two-way data binding: https://changelog.com/131/ https://changelog.com/131/ (skip to 0:43)
- MatthewPhillips 11y ago> The motivation behind MVVM appears to be to update the UI automatically when data changes. Modern frameworks are moving away from two-way data binding (React, Angular 2.0, Ember, etc.) Angular still has ngModel according to its docs. Whether you have two-way binding or not, View Models are still useful. Cycle.js doesn't have two-way binding but uses Event Streams and has a pattern that is similar to MVVM (they call it Model-View-Intent but the Model is a View Model by normal definition). React not having something like MVVM makes it difficult to create reusable components. Most React apps are divided into the view layer (which are "components" but really just dumb views) and application logic which lives in the flux layer. This division means you can't / shouldn't write components that fetch their own data.
- rjayatilleka 11y agoShouldn't, not can't. You still can have components keep their own state, and that may be the right decision for small/localized/ephemeral state, such as what's selected in a dropbox, or the coordinates of a widget that's being dragged around. But it's more common to have views trigger events/send actions, which then update the top-level state and trigger a re-render.
- nodamage 11y agoI get the impression that MVVM only really works well when you have robust data-binding support baked into the framework (e.g. WPF/XAML). Otherwise you end up with a bit of an impedance mismatch and a lot of overhead in keeping the views synced with the view model. For example under iOS this probably means going all-in with ReactiveCocoa. But I'm not convinced that completely switching paradigms like that is the right way to go.
- idibidiart 11y agoAll these acronyms don't matter. What matters is how the architecture deals with shared mutable state and whether or not it allows for UI functionality to be easily composed without turning app state into an incomprehensible, incoherent mess. MMVM sounds like a mutable inheritance based architecture. Would love to dig deeper, but here is "how I feel" https://evolvingtrends.wordpress.com/2015/12/03/why-react-native-is-a-huge-deal/ https://evolvingtrends.wordpress.com/2015/12/03/why-react-na...
- Aleman360 11y agoUI apps have all sorts of unavoidable copied state. For example, your data base might have separate fields for first name and last name, but your UI might concatenate these strings into a single one. Whether that's stored in a ViewModel or DOM is not a practical difference. There's nothing about MVVM that says you have to copy Model state in your ViewModel either.
- idibidiart 11y agoThat's why UI architecture (at least on the web) has been moving toward an architecture where you have a single app state store and a unidirectional flow of app state mutations (e.g. in Flux terms: from Action to Store and Store back to View but not the other way around) If you make the app state store immutable then you land in the sane model of having app state transitions (e.g. Redux) where you can have time travel thru app state, which is awesome and aids in debugging. The REST layer decouples server and client states, so we're just concerned with UI state here. Local state isn't avoidable I agree but should be reserved for things like animations that are outside the app state model (unless we're talking about interruptible, resumable, rewindable animations) ... Again, roughly speaking, but love to dig deeper.
- Aleman360 11y agoThat's generally what you try to do in MVVM apps too... you have some "service" that stores all the state. User input goes: View -> ViewModel -> Service and the data goes Service -> ViewModel -> View However, the same app state may be presented in different ways in different parts of the UI. Those different ways could each have their own ViewModel for transforming that state as needed for its presentation. Poorly architected MVVM apps have lots of inter-ViewModel dependencies... that's where you wind up with state spaghetti.
- dimgl 11y agoI must have missed the MVVM hate; what happened? I've been using the MVVM pattern fine for a while now without any major problems.
- _3u10 11y agoIt's from the same people who do MVC wrong leading to 450 line view controllers, thus hailing MVVM which lets them shove 400 lines into another class. MVVM and MVC work well if you're doing it right, which most people aren't. We've all seen the code where they started with MVC and made a bigger mess moving to MVVM because they didn't do MVC right in the first place. My rule of thumb is to grep for .tag, if you see more than one or two references to view.tag the code is totally fucked. If you see switch(view.tag) just run.
- fleitz 11y agoMeh. MVVM just moves the problem, so what if your view controllers are testable but now your ViewModel isn't. You need to be testing those 400 lines of code. Since it's UI code that usually breaks when exposed to weird patterns just write something that sends random touches to the screen in a rapid manner, it surfaces the bugs really quickly and generally disallows bandaid patches. I find regular UI unit tests on the verge of useless, it's generally just coding the pattern the developer moves through the UI anyway, eg. fill first form, second, press submit, not random stuff in 3rd form, press submit while simultaneously pressing the back button, then move forward back into the same controller. eg. If you press a text field and the back button at the same time does it leave the keyboard up when navigating back? That's where the real bugs are. The solution is extensions and inheritance that cut down on boiler plate in the VC, as well as child view controllers. Chuck your models into your views and call it a day. For example take your ViewCell, add a method called setData: / setModel: / configureCell: whatever you want to call it, and put your UI manipulation code in there. The puritans will tell you you're doing it wrong but it declutters the code into a bunch of 25-100 line views. If you really need a lot of logic in there make a ViewController for that view and add it as a childViewController.
- mpweiher 11y ago> Since view controllers do everything in MVC apps Not even close. The model does everything in MVC apps. Views display the model and react to model changes. Controllers pick up the slack, which shouldn't be very much. Now in Model Widget Controller[1] the "view controllers" (something that doesn't even exist in actual MVC) have to do more work because the widgets are generic. Still, if you find your "view controller" doing "everything", you've pretty much missed the point of MVC. Completely. [1] http://blog.metaobject.com/2015/04/model-widget-controller-mwc-aka-apple.html http://blog.metaobject.com/2015/04/model-widget-controller-m...
- fleitz 11y agoCouldn't agree more, if you regularly have 400 line classes you're doing it wrong.
- girvo 11y agoThe authors point, is that most people in the native app world are doing it wrong. And in my experience, he's right.
- TheOtherHobbes 11y agoSome of the specialised iOS/OS X view controllers - e.g. UIImagePickerController - probably have a lot more than 400 lines. Other classes, like NSLayoutManager, look a lot like most of a view controller. But they're not officially a subclass of UIViewController, because they don't link directly to a view - even though they could have been designed to. Apple makes a big deal of MVC, but I sometimes wonder if anyone knows what MVC really is - except possibly a design pattern for generating disagreements about MVC.
- jtwebman 11y agoI think I like the components, command, dispatcher (I call it CCD) way that React and Redux deals with UI! MVVM, MVC, and MVP just don't scale like CCD. MVVM, MVC, and MVP also make it very hard to reason with your code unless it is a very simple single model maps to a view and a controller. MVVM, MVC, and MVP also are very bad at being composable unlike CCD.
- overgard 11y agoSomething bothers me about all this MV* pattern stuff. It's the notion that there is this canonical great pattern applications should follow. There's also a lot of "we" involved in this, and social posturing of "best practices". Look if MVWhatever works for your particular problem, knock yourself out, but I've seen so many badly designed applications because they tried to hammer something into an MVC framework without considering if any of that actually made sense for what their application does. And if you suggest that all this scaffolding is just hiding a more elegant design, you're going against "best practices" (despite the fact that most of these "best practices" arise from opinionated bloggers.) I feel like MVVM is generally solving the wrong problem though. Ok, so MVC tends to get nasty because people shove all the logic into the controller, the model ends up being a crappy interface to the database, and views do too much. But maybe that just means that MVC is a bad fit for what you're doing. It doesn't mean "we" need the "next" MVC, it means you have to do the hard work of actually designing what your application does without training wheels.
- Aleman360 11y agoIt's all about managing state and dependencies. Doesn't matter much for small apps but does when you have tons of people trying to work on the same thing. Also helps in large organizations that develop lots of apps because it reduces the learning curve for new team members. Besides, it's not like MVVM is a huge thing. It can be explained in a paragraph.
- overgard 11y ago> It's all about managing state and dependencies. Doesn't matter much for small apps but does when you have tons of people trying to work on the same thing. That literally applies to any program though. A compiler has to manage a lot of state too, but I've yet to hear compiler makers trying to figure out why they have so much logic in their controllers, and why their views are too big (because nobody would write an MVC compiler). > Besides, it's not like MVVM is a huge thing. It can be explained in a paragraph And yet there's like 500 blog posts about why you're doing it wrong, and how to do it better, etc. Of course, in truth it's not complicated, what makes it complicated is when it's applied in contexts that make little sense.
- PhilWright 11y agoI have written several large WPF applications that use the MVVM pattern and it has worked very nicely. So I have always been a little confused as to why web developers have struggled to write web apps using the same approach. The desktop apps I have worked on are easily bigger than any SPA I have ever seen. So I have not seen any issue with it working when scaling MVVM to large code bases. Maybe there is something fundamentally different about web development and/or JavaScript that causes it to not work well? For example, lets say you have a User model object. You want to display information about the user in three different places in the user interface. With MVVM this is simple. You have a single User model and three different VM instances that each point at the source model. Each VM has a matching View. Any change in the User model propagates down to the VM and then the View. If you edit the users name in the View it updates the VM and then the User model. Changes then cascade back down so the other two views update if needed. Very simple. But how is this done in Flux/Redux? Does the store contain the user information just once? But then what about the intermediate information that is the equivalent of the three views? I presume you need to store this state information in some store as well. But then how do you handle updating the user and having the three other stores updated at the same time as needed? I am not a web developer so this might be trivially simple to those that know how it fits together.
- rjayatilleka 11y agoIn Redux, if you edit the user's name, that would dispatch/trigger an action {type: 'SET_USER_NAME', payload: 'New Name'}. The store would take the current state and the action and generate the new state. Then it would send it to React to cause a re-render of everything to the virtual DOM (not just everywhere the username was, but actually the entire view). And then it diffs the vDOM with the real DOM and updates the real DOM anywhere it's different.
- ry_ry 11y agoSlightly pedantic point, but I was under the impression the diff didn't touch real DOM unless there was a change required, and just dirty checked the virtual DOM - ie. doing everything in memory without a bunch of DOM access was where the performance came from?
- lihongxun945 11y agoMVVM is useful when I develop a big project with complex logic. But I do not use any MV* framework when I develop a mobile web app. I want to make it simple, so, there is only some basic class like AjaxList and SessionManager, no view or controller at all.