Pokazywanie postów oznaczonych etykietą mvvm. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą mvvm. Pokaż wszystkie posty

czwartek, 17 grudnia 2015

"MVVM is not very good" - How do you make it better ?

Soroush has created a blog post that describes my funny feelings when using MVVM.

MVVM is an evolution of MVC. It's "better" than MVC, because it reorganizes the way you layout your logic between the modules. View and Model are very clear in their purpose, so where did all the rest of the logic go ?

The ViewModel naturally. As Soroush states, you just push all of your code from the ViewController to the ViewModel and how does that solve anything really ?

What if I told you...

What if I told you that design patterns are just ideas, and you should never follow the blindly ? The problem with design patterns, tutorials and examples that describe them are written in the void. They usually contain a couple of lines of code that don't exist in context of a big system. That's why MVVM looks great in case of a simple tutorial timer interface.

The problem appears, when you start using it in an actual app that does a lot of things. You end up with a ViewModel that contains business logic, sorting, validating, calls to database model, calls to the networking model. You start to realize that you have an class that's called ViewModel, you can't really say what it does. That spits at Single Responsibility Principle.

Does that mean that MVVM is bad and you should not use it ? No. you're going to run into the same problem using VIPER. You'll have tons of classes named Presenters and they'll all do a lot of different things. Sure, they'll follow SRP a little better, but they still won't be perfect.

MVVM, MVC, VIPER are just paradigms and you as the architect of your system have to choose explicit design that's best for your context. 

It's hard, but it's beautiful - it means that you have to be creative, you still have a lot of work to do. Just because someone invented MVVM it doesn't mean that you're free of thinking about architecture.

So how do you do it right, while following MVVM ?

• Anything can be your ViewModel - ViewModel is just an idea. It's just something that tells you: "Hey, stop putting logic into your view". ViewModel is just a class with a couple of properties and commands and that's it - it doesn't say anywhere, that you have to put everything in one class.

• You can have a lot of ViewModels for one view - That's the main sin of ViewModel tutorials. They create one big ViewModel for each View and that's it. It works for simple tutorials, but doesn't for big applications.

• Follow the Single Responsibility Principle - You should be able to describe what your ViewModel does in a very short sentence. It'll help you decide how many ViewModels you need for one view.

• Name your ViewModels accordingly - Naming things in programming is hard, I know, but anything other than XViewModel is better already.

• Think of your ViewModel as a Mediator (design pattern) - If you need to. It mediates between all sorts of different modules and presents the data gathered. It's very useful for collections for example. It's hard to divide logic of a collection, between different ViewModels, because it has to be presented in one particular place. In short, you can't have 3 ViewModels for sorting the collection, fetching the collection locally and fetching the collection remotely, because the View is bound to only one ViewModel.

MVVM Card Game

Very simple and quick example.

Requirements:

• You have a view with a table of cards
• User can put cards from a deck on the table
• The table's function is to sort the cards
• The table accepts carts that values sum to 100
• The sort result is saved to the server after sorting

Blindly following MVVM you'd put that all in CardTableViewModel, but that's bad. Here's all modules you define instead:

• UsersHand (ViewModel) - Contains logic for user's cards in the deck. Used to draw and put cards back.
•• UsersHandLocalStorage - Used by UsersHand to store the user's hand in the database.

• CardsTableMediator(ViewModel) - Mediator for sorting, validating, storing the table locally and sending it to the server. It presents the table to the view, after mediating the data between all the modules.
•• CardsTableCollection, CardsTableLocalStorage, CardsTableRemoteStorage, CardsTableValidator, CardsTableSorter - Modules used by the mediator to present the table.

So, we don't have a huge ViewModel, and it's still MVVM, isn't it ?

Stop following patterns blindly and be the architect of your app.

poniedziałek, 26 stycznia 2015

Why you should use MVVM instead of MVC

The View-Controller in MVC is responsible of interpreting the Model (business logic) and managing UI. See that "and" in the middle ? It's a sign that a class might be breaking the Single Responsibility Principle. 

In theory, MVC sounds pretty nice, in practice it usually ends up the same: view controllers end up bloated and huge. They mix a lot of logic inside, which makes them hard to reuse and to test.

Microsoft to the rescue!

I have experience with Windows Presentation Foundation and I've learned a one very useful pattern there: MVVM. MVVM is almost like MVC, with slight different distribution of tasks. 

                                                           source

ViewController is now a part of the view. It's responsible for the UI: animations, dynamic changes, adding views, removing views, etc.

ViewModel is something that can be used in different projects, not only iOS. It's your business logic.

It takes data from the model, and interprets it. 

This way you achieve decoupling and you can test your business logic very easily. Something that was very challenging with ViewController.

Data Binding

MVVM is very powerful when combined with data binding. You can set your View to react to changes in the ViewModel via callbacks/events. This way you don't have to think what to do when certain data changes in the ViewModel, it's done "automatically".


Reactive Cocoa

How would we implement data binding on iOS ? Probably through some event system or Key-Value Observation (KVO). There's a cleaner way: functional reactive programming. We can achieve the functional programming in Objective-C thanks to a framework called ReactiveCocoa. Reactive Cocoa is built upon KVO and it saves you a lot of time, also making your code cleaner. MVVM and ReactiveCocoa is a great match for creating independent, clean and reusable modules of a system. Here's a great tutorial to get you started.