For smaller MVVM projects, I use something I borrowed from Paul Hudson and put the ViewModel inside the View. *taps forehead* It's a compromise between the two approaches, but still keeps the viewmodel code directly out of the view code.
To be really honest, I don't think these kind of architecture is just for small app/prototyping, they really could work in a bigger project since SwiftUI views are meant to be small and cheap. The only thing we need to improve to make this architecture (that you call "View-only") is make it testable, corporate people love talking about their code-coverage even if 90% of the tests are total bullshit because they mock everything and in the end nothing is tested. Seriously, I've worked in a company that we had a lot of tests like this: "sut.response = mock(); sut.request().response == mock()". Anyways, I'm now in another company and I'm facing a similar problem, we are building a POC and the guy I'm working with wants to follow the Bible of Uncle Bob and that's pissing me off. Sorry for the vent in those last sentences, it's just that I'm full of people making complex stuff when it shouldn't be.
Not yet, because I wasn't sure how this video would be received. Turns out it is very controversial, even though I am just talking about my experience. I will think about showing examples in the future though :)
Thank you for this insightful video. I'm not sure using view-only completely removes testability. Don't you think there's still a way to test the properties and functions of the struct? At the end it's just a normal struct with a special body property? There's also the ViewInspector library for unit testing SwiftUI views, which looks very promising in covering the testability of view-only architectures.
The MVVM crowd didn't bother to learn that the View struct plus modifiers property wrappers is equivalent to a view model object already so they don't need another one. I think they also don't know that SwiftUI diffs the hierarchy of View structs to create/update/remove UIView/NSView objects.
I agree for simple apps, but some functionality is not even possible to do in the view file. I use hybrid, view models only for main screens of the app.
Some overlayed code snippets would have gone a long way toward explaining the differences between MVVM and View-only. I'm 7 minutes in, and I still don't really follow what's going on.
I always like to write my projects "future proof". Who knows, maybe it's successful and then you have to expand on it. I prefer MVVM. Yes, sometimes you have to write a VM class just for 2-3 properties, but in the end, it's just a few additional lines of code so it's not that big of a deal.
How to call a pattern, when you're sticking to MVVM for actual app screens, but keep it to MV for simpler views? And also largely use service classes, because they are even better solution for unit testing?
🎉 I congratulate you for having the courage to express your opinion even though you knew it was unpopular and that probably many people do not agree because is not that academic. I believe many times we use all sorts of architectures because we are simply used to and we feel kinda unprofessional if we do things simply, without any fancy pattern. You’ve highlighted a core idea that no architecture is bulletproof and we shouldn’t be scared of taking unpopular decisions in projects as long as they’re justified. I very much share the same thoughts.
Thanks, Daniel. The video was decently well received on UA-cam (also got a bunch of dislikes, which are invisible to you :/), but not so much on Twitter. I absolutely stand by it's content, which is just me talking about my experience.
Yup, I totally agree with you, Daniel and Flo. So much so that I even teach the same exact thing. Ha ha, but I don't feel unprofessional. For our corporate apps, we have NO tests. Yup, zero tests. (Though we do have testers that write automated UI tests.) We use views and observable objects. That's it. It's simple and it allows us to get a lot done. We constantly work to simplify.
@@bigmtnstudio Environment Injection Makes Sense In my quiz app, I have a Quiz model that holds the game state (gameState) and I share that state across multiple views (e.g., QuestionView, ScoreView, GameOverView), injecting the Quiz instance into the environment. This allows those views to access and react to changes in the game state without explicitly passing it as a parameter. It is descriptive but on another hadn't the OOP approach offered by Paul Hudson, with extending ContentView seems more imperative to me and as an overhead.
Great video! I concur with your point that in smaller projects, particularly when working alone, strict adherence to a specific architecture may not be necessary. I would also advise having as testable and clean code as possible for bigger and more serious projects. The advantages of Core Data and View-Only are one of the reasons I don't like Core Data for larger projects because of the added complexity and overhead required to write scalable code. For my own project, I have chosen to use MVVM, even in the early stages, as I am looking at the project as a start-up business with potential to expand the team in the future. By using MVVM and learning best practices from the start, I aim to avoid technical debt and establish strong foundations for future development.
I get where you are coming from! It always depends on what your goals are. This video is just about my personal experience :) Thanks for sharing, Damjan!
5:59 I am sorry, but I have done this custom init to View Model many times, and what I have found out (as far as I remember) is that you can not use @StateObject, but have to use @ObservedObject instead. Unless there is some work around possible to make it work with @ObservedObject, which I do not know about
There is an ugly hack that you can do. You can define your property in the ViewModel class as forced unwrapped, so for example var property: SomeType! and have a setter in your VM, for example setProperty(_ value: SomeType) that assigns the value to your property . This method can be called on appear so you would have something like this: onAppear { viewModel.setProperty(parameterProperty) }. I don't really like this approach, but sometimes, you need a @StateObject instead of @ObservedObject. Or you could pass your VM as an environment object. But then you would have to store it in some parent.
Not 100% sure what you are referring to, but you can create StateObjects in your init with `_viewModel = StateObject(wrappedValue: ViewModel())`. According to an Apple engineer it doesn't even get recreated when the View is recreated.
@@FloWritesCode I did not know that this is not recreated! I think I saw this on SO, but the people in the comments were saying that it gets recreated everytime, so I just used the hack above. Thank you!
Nice Video! MVVM is a cool pattern, because, if I edit the View, then I have only the view at the file and for logic the same. But SwiftUI also has cool features for writing logic in the view struct and with extension I also can write functions and View separate. I think with Swiftdate is View-Only much better as CoreData and View-Only. Because of this framework I try to use no Viewmodel in next projects for iOS 17 and macOS 14. With View-Only I can keep the lines and structure of the project small and simple. But if I know, I will testing the code or I use logic for backend, the better or only way is to use a viewModel or service classes. Both architectures are good and have advantages and disadvantages. I like the words from steve jobs. Another reason for me to write logic in the view struct is this thinking and the power of minimalism.🤏 (I hope, these sentences are understandable. Normally I speak german and my english is not perfect 😅.)
For smaller MVVM projects, I use something I borrowed from Paul Hudson and put the ViewModel inside the View. *taps forehead* It's a compromise between the two approaches, but still keeps the viewmodel code directly out of the view code.
I like how this sounds. Do you happen to remember the video or have a link to see where/how he does this?
Good topic to discuss further. Another video on this view-only approach with code examples would be nice 👍
Thanks for the idea! Others have also asked for this, so I am considering it for the future :)
Could you provide a video with examples in cases where you think it reduces complexity to musing view only or shared instances? 😄🙏🏻
Sure, I'll add it to the list of ideas! Thanks for the suggestion :)
To be really honest, I don't think these kind of architecture is just for small app/prototyping, they really could work in a bigger project since SwiftUI views are meant to be small and cheap.
The only thing we need to improve to make this architecture (that you call "View-only") is make it testable, corporate people love talking about their code-coverage even if 90% of the tests are total bullshit because they mock everything and in the end nothing is tested.
Seriously, I've worked in a company that we had a lot of tests like this: "sut.response = mock(); sut.request().response == mock()".
Anyways, I'm now in another company and I'm facing a similar problem, we are building a POC and the guy I'm working with wants to follow the Bible of Uncle Bob and that's pissing me off.
Sorry for the vent in those last sentences, it's just that I'm full of people making complex stuff when it shouldn't be.
Flo, do you have any videos showing examples of View-Only?
Not yet, because I wasn't sure how this video would be received. Turns out it is very controversial, even though I am just talking about my experience. I will think about showing examples in the future though :)
Thank you for this insightful video. I'm not sure using view-only completely removes testability. Don't you think there's still a way to test the properties and functions of the struct? At the end it's just a normal struct with a special body property? There's also the ViewInspector library for unit testing SwiftUI views, which looks very promising in covering the testability of view-only architectures.
You're right, it is still possible to test structs, but things might get a bit more complex than with dedicated ViewModels.
It seems so much easier to read and write the code when dropping the view model, and just using service classes.
The MVVM crowd didn't bother to learn that the View struct plus modifiers property wrappers is equivalent to a view model object already so they don't need another one. I think they also don't know that SwiftUI diffs the hierarchy of View structs to create/update/remove UIView/NSView objects.
view is a vm
I agree for simple apps, but some functionality is not even possible to do in the view file. I use hybrid, view models only for main screens of the app.
That's also a good approach!
Some overlayed code snippets would have gone a long way toward explaining the differences between MVVM and View-only. I'm 7 minutes in, and I still don't really follow what's going on.
I always like to write my projects "future proof". Who knows, maybe it's successful and then you have to expand on it. I prefer MVVM. Yes, sometimes you have to write a VM class just for 2-3 properties, but in the end, it's just a few additional lines of code so it's not that big of a deal.
With that in mind I agree that sticking with a more sophisticated architecture makes sense. Thanks for sharing!
How to call a pattern, when you're sticking to MVVM for actual app screens, but keep it to MV for simpler views? And also largely use service classes, because they are even better solution for unit testing?
Not sure about a name here, but this sounds like it makes sense!
Maybe you look for MVP (Model View Presenter)?
MVU
🎉 I congratulate you for having the courage to express your opinion even though you knew it was unpopular and that probably many people do not agree because is not that academic.
I believe many times we use all sorts of architectures because we are simply used to and we feel kinda unprofessional if we do things simply, without any fancy pattern.
You’ve highlighted a core idea that no architecture is bulletproof and we shouldn’t be scared of taking unpopular decisions in projects as long as they’re justified. I very much share the same thoughts.
Thanks, Daniel. The video was decently well received on UA-cam (also got a bunch of dislikes, which are invisible to you :/), but not so much on Twitter. I absolutely stand by it's content, which is just me talking about my experience.
Yup, I totally agree with you, Daniel and Flo. So much so that I even teach the same exact thing. Ha ha, but I don't feel unprofessional. For our corporate apps, we have NO tests. Yup, zero tests. (Though we do have testers that write automated UI tests.) We use views and observable objects. That's it. It's simple and it allows us to get a lot done. We constantly work to simplify.
@@bigmtnstudio Environment Injection Makes Sense
In my quiz app, I have a Quiz model that holds the game state (gameState) and I share that state across multiple views (e.g., QuestionView, ScoreView, GameOverView), injecting the Quiz instance into the environment. This allows those views to access and react to changes in the game state without explicitly passing it as a parameter. It is descriptive but on another hadn't the OOP approach offered by Paul Hudson, with extending ContentView seems more imperative to me and as an overhead.
do I feel a new "view only" playlist coming up...? :) it be greatly appreciated. I do agree with the points u made there
I didn't plan an entire playlist initially, but since a few people asked already I'm now considering it, yes!
Makes sense. If your service classes are already tested I would argue why then introduce a ViewModel for the sake of wanting more testing to happen
Great video!
I concur with your point that in smaller projects, particularly when working alone, strict adherence to a specific architecture may not be necessary.
I would also advise having as testable and clean code as possible for bigger and more serious projects.
The advantages of Core Data and View-Only are one of the reasons I don't like Core Data for larger projects because of the added complexity and overhead required to write scalable code.
For my own project, I have chosen to use MVVM, even in the early stages, as I am looking at the project as a start-up business with potential to expand the team in the future. By using MVVM and learning best practices from the start, I aim to avoid technical debt and establish strong foundations for future development.
I get where you are coming from! It always depends on what your goals are. This video is just about my personal experience :) Thanks for sharing, Damjan!
Is a good point find your own development style, thanks for the video
If you think MVVM adds complexity, then try VIPER out 😂
Yup...
5:59 I am sorry, but I have done this custom init to View Model many times, and what I have found out (as far as I remember) is that you can not use @StateObject, but have to use @ObservedObject instead. Unless there is some work around possible to make it work with @ObservedObject, which I do not know about
There is an ugly hack that you can do. You can define your property in the ViewModel class as forced unwrapped, so for example var property: SomeType! and have a setter in your VM, for example setProperty(_ value: SomeType) that assigns the value to your property . This method can be called on appear so you would have something like this: onAppear { viewModel.setProperty(parameterProperty) }. I don't really like this approach, but sometimes, you need a @StateObject instead of @ObservedObject. Or you could pass your VM as an environment object. But then you would have to store it in some parent.
Not 100% sure what you are referring to, but you can create StateObjects in your init with `_viewModel = StateObject(wrappedValue: ViewModel())`. According to an Apple engineer it doesn't even get recreated when the View is recreated.
@@FloWritesCode I did not know that this is not recreated! I think I saw this on SO, but the people in the comments were saying that it gets recreated everytime, so I just used the hack above. Thank you!
Nice Video! MVVM is a cool pattern, because, if I edit the View, then I have only the view at the file and for logic the same. But SwiftUI also has cool features for writing logic in the view struct and with extension I also can write functions and View separate. I think with Swiftdate is View-Only much better as CoreData and View-Only. Because of this framework I try to use no Viewmodel in next projects for iOS 17 and macOS 14. With View-Only I can keep the lines and structure of the project small and simple. But if I know, I will testing the code or I use logic for backend, the better or only way is to use a viewModel or service classes.
Both architectures are good and have advantages and disadvantages.
I like the words from steve jobs. Another reason for me to write logic in the view struct is this thinking and the power of minimalism.🤏
(I hope, these sentences are understandable. Normally I speak german and my english is not perfect 😅.)