-
Notifications
You must be signed in to change notification settings - Fork 43
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
More UI coding conventions #753
Conversation
erri120
commented
Nov 6, 2023
- Adds more context to OAPH
- Adds a section about design view models
docs/UICodingConventions.md
Outdated
} | ||
``` | ||
|
||
If a view model creates other view models, those view models **should** not be design view models. Don't try and get fancy with factory methods and other unnecessary abstractions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if a Design VM has properties containing other VMs, that require passing stuff in the constructor, can I just instantiate the Design version of the child VMs instead since we are already in a design VM?
This would avoid having to create mock data for the non design version in the parent DesignVM, on top of having to create that mock data already in the child DesignVM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As stated above, the design view model should only set up data. The normal VM would then take that data and create other VMs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can check the FOMOD changes I recently did. I massively cleaned up the design VMs: https://github.com/Nexus-Mods/NexusMods.App/pull/738/files#diff-9867405e9fbd8549cf89ffca330cee4eef1c8a421dba0cb637e5e5b36f59d897
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then you end up in a situation where if a standard VM has a constructor with custom parameters, you need to fabricate mock version of that data twice, once in the DesignVM to allow for a constructor without arguments, and then again in any parent DesignVM that needs to instantiate the standard VM.
This would then call for getting "fancy" to generate that data to avoid ending up with replicated code.
Is there a specific reason why we should not instantiate child designVMs inside designVMs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the parent has a list of children, you can make a data generation method on the child and re-use it in the parent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to avoid a case where the design view model and the normal view model do the same thing by instantiating child view models, but the difference is in the type. This was an issue with the previous FOMOD code, where I'd had duplicate code that did the same thing but with a different type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if the alternative is
// inside a DesignVM constructor
ChildVM = new ChildVM(ChildDesignVM.GenerateDummyData());
Is it really any better than just:
// inside a DesignVM constructor
ChildVM = new ChildDesignVM();
Assuming ChildDesignVM
extends ChildVM
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that scenario there isn't much difference. My concern mainly lies with collection of child view models, since you usually construct those by connecting to a SourceCache
:
//MyViewModel:
_sourceCache
.Connect()
.Transform(data => new ChildViewModel(data))
.BindTo(out _children);
If you'd want to create a MyDesignViewModel
and you have a ChildDesignViewModel
, then you should not copy this code and change the Transform
call to create a ChildDesignViewModel
instead of a ChildViewModel
. The ideal solution would be to just create dummy data in the MyDesignViewModel
and let the base class MyViewModel
create instances of ChildViewModel
using that dummy data, similar to how a ChildDesignViewModel
uses dummy data to pass it to the base constructor of ChildViewModel
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, so the general idea is to reduce as much as possible the changes in logic between MyVM and MyDesignVM.
I guess the example you posted above then is a better one to illustrate the point the documentation is trying to make.
If possible the DesignVM should just generate dummy data and feed it to the base VM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update the docs to be more precise.
Codecov Report
@@ Coverage Diff @@
## main #753 +/- ##
==========================================
+ Coverage 62.73% 62.76% +0.03%
==========================================
Files 585 585
Lines 17422 17420 -2
Branches 1219 1219
==========================================
+ Hits 10930 10934 +4
+ Misses 6170 6169 -1
+ Partials 322 317 -5
Flags with carried forward coverage won't be shown. Click here to find out more.
|