Very insightful. It reminds me of what is said a lot in our Utah Slack group when a person is having too much trouble organizing their project: "Don't fight the framework." It just leads to too many unnecessary headaches in the long term.
Not convinced. It may be that we write different kinds of applications, but in the banking and financial applications that I write having a VM is a requirement in many cases simply in order to correctly handle differences in account types, payment types, and so on. You also conflated a few issues in regard to mapping server entities to view model entities and the need for a "view model" to do so. But if we simply consume the items directly from the server as you recommend, then both the code for the "view model" and the "web service" are now identical, and all you've done is change the name of what they're called. A VM also helps when you need to manage state from multiple sources and services. Say, cross-matching a list of account permissions obtained from a repo with user information obtained from the auth system, also with states controlled by user preferences and by feature flags also returned from the server. That code isn't wanted in the view. Moving on, in many cases form validation isn't field-only, but also occurs across multiple fields. Again, you punted and indicated that one could add some sort of external "validation engine", but I feel like you once more decided to add the same ObservableObject... with a different name and coat of paint. "It's not a View Model! It's a Validation Engine! For that View." ;) I'm also not quite as sanguine about discarding unit tests on complex entities managing complex states. Your simple example doesn't need them, but then again, simple examples rarely do, and most real-world apps aren't quite so simple. Now, if you were to ask me if EVERY view needed a view model, then I'd agree and say no. VM's are a tool to be used when needed. The way I look at it, Apple provided a lot of shortcuts and built-in property wrappers to handle some of the most common use cases people might need. Step outside of those common use cases, or when an app starts increasing in size and complexity, and you rapidly reach a point where shortcuts simply don't cut it.
I agree! Creating VM for each screen just because of the VM is never a good idea. It is based on the type of screen and what it is doing. Just recently I had to create VM to map location data returned from local search service. As said it should be based on the requirements and not blindly making VM for each screen. Thanks
For Validation engine, the difference would be that it will not be for per screen like VM. Each screen can use it. And that is my main concern to not to create VM for each screen unless it needs it. You have also mentioned it in your comment.
@@azamsharp The "rules" have to be created and stored somewhere. Plus typically if you're validating a form then you also need to handle correct tab order (which can get difficult if some fields are optional and hidden or disabled). And then the data has to be persisted back to the server or db, and errors and error messages handled correctly. All of a sudden even relatively simple forms need a place for all of the code that has no business being in the view.
The purpose of MVVM, MVI, MVC, MVP etc is to separate code with similar characteristics to keep the code organized. MVVM does this very well, it takes out variables and functions that depend on or interact with the domain/data layer and keeps the view as minimal as possible with maybe a few states for view manipulation like opening a dialog. (If you have a lot of states holding data in the view those should probably be in the view model using published). This separation increases readability and testability.
Thanks! You are absolutely right. The only difference is that View in SwiftUI is not only a View but also a View Model. Unlike frameworks like WPF etc where the View is only XAML, SwiftUI consists of data binding right within the view. Even Apple says that in their own documentation. Check out my other videos where I explained it in great detail. Also, I wrote an article on this issue: azamsharp.com/2022/07/21/view-is-the-view-model.html
@@azamsharp Apple also says to use MVC, but all we know it's not a case with mid or big project. but in MVVM in ViewModel you don't have only api calls or validations. in complex projects you also have a lot of business logic which you can't put into model. model are just for... model, not for business logic. so, If I understood you right you advising put all the business logic into model or views? that what's the difference between massive view controller and bloaded views in SwiftUI?
@@jackdanyal4329 No don't put business logic in the View (Which is also a VM). Keep in mind UI validation is not business logic. I have explained in this article. azamsharp.com/2022/08/09/intro-to-mv-state-pattern.html and also in my new course: www.udemy.com/course/mv-design-pattern-in-ios-for-swiftui/?couponCode=780EABCF3E4DC632EC9F
There are very good reasons to want to separate "VM" logic from pure View code. Nevertheless, it doesn't mean that the MVVM pattern is the solution. Introducing a wrapping View should be the preferred solution. Your View can hold pure code and your wrapping View can be used for anything you used to do in your VM.
Imo, the debate shouldn't be about whether a VM is needed. Instead, it should be about what's a good home for VM logic. In SwiftUI, it should be in a View wrapping your pure UI-code View. SwiftUI Views are lightweight so it should have no impact on perf or memory. And the introduction of the Observation framework also helps to go in that direction (in the sense that people will be less prone to introduce perf issue when injecting properties).
Thank You Azam, for your quite good clarification on "MVVM with Swift UI" is not a good choice for building SwiftUI apps. Looking forward more detail topics/articles on this.
There’s performance, code readability and maintainability considerations. Abstracting the logic from the views still probably makes sense in larger applications, and if you are having different views for different sized devices.
In my opinion, MVVM tends to be a kind of Global variables, and, for my experience, tends to inject sources of problem in complex models. So I totally agree with your advice.
The video is around 10 months old and during that time I have refined my thoughts and published it in an article. You can read the detail article here: azamsharp.com/2023/02/28/building-large-scale-apps-swiftui.html Hope it helps!
I used MVC, MVVM and other concepts. My biggest concern with MVVM is that it can get pretty messy and it feels like you also violate the DRY principle. Your view needs Data, so it talks to a "getMyData" function in the ViewModel and the ViewModel calls a "getMyData" function in the service class which finally gets the data. It also gets complicated when one model needs to cross-reference data another model already holds. For example when your class responsible for a users post wants to fill in the user object for the posts creator without doing another API call. I do know there are ways to do this, but it feels overly complicated. I don't know if it is the right way to do it, but it works for me so far. I use the View as a ViewModel and I create a "Model" as my general service class which I use as an EnvironmentObject throughout my application. For not ending up with a two kilometer long file not being able to find anything, the class only contains the basics eg. properties. Any function group I would have before put in their own service, I create an extension of my model in a seperate file. This way I can keep my code clean, easy to find what I am looking for and still being able to access all data I need from throughout the whole application if needed.
Lol, yesterday inbought the course for mvvm in SwiftUI on Udemy from you and I was referred to a video and after the video was this Video suggested. Now you owe me a course where I can use this without vm. 😅 you’re a really good teacher.
I would still encourage you to try out MVVM and see if it fits your needs. For client/server apps, I have been using the following architecture: azamsharp.com/2022/10/06/practical-mv-pattern-crud.html For SwiftUI + Core Data, I am using the following: azamsharp.com/2023/01/30/active-record-pattern-swiftui-core-data.html
In the take home projects, where companies want you to write the SwiftUI App in 2-3 days, Which Architectural Pattern would you recommend? Because TCA would be an overkill for such a small project right?
My opinion: the only validation I'd perform in UI is view-based validation (e.g. the enabling/disabling of a control in response to entering characters in a text field), rather than business logic validation. Any such UI validation should be as simple as possible, and if it's messy at all -- i.e. it makes the view code hard to read -- then the model should handle that, either itself or through services. The view should be as dumb as possible. I don't think that philsophy has changed between UIKit an SwiftUI. It shouldn't know much about the data being passed in.
The View in SwiftUI is not only a View but also a ViewModel. Yes you are correct only validation in the View should be related to the UI validation. Business validation can occur in the Models.
This is one thing I really like about React. You can simply create a custom hook to handle any view-based validation and return all required data back to the view.
I find this is actually misleading. React + Redux architecture has components what a ViewModel does , it just uses different terminology. You never pass a service class directly to the UI in a react app and call it from there. Purpose of a VM is do the model-to-view preparation so , that logic is testable easily and you don't have to alter model for different view representations and your models can stay agnostic of your views. In a redux architecture you can never directly mutate the single source of truth from your view, you have to dispatch actions and follow their uni directional data flow. Biggest issue with your approach is now your single source of truth is not thread safe in Swift. You have to manually do it, specially in 'counter' example. In this example it seems ok since there's only one method accessing it, but in a large project this could be a huge problem. And also this approach introduces side effects to your View, which is never the case with redux architecture. To deal with side effects we usually use middleware such as redux-saga, or redux-thunk, because reducers must be pure functions and can not handle side effects. So 'effects' in sagas or 'asynchronous action creators' in thunk, actually performs what ViewModel does in an MVVM architecture in my opinion. If you like redux architecture in a SwiftUI app, you should look at The Composable Architecture introduced by pointfree.co team which is a proper usage of that architecture in iOS.
Component in React is View in SwiftUI. In React, you call WS directly from component. Also I am not showing Redux pattern, I am showing State Management Pattern.
@@azamsharp Yes, that's how declarative UI frameworks work isn't it? You update the state and , related UI update themselves when state changes. But my point is still valid. Even in a non-redux react project no professional developer would handle side effects inside UI components (just like it's possible to write network calls in your Viewcontrollers or even Views in a UIKit app). At least you can move them to 'Action Creators' , and they act like VMs in this case. And almost all enterprise react projects use a state management something like redux, because built in react state management is too simple. And you end up having to do 'props drilling' and it can get out of hands in a large scale projects. So I don't think VMs are not useful in SwiftUI, because that's how state management work in vanilla React that nobody uses.
I think you are confusing Redux with State pattern. I am not using Redux. In state pattern your View is the View Model. So VM is calling web service to get data and populate global state using environment object. This is the same pattern Apple uses in their demos and SwiftUI applications.
@@azamsharp tbh I'm not confused , and please ignore everything about redux and think about what I said. (all I said was inbuilt react's state pattern wasn't enough for enterprise application development and professional devs had to rely on redux). Apple never ever used ViewModels in their demos since the beginning. I maybe wrong, because I haven't gone through all of their samples. They never endorsed it because enforcing a specific architecture is not their job. One can argue apple never used Viper so we shouldn't use it either etc. Apple uses the simplest possible way to demo their technology. While this idea sounds great in theory I really like to see how it works in a pretty complex real-world application. Do you have a Udemy course with this approach? I'd like to buy and give it a try. because this sounds much simpler than the composable architecture.
@@RukshanMarapana I am currently working on a clone app using this pattern. I have experienced lot of problems when using MVVM with SwiftUI since it does not blend into the framework and it always feel like we are fighting it. Anyways... I will let you know when the course is available. Thanks!
Hi Azam, thank you for the video and the great article. Can you maybe also explain in your article how you are managing the preview? If a view depends on the webservice as an environment object how does this work? Thanks
The preview is created using the PreviewProvider usually at the bottom of the SwiftUI view. When returning the view from the PreviewProvider you can add environmentObject to it. For previews you can use some sort of mocked webservice data, which will make sure that you are not accessing the webservice when working on your previews.
How would you write Unit test cases when there's no View Model. How would you make sure Dependency Injection and Inversion along with that. With view model we have the validation and the api result available at one common place. Any views on this ?
Even with View Models I never test them because they don't have any logic. You can use Xcode UI Test to test your Views. Make sure to test your domain layer since that is the most important.
@@azamsharp That's not very convincing. What if, there is an entity framework which works on last data captured when there is not internet. Wouldn't we need a Dependency injection and testing the layer for the data retrieval ? Although UI test scripts would run on local data. And what about the Architecture ? For Domain testing Noted your point.
@@azamsharp I mean say for example the application also has a facility to run without internet. And the data on which it will work in offline mode will be the last data hit when there was internet. And the latest data will be stored in core data. Now with no viewmodels how do make sure that in offline mode it hits coredata and in online mode it hits actual service..?
Hello Mohammad. This is a surprise for me. You are a great supporter of MVVM. Paul Hudson is very skeptical about MVVM in SwiftUI. Apple in their own example codes does not use MVVM patern. What do you think about VOODO architecture presented by Mark Moeykens?
I am not familiar with VOODO architecture. I would just follow Apple guidelines and remove the VM from my apps. V can directly consume the DTO (Model) returned from the server.
now I am confused , what does a domain layer look like , doesn't he view model essentially contain logic for the screen in question ...very confused right now
The UI validation like required textbox values and stuff will happen in the View itself and the business validation can happen in the Model or on the Server depending on the type of the app.
This is pretty bad advice to be honest. Making your view layer directly dependent on your network layer goes against so many architectural rules. Unless you're working on a small personal project, this is a sure way to make your life harder in the future.
I think there are some interesting points in @azamsharp argument against SwiftUI. I, like you, prefer to have separation between the models used for UI and the contracts for the Network Layer. However, who says it has to be a ViewModel? It could be that you have a service layer between the network layer and the view that maps to local models. The samples here already define a service layer so perhaps after deserializing they are transformed again to app specific models. Or you have a layer between UI and network that handles mapping.
emmmm, interesting. I have been using MVVM for all my SwiftUI project, I felt noting wrong with it tho... I have heard some people talking about this MVVM pattern is not good for SwiftUI, I might need to look up more articles to get more info.
@@kr1s0404 Because it is noticeable that he is not convinced to MVVM pattern. Check the 100 days of SwiftUI when he presents mvvm. Also if you check all his tutorials, including HWS+, you will notice in how meny he uses MVVM...
I feel 💯 the same since coding more and more apps. The first lines work well, then I am getting frustrated that MVVM hints me. Are you planning on updating your Firebase-Courses on not using MVVM anymore? That would be great 🙂
I thought View Model concept derives from Android development, isn't it so? Holds the view data "model" when/while the app is in background, due to the equipment "processing restrictions"
The ViewModel concept was introduced long ago, it was popular with C# projects. Android just created a dedicated ViewModel framework hoping to make development less problematic.
I personally don't agree taking business logic at the Model Level. Each View has its on view logic based on what it renders. In any real time project iModel will end up having to many functions which breaks the SOLID principle. Again If you are making any changes in Model level function, it might affect some other function thus increasing the risk of other failures. Even the view will endup doing so many things in this approach thus violating Single responsibility and other architectural pattern. For testability as well you will end up depending on your View, thus migrating back to MVC -- I can call MV is nothing but MVC where VC is being presented as View. Also you talked about redux, Redux is much better then MV as there the Model is not handling any sorts of Logic For small demos its good but for a scaleup project it will fail definitely .
Nice article... Still not convinced that view in swiftui acts as viewmodel.. May be MV architecture is best for your project but telling MVVM as anti pattern for swiftui and asking people to not to use it in swiftui project doesn't sounds logical for me Atleast..
@@AppDeveloperPoint it is an anti pattern because in majority of the cases you don’t need to create VM for each screen. The View already provides binding features. Just look at React and Flutter. Those frameworks don’t use the MVVM approach. I think Apple did a disservice to call it a view. A component would have been a better name.
Considering MVVM patern in SwiftUI, the V is the body property and that's it. The most important is not to put any logic / calculations in body property.
No the V is the UIView or NSView that SwiftUI generates automatically from our View structs (which is like a view model and the property wrappers like @State make it behave like a view model object).
I find this moving away from MVVM troubling, to be sure. Call it what you will, MVC, MVVC, ABC...they all strive to do one thing: maintain a Separation of Concerns (SoC) so that the code is clean, short, sweet, and easy to understand, maintain, upgrade, and refactor. Moving away from MVVC because of the exceedingly weark reasoning ("SwiftUI Views are also VMs") is to hinge one's thinking on a technicality, while forgetting the massive benefit of using an architecture that demands SoC is enforced. When I look at SwiftUI code for a VIEW, I do NOT want to see clutter, code that is not even the concern of the VIEW, except to call it as a service. What I want to ONLY see is presentation code specifically for that VIEW, and in the form of calls...let the service or network of model or DB layers worry about specifics. Additionally, the more code you clutter the VIEW with, the less sharable it is, the harder it is to maintain, to understand, to support, refactor and modify. Lets not go back to monolithic programming!!
I’m totally not agree with this. You skip whole layer and just transfer same logic to other layers. UI layer should keep only Ui elements and really simple logic. Validations should be outside of UI and service logic. First because for Unit tests and second for services should not manage this validations. If you work on small app this could work pretty well. I worked on a medical application with 50 fields of interaction and validations, without VM this will be nightmare.
I know this is hard pill to swallow. I was also very much an advocate of MVVM. But after working and facing a lot of challenges, I looked at React and Flutter and also Apple source code and learned that View is also View Model. Take a look at my new article azamsharp.com/2022/07/21/view-is-the-view-model.html
I will create a new video on validation. And you are write in those cases you will create a state model/view model to perform validation. But I would still not create a VM per screen. I would only create a view model to hold the state of my fields.
Bro... first off, if you are closer to the React-verse, you'll know that Redux (and similar) are on the way out. They have been for years. So, suggesting we switch to an outdated design pattern is not great advice. Additionally... you area also just talking about semantics. Those "services" you point out, are just view models with a different name. A class that conforms to an ObservableObject is a View Model. You can call it a service or anything else... that's irrelevant. The patter is still the same. Yes... some of them should be singletons and we typically refer to those as services, but the structure is the same. Environment objects have their place as well, but as you even pointed out... they don't always have the behavior you want. A mature developer doesn't hang their hat on one pattern over the other. A mature developer chooses the write patter for the desired result. It's good for youtube views, though, I guess. Even if it kind of hurts your reputation as a developer.
I wrote a detailed article on the MV Architecture that I am using. You can read about it here: azamsharp.com/2022/10/06/practical-mv-pattern-crud.html
Very insightful. It reminds me of what is said a lot in our Utah Slack group when a person is having too much trouble organizing their project: "Don't fight the framework." It just leads to too many unnecessary headaches in the long term.
Thanks Mark!
Hi Mark and Azam can you please share Utah Slack group link?
Not convinced. It may be that we write different kinds of applications, but in the banking and financial applications that I write having a VM is a requirement in many cases simply in order to correctly handle differences in account types, payment types, and so on.
You also conflated a few issues in regard to mapping server entities to view model entities and the need for a "view model" to do so. But if we simply consume the items directly from the server as you recommend, then both the code for the "view model" and the "web service" are now identical, and all you've done is change the name of what they're called.
A VM also helps when you need to manage state from multiple sources and services. Say, cross-matching a list of account permissions obtained from a repo with user information obtained from the auth system, also with states controlled by user preferences and by feature flags also returned from the server. That code isn't wanted in the view.
Moving on, in many cases form validation isn't field-only, but also occurs across multiple fields. Again, you punted and indicated that one could add some sort of external "validation engine", but I feel like you once more decided to add the same ObservableObject... with a different name and coat of paint. "It's not a View Model! It's a Validation Engine! For that View." ;)
I'm also not quite as sanguine about discarding unit tests on complex entities managing complex states. Your simple example doesn't need them, but then again, simple examples rarely do, and most real-world apps aren't quite so simple.
Now, if you were to ask me if EVERY view needed a view model, then I'd agree and say no. VM's are a tool to be used when needed.
The way I look at it, Apple provided a lot of shortcuts and built-in property wrappers to handle some of the most common use cases people might need. Step outside of those common use cases, or when an app starts increasing in size and complexity, and you rapidly reach a point where shortcuts simply don't cut it.
I agree! Creating VM for each screen just because of the VM is never a good idea. It is based on the type of screen and what it is doing. Just recently I had to create VM to map location data returned from local search service. As said it should be based on the requirements and not blindly making VM for each screen. Thanks
For Validation engine, the difference would be that it will not be for per screen like VM. Each screen can use it. And that is my main concern to not to create VM for each screen unless it needs it. You have also mentioned it in your comment.
@@azamsharp The "rules" have to be created and stored somewhere. Plus typically if you're validating a form then you also need to handle correct tab order (which can get difficult if some fields are optional and hidden or disabled). And then the data has to be persisted back to the server or db, and errors and error messages handled correctly. All of a sudden even relatively simple forms need a place for all of the code that has no business being in the view.
The purpose of MVVM, MVI, MVC, MVP etc is to separate code with similar characteristics to keep the code organized. MVVM does this very well, it takes out variables and functions that depend on or interact with the domain/data layer and keeps the view as minimal as possible with maybe a few states for view manipulation like opening a dialog. (If you have a lot of states holding data in the view those should probably be in the view model using published). This separation increases readability and testability.
Thanks! You are absolutely right. The only difference is that View in SwiftUI is not only a View but also a View Model. Unlike frameworks like WPF etc where the View is only XAML, SwiftUI consists of data binding right within the view. Even Apple says that in their own documentation. Check out my other videos where I explained it in great detail. Also, I wrote an article on this issue: azamsharp.com/2022/07/21/view-is-the-view-model.html
@@azamsharp Apple also says to use MVC, but all we know it's not a case with mid or big project. but in MVVM in ViewModel you don't have only api calls or validations. in complex projects you also have a lot of business logic which you can't put into model. model are just for... model, not for business logic. so, If I understood you right you advising put all the business logic into model or views? that what's the difference between massive view controller and bloaded views in SwiftUI?
@@jackdanyal4329 No don't put business logic in the View (Which is also a VM). Keep in mind UI validation is not business logic. I have explained in this article. azamsharp.com/2022/08/09/intro-to-mv-state-pattern.html and also in my new course: www.udemy.com/course/mv-design-pattern-in-ios-for-swiftui/?couponCode=780EABCF3E4DC632EC9F
There are very good reasons to want to separate "VM" logic from pure View code. Nevertheless, it doesn't mean that the MVVM pattern is the solution. Introducing a wrapping View should be the preferred solution. Your View can hold pure code and your wrapping View can be used for anything you used to do in your VM.
I like it because it keeps my code clean and I don't get confused.
Exactly MVVM looks clean,easier and you can use for any complex apps .
Imo, the debate shouldn't be about whether a VM is needed. Instead, it should be about what's a good home for VM logic. In SwiftUI, it should be in a View wrapping your pure UI-code View.
SwiftUI Views are lightweight so it should have no impact on perf or memory. And the introduction of the Observation framework also helps to go in that direction (in the sense that people will be less prone to introduce perf issue when injecting properties).
Thank You Azam, for your quite good clarification on "MVVM with Swift UI" is not a good choice for building SwiftUI apps. Looking forward more detail topics/articles on this.
There’s performance, code readability and maintainability considerations.
Abstracting the logic from the views still probably makes sense in larger applications, and if you are having different views for different sized devices.
I wrote a detailed article on this: azamsharp.com/2022/10/06/practical-mv-pattern-crud.html
In my opinion, MVVM tends to be a kind of Global variables, and, for my experience, tends to inject sources of problem in complex models. So I totally agree with your advice.
The video is around 10 months old and during that time I have refined my thoughts and published it in an article. You can read the detail article here: azamsharp.com/2023/02/28/building-large-scale-apps-swiftui.html
Hope it helps!
I used MVC, MVVM and other concepts. My biggest concern with MVVM is that it can get pretty messy and it feels like you also violate the DRY principle. Your view needs Data, so it talks to a "getMyData" function in the ViewModel and the ViewModel calls a "getMyData" function in the service class which finally gets the data. It also gets complicated when one model needs to cross-reference data another model already holds. For example when your class responsible for a users post wants to fill in the user object for the posts creator without doing another API call. I do know there are ways to do this, but it feels overly complicated. I don't know if it is the right way to do it, but it works for me so far. I use the View as a ViewModel and I create a "Model" as my general service class which I use as an EnvironmentObject throughout my application. For not ending up with a two kilometer long file not being able to find anything, the class only contains the basics eg. properties. Any function group I would have before put in their own service, I create an extension of my model in a seperate file. This way I can keep my code clean, easy to find what I am looking for and still being able to access all data I need from throughout the whole application if needed.
Lol, yesterday inbought the course for mvvm in SwiftUI on Udemy from you and I was referred to a video and after the video was this Video suggested. Now you owe me a course where I can use this without vm. 😅 you’re a really good teacher.
I would still encourage you to try out MVVM and see if it fits your needs. For client/server apps, I have been using the following architecture:
azamsharp.com/2022/10/06/practical-mv-pattern-crud.html
For SwiftUI + Core Data, I am using the following:
azamsharp.com/2023/01/30/active-record-pattern-swiftui-core-data.html
In the take home projects, where companies want you to write the SwiftUI App in 2-3 days, Which Architectural Pattern would you recommend?
Because TCA would be an overkill for such a small project right?
Just use the simplest approach that Apple has shown in their code samples.
My opinion: the only validation I'd perform in UI is view-based validation (e.g. the enabling/disabling of a control in response to entering characters in a text field), rather than business logic validation.
Any such UI validation should be as simple as possible, and if it's messy at all -- i.e. it makes the view code hard to read -- then the model should handle that, either itself or through services.
The view should be as dumb as possible. I don't think that philsophy has changed between UIKit an SwiftUI. It shouldn't know much about the data being passed in.
The View in SwiftUI is not only a View but also a ViewModel. Yes you are correct only validation in the View should be related to the UI validation. Business validation can occur in the Models.
This is one thing I really like about React. You can simply create a custom hook to handle any view-based validation and return all required data back to the view.
I agree! Only person View based validated in View. I talked about this in my new article: azamsharp.com/2022/10/06/practical-mv-pattern-crud.html
please do a video that shows your example
I find this is actually misleading. React + Redux architecture has components what a ViewModel does , it just uses different terminology. You never pass a service class directly to the UI in a react app and call it from there. Purpose of a VM is do the model-to-view preparation so , that logic is testable easily and you don't have to alter model for different view representations and your models can stay agnostic of your views. In a redux architecture you can never directly mutate the single source of truth from your view, you have to dispatch actions and follow their uni directional data flow. Biggest issue with your approach is now your single source of truth is not thread safe in Swift. You have to manually do it, specially in 'counter' example. In this example it seems ok since there's only one method accessing it, but in a large project this could be a huge problem. And also this approach introduces side effects to your View, which is never the case with redux architecture. To deal with side effects we usually use middleware such as redux-saga, or redux-thunk, because reducers must be pure functions and can not handle side effects. So 'effects' in sagas or 'asynchronous action creators' in thunk, actually performs what ViewModel does in an MVVM architecture in my opinion. If you like redux architecture in a SwiftUI app, you should look at The Composable Architecture introduced by pointfree.co team which is a proper usage of that architecture in iOS.
Component in React is View in SwiftUI. In React, you call WS directly from component. Also I am not showing Redux pattern, I am showing State Management Pattern.
@@azamsharp Yes, that's how declarative UI frameworks work isn't it? You update the state and , related UI update themselves when state changes. But my point is still valid. Even in a non-redux react project no professional developer would handle side effects inside UI components (just like it's possible to write network calls in your Viewcontrollers or even Views in a UIKit app). At least you can move them to 'Action Creators' , and they act like VMs in this case. And almost all enterprise react projects use a state management something like redux, because built in react state management is too simple. And you end up having to do 'props drilling' and it can get out of hands in a large scale projects. So I don't think VMs are not useful in SwiftUI, because that's how state management work in vanilla React that nobody uses.
I think you are confusing Redux with State pattern. I am not using Redux. In state pattern your View is the View Model. So VM is calling web service to get data and populate global state using environment object. This is the same pattern Apple uses in their demos and SwiftUI applications.
@@azamsharp tbh I'm not confused , and please ignore everything about redux and think about what I said. (all I said was inbuilt react's state pattern wasn't enough for enterprise application development and professional devs had to rely on redux). Apple never ever used ViewModels in their demos since the beginning. I maybe wrong, because I haven't gone through all of their samples. They never endorsed it because enforcing a specific architecture is not their job. One can argue apple never used Viper so we shouldn't use it either etc. Apple uses the simplest possible way to demo their technology. While this idea sounds great in theory I really like to see how it works in a pretty complex real-world application. Do you have a Udemy course with this approach? I'd like to buy and give it a try. because this sounds much simpler than the composable architecture.
@@RukshanMarapana I am currently working on a clone app using this pattern. I have experienced lot of problems when using MVVM with SwiftUI since it does not blend into the framework and it always feel like we are fighting it. Anyways... I will let you know when the course is available. Thanks!
Hi,
do you have opinion on following clean architecture for Swift UI app? Kindly comment and share your views.
Hi Azam,
thank you for the video and the great article.
Can you maybe also explain in your article how you are managing the preview?
If a view depends on the webservice as an environment object how does this work?
Thanks
The preview is created using the PreviewProvider usually at the bottom of the SwiftUI view. When returning the view from the PreviewProvider you can add environmentObject to it. For previews you can use some sort of mocked webservice data, which will make sure that you are not accessing the webservice when working on your previews.
Thank you for your answer!
I try this :)
How would you write Unit test cases when there's no View Model. How would you make sure Dependency Injection and Inversion along with that. With view model we have the validation and the api result available at one common place. Any views on this ?
Even with View Models I never test them because they don't have any logic. You can use Xcode UI Test to test your Views. Make sure to test your domain layer since that is the most important.
@@azamsharp That's not very convincing. What if, there is an entity framework which works on last data captured when there is not internet. Wouldn't we need a Dependency injection and testing the layer for the data retrieval ? Although UI test scripts would run on local data. And what about the Architecture ? For Domain testing Noted your point.
@@saurabhbisht2181 I don't understand your question?? Entity framework??
@@azamsharp I mean say for example the application also has a facility to run without internet. And the data on which it will work in offline mode will be the last data hit when there was internet. And the latest data will be stored in core data. Now with no viewmodels how do make sure that in offline mode it hits coredata and in online mode it hits actual service..?
@@saurabhbisht2181 I don't understand what being offline has anything to do with what is discussed in the video.
Hello Mohammad. This is a surprise for me. You are a great supporter of MVVM. Paul Hudson is very skeptical about MVVM in SwiftUI. Apple in their own example codes does not use MVVM patern. What do you think about VOODO architecture presented by Mark Moeykens?
I am not familiar with VOODO architecture. I would just follow Apple guidelines and remove the VM from my apps. V can directly consume the DTO (Model) returned from the server.
Did Paul mentioned it somewhere his thoughts on MVVM?
@@azamsharp As I remember, he mentioned (not explicitly) this during 100 days of SwiftUI series.
I love how he annotates as he explains. Does anyone know what app he's using to do that?
DemoPro
now I am confused , what does a domain layer look like , doesn't he view model essentially contain logic for the screen in question ...very confused right now
The UI validation like required textbox values and stuff will happen in the View itself and the business validation can happen in the Model or on the Server depending on the type of the app.
This is pretty bad advice to be honest. Making your view layer directly dependent on your network layer goes against so many architectural rules. Unless you're working on a small personal project, this is a sure way to make your life harder in the future.
View in SwiftUI is not only a View but also a ViewModel. Adding separate VM is not required.
I think there are some interesting points in @azamsharp argument against SwiftUI. I, like you, prefer to have separation between the models used for UI and the contracts for the Network Layer.
However, who says it has to be a ViewModel? It could be that you have a service layer between the network layer and the view that maps to local models.
The samples here already define a service layer so perhaps after deserializing they are transformed again to app specific models. Or you have a layer between UI and network that handles mapping.
emmmm, interesting. I have been using MVVM for all my SwiftUI project, I felt noting wrong with it tho... I have heard some people talking about this MVVM pattern is not good for SwiftUI, I might need to look up more articles to get more info.
Check the 100 days of SwiftUI by Paul Hudson
If your app is working fine with MVVM then I would keep it that way.
@@marcinfrydrych5319 I do, Paul’s videos are one of my learning resources. But why do you mention it?
@@kr1s0404 Because it is noticeable that he is not convinced to MVVM pattern. Check the 100 days of SwiftUI when he presents mvvm. Also if you check all his tutorials, including HWS+, you will notice in how meny he uses MVVM...
I feel 💯 the same since coding more and more apps. The first lines work well, then I am getting frustrated that MVVM hints me. Are you planning on updating your Firebase-Courses on not using MVVM anymore? That would be great 🙂
Currently, I am working on a separate course to make clone apps in SwiftUI.
@@azamsharp please will you make your clone App responsive , i mean work on all Device .
I thought View Model concept derives from Android development, isn't it so? Holds the view data "model" when/while the app is in background, due to the equipment "processing restrictions"
The ViewModel concept was introduced long ago, it was popular with C# projects. Android just created a dedicated ViewModel framework hoping to make development less problematic.
I personally don't agree taking business logic at the Model Level. Each View has its on view logic based on what it renders. In any real time project iModel will end up having to many functions which breaks the SOLID principle. Again If you are making any changes in Model level function, it might affect some other function thus increasing the risk of other failures. Even the view will endup doing so many things in this approach thus violating Single responsibility and other architectural pattern. For testability as well you will end up depending on your View, thus migrating back to MVC -- I can call MV is nothing but MVC where VC is being presented as View. Also you talked about redux, Redux is much better then MV as there the Model is not handling any sorts of Logic For small demos its good but for a scaleup project it will fail definitely .
I wrote an update version of the article with more details: azamsharp.com/2022/10/06/practical-mv-pattern-crud.html
For our team, this approach has been a great success. You should use the architecture which fits your needs.
@@azamsharp Yes will have a look
Nice article... Still not convinced that view in swiftui acts as viewmodel.. May be MV architecture is best for your project but telling MVVM as anti pattern for swiftui and asking people to not to use it in swiftui project doesn't sounds logical for me Atleast..
@@AppDeveloperPoint it is an anti pattern because in majority of the cases you don’t need to create VM for each screen. The View already provides binding features. Just look at React and Flutter. Those frameworks don’t use the MVVM approach. I think Apple did a disservice to call it a view. A component would have been a better name.
Considering MVVM patern in SwiftUI, the V is the body property and that's it. The most important is not to put any logic / calculations in body property.
No the V is the UIView or NSView that SwiftUI generates automatically from our View structs (which is like a view model and the property wrappers like @State make it behave like a view model object).
Full projects with MV on Udemy please
Check my new course on Udemy. Search for MV Design Pattern in iOS.
@@azamsharp yes just joined that one and want more :)
I find this moving away from MVVM troubling, to be sure. Call it what you will, MVC, MVVC, ABC...they all strive to do one thing: maintain a Separation of Concerns (SoC) so that the code is clean, short, sweet, and easy to understand, maintain, upgrade, and refactor. Moving away from MVVC because of the exceedingly weark reasoning ("SwiftUI Views are also VMs") is to hinge one's thinking on a technicality, while forgetting the massive benefit of using an architecture that demands SoC is enforced. When I look at SwiftUI code for a VIEW, I do NOT want to see clutter, code that is not even the concern of the VIEW, except to call it as a service. What I want to ONLY see is presentation code specifically for that VIEW, and in the form of calls...let the service or network of model or DB layers worry about specifics. Additionally, the more code you clutter the VIEW with, the less sharable it is, the harder it is to maintain, to understand, to support, refactor and modify. Lets not go back to monolithic programming!!
Here is the more updated version azamsharp.com/2022/10/06/practical-mv-pattern-crud.html
None of these fears is founded in reality though. Every time you write a view model you're violating DRY, YAGNI or both.
I’m totally not agree with this. You skip whole layer and just transfer same logic to other layers.
UI layer should keep only Ui elements and really simple logic.
Validations should be outside of UI and service logic. First because for Unit tests and second for services should not manage this validations.
If you work on small app this could work pretty well. I worked on a medical application with 50 fields of interaction and validations, without VM this will be nightmare.
I know this is hard pill to swallow. I was also very much an advocate of MVVM. But after working and facing a lot of challenges, I looked at React and Flutter and also Apple source code and learned that View is also View Model. Take a look at my new article azamsharp.com/2022/07/21/view-is-the-view-model.html
I will create a new video on validation. And you are write in those cases you will create a state model/view model to perform validation. But I would still not create a VM per screen. I would only create a view model to hold the state of my fields.
Here is another video: th-cam.com/video/j2x7GylAnmE/w-d-xo.html
🔥
More recent article:
azamsharp.com/2022/10/06/practical-mv-pattern-crud.html
it will looks too ugly bro, i can understand from your perspective but coming from android background I really prefer abstractions
azamsharp.com/2022/10/06/practical-mv-pattern-crud.html
Bro... first off, if you are closer to the React-verse, you'll know that Redux (and similar) are on the way out. They have been for years. So, suggesting we switch to an outdated design pattern is not great advice. Additionally... you area also just talking about semantics. Those "services" you point out, are just view models with a different name. A class that conforms to an ObservableObject is a View Model. You can call it a service or anything else... that's irrelevant. The patter is still the same. Yes... some of them should be singletons and we typically refer to those as services, but the structure is the same. Environment objects have their place as well, but as you even pointed out... they don't always have the behavior you want. A mature developer doesn't hang their hat on one pattern over the other. A mature developer chooses the write patter for the desired result. It's good for youtube views, though, I guess. Even if it kind of hurts your reputation as a developer.
I discussed my thoughts in the following article.
azamsharp.com/2023/02/28/building-large-scale-apps-swiftui.html
React in more mature than cf flutter? Dude, look again. Also, MVVM is to separate view from logic. @State if for local state only
haha . the long topic i would to said a long time ago. keep as simple stu***