This project is part of a benchmark between MVVM+FRP and MVC architectures in iOS app development.
This project serves as the MVVM with FRP benchmark project.
You can read more about it in Medium.
MVVM denotes the Model-View-ViewModel arquitectural pattern, where Model data is encapsulated in ViewModel objects and the View does a (sometimes two-way) binding with the ViewModel's Model representation.
MVC denotes the Model-View-Controller arquitectural pattern, where the Controller operates the Model and the View represents the Model state.
For this particular benchmark we're going to create a simple Reddit application using their JSON API.
This application will try to cover most of the concerns that iOS developers actually have nowadays (e.g. asynchronous network calls, JSON parsing, image loading, collection/table views, storyboarding, user authentication, etc)
The application will be developed twice, once with an MVC arquitecture and again in MVVM.
When both application arquitectures are developed, some metrics will be measured, including:
- Binary:
- Binary size
- Bootup time
- CPU usage (and peaks)
- Memory usage (and peaks)
- Main thread locks
- Code:
- Lines of code (total and average per file)
- Number of classes
- Number of functions and variables
- Mutability vs Immutability
- Testability
- Compile time
Afterwards we will reflect upon results, and try to understand on which cases one of them trumps the other.
In order to minimize development time, a few dependencies will be used:
- Moya: Network abstraction layer written in Swift.
- Kingfisher: A lightweight and pure Swift implemented library for downloading and caching image from the web.
- ObjectMapper: Simple JSON Object mapping written in Swift
- Moya-ObjectMapper: ObjectMapper bindings for Moya and RxSwift
- RxSwift: Reactive Programming in Swift
- RxCocoa: A bundle with common-usage iOS reactive extensions.
- NSObject+Rx: Handy RxSwift extensions on NSObject, including rx_disposeBag.
- RxOptional: RxSwift extensions for Swift optionals and "Occupiable" types.
- KeychainSwift: Helper functions for saving text in Keychain securely for iOS, OS X, tvOS and watchOS.
- Result: This is a Swift µframework providing Result<Value, Error>.
- Device: Device detect the current device model and screen size.
- Cell-Rx: Cell+Rx provides a similar API to NSObject+Rx but for cells who are reused along the way.
RxSwift, RxCocoa, RxOptional, Cell-Rx and NSObject+Rx will only be used on the MVVM+FRP project as they are the basis for FRP usage in iOS (in this particular case Swift).
This project will try to follow the GitHub Swift Styleguide in every way possible.
In order to enforce this, the project will also have a Swiftlint build phase to run the linter everytime the app is built.
Variable naming conventions will be ignored whenever a RxSwift-based variable is created (as the naming convention of the library is to start it with rx_ (e.g. rx_contentOffset
).
The project will follow this folder structure whenever applicable:
Reddit
├── App
│ └── AppDelegate
├── Enums
├── Extensions
├── Externals
├── Globals
├── Helpers
├── Models
├── Networking
├── Protocols
├── Resources
│ ├── LaunchScreen.storyboard
│ ├── Localizable.strings
│ └── Info.plist
├── Structs
├── ViewControllers
│ ├── Onboarding
│ │ └── Onboarding.storyboard
│ └── Main
│ └── Main.storyboard
├── ViewModels
└── Views
In order to enforce it to the filesystem we'll also be using Synx to keep the folder structures clean and mirroring the project structure.
We will be using Travis alongside Fastlane to perform continuous integration both by unit testing and deploying to Fabric or iTunes Connect later on.
Should anyone want to contribute to this long-term benchmark, feel free to do pull requests, open up issues and even join me on Twitter to discuss the architecture.