Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace MVVM with MVC for the architecture pages #11438

Open
1 task
alefwd opened this issue Nov 24, 2024 · 23 comments
Open
1 task

Replace MVVM with MVC for the architecture pages #11438

alefwd opened this issue Nov 24, 2024 · 23 comments
Assignees

Comments

@alefwd
Copy link

alefwd commented Nov 24, 2024

Page URL

https://docs.flutter.dev/app-architecture/guide#mvvm

Page source

https://github.com/flutter/website/blob/main/src/content/app-architecture/guide.md

Describe the problem

I understand this request is opinable, and debatable, because it depends on the definitions we use, but when I presented Flutter Architecture Components, which was inspired by Android Architecture Components, I realised the Android's MVVM model doesn't apply to Flutter, while the MVC is more representative of how Flutter works.

Let's stick to some generic definition of the MVVM and MVC patterns.

1 We can see from this picture:

Screenshot 2024-11-24 at 22 29 12

that an MVVM requires data binding between the view and the view model. This is old legacy, coming from Android using xml as binder between the UI and the data (side note: now with Compose, someone should tell the Android team to reconsider the MVVM pattern as well).

"Declarative data and command-binding are implicit in the MVVM pattern. In the Microsoft solution stack, the binder is a markup language called XAML.[10] The binder frees the developer from being obliged to write boiler-plate logic to synchronize the view model and view. When implemented outside of the Microsoft stack, the presence of a declarative data binding technology is what makes this pattern possible,[5][11] and without a binder, one would typically use MVP or MVC instead and have to write more boilerplate (or generate it with some other tool)"

2 We can see from this picture:

Screenshot 2024-11-24 at 22 34 42

that the MVC represents more precisely (than MVVM) the cycle where the user clicks the UI, which access the controller to manipulate the model, and after the manipulation the UI is notified and gets updated.

"If user input prompts a change in a model, the controller will signal the model to change, but the model is then responsible for telling its views to update"
"The controller responds to the user input and performs interactions on the data model objects. The controller receives the input, optionally validates it and then passes the input to the model"

3 This is argumented not only by me here, but also by Christian here, by Thomas here, and many others. I think these 3 comments from Ahmed summarise it well.

4 I have a repo with an entire app build with MVC here, if someone wants to have a look.

Expected fix

In my best wishes, I would like to see the MVVM taken away from the guide, and replaced with MVC

Additional context

No response

I would like to fix this problem.

  • I will try and fix this problem on docs.flutter.dev.
@alefwd alefwd added the from.page-issue Reported in a reader-filed concern label Nov 24, 2024
@human2-0
Copy link

That's so elegant way, I wish I could see that when I was starting with Flutter

@Turskyi
Copy link

Turskyi commented Nov 25, 2024

I appreciate the discussion on Flutter architecture, but I disagree with replacing MVVM with MVC. First, Flutter’s architecture guide is a big step toward standardization—having a consistent guide is better than none.

Second, while you argue MVVM isn’t suitable for Flutter because it lacks binding, the same strict logic applies to MVC: Flutter’s UI acts as the controller, making MVC just as incompatible.

Third, Android’s architecture isn’t explicitly MVVM, so suggesting a shift away due to Compose misrepresents its guidance.

Finally, I believe MVP is a better fit than both MVC and MVVM for Flutter. Simply renaming “ViewModel” to “Presenter” would align with definitions while keeping the guide intact. Perhaps the request could be reframed to propose MVP instead?

@afterwire
Copy link

afterwire commented Nov 25, 2024

I think the entirety of the Bluesky thread you linked to actually provides a number of very compelling counterpoints against this issue and I have to agree that this entire debate feels entirely unproductive and just catering to the (very strong) opinions of a tiny minority of folks.

edit: I would also point out that the author is encouraging people to give a thumbs up to this issue on social media which is perhaps leading it to appear that there is a level of support for this which may not actually exist though it’s impossible to know people’s motivations, I just point it out to say that this is something to be considered.

@RobertBrunhage
Copy link

RobertBrunhage commented Nov 25, 2024

I tend to think these kind of topics are very nit-picky with acronyms, and there are history were acronyms like these are slightly changed to accommodate the usage and even heavily debated on with no real conclusion that's fully agreed on.

If you put ten software architects into a room and have them discuss what the Model-View-Controller pattern is, you will end up with twelve different opinions.

Here is an example how Django uses a acronym with their own changes django docs

From wikipedia about mvvm

"To function efficiently, this requires a binding technology or generating boilerplate code to do the binding."

which I would say Flutter uses the boilerplate approach by using builders and access to the listenable, but that is just my interpretation of it.


MVP is a fully different approach where the presenter has access to the view, which is not the case with MVVM or MVC, to me that is a real difference that would change the way the architecture is implemented.

The main difference between the view model and the Presenter in the MVP pattern is that the presenter has a reference to a view, whereas the view model does not.


MY OPINION

At the end of the day I am open for whatever, the course we have uses the same architecture (MVVM, and some differences in convention for services, repositories, and going simplicity first). But yeah, if we end up all agreeing that MVC describes this convention better we will just s/ViewModel/Controller/g in our course and still not really care as the end result will be the same.

Also, as already mentioned in this issue both Compose world and SwiftUI world has been going the MVVM direction so if this goes through expect some confusion.

Compose

@miquelbeltran
Copy link
Member

Hi all, thanks @alefwd for creating this ticket.

4 I have a repo with an entire app build with MVC here, if someone wants to have a look.

I looked at the code of the Pokemon app example provided here, and the PokemonController extends ChangeNotifier just like a ViewModel would do. That isn't MVC either, because the Model doesn't update the View, it is the Controller who does it. So I am very much against renaming this to MVC because if we take the academic definition of the pattern, it isn't it either.

I've seen a similar pattern in the past called "the Riverpod architecture" which is probably a better name for it.

Code with Andrea has a good comparison between "The Riverpod Architecture" and MVC here: https://codewithandrea.com/articles/comparison-flutter-app-architectures/#comparison-with-mvc


I personally think MVVM is still the best way to describe the design pattern, even if the Wikipedia's definition of the pattern doesn't fully match it because it doesn't have Data Binding.

This naming is also supported by other learning materials, for example in the Flutter Engineering book by Majid Haijan, his implementation of MVVM is very similar to the one in the Flutter Architecture Guidelines.

But, if we are looking for a more accurate naming, it ain't MVC either.

@rsajdok
Copy link

rsajdok commented Nov 25, 2024

@miquelbeltran The same naming is also in the book "Flutter Design Patterns and Best Practices"

@dhafinrayhan
Copy link

dhafinrayhan commented Nov 25, 2024

I would also point out that the author is encouraging people to give a thumbs up to this issue on social media which is perhaps leading it to appear that there is a level of support for this which may not actually exist though it’s impossible to know people’s motivations, I just point it out to say that this is something to be considered.

@afterwire This comment itself, whether you're aware of it or not, is suggesting the reader that the support on this issue is backed up by people who have no idea what the issue is about and blindly went to the issue to give a like just because they saw it on social media. It should be simple to understand that the people who agree with this issue tend not to write down their own motivations if they're the same as what's written by the author, in which leaving a like is sufficient. On the other hand, those who disagree with this issue are more to be expected to write down their reasoning of what they disagree with.

While you're just expressing concern and not accusations, I'd suggest you reconsider writing such comment as the reader could easily interpret it as an invalidation of the level of support here, which may introduce an unnecessary bias into the discussion.

@afterwire
Copy link

afterwire commented Nov 25, 2024

I don’t mean it in an accusatory way that something particularly nefarious is going on but I do at the same time think that the drive by like without really considering the issue is actually exactly what is happening here.

The original thread I referenced actually went into some detail where it was pointed out that the reasons for why MVVM make sense is actually a nuanced and multifaceted issue where the idea of how closely it maps to the Wikipedia article is just one of many factors and it was repeatedly pointed out that there was a total absence of real world evidence to suggest this was anything other than the personal preferences of a small handful of people.

It wasn’t even hinted at in the issue that there was an opposing set of viewpoints or considerations here so kind of by definition it seemed rather difficult to see it as a particularly nuanced topic and seemed to fit a pattern of drive by likes that was worth point out without pointing fingers because to be clear I don’t think anyone did anything wrong here at all but I do think the context is important.

Edit: I also just find it to be a really weird premise to turn around and tell both the Flutter and Android teams that they don’t know what they are talking about when it comes to their own products and how to talk about them.

@alefwd
Copy link
Author

alefwd commented Nov 25, 2024

Edit: I also just find it to be a really weird premise to turn around and tell both the Flutter and Android teams that they don’t know what they are talking about when it comes to their own products and how to talk about them.

@afterwire my idea is to improve the Flutter's docs about architecture, and you can disagree with me and I'm fine with that, but my intentions are honest. I don't think the de-facto reference for Flutter architecture is an MVVM. I personally couldn't care less if it came from the Android team, the Flutter team, the Pope or God directly, if I find it incorrect, I'll point it out. If I'm proved wrong, so that what we're actually using it is MVVM, then I'm totally fine with changing my mind. Until then, I think using MVVM is very misleading because of the reason I explained.
I'm sure both the Android and Flutter team btw know what they are doing. I think MVVM was matching perfectly the old Android architecture when xml and data binding was used. Now that they have Compose, I think it's legacy and they'll end up updating it at one point. In Flutter we don't have such legacy, so I don't see any reason why we would inherit it

@romanejaquez
Copy link

Maybe we’re trying to forcefully fit Flutter into a pre-existing and well-known paradigm in order to conform to the norms of the industry as well as existing architectures which were designed for older types of technologies, and it makes us feel warm and fuzzy as we don’t have to yet learn another pattern. I believe Flutter has been such a revolutionary framework and owes its success by not standing next to legacy technologies like Microsoft’s Xamarin or Android’s XML because it is a modern paradigm (declarative vs imperative). If we stick to the Wikipedia definition of MVC, and if we revisit MVVM and what Microsoft intended it to be - a model-binder, I still feel that Flutter is slightly closer to the MVVM in the case that the ViewModel does not know anything about the View and the way it implements the Command Pattern, which makes it for a truly unidirectional data flow (data flows down while events go up). However, if we’re in the renaming discussion, maybe it should be called MVVN (Model-View-View-Notifier) since it aligns a bit closer to what’s doing: notifying listening views to rebuild themselves upon state changes. I'm just happy the Flutter team added this documentation which was long overdue and much needed by the community. Call it one way or the other - the community won already.

@alefwd
Copy link
Author

alefwd commented Nov 25, 2024

MVVN (Model-View-View-Notifier)

I really like this name Roman, it's at the same time descriptive and unambiguous!
Also, I'm very happy about the work the Flutter team has done about the docs, long overdue and definitely welcome

@rydmike
Copy link
Contributor

rydmike commented Nov 25, 2024

Some favor calling it MVVM, some MVC, others MVU (Model View Updater, which is Microsoft naming for this architecture).

Whatever you call it, it orchestrates and coordinates updates between the Model and the View. I like to think it "controls" what goes where, and simply call it a controller for that reason.

However, since it in Flutter typically is, and especially in this guide, based on a Notifier, calling it MVVN sounds fine too, good suggestion @romanejaquez. I don't mind calling it an MVU or MVC either, but an MVVM it is not, for all the "binding" reasons mentioned earlier 🤷🏻‍♂️ 😄

@johnpryan
Copy link
Contributor

johnpryan commented Nov 25, 2024

It sounds like the majority of the responses in this thread are in favor of recommending the same pattern, but disagree on the name.

I think MVVM is a better name than MVC, because Flutter is a reactive UI framework, and we want developers to avoid thinking in terms of "controlling" the view, and instead get them to think about the view as a function of the state (whether that state is a State, a ChangeNotifier, Stream, Future, Bloc, or something else). Maybe it's better to call it a View-Notifier as @romanejaquez suggests, but MVVM is different from MVC because the ViewModel doesn't have a reference to the view.

MVVM requires data binding between the view and the view model

It's true that other frameworks use data binding to publish changes from the view model to the view, but in the Flutter docs we are moving in the direction of recommending using ChangeNotifier, a class with ValueNotifiers, or simply a StatefulWidget for your ViewModel.

Perhaps we could make it more clear. For these docs, the exact structure of your code is less important, you may prefer to use Streams, ChangeNotifiers, or your own custom Dart classes to implement the design pattern we are recommending.

The important point is that the ViewModel publishes that something changed, and the view needs to listen to the ViewModel so that it can rebuild based on the new data. When something happens in the view, it needs a reference to the ViewModel so it can respond to user input.

@ericwindmill
Copy link
Contributor

ericwindmill commented Nov 26, 2024

It sounds like the majority of the responses in this thread are in favor of recommending the same pattern, but disagree on the name.

💯

MVVN (Model-View-View-Notifier)

When writing these docs, I debated whether I should explicitly mention MVVM. I considered ignoring it altogether and not using any existing architecture acronym. I decided to use MVVM because it's a frame of reference that most developers are already familiar with, which makes the content easier to digest.

Using an unfamiliar acronym like MVVN requires far more explanation. I would have to (ironically) explain MVVM more in depth than I did, because I'd need to start with a well known concept (VM) as the frame of reference to then move to the unfamiliar concept (VN). The reader would need to know MVVM intimately in order to understand the trivial differences between VM and VN. This would be a distraction and ultimately hurt the readers ability to internalize the important parts of the docs.

I actually like the idea of MVVN quite a bit in theory, but I'm not convinced (yet) that it would improve the readers ability to learn this design pattern, and that is the only goal of this project.

As always, I encourage everyone to continue this conversation, and I'm open to being wrong.

edit: This argument applies to all suggestions of changing the docs to support a different acronym. In order to consider that, the new acronym must:

  • clearly be the perfect mapping to the pattern we describe
  • not require side tangents about MV* to explain

@afterwire
Copy link

afterwire commented Nov 26, 2024

Agreed 100%. As was mentioned elsewhere when this topic came up, it’s incredibly difficult to find any real life evidence that anyone can point to that would suggest this is causing anyone real confusion in practice rather than a strong personal preference of a small number of people.

That’s not to say that it’s a perfect one to one mapping with everybody’s idea of what MVVM might look like in other contexts but as you mentioned it does help provide an actively useful frame of reference upon which people can build upon and not feel overwhelmed by thinking this is some obscure Flutter specific pattern that they have to learn.

I’d also make the argument that there are only a tiny number of scenarios where the differences between this and say the Wikipedia version that was referenced have any kind of relevance to whatever the topic may be. I think the entire premise of the term “design pattern” actually encapsulates the concept very clearly that there is variation between implementations that adapt to the specific problem set at hand.

In terms of the overall tradeoffs I think this actually makes the most sense of all the options presented so far.

@alefwd
Copy link
Author

alefwd commented Nov 26, 2024

@miquelbeltran thanks for the reply, I try to enter into details without being too demanding

I looked at the code of the Pokemon app example provided here, and the PokemonController extends ChangeNotifier just like a ViewModel would do. That isn't MVC either, because the Model doesn't update the View, it is the Controller who does it. So I am very much against renaming this to MVC because if we take the academic definition of the pattern, it isn't it either.
I personally think MVVM is still the best way to describe the design pattern, even if the Wikipedia's definition of the pattern doesn't fully match it because it doesn't have Data Binding.

This naming is also supported by other learning materials, for example in the Flutter Engineering book by Majid Haijan, his implementation of MVVM is very similar to the one in the Flutter Architecture Guidelines.

But, if we are looking for a more accurate naming, it ain't MVC either.

so last night you gave me some thinking, I had to find some old notes, and it turns that the actual implementation I use of the controller, a ChangeNotifier containing a UiState (so a state holder), comes from the Flutter's skeleton (new) template. There the SettingsController is defined, and it holds the theme of the app, and when changed it triggers the UI rebuild.
In this respect you're right, this approach is not strictly an MVC, and I'm thankful to you here. And it's not an MVC because the controller (ChangeNotifier) first updates the state, but then itself notifies the UI that "something has changed, please update yourself".

Now 2 points:

  1. I disagree that MVVM is better to be used. Given what I just said, MVN (or MVVN if we really want) represents precisely what we're implementing, as suggested by Roman. I personally don't buy that we should keep on using MVVM just because people are familiar with it, even when we know it's not appropriate, as this is a way to perpetuate the error and having a misleading communication

  2. I made a quick prototype last night; because as you know by now, I have a controller and a UI state, so I tinkered with the idea to wrap my UI state into a ValueNotifier, and expose that one directly to the UI, instead of the controller, which by now doesn't need to be a ChangeNotifier anymore. With this small change, I got an MVC without any ambiguity, and I still haven't decided myself which way is better, meaning pure MVC or MVN like we're discussing here, but they both work and they both are simple to reason about
    So I moved from this:

build() {
  final controller = ale.getAleController();
  return ListenableBuilder(listenable: controller);
}

to this:

build() {
  final controller = ale.getAleController();
  return ListenableBuilder(listenable: controller.state);
}

the part I like here is that the user's actions are triggered having a reference to the controller, while the UI needs to have a reference to the state obtained through the controller

@alefwd
Copy link
Author

alefwd commented Nov 26, 2024

I think MVVM is a better name than MVC, because Flutter is a reactive UI framework, and we want developers to avoid thinking in terms of "controlling" the view, and instead get them to think about the view as a function of the state (whether that state is a State, a ChangeNotifier, Stream, Future, Bloc, or something else). Maybe it's better to call it a View-Notifier as @romanejaquez suggests, but MVVM is different from MVC because the ViewModel doesn't have a reference to the view.

@johnpryan just to clarify, the controller doesn't have a reference to the view at all, and the controller doesn't control the view, it controls the model. You can clearly see it here, there's no connection between the view and the controller:

Screenshot 2024-11-26 at 23 12 54

the view and the "controller" are instead connected, and heavily connected as they're data-binded, in an MVVM, as you can clearly see here:

Screenshot 2024-11-26 at 23 14 20

so please remember when you talk about MVVM, don't have in mind the code which is presented in Flutter's guide, because that is not an MVVM, which is the whole point of this discussion. What we implemented is not an MVC either (see my previous message), but is actually an MVN, this is the correct term we should introduce and use, it expresses the reactiveness, it gets rid of the legacy of the data-binding / xml we don't have, and it doesn't have much overhead to learn as it's quite easy to grasp IMHO

@ericwindmill ericwindmill removed the from.page-issue Reported in a reader-filed concern label Nov 26, 2024
@johnpryan
Copy link
Contributor

The MVC pattern comes from Smalltalk's interpretation, but in other frameworks like Cocoa, the role of the controller changed, and became the intermediary between the model and the view. When I'm talking about MVC, I should probably call it Model-view-presenter instead.

MVC diagram - Cocoa / Apple Developer

So are we recommending MVC? Or are we recommending MVVM? Or something else?

I see two main criteria for MVVM:

  1. How properties are bound to the view
  2. How the view, and view model, and model refer to each other

The view model is an abstraction of the view exposing public properties and commands. Instead of the controller of the MVC pattern, or the presenter of the MVP pattern, MVVM has a binder, which automates communication between the view and its bound properties in the view model. The view model has been described as a state of the data in the model.[8]

It's true that Flutter does not support two-way data binding. Instead, it's a reactive framework. You don't need binding if the view layer is updates when setState is called. The way you achieve this "binding" from the view-model to the view is by notifying the view that something changed, and having the view re-build with the new properties from the view model (or (the "view" / State object).

The main difference between the view model and the Presenter in the MVP pattern is that the presenter has a reference to a view, whereas the view model does not. Instead, a view directly binds to properties on the view model to send and receive updates. (MVVM - Wikipedia)

A controller has a reference to the view, but a view-model "notifies" the view when something changed, and the data-binding system updates the screen to show the changed data.

From an architecture point of view, I think MVVM is a good recommendation so that developers can separate their business logic from their view logic. If you're writing app-specific code (business logic), it's a good idea to separate it out so you can test it independently. If you're writing UI code, you probably want to make it as reusable as possible if you are building a large app.

@jtkeyva
Copy link

jtkeyva commented Nov 27, 2024

fyi, i don't know what i'm doing and i didn't understand why it was called MVVM. it actually confused me because i didn't know what MVVM was (there's a lot of us new to this stuff).

i thought models didn't have any moving parts. i thought models were just guides/rules to reference and keep things tight and organized

if something is telling something what happened or what to do, then ya it's notifying something. it's delivering a message.

if something else can receive instructions and commands then ya it's a receiver or listener or watcher or part of a messaging system.

if someone told me there was this model that a view referenced and that view had a messenger to tell something else what happened or what to do, then i would have learned this way faster just through a simple choice of words.

what about MVM?
model view message
model view messenger?

really, what else does it need?
you have your model that things look at for guidance
you have your view to show what the model has
you have your messenger to tell things what/when and how to do them

@jtkeyva
Copy link

jtkeyva commented Nov 27, 2024

Model View Signal?

@afterwire
Copy link

afterwire commented Nov 27, 2024

@jtkeyva I think the argument here is more along the lines of do you find a term which is known by a huge amount of people but varies by an admittedly fairly obscure and not very relevant part (I.e this entire argument about data binding) or do you try and come up with some new term that nobody knows but maybe more accurately reflects the small amount of conversations where that point of difference might be relevant.

To me personally, it’s not even close in terms of trade offs. Nobody’s level of comprehension is improved with a new term that nobody knows unless you then go on to present a lot of background text around the intricacies of MV* patterns and how this one is 95% the same as this other one but then is different in this one very specific way.

At that point you are off on an entire side quest that has zero to do with the actual purpose of these guides, made everything longer and less focused and picked up almost no meaningful benefits.

Like at most I would say this topic maybe would justify 2-3 sentences that perhaps point out that unlike in some other frameworks that rely on markup for the UI as a part of their MVVM architecture and therefore need this concept of data binding in order to implement the pattern, Flutter is a reactive framework which actually simplifies things a bit and here’s how it looks...

But to me the idea that we would even consider throwing away the bridge that we could offer a huge number of developers by associating this to a term that they are in many cases already familiar with for no good reason is an objectively terrible set of trade offs for me when you think about it for a moment.

@alefwd
Copy link
Author

alefwd commented Nov 27, 2024

To me the fact that we, willingly and as part of the Flutter community, decide not to care about a name which doesn't reflect the pattern we're actually using, just not to confuse the users, is simply disgusting. And I think it will create even more confusion on the long run

@ericwindmill
Copy link
Contributor

This conversation is no longer productive and careening toward nasty. This is not the place to throw around insults. I've set a reminder for myself to unlock this post in 2 weeks.

@flutter flutter locked as too heated and limited conversation to collaborators Nov 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests