Some of you that used to work (or work) with Unity3D might be tempted to use library called uFrame MVVM to get things seperated in proper, documented way.
As I’m currently working on a project that uses uFrame MVVM, I’d like to add few words of how and where I find uFrame MVVM actually not meeting one from many SOLID rules, that is Single Responsibility Principle and it’s a-like principle: Separation of Concerns (SoC).
About uFrame MVVM
Few words about uFrame MVVM first.
UFrame has been developed by Invert Game Studios to mimic MVVM pattern behaviour known to C# developers from WPF or ASP.NET frameworks.
Direct link to uFrame is here:
Although it’s marketed as ‘MVVM’ and it does have Views that bind to ViewModels, it resembles me more how ASP.NET MVC work with MVVM client-side, JS-based frontends.
Actually it lacks the ‘M’ (Model) part. ViewModels are used from start in a way generally models are. Logic that sometimes grows too much in WPF MVVM inside ViewModels lays in Controllers here.
I’m really delighted that finally that big-blob-VM are gone from my code and instead a true Controller taken from MVC pattern takes the responsibility.
Current way how uFrame works would be probably easier to understand with diagram I’ve prepared:
Straight to the problem
Here comes the real problem though: access to instantiating views from code is accessible from Views only(!?).
I can imagine that it’s due to the fact that they’re the only ones deriving from
MonoBehaviour but it strictly implies that we should use them for non-UI logic, that is validation and modification of data that should drive instantiation of Views (for ex.
ModelCollection that instantiates new View based on ViewModel added to it and notified
Although I can understand reasons why it was designed that way (Unity3D limitations probably), I can hardly accept way of design it promotes.
My idea is to implement widely known (also from everyday life) pattern known as Producer/Consumer pattern.
We can subscribe with great reactive-programming library
UniRx tool that is already used in uFrame, that is
ModelCollection, then we can do any business logic and validation in Controller, that is in way it’s mean to be designed.
Our next step will be pushing newly added item do
InitializationContainer if it meets our business requirements/is valid etc. Then we will need an
Initializer (that will be View in uFrame sense but will behave as normal
MonoBehaviour for us) where T is type of ViewModel/View that we’re going to subscribe for to
InitializationContainer and then consume it.
Consuming of notified View to initialize should end up in deleting the item from initialization queue in container.
We need to remember that our notification should contain both View and ViewModel, so that
Initializer knows what View with what ViewModel it should instantiate.
For better understanding of an idea, here’s a next diagram:
Hope it helps anyone struggling with inconsistend seperation of concerns in uFrame MVVM! :)