Rethinking iOS Architecture: From MVC to a Refined MVVM Approach
This article analyzes the limitations of classic iOS MVC, explores MVVM's benefits and drawbacks, and proposes a new service‑oriented architecture with a simple DSL to define and compose atomic business functions, aiming for cleaner, more maintainable mobile code.
Preface
Discusses the evolution, optimization direction, and possibilities of next‑generation development models, inviting readers to share opinions.
Background
Reviews iOS’s classic MVC pattern where Model is data from network, View is UI, and Controller (ViewController) mediates between them. As business complexity grows, Controllers become bloated, prompting the shift to MVVM.
In MVVM, View and ViewController stay in the view layer, Model remains the data model, and ViewModel acts as a UI adapter exposing read‑only properties that map to UI elements, relieving the Controller.
View layer: UI components (UIView, UIViewController) that may hold a ViewModel.
ViewModel layer: UI adapter exposing properties, usually read‑only, can hold Model.
Model layer: data model (JSON) and persistence abstractions; sometimes a separate DataAdapter layer.
Binder: core of MVVM providing two‑way data binding between View and ViewModel.
Important rule: View holds ViewModel, but ViewModel must not hold View to keep testability and enable parallel development.
Existing Problems
Common MVVM drawbacks include high learning cost, cumbersome data binding that can cause crashes, and the decision whether to introduce ReactiveCocoa (RAC).
Problem 1
Learning cost exists but can be mitigated by reading articles and demos; a few features are enough to master.
Problem 2
Without RAC, developers rely on KVO or similar mechanisms, requiring careful binding and unbinding to avoid UI loops; alternative open‑source solutions exist.
Problem 3
Personal opinion: avoid RAC unless necessary because it adds learning overhead and performance overhead.
Additional Issues
When multiple ViewModels share similar business logic, inheritance can lead to bloated ViewModels, while separate ViewModels cause code duplication.
Proposed Solutions
Solution 1: Let ViewModelB inherit from ViewModelA and expose a public method -(bool)shouldToDoNextAction to decide whether to invoke shared actions, but this may still bloat the ViewModel.
Solution 2: Keep independent ViewModels for each page, accepting duplicated login logic but preserving isolation.
Question: Is there a better approach?
Analysis
Initially both pages A and B need login check, upload/modify, and view info; later page A adds a ban‑user check. The current design forces each ViewModel to own business definitions, making changes risky.
Solution Concept
Separate business definition from execution: the view tells the ViewModel what business to perform, the ViewModel defines required functions, while actual implementations reside in a Service layer.
Introduce a “Service” that registers atomic functions (e.g., Account01 for login check) and a simple DSL to compose them, e.g., (Account01-Account02)+Account03+Info01 where “-” means execute right side only if left fails, “+” means sequential execution.
Service responsibilities: parse the DSL, register/execute atomic modules, support module bucket loading to avoid loading unused modules.
Feasibility
Prototype existed in 2020 within Youku’s projects; framework still needs refinement but shows clear benefits: reduced code duplication, reusable atomic functions, and easier scaling as team grows.
Conclusion
The optimized MVVM framework is not the final answer but a step toward more flexible development models; readers are encouraged to comment and discuss.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
