VIPER Entities and where to store 'em - ios

So, I am currently refactoring a really large project to VIPER architecture and most of its module's views are UITableViews. I discovered almost every topic on the internet about VIPER and UITableView, but one thing remains unclear: where should I store ViewModel and do I really need them?
For example, I have simple VIPER module with UITableViewController and I need to present list of items. Interactor fetches JSON with array of some items which I decode to Codable structs. Then I push array of this structs from interactor back to presenter via InteractorOutput protocol. And now I have two questions:
Do I have to use another data model (ViewModel) to show data in view, or can I go with already existing Codable Struct?
Where should I store my ViewModels? Inside Presenter and ask for the data from the View like this: presenter.getData(forItemAt: indexPath.row). Or I have to push array of ViewModels to View and ask View to show them?

As described in https://TheSwiftDev.com/the-ultimate-viper-architecture-tutorial,
The UITableView is quarantined within the view zone.
There are no view models per se. That purpose of other architectures is carved up differently in VIPER, mainly in the presenter zone but without overt knowledge of the view itself (instead focusing on the business-rules of the use-case). A UI-view in the VIPER view zone conforms to at least one use-case. The data flowing from interactor zone (acquisition/storage) through presenter zone (business/app-domain rule-enforcement/processing) to view zone (and vice versa) is modeled without direct knowledge of the specific OS's specific UI constructs & their parameter needs. When crossing VIPER zones, the entities are modeled as if portable (even if not yet) to other UIs on other OSes. For example, when developing for iOS/iPadOS/WatchOS apps, the interzone exchange of events & data/entities is done so that they are at least agnostic of the peculiarities of iOS/iPadOS/WatchOS UI view constructs & parameters thereof so that the 4 VIPER zones other than view & router {interactor, presenter, entities} remain unchanged in a MacOS version of the same app. With care (e.g., Swift on all non-Apple platforms; OpenCombine framework instead of Apple Combine framework for interzone effect-reactive dataflow) this concept can be extrapolated to Android & UWP version of the app as well, but the Apple-centric portions of interactor zone would need to change as well, which is the reason for quarantining each topic compartmentalized in a zone so that it does not contaminate other zones (as seen is Massive View Controller architecture).
The presenter zone should have no knowledge of or access to UITableView constructs at all. Hence, presenter.getData(forItemAt: indexPath.row) would be replaced with the presenter working on a collection of entities where the collection of entities might get UI-viewed in view zone as a UITableView on iOS/iPadOS/WatchOS but get UI-viewed quite differently on MacOS or Android or UWP, perhaps not as a table at all, but rather as a 2D array of icons/choices to router to navigate. Your “Or [do] I [need to] have to push array of ViewModels to View and ask View to show them?” is nearly hitting the nail on the head, except that VIPER architecture does not use the term ViewModel there; use the word entity instead (i.e., purely app-domain entities divorced from UI and from OS).
Codable is an interface within Apple's JSON processing. Hence, it would need to be quarantined within interactor zone for portability (real or anticipated-for-good-mental-hygiene) to nonApple OSes. The input from (and output to) JSON interactor would need be expressed in entities that are purely app-domain without knowledge of a nonportable framework such as Codable in SwiftUI. There would need to be a conversion from Apple-centric ways of representing JSON processing's output to the purely app-domain ways of representing those equivalent entities.

Related

Where to keep and how to propagate in memory data in iOS project using VIPER pattern?

I have a flow in my project where I have different screens to edit different parts of an entity, that is created only in the end of this flow. How do I organize the code in VIPER in this scenario?
Example:
I want to create a Test entity. It has a Title and Description, questions and some auxiliar text at the end. Each part is edited on a separate screen, in sequence, like:
Create Title/Description ---> Create Questions ---> Enter Auxiliar Text ---> Create
Where do I keep all the data needed at the end?
Do I pass it for each presenter? Do I keep all of them in the Interactor?
In our team we decided that Presenter can store some state. So we pass model to the next module and store it in Presenter.
You can find demo usage of VIPER architecture in my open source project here, but there is no example for flow that you've asked.
As explained lucidly & succinctly in https://theswiftdev.com/the-ultimate-viper-architecture-tutorial the interactor zone quarantines how the acquisition of entities/data are technologically obtained. For example, your in-memory data might be simple DRAM right now, but conceivably could be in the future or on a different platform be cache-coherent NUMA for many-core procressor or TimesTen in-memory database engine or shared memory interprocess. The value of the VIPER architecture is that over time the details of which variant of in-memory {UMA DRAM, ccNUMA, TimesTen, shared memory} is quarantined in interactor zone so that upheavals due to these differing technologies of representing in-memory data does not commingle & intertwine with business logic over in the presenter zone (or worse, throughout other zones too). Plus, as your app goes from its first platform to 2nd & subsequent platforms, you will appreciate the ability to swap in at build-time different interactor zones for simple UMA DRAM on one small platform, ccNUMA on a many-core platform, TimesTen on a data-center scale, and shared-memory on, say, an embedded system or general-purpose desktop OS.

implementation of mvvm architecture in objective-c

How to implement the mvvm architecture in objective-c ? I need sample project to learn the mvvm architecture and also i need to know that what is needed to give in model, view, viewModel and how to separate in objective-c ? what is the difference between the normal project and mvvm project ?
Jesto I can give you details about what you ask briefly.Even if it is explanation you can easily understand what I post here because it has sources with examples and you can directly try the source.
First the Model
The model layer is not as self-explanatory as it may seem.
As you would expect, it will have your model objects, potentially
covering most of the layer surface. In the tickets example, you would
have a Ticket struct that would live in your model.
I find the following components to also be part of the model layer:
Network Code. The shape should be something like this. Ideally, you’d only use a single class for network communication across your
entire app.
Persistence Code. You would implement this with Core Data or simply by saving an NSData blob directly to disk.
Parsing Code. Any objects that parse network responses and the like should be included in the Model layer as well.
While the model objects and the parser are domain-specific, the
network code will be highly reusable.
The controller will then use all the elements in your model layer to
define the flow of information in your app.
Second the View
When a user interacts with your app, they are interacting with the
view layer. The view is considered the “dumb” part of your app, since
it shouldn’t contain any business logic. In code terms, you’ll
normally see:
UIView subclasses. These range from a basic UIView to complex custom UI controls.
A UIViewController (arguably). Since a UIViewController is strongly coupled with its own root UIView and its different cycles
(loadView, viewDidLoad), I personally consider it to be part of this
layer, but not everyone agrees.
Animations and UIViewController transitions.
Classes that are part of UIKit/AppKit, Core Animation and Core Graphics.
Typical code smells found in this layer manifest in different ways,
but boil down to including anything unrelated to UI in your view
layer. A classic code smell is making a network call from a
UIViewController.
It’s tempting to put a bunch of code in your UIViewController and be
done with it, so you can meet that deadline. Don’t do it! In the short
term, you might save a couple of minutes, but in the long term, you
could lose hours looking for a bug, or have trouble when you want to
reuse code inside one view controller in another.
Third MVVM
Model-View-ViewModel, or MVVM, is an MVC derivation. Conceptually,
it’s similar. The biggest difference is in the communication between
layers, and instead of a controller, you use a view model.
In practice, MVVM shines when it has an FRP framework to support it.
Since the model is now observed by the view model and the view model
by the view, the FRP paradigm becomes a natural choice to manage the
information flow. This leads to a better separation between layers,
which translates in decoupled components that are easy to test.
Bottom line: architecture is important, but in my opinion the right
programming paradigm will influence more the overall quality of your
code. It’s also important to note, that most often that not, you will
have in the same app different approaches. This includes both
architecture and paradigm. You might think this will disrupt
consistency inside the codebase, but you should always use the right
tool for the job.
Finally MVC
The Model-View-Controller (MVC) design pattern assigns objects in an
application one of three roles: model, view, or controller. The
pattern defines not only the roles objects play in the application, it
defines the way objects communicate with each other. Each of the three
types of objects is separated from the others by abstract boundaries
and communicates with objects of the other types across those
boundaries. The collection of objects of a certain MVC type in an
application is sometimes referred to as a layer—for example, model
layer.
MVC is central to a good design for a Cocoa application. The benefits
of adopting this pattern are numerous. Many objects in these
applications tend to be more reusable, and their interfaces tend to be
better defined. Applications having an MVC design are also more easily
extensible than other applications. Moreover, many Cocoa technologies
and architectures are based on MVC and require that your custom
objects play one of the MVC roles.
Difference between Normal and MVVM
Models — responsible for the domain data or a data access layer
which manipulates the data, think of ‘Person’ or ‘PersonDataProvider’
classes.
Views — responsible for the presentation layer (GUI), for iOS environment think of everything starting with ‘UI’ prefix.
Controller/Presenter/ViewModel — the glue or the mediator between the Model and the View, in general responsible for altering the Model
by reacting to the user’s actions performed on the View and updating
the View with changes from the Model.
MVVM Says
The latest and the greatest of the MV(X) kind The MVVM is the newest
of MV(X) kind thus, let’s hope it emerged taking into account problems
MV(X) was facing previously. In theory the Model-View-ViewModel looks
very good. The View and the Model are already familiar to us, but also
the Mediator, represented as the View Model. MVVM It is pretty similar
to the MVP:
the MVVM treats the view controller as the View
There is no tight coupling between the View and the Model In addition, it does binding like the Supervising version of the MVP;
however, this time not between the View and the Model, but between the
View and the View Model. So what is the View Model in the iOS reality?
It is basically UIKit independent representation of your View and its
state. The View Model invokes changes in the Model and updates itself
with the updated Model, and since we have a binding between the View
and the View Model, the first is updated accordingly.
Also the MVVM Design Pattern and How does MVVM work?
Check it out this topic -> What is the difference between MVC and MVVM?
Model-View-ViewModel basic example is here -> https://github.com/futurice/mvvm-example-objc and maybe next step, you can use reactive cocoa because it can be more effective with mvvm -> https://github.com/ReactiveCocoa/ReactiveViewModel
reactive cocoa -> https://github.com/ReactiveCocoa/ReactiveCocoa
goodluck :)

How does different components communicate in MVVM in iOS

knowing that in typical MVC implemented iOS projects the Model, view, Controller will communicate in the below patterns.
View to Controller using IBActions, Delegation
Controller to Model using direct method invocations or call backs using blocks
Model to Controller using Delegation or KVO
Controller to View using IBOutlets
correct me if i was wrong anyplace.
My question is how this would happen in a typical MVVM implemented Projects.I want the best communication approaches between components & please justify also how a particular one is better than others if anything has more than one way of communication availability.for example (Delegation & callBacks) mostly its preferable going with Call backs for more precise & readable code.
I will also up vote those who gives me the best answer.
Data Flow describe the communication of elements in MVVM:
Data Flow
1. UI calls method from ViewModel (Presenter).
2. ViewModel executes Use Case.
3. Use Case combines data from User and Repositories.
4. Each Repository returns data from a Remote Data (Network), Persistent DB Storage Source or In-memory Data (Remote or Cached).
5. Information flows back to the UI where we display the list of items.
In this article, there is a more detailed description of MVVM
https://tech.olx.com/clean-architecture-and-mvvm-on-ios-c9d167d9f5b3
First of all, I agree with you about what you pointed out about MVC. I just want to make a discussion about MVC and MVVM from my point of views
From the architecture point of view, in the typical MVC setup, Models represent data, Views represent user interfaces, and View Controllers mediate the interactions between the V and M. The relationships between VC and V, VC and M are tight coupling. Moreover, from that setup, VC will handle a lot of logics and become massive due to over responsibilities.
In MVVM, VC and V are be treated as a component, M still works as it is in MVC. The new component VM, which encapsulates data/logics that the V can bind to and any logics and action can be performed. The connection between V and VM is loose coupling. Why? because the V keeps referent of VM, however, the VM doesn't know the V and it just can be communication with the V via binding system.
From the advantages of MVVM in application development point of view, in which it comes with several benefits. We can easy to write Unit Test to test the logic of VM. We can easy to modify the V (UI) due to now it is just binding to VM.

Does a data source (as in UITableViewDataSource) count as model or controller in MVC paradigm?

I am wondering where an iOS data source (as in UITableViewDataSource) fits in the MVC paradigm: under model or under controller (or where else)?
For instance, the name UITableViewDataSource as such would suggest model. But then data sources may be backed by NSFetchedResultsControllers (as described under "implementing the Table View Datasource Methods") and that name would suggest controller.
Is there a recognized design pattern that provides a rational answer?
I have by now decided that insofar as a single choice should be taken, data sources are closer to controllers than to models.
The decision is not critical. I use it mainly as a rationale for placing classes that represent data sources in Xcode groups, UML diagrams and the like.

Separating Data model from View Model

I have an approach in designing MVC components which is to separate the Data Model (DB persistence) from the View Model of my component despite they represent theoretically the same element. I just map later the two models.
Do you think it's a good approach? Or I should try to make only one model?
When I run into issues like this, I try to create only the necessary classes that I need. This will help to keep the project smaller and to avoid confusion as to what class or object you are supposed to be using. I always try to picture the next guy coming and working on my code and what he would think of and where he would stumble in my logic. I would only use a ViewModel if you are creating objects from multiple Models you retrieved from the database.
Based on your statement it seems that you've created a duplicate data model which is mapped to a second model and would like to know if this is an optimal approach.
Recommendation
I don't think this is necessarily an optimal solution, but a lot depends on your use-case. What I typically do is create a data model that represents unique entities. Then I create a data management class that handles the interactions and use-cases of the data. The data manager would cover things like adding/removing custom objects from a collection. The approach I take is basically a lightweight approach to Apple's use of it's Core Data Framework (docs).
So for example one could use a dictionary, array, or set (or some combination of these) to manage the collection of custom objects together with a shared singleton object acting as a data manager and leveraging built-in archiving/unarchiving capabilities to handle a data graph requirements for an app. Actually,y the result is about the same as a simple use of Core Data, so I'd definitely recommend you get familiar with the standard approach used by Apple (it's embedded into every project template by default).
The good news is that once you choose an approach and develop it very carefully you could end up with a sharable resource that can be reused in many different projects. So for example, the data manager class might encapsulate the movement of data internally (files, local urls, etc) and externally (urls, soa, etc) and even deal with caching, serialization, etc.
I use only classes with get / set methods that operate a mapping of the DB and the VIEW. These are development policies. Using hybrid objects have a greater lightness of the project is in development at runtime. In some scenarios, there may be redundancy in the classes. It is important to aspire to the perfection of the code :-)

Resources