SlideShare a Scribd company logo
1 of 38
Download to read offline
Choosing mobile architecture
David Broza
• 135 years old
• Helicopters
• Mobile apps
• 4.5 million members
• In house development
• 2 teams maintaining 5 apps
• Travel, Roadside assistance,
Parking, …
• Native apps Swift, Kotlin, Java
App requirements
• Support constant change
• Easy to test
• Release often
• Fast to change
Assess state of a codebase
• Is your app green field app?
• How current codebase looks like?
• How big is the team?
Architecture requirements
• Easy to learn
• Highly testable - Supports refactoring
• Single responsibility of components
• Causes excitement
• Applicable to legacy system
MVP+?
• Variation of MVP
• Highly testable
• Dependency injection of components
• Applicable for both platforms
• Simple definition of your app structure
Key components
• Views
• Presenters
• Navigator?
• Assembly
• Interactor?
View
• Allows you to display things
• Is an interface
• ViewControllers or Views
• Should not know about UIKit
View
12
protocol TODOListView: class {
func showTODOs(todo: [TODOItem]) -> ()
}
class TODOListViewController: UIViewController, TODOListView {
func showTODOs(todo: [TODOItem]) {
//...
}
}
Presenter
• Receives actions - UI Input
• Implements logic
• Sends display events to view
Presenter
class TODOListPresenter {
weak var view: TODOListView?
func didLoad() {
let todos = self.todoListRepository.getAllTODOs()
self.view?.showTODOs(todo: todos)
}
}
Presenter Test
class TODOListPresenterTest: XCTestCase {
var mockRepository: MockTodoRepo!
var presenter: TODOListPresenter!
override func setUp() {
self.mockRepository = MockTodoRepo()
self.presenter = TODOListPresenter(repository: mockRepository)
}
func testDidLoad() {
XCTAssertFalse(verify(MockTodoRepo.getAllTODOs))
presenter.didLoad()
XCTAssertTrue(verify(MockTodoRepo.getAllTODOs))
}
}
Presenter - View Test
class TODOListPresenterTest: XCTestCase {
var mockRepository: MockTodoRepo!
var presenter: TODOListPresenter!
var view: MockTodoView!
override func setUp() {
self.mockRepository = MockTodoRepo()
self.presenter = TODOListPresenter(repository: mockRepository)
self.view = MockTodoView()
self.presenter.view = self.view
}
func testDidLoad() {
presenter.didLoad()
XCTAssert(verify(MockTodoRepo.getAllTODOs))
XCTAssertTrue(verify(MockTodoView.showTODOs))
}
}
Assembly
• Wires together presenters, views, navigators, …
• Creates other assemblies
• Acts as a factory for view controllers
• Assembly tree defines your whole app
Assembly
class TODOAssembly {
var navigationController: UINavigationController
var todoRepository: TODORepository
init(navigationController: UINavigationController, todoRepository: TODORepository) {
self.navigationController = navigationController
self.todoRepository = todoRepository
}
var todoViewController: TODOListViewController {
let todoPresenter = TODOListPresenter(repository: todoRepository)
let vc = TODOListViewController(presenter: todoPresenter)
return vc
}
}
Assembly tree
class LoginAssembly {
// ...
var loginViewController: LoginViewController {
return LoginViewController()
}
}
class TrafficAssembly {
// ...
var trafficViewController: TrafficViewController {
return UIViewController()
}
}
class CoreAssembly {
lazy var loginAssembly = LoginAssembly(self)
lazy var trafficAssembly = TrafficAssembly(self)
var rootViewController: UIViewController {
return trafficAssembly.trafficViewController
}
}
Assembly example #2
let coreAssembly = CoreAssembly()
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions: …) -> Bool
{
self.window?.rootViewController = coreAssembly.rootViewController
return true
}
Assembly Example #2
final class CoreAssembly {
var navigationController: UINavigationController
var appStateRepository: AppStateRepository
lazy var tourAssembly = TourAssembly(self.navigationController)
lazy var todoAssembly = TODOAssembly(self.navigationController)
init(navigationController: UINavigationController,
appStateRepository: AppStateRepository) {
self.navigationController = navigationController
self.appStateRepository = appStateRepository
}
var rootViewController: UIViewController {
if appStateRepository.isNewInstall {
return tourAssembly.tourViewController
} else {
return todoAssembly.todoViewController
}
}
}
Assembly Test
class RootAssemblyTest: XCTestCase {
func testRootViewControllerTour() {
let mockAppStateRepo = MockStateRepository(isNewInstall: true)
let assembly = RootAssembly(navigationController: UINavigationController(),
appStateRepository: mockAppStateRepo)
XCTAssert(type(of: assembly.rootViewController) == TourViewController.self)
}
func testRootViewControllerTODO() {
let mockAppStateRepo = MockStateRepository(isNewInstall: false)
let assembly = RootAssembly(navigationController: UINavigationController(),
appStateRepository: mockAppStateRepo)
XCTAssert(type(of: assembly.rootViewController) == TODOListViewController.self)
}
}
Navigator
protocol TODOListNavigator {
func showTODODetail(id: Int) -> ()
}
Navigator Implementation
class TODOAssembly {
// ...
var todoViewController: TODOListViewController {
let todoPresenter = TODOListPresenter(repository: todoRepository, navigator: self)
let vc = TODOListViewController(presenter: todoPresenter)
return vc
}
var todoDetailViewController: TODODetailViewController {
let presenter = TODODetailPresenter(repository: self.todoRepository)
let vc = TODODetailViewController(presenter: presenter)
return vc
}
}
extension TODOAssembly: TODOListNavigator {
func showTODODetail(id: Int) {
let vc = self.todoDetailViewController
vc.presenter.selectedTodoId = id
self.navigationController.pushViewController(vc, animated: true)
}
}
Navigator Test
class TODOListNavigatorTest: XCTestCase {
var mockNavigator: MockNavigator!
var presenter: TODOListPresenter!
override func setUp() {
self.mockNavigator = MockNavigator()
self.presenter = TODOListPresenter(navigator: mockNavigator)
}
func testOnTodoTap() {
XCTAssertFalse(verify(MockNavigator.showTODODetail))
presenter.onTodoTap(id: 4)
XCTAssertTrue(verify(MockNavigator.showTODODetail))
}
}
Component optionality
• You don’t need all components if your screen is
simple
• Hard to find the line
Component optionality
Problem with state
• Managing state can be hard
• State representation often leads to confusion
• Good state representation can improves
readability
View State
protocol TODODetailView: class {
func showTodo(todo: TODOItemDetail)
func showError(error: Error)
func showLoading()
}
class TODODetailViewController: UIViewController {
var isLoading: Bool = false
var error: Error? = nil
var data: TODOItemDetail?
// …
View State
enum ViewState<T> {
case initial
case loading
case data(T)
case error(Error)
}
protocol TODODetailsStateView: class {
var state: ViewState<TODOItemDetail> { get set }
}
class TODODetailViewController: UIViewController {
var state: ViewState<TODOItemDetail> = .initial {
didSet {
// ...
Simple view models
• Simple data model
• No logic
• Just holds values to be rendered
View Models
struct TodoTableViewCellViewModel {
var formattedDate: String
var content: String
}
class TodoTableViewCell: UITableViewCell {
var viewModel: TodoTableViewCellViewModel? {
didSet {
guard let viewModel = viewModel else { return }
date.text = viewModel.formattedDate
content.text = viewModel.content
}
}
@IBOutlet weak var date: UILabel!
@IBOutlet weak var content: UILabel!
}
Enable gradual refactoring
• Apply change gradually
• Isolate modules and surround them by tests
• Easy to add presenter to any view controller
• Obj-C rewrite
Code sharing among apps
• Start with an interface
• Assembly can be used in any architecture
Take aways
• There is no silver bullet
• Don’t build thing you don’t need today
• Uncertainty is only certain thing
• You write code for people, not computers.
• Good test is better than outdated documentation
Thank you!
dbroza@anwb.nl

More Related Content

What's hot

Introductionandgreetings
IntroductionandgreetingsIntroductionandgreetings
IntroductionandgreetingsPozz ZaRat
 
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumaiクリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumaiShohei Okada
 
Creating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 ComponentsCreating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 ComponentsDeepak Chandani
 
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawa
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawaクリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawa
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawaShohei Okada
 
RichFaces 4 Webinar - New and Advanced Features
RichFaces 4 Webinar - New and Advanced FeaturesRichFaces 4 Webinar - New and Advanced Features
RichFaces 4 Webinar - New and Advanced FeaturesMax Katz
 
Laravel 5 In Depth
Laravel 5 In DepthLaravel 5 In Depth
Laravel 5 In DepthKirk Bushell
 
JavaOne - The JavaFX Community and Ecosystem
JavaOne - The JavaFX Community and EcosystemJavaOne - The JavaFX Community and Ecosystem
JavaOne - The JavaFX Community and EcosystemAlexander Casall
 
Laravel.IO A Use-Case Architecture
Laravel.IO A Use-Case ArchitectureLaravel.IO A Use-Case Architecture
Laravel.IO A Use-Case ArchitectureShawn McCool
 
Effective C++/WinRT for UWP and Win32
Effective C++/WinRT for UWP and Win32Effective C++/WinRT for UWP and Win32
Effective C++/WinRT for UWP and Win32Windows Developer
 
Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2Vikas Chauhan
 
RESTful API development in Laravel 4 - Christopher Pecoraro
RESTful API development in Laravel 4 - Christopher PecoraroRESTful API development in Laravel 4 - Christopher Pecoraro
RESTful API development in Laravel 4 - Christopher PecoraroChristopher Pecoraro
 
Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POPNatasha Murashev
 
Some tips to improve developer experience with Symfony
Some tips to improve developer experience with SymfonySome tips to improve developer experience with Symfony
Some tips to improve developer experience with Symfonytyomo4ka
 
Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Morris Singer
 

What's hot (20)

Introductionandgreetings
IntroductionandgreetingsIntroductionandgreetings
Introductionandgreetings
 
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumaiクリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
 
Creating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 ComponentsCreating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 Components
 
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawa
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawaクリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawa
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #phpconokinawa
 
RichFaces 4 Webinar - New and Advanced Features
RichFaces 4 Webinar - New and Advanced FeaturesRichFaces 4 Webinar - New and Advanced Features
RichFaces 4 Webinar - New and Advanced Features
 
Laravel 5 In Depth
Laravel 5 In DepthLaravel 5 In Depth
Laravel 5 In Depth
 
JavaOne - The JavaFX Community and Ecosystem
JavaOne - The JavaFX Community and EcosystemJavaOne - The JavaFX Community and Ecosystem
JavaOne - The JavaFX Community and Ecosystem
 
Laravel.IO A Use-Case Architecture
Laravel.IO A Use-Case ArchitectureLaravel.IO A Use-Case Architecture
Laravel.IO A Use-Case Architecture
 
Effective C++/WinRT for UWP and Win32
Effective C++/WinRT for UWP and Win32Effective C++/WinRT for UWP and Win32
Effective C++/WinRT for UWP and Win32
 
React native by example by Vadim Ruban
React native by example by Vadim RubanReact native by example by Vadim Ruban
React native by example by Vadim Ruban
 
Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2
 
Pragmatic Swift
Pragmatic SwiftPragmatic Swift
Pragmatic Swift
 
Laravel 101
Laravel 101Laravel 101
Laravel 101
 
RESTful API development in Laravel 4 - Christopher Pecoraro
RESTful API development in Laravel 4 - Christopher PecoraroRESTful API development in Laravel 4 - Christopher Pecoraro
RESTful API development in Laravel 4 - Christopher Pecoraro
 
Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POP
 
Some tips to improve developer experience with Symfony
Some tips to improve developer experience with SymfonySome tips to improve developer experience with Symfony
Some tips to improve developer experience with Symfony
 
Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015Unit Testing Express and Koa Middleware in ES2015
Unit Testing Express and Koa Middleware in ES2015
 
Laravel level 0 (introduction)
Laravel level 0 (introduction)Laravel level 0 (introduction)
Laravel level 0 (introduction)
 
Laravel level 2 (Let's Practical)
Laravel level 2 (Let's Practical)Laravel level 2 (Let's Practical)
Laravel level 2 (Let's Practical)
 
Laravel Level 1 (The Basic)
Laravel Level 1 (The Basic)Laravel Level 1 (The Basic)
Laravel Level 1 (The Basic)
 

Similar to Do iOS Presentation - Mobile app architectures

«Управление логикой переходов между экранами приложения с помощью координатор...
«Управление логикой переходов между экранами приложения с помощью координатор...«Управление логикой переходов между экранами приложения с помощью координатор...
«Управление логикой переходов между экранами приложения с помощью координатор...Mail.ru Group
 
Advanced #6 clean architecture
Advanced #6  clean architectureAdvanced #6  clean architecture
Advanced #6 clean architectureVitali Pekelis
 
Presentation - Windows App Development - II - Mr. Chandan Gupta
Presentation - Windows App Development - II - Mr. Chandan GuptaPresentation - Windows App Development - II - Mr. Chandan Gupta
Presentation - Windows App Development - II - Mr. Chandan GuptaMobileNepal
 
20150516 modern web_conf_tw
20150516 modern web_conf_tw20150516 modern web_conf_tw
20150516 modern web_conf_twTse-Ching Ho
 
MvvmQuickCross for Windows Phone
MvvmQuickCross for Windows PhoneMvvmQuickCross for Windows Phone
MvvmQuickCross for Windows PhoneVincent Hoogendoorn
 
MBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&CoMBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&Coe-Legion
 
22Flutter.pdf
22Flutter.pdf22Flutter.pdf
22Flutter.pdfdbaman
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Patterngoodfriday
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Loiane Groner
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 
Voiture tech talk
Voiture tech talkVoiture tech talk
Voiture tech talkHoppinger
 
SE2016 Android Dmytro Zaitsev "Viper make your MVP cleaner"
SE2016 Android Dmytro Zaitsev "Viper  make your MVP cleaner"SE2016 Android Dmytro Zaitsev "Viper  make your MVP cleaner"
SE2016 Android Dmytro Zaitsev "Viper make your MVP cleaner"Inhacking
 
Sexy Architecting. VIPER: MVP on steroids
Sexy Architecting. VIPER: MVP on steroidsSexy Architecting. VIPER: MVP on steroids
Sexy Architecting. VIPER: MVP on steroidsDmytro Zaitsev
 
Net conf BG xamarin lecture
Net conf BG xamarin lectureNet conf BG xamarin lecture
Net conf BG xamarin lectureTsvyatko Konov
 
How to build rock solid apps & keep 100m+ users happy
How to build rock solid apps & keep 100m+ users happyHow to build rock solid apps & keep 100m+ users happy
How to build rock solid apps & keep 100m+ users happyIordanis (Jordan) Giannakakis
 

Similar to Do iOS Presentation - Mobile app architectures (20)

Conductor vs Fragments
Conductor vs FragmentsConductor vs Fragments
Conductor vs Fragments
 
«Управление логикой переходов между экранами приложения с помощью координатор...
«Управление логикой переходов между экранами приложения с помощью координатор...«Управление логикой переходов между экранами приложения с помощью координатор...
«Управление логикой переходов между экранами приложения с помощью координатор...
 
Advanced #6 clean architecture
Advanced #6  clean architectureAdvanced #6  clean architecture
Advanced #6 clean architecture
 
Presentation - Windows App Development - II - Mr. Chandan Gupta
Presentation - Windows App Development - II - Mr. Chandan GuptaPresentation - Windows App Development - II - Mr. Chandan Gupta
Presentation - Windows App Development - II - Mr. Chandan Gupta
 
Rcp by example
Rcp by exampleRcp by example
Rcp by example
 
20150516 modern web_conf_tw
20150516 modern web_conf_tw20150516 modern web_conf_tw
20150516 modern web_conf_tw
 
MvvmQuickCross for Windows Phone
MvvmQuickCross for Windows PhoneMvvmQuickCross for Windows Phone
MvvmQuickCross for Windows Phone
 
MBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&CoMBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&Co
 
22Flutter.pdf
22Flutter.pdf22Flutter.pdf
22Flutter.pdf
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Pattern
 
What is your money doing?
What is your money doing?What is your money doing?
What is your money doing?
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018
 
Android classes in mumbai
Android classes in mumbaiAndroid classes in mumbai
Android classes in mumbai
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Voiture tech talk
Voiture tech talkVoiture tech talk
Voiture tech talk
 
SE2016 Android Dmytro Zaitsev "Viper make your MVP cleaner"
SE2016 Android Dmytro Zaitsev "Viper  make your MVP cleaner"SE2016 Android Dmytro Zaitsev "Viper  make your MVP cleaner"
SE2016 Android Dmytro Zaitsev "Viper make your MVP cleaner"
 
Dmytro Zaitsev Viper: make your mvp cleaner
Dmytro Zaitsev Viper: make your mvp cleanerDmytro Zaitsev Viper: make your mvp cleaner
Dmytro Zaitsev Viper: make your mvp cleaner
 
Sexy Architecting. VIPER: MVP on steroids
Sexy Architecting. VIPER: MVP on steroidsSexy Architecting. VIPER: MVP on steroids
Sexy Architecting. VIPER: MVP on steroids
 
Net conf BG xamarin lecture
Net conf BG xamarin lectureNet conf BG xamarin lecture
Net conf BG xamarin lecture
 
How to build rock solid apps & keep 100m+ users happy
How to build rock solid apps & keep 100m+ users happyHow to build rock solid apps & keep 100m+ users happy
How to build rock solid apps & keep 100m+ users happy
 

Recently uploaded

CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual serviceanilsa9823
 
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRFULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRnishacall1
 
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceDelhi Call girls
 
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun serviceCALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun serviceanilsa9823
 
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPowerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPsychicRuben LoveSpells
 
9892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x79892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x7Pooja Nehwal
 
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,Pooja Nehwal
 

Recently uploaded (7)

CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
 
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCRFULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
FULL ENJOY - 9999218229 Call Girls in {Mahipalpur}| Delhi NCR
 
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort ServiceBDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
BDSM⚡Call Girls in Sector 71 Noida Escorts >༒8448380779 Escort Service
 
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun serviceCALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
 
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPowerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
 
9892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x79892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x7
 
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
 

Do iOS Presentation - Mobile app architectures

  • 2.
  • 3. • 135 years old • Helicopters • Mobile apps • 4.5 million members
  • 4. • In house development • 2 teams maintaining 5 apps • Travel, Roadside assistance, Parking, … • Native apps Swift, Kotlin, Java
  • 5. App requirements • Support constant change • Easy to test • Release often • Fast to change
  • 6. Assess state of a codebase • Is your app green field app? • How current codebase looks like? • How big is the team?
  • 7. Architecture requirements • Easy to learn • Highly testable - Supports refactoring • Single responsibility of components • Causes excitement • Applicable to legacy system
  • 8. MVP+? • Variation of MVP • Highly testable • Dependency injection of components • Applicable for both platforms • Simple definition of your app structure
  • 9. Key components • Views • Presenters • Navigator? • Assembly • Interactor?
  • 10.
  • 11. View • Allows you to display things • Is an interface • ViewControllers or Views • Should not know about UIKit
  • 12. View 12 protocol TODOListView: class { func showTODOs(todo: [TODOItem]) -> () } class TODOListViewController: UIViewController, TODOListView { func showTODOs(todo: [TODOItem]) { //... } }
  • 13. Presenter • Receives actions - UI Input • Implements logic • Sends display events to view
  • 14. Presenter class TODOListPresenter { weak var view: TODOListView? func didLoad() { let todos = self.todoListRepository.getAllTODOs() self.view?.showTODOs(todo: todos) } }
  • 15. Presenter Test class TODOListPresenterTest: XCTestCase { var mockRepository: MockTodoRepo! var presenter: TODOListPresenter! override func setUp() { self.mockRepository = MockTodoRepo() self.presenter = TODOListPresenter(repository: mockRepository) } func testDidLoad() { XCTAssertFalse(verify(MockTodoRepo.getAllTODOs)) presenter.didLoad() XCTAssertTrue(verify(MockTodoRepo.getAllTODOs)) } }
  • 16. Presenter - View Test class TODOListPresenterTest: XCTestCase { var mockRepository: MockTodoRepo! var presenter: TODOListPresenter! var view: MockTodoView! override func setUp() { self.mockRepository = MockTodoRepo() self.presenter = TODOListPresenter(repository: mockRepository) self.view = MockTodoView() self.presenter.view = self.view } func testDidLoad() { presenter.didLoad() XCTAssert(verify(MockTodoRepo.getAllTODOs)) XCTAssertTrue(verify(MockTodoView.showTODOs)) } }
  • 17. Assembly • Wires together presenters, views, navigators, … • Creates other assemblies • Acts as a factory for view controllers • Assembly tree defines your whole app
  • 18. Assembly class TODOAssembly { var navigationController: UINavigationController var todoRepository: TODORepository init(navigationController: UINavigationController, todoRepository: TODORepository) { self.navigationController = navigationController self.todoRepository = todoRepository } var todoViewController: TODOListViewController { let todoPresenter = TODOListPresenter(repository: todoRepository) let vc = TODOListViewController(presenter: todoPresenter) return vc } }
  • 19.
  • 20. Assembly tree class LoginAssembly { // ... var loginViewController: LoginViewController { return LoginViewController() } } class TrafficAssembly { // ... var trafficViewController: TrafficViewController { return UIViewController() } } class CoreAssembly { lazy var loginAssembly = LoginAssembly(self) lazy var trafficAssembly = TrafficAssembly(self) var rootViewController: UIViewController { return trafficAssembly.trafficViewController } }
  • 21. Assembly example #2 let coreAssembly = CoreAssembly() @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions: …) -> Bool { self.window?.rootViewController = coreAssembly.rootViewController return true }
  • 22. Assembly Example #2 final class CoreAssembly { var navigationController: UINavigationController var appStateRepository: AppStateRepository lazy var tourAssembly = TourAssembly(self.navigationController) lazy var todoAssembly = TODOAssembly(self.navigationController) init(navigationController: UINavigationController, appStateRepository: AppStateRepository) { self.navigationController = navigationController self.appStateRepository = appStateRepository } var rootViewController: UIViewController { if appStateRepository.isNewInstall { return tourAssembly.tourViewController } else { return todoAssembly.todoViewController } } }
  • 23. Assembly Test class RootAssemblyTest: XCTestCase { func testRootViewControllerTour() { let mockAppStateRepo = MockStateRepository(isNewInstall: true) let assembly = RootAssembly(navigationController: UINavigationController(), appStateRepository: mockAppStateRepo) XCTAssert(type(of: assembly.rootViewController) == TourViewController.self) } func testRootViewControllerTODO() { let mockAppStateRepo = MockStateRepository(isNewInstall: false) let assembly = RootAssembly(navigationController: UINavigationController(), appStateRepository: mockAppStateRepo) XCTAssert(type(of: assembly.rootViewController) == TODOListViewController.self) } }
  • 24. Navigator protocol TODOListNavigator { func showTODODetail(id: Int) -> () }
  • 25. Navigator Implementation class TODOAssembly { // ... var todoViewController: TODOListViewController { let todoPresenter = TODOListPresenter(repository: todoRepository, navigator: self) let vc = TODOListViewController(presenter: todoPresenter) return vc } var todoDetailViewController: TODODetailViewController { let presenter = TODODetailPresenter(repository: self.todoRepository) let vc = TODODetailViewController(presenter: presenter) return vc } } extension TODOAssembly: TODOListNavigator { func showTODODetail(id: Int) { let vc = self.todoDetailViewController vc.presenter.selectedTodoId = id self.navigationController.pushViewController(vc, animated: true) } }
  • 26. Navigator Test class TODOListNavigatorTest: XCTestCase { var mockNavigator: MockNavigator! var presenter: TODOListPresenter! override func setUp() { self.mockNavigator = MockNavigator() self.presenter = TODOListPresenter(navigator: mockNavigator) } func testOnTodoTap() { XCTAssertFalse(verify(MockNavigator.showTODODetail)) presenter.onTodoTap(id: 4) XCTAssertTrue(verify(MockNavigator.showTODODetail)) } }
  • 27. Component optionality • You don’t need all components if your screen is simple • Hard to find the line
  • 28.
  • 30. Problem with state • Managing state can be hard • State representation often leads to confusion • Good state representation can improves readability
  • 31. View State protocol TODODetailView: class { func showTodo(todo: TODOItemDetail) func showError(error: Error) func showLoading() } class TODODetailViewController: UIViewController { var isLoading: Bool = false var error: Error? = nil var data: TODOItemDetail? // …
  • 32. View State enum ViewState<T> { case initial case loading case data(T) case error(Error) } protocol TODODetailsStateView: class { var state: ViewState<TODOItemDetail> { get set } } class TODODetailViewController: UIViewController { var state: ViewState<TODOItemDetail> = .initial { didSet { // ...
  • 33. Simple view models • Simple data model • No logic • Just holds values to be rendered
  • 34. View Models struct TodoTableViewCellViewModel { var formattedDate: String var content: String } class TodoTableViewCell: UITableViewCell { var viewModel: TodoTableViewCellViewModel? { didSet { guard let viewModel = viewModel else { return } date.text = viewModel.formattedDate content.text = viewModel.content } } @IBOutlet weak var date: UILabel! @IBOutlet weak var content: UILabel! }
  • 35. Enable gradual refactoring • Apply change gradually • Isolate modules and surround them by tests • Easy to add presenter to any view controller • Obj-C rewrite
  • 36. Code sharing among apps • Start with an interface • Assembly can be used in any architecture
  • 37. Take aways • There is no silver bullet • Don’t build thing you don’t need today • Uncertainty is only certain thing • You write code for people, not computers. • Good test is better than outdated documentation