Skip to content

Comments

Proof of concept of MVVM refactoring: ruler#2003

Draft
Lehonti wants to merge 2 commits intoPintaProject:masterfrom
Lehonti:refactoring/ruler_mvvm_demo
Draft

Proof of concept of MVVM refactoring: ruler#2003
Lehonti wants to merge 2 commits intoPintaProject:masterfrom
Lehonti:refactoring/ruler_mvvm_demo

Conversation

@Lehonti
Copy link
Contributor

@Lehonti Lehonti commented Feb 23, 2026

As discussed in #1879

This is a rough demo of how I imagine the refactoring to MVVM would go. A few explanations:

  • Notice that RulerModel is in the Pinta.Core project
  • RulerModel might look boring and/or pointless, but the reason is that it does not need to be more complex. The model in MVVM does not notify listeners, or knows anything about how it will be rendered. Its only job is to guard internal state consistency.
  • Expanding on the previous point, since in this case all properties are independent of each other, and all representable values are valid, no validations are needed. Sure, we could throw an exception if someone tries to assign double.NaN to Position, or something like (MetricType)992635 to Metric, but I think that it's quite safe in general.
  • In the future, for more complex state management, we would most likely have to go beyond plain setters and getters, and use methods with parameters instead.
  • Expanding further, my long-term vision for the model would be something like a PintaEngine or PintaKernel that can hold the entirety of the internal state of Pinta without even needing to reference GUI libraries to function (although, practically, it would need to reference Cairo)
  • The code of the ruler can be refactored further, but I am skipping all of those changes because I want this specific pull request to be illustrative

@badcel
Copy link
Contributor

badcel commented Feb 24, 2026

I have a comment but won't be able to write it down until later today. Do you mind holding this back a bit?

@Lehonti Lehonti marked this pull request as draft February 24, 2026 13:19
@Lehonti
Copy link
Contributor Author

Lehonti commented Feb 24, 2026

@badcel sure, I just converted it to draft. Maybe I should have opened it as a draft

@badcel
Copy link
Contributor

badcel commented Feb 24, 2026

This is not concrete feedback for your PR but more general. Just recently I had some discussions with @mirthestam on the gircore matrix channel on MVVM and MVP patterns.

@mirthestam started devloping a new APP Aria and chose MVP to devlop it. I always wanted to have MVVM for GirCore available for GirCore based apps. According to wikipedia MVVM has some automatic binding mechanic which is not available for GirCore. So we concluded the MVP-Pattern is a good choice as the go to pattern for GTK apps which are written in C#.

After I saw your PR I thought again about this topic and what the actual difference between MVVM and MVP is. From my point of view it is like this:

  • MVVM wants to avoid coding the view. To achieve this goal, there is some automatic binding mechanic between the ViewModel and the view (e.g. through XAML in WPF). This automatic binding is based on events. But it's not critical as all the magic is hidden in the invisible "binder" of the MVVM concept.
  • MVP is similar in the way that all data always flows through the presentation layer (like the view model). But the presentation layer has a reference to the UI.

In the first moment I thought this is not a very elegant solution. But if the view is an interface it has one major benefit: The communication between view and viewmodel can rely on actual method calls as the view knows the presentation layer and the presentation layer knows the view.

In a concrete implementation one can decide if only the view should hold any references to GTK or how much the presentation is allowed to use from GTK. So a project can decide where exactly to "encapsulate" GTK from the rest of the app.

But if the actual communication can be made through method calls (meaning the simplest push system possible) there is no need for events as a transportation mechanism between view and viewmodel anymore (it was there for the binder in the first place).

In the initial discussion for MVVM in Pinta we concluded that a view model is not meant to be reused for different views. If this holds true for the presentation layer there is no need to communicate via events. INotifyPropertyChanged would require some method that de-multiplexes any event as there is only one signal for all properties that change. Another solution is to have one event per possible source of change which just is not needed if MVP is used.

Thus testing could be done by checking which calls are reveived on a "ViewMock".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants