
MVVM is Exceptionally OK - marvel_boy
https://ashfurrow.com/blog/mvvm-is-exceptionally-ok/
======
overgard
Something 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
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.

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

~~~
Arnavion
>because nobody would write an MVC compiler

Model - Input -> output format transformation

View - input/output

Controller - Drives the model

And not much coupling between them except to pass data back and forth.

Sounds like a regular compiler to me.

~~~
overgard
You can make pretty much anything seem equivalent if you abstract it enough.
You've basically just equated MVC with any program that does IO. I can't see
how that's a useful thing to do.

Just looking at what you said though: why would you represent a transformation
(something inherently a verb/action) as a model? "Model - Input -> output
format transformation". It _operates_ on models, it's not A model.

Also, claiming the view as input/output is pretty reductive. How do I
represent a lexer as a view? More importantly, why would I want to?

Fun experiment, find the views and controllers in here:
[https://github.com/llvm-mirror/clang](https://github.com/llvm-mirror/clang)

~~~
Arnavion
>You can make pretty much anything seem equivalent if you abstract it enough.
You've basically just equated MVC with any program that does IO. I can't see
how that's a useful thing to do.

 _shrug_ MVC / MVVM is that simple.

>why would you represent a transformation (something inherently a verb/action)
as a model? "Model - Input -> output format transformation". It operates on
models, it's not A model.

Models are not limited to being data stores. Models are responsible for doing
work, so-called business logic. Controllers / ViewModels work with Views to
take in user input and apply it to the models, then take the updated model and
give it back to the user.

>How do I represent a lexer as a view?

The lexer is part of the model.

The view would be what the compiler uses for input/output: for a CLI compiler
it would be the function that reads stdin or the filesystem + the function
that writes to stdout and the filesystem, for a compiler hosted in an IDE or
webpage would be the compiler library interface (ie: a programmatic way to
give it files or strings and receive output + errors), and so on. Separate
views that only know how to take in user input and display user output,
interfacing with a common controller/viewmodel + model.

Edit: Minor clarifications.

~~~
Arnavion
To clarify, an example of a non-MVC compiler would be something that expects
to read a list of files from argv and expects to write to stdout.

An example of a MVC compiler would be something that abstracts the act of
compiling bytes into bytes from how it obtains those bytes or puts them out.

I _think_ gcc works like the former and clang like the latter? I'm not
familiar with either.

An example I _am_ familiar with is the TypeScript transpiler - a "Compiler"
class with a pluggable "Host" interface. There is one implementation of that
host for each environment it can run in (in-memory, node.js, cscript.exe) that
knows how to read files and write output. The compiler class would call
host.writeFile(filename, contents) and it's up to the host whether to write
that to a file, or a textarea in a web page, or pipe the string to another
transpiler, or whatever. It's up to the view to decide whether to colorize
output or not, whether to show an underline that the user can click to jump to
the error or not, etc.

Basically the view is independent of the model, and provides functionality
local only to its interaction context that the model shouldn't need to care
about. As a bonus it's pluggable and thus easy to write new views.

~~~
jerf
If your model fits everything, it fits nothing. If you've stretched until
compilers are "MVC", you haven't got MVC anymore. Something has to be
meaningfully a good design that is _not_ MVC for MVC to exist as a distinct
solution.

MVC is not simply "things should be abstracted from each other". That just,
well, _abstraction_. (Or, better, indirected:
[http://zedshaw.com/archive/indirection-is-not-
abstraction/](http://zedshaw.com/archive/indirection-is-not-abstraction/) )

I've been anti-MVC (unless you are in the rare situations where it really
works) for a while, and this is precisely why. It clouds people's thought. It
convinces people they're doing "design" when they are often just complexifying
things by rote application of badly misunderstood ideas.

~~~
Arnavion
Separation of concerns is neither complexity or misunderstood. It's just good
design.

~~~
jerf
MVC !=== separation of concerns. Separation of concerns is something else. If
"MVC is just exactly the same as separation of concerns", then, again, _we don
't need "MVC" as a concept_. We already have "separation of concerns".

Again, this is why I find the term loathsome as it is actually used. Not only
do people not think about it, they, like, _actively_ won't think about it.
Anyone who actually tries to nail down "what _exactly_ is MVC" will find
themselves coming up empty. It is an undefined term, and should be discarded
for pretty much everybody who isn't writing a CAD/CAM app, not used as some
sort of vague template for "all good design".

You've progressively shrunk the goalposts in every post in this series until
you can't help but hit MVC. That's not useful.

~~~
Arnavion
>If "MVC is just exactly the same as separation of concerns", then, again, we
don't need "MVC" as a concept. We already have "separation of concerns".

MVC is an example of separation of concerns, specifically applied to
separating the computation of data from the input and output of that data. I
don't see how this is such a difficult thing to understand.

(Edit: Heck, even Wikipedia calls it "a software architectural pattern mostly
for implementing user interfaces _(but not only for user interfaces)._ It
divides a given software application into three interconnected parts, _so as
to separate internal representations of information from the ways that
information is presented to or accepted from the user._ " Emphasis mine.)

>Again, this is why I find the term loathsome as it is actually used.

From this and sibling post I seem to detect some hostility against the term
due to there being articles about "you're doing MVC wrong." You can find those
a dime a dozen on any topic. Don't misdirect your anger.

>Anyone who actually tries to nail down "what exactly is MVC" will find
themselves coming up empty.

See above, as well as my previous posts in this thread.

>You've progressively shrunk the goalposts in every post in this series until
you can't help but hit MVC. That's not useful.

On the contrary, I've been consistent from the very first post what MVC is and
how it applies to software. You're the one here insisting that it's something
magic that needs to be different from what I've been saying it is.

------
interlocutor
I 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
From 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.

~~~
interlocutor
> 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
UI 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.

------
mpweiher
> 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-m...](http://blog.metaobject.com/2015/04/model-widget-controller-
mwc-aka-apple.html)

~~~
fleitz
Couldn't agree more, if you regularly have 400 line classes you're doing it
wrong.

~~~
TheOtherHobbes
Some 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.

------
PhilWright
I 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
In 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
Slightly 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?

------
idibidiart
All 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-
na...](https://evolvingtrends.wordpress.com/2015/12/03/why-react-native-is-a-
huge-deal/)

~~~
Aleman360
UI 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
That'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
That'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.

------
jtwebman
I 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.

------
fleitz
Meh. 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.

------
dimgl
I 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
It'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.

------
lihongxun945
MVVM 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.

