SlideShare a Scribd company logo
Refactor Your
Way Forward
Jorge D. Ortiz-Fuentes
@jdortiz
A Canonical

Examples

Production
#AdvArchMobile
Agenda
★ The challenge
★ Strategy
★ Tactics
★ Recap
The
Challenge
#AdvArchMobile
Sounds familiar?
★ Legacy application
• No tests
• Outdated
★ Written in Objective-C
★ Not (m)any tests
★ Multiple styles and ways to do things
★ Not much info from the previous developer
#AdvArchMobile
Need a Better
Architecture
★ Difficult to add new features without
breaking existing ones
★ Difficult to find and solve bugs
★ Expensive to maintain
★ Difficult to add tests
#AdvArchMobile
My Example
★ App: OpenIt
★ Credit: Patrick Balestra
★ Thanks!
★ Great code for an example
★ All criticism IS constructive
Strategy
Ideas to Enhance
Persistance FW
View
Network
LocationFW
Presenter
Entity Gateway
Clean Architecture
Interactor
Entity
Clean Architecture: iOS
App
Delegate
View (VC) Presenter Interactor
Entity
Gateway
Connector
#AdvArchMobile
Goals
★ New feature: Apple rating API
★ Don’t break anything
★ Enhance when possible
No Big Bang Rewrite
Still love the TV series
Information
Gathering
– Sun Tzu
“Know your enemy and know yourself and
you can fight a hundred battles without
disaster.”
Pragmatic Information
Gathering
Make it Work
#AdvArchMobile
Make it Work
★ Install dependencies
• Pods/Carthage, if any
• API keys
★ Build
★ Fix big problems until it works
#AdvArchMobile
Make it Work
★ DON’T update the project settings yet
★ DON’T add any functionality yet
★ DON’T fix any other bugs yet
Commit!
#AdvArchMobile
Explore the Battlefield
★ Take a glimpse a the code
★ Tests? Runnable? Pass?
★ Documentation?
★ Oral transmission?
★ Business goals
#AdvArchMobile
Design your strategy
★ Planed features
★ Pain points
#AdvArchMobile
Main Strategic
Approaches
★ From the model upwards
• Less intuitive
• Still requires injections from top to bottom
★ From the views inwards
• More work initially
#AdvArchMobile
Shape the Strategy
★ App delegate: Size? Relevant tasks? Easy to
replace (And remove main.m)?
★ Storyboards?
★ Tests coverage? Only for the model?
★ Frameworks used (Persistence & others)?
★ DI? Abstractions for DIP?
★ VCs screaming for changes?
But remember
Only small non breaking changes allowed
Tactics
Add Tests
#AdvArchMobile
Add Tests
★ Set up the testing target
★ Language is Swift
★ Start with main target
★ Don't add others (frameworks) until required
★ Cmd+U To test that it works.
★ Delete the default tests
Commit!
Zero Visibility
Here Be Dragons
Use the Tools
#AdvArchMobile
Proper Git
★ Branch often
★ Better, git flow: Feature branch for each
part of migration
★ Avoid long lived branches
★ Use branch by abstraction instead
#AdvArchMobile
Branch by Abstraction
2 1
1
1 2
#AdvArchMobile
Use Xcode Groups
★ Put all legacy code in a group
★ Support files and assets in another one
★ Create new Groups (or folders) to organize
new code
Use Xcode Refactor
Feature
😂
Replace App
Delegate (& main.m)
#AdvArchMobile
Very Simple (when it is)
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
}
Commit!
Enable Dependency
Injection
#AdvArchMobile
Introduce DI
from Root VC
★ Change behavior in Info.plist
★ App delegate creates initial view controller
★ Pass into a dumb (yet) connector
★ Add Bridging header
#AdvArchMobile
Info.plist
Commit!
View Controller Talks
to Dumb Presenter
Mark Connection Points
#AdvArchMobile
Introduce Presenter
★ @objc
★ Pass events
★ Test VC
★ Generate a skeleton for the presenter
#AdvArchMobile
Cheat to keep it working
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
// DONE: Invoke presenter numberOfActions
NSInteger rows = self.presenter.numberOfActions;
// TODO: Remove when using real presenter
if (rows < 0) {
rows = self.actions.count;
}
return rows;
}
#AdvArchMobile
Cheat to provide
dependencies
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// DONE: Invoke presenter configure(cell:forRow:)
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
// TODO: In the new view replace with the actual cell
[self.presenter configureWithCell:[[ActionTableViewCell alloc]
init] atRow:indexPath.row];
cell.textLabel.text = self.actions[indexPath.row][0][@"Title"];
cell.detailTextLabel.text = self.actions[indexPath.row][1]
[@"Type"];
cell.imageView.image = [UIImage
imageNamed:self.actions[indexPath.row][1][@"Type"]];
return cell;
}
Commit!
Refactor Persistence
#AdvArchMobile
- (void)viewDidLoad {
[super viewDidLoad];
[self.presenter viewReady];
// …
self.actions = [self
fetchActions];
// …
}
- (NSMutableArray *) fetchActions
{
return [[NSMutableArray alloc]
initWithArray:[[NSUserDefaults
standardUserDefaults]
objectForKey:@"actions"]];
}
Extract Methods with
Persistence
- (void)viewDidLoad {
[super viewDidLoad];
[self.presenter
viewReady];
// …
self.actions =
[[NSMutableArray alloc]
initWithArray:
[[NSUserDefaults
standardUserDefaults]
objectForKey:@"actions"]];
// …
}
#AdvArchMobile
And Test It
func testFetchActionsObtainsDataFromUserDefaults() {
let userDefaultsMock = UserDefaultsMock()
sut.setValue(userDefaultsMock, forKey: "userDefaults")
_ = sut.fetchActions()
XCTAssertTrue(userDefaultsMock.objectForKeyInvoked)
}
Commit!
Get the new VC in
#AdvArchMobile
New Swift VC
★ Replaces the old one
★ Refactor Storyboard
★ New Swift class with the desired name
★ Reuse the tests to create an instance of this
one
Refactor the Storyboard
Deal with
Limitations
#AdvArchMobile
Rough Edges
★ Structs & Enums
★ Tuples
★ Generics
★ Curried & global functions
★ Typealiases
#AdvArchMobile
@objcMembers class ActionWrapper: NSObject
{
private var action: Action
var title: String {
get {
return action.title
}
set(newTitle) {
action.title = newTitle
}
}
//…
init(action: Action) {
self.action = action
}
init(title: String, type: String, url:
String) {
action = Action(title: title,
type: type, url: url)
}
}
Use Wrappers
struct Action {
var title: String
var type: String
var url: String
}
Commit!
#AdvArchMobile
But…
★ Entity Gateway should implement both
★ Value semantics are lost
★ Use scarcely
★ Remove when possible
And Finally…
New Use Case
#AdvArchMobile
Use Case
typealias AskForRatingCompletion = (Bool) -> ()
class AskForRatingUseCase: UseCase {
let entityGateway: EntityGateway
let preferencesGateway: PreferencesGateway
let completion: AskForRatingCompletion
init(entityGateway: EntityGateway, preferencesGateway:
PreferencesGateway,
completion: @escaping AskForRatingCompletion) {
self.entityGateway = entityGateway
self.preferencesGateway = preferencesGateway
self.completion = completion
}
func execute() {
let ask = entityGateway.numberOfActions > 10
&& preferencesGateway.daysSinceLastRating > 180
completion(ask)
}
}
#AdvArchMobile
// View (extension)
func askForRating() {
SKStoreReviewController.requestRe
view()
}
Presenter & View
// Presenter
func viewReady() {
actions = fetchActions()
mayAskUserForRating()
}
private func
mayAskUserForRating() {
let useCase =
useCaseFactory.askForRatingUseCas
e(completion: { (shouldAsk: Bool)
in
view.askForRating()
})
useCase.execute()
}
Commit!
Recap
#AdvArchMobile
Recap
★ Incremental refactoring is feasible
★ Design your strategy
★ Use the tactics
★ Small non breaking changes are best
★ Tests are key
★ Don’t follow sequential order
Tusen
Takk!
Thank
You!
@jdortiz
#AdvArchMobile
Ad

More Related Content

What's hot (20)

Selenium In The Real World
Selenium In The Real WorldSelenium In The Real World
Selenium In The Real World
iainrose
 
Roslyn
RoslynRoslyn
Roslyn
Tomas Jansson
 
Variables in Pharo5
Variables in Pharo5Variables in Pharo5
Variables in Pharo5
Marcus Denker
 
CocoaConf DC - Automate with Swift - Tony Ingraldi
CocoaConf DC -  Automate with Swift - Tony IngraldiCocoaConf DC -  Automate with Swift - Tony Ingraldi
CocoaConf DC - Automate with Swift - Tony Ingraldi
Tony Ingraldi
 
Javascript omg!
Javascript omg!Javascript omg!
Javascript omg!
bwullems
 
Wuff: Building Eclipse Applications and Plugins with Gradle
Wuff: Building Eclipse Applications and Plugins with GradleWuff: Building Eclipse Applications and Plugins with Gradle
Wuff: Building Eclipse Applications and Plugins with Gradle
Andrey Hihlovsky
 
Ebay legacy-code-retreat
Ebay legacy-code-retreatEbay legacy-code-retreat
Ebay legacy-code-retreat
Konrad Malawski
 
El viaje de Angular1 a Angular2
El viaje de Angular1 a Angular2El viaje de Angular1 a Angular2
El viaje de Angular1 a Angular2
Antonio de la Torre Fernández
 
ClassJS
ClassJSClassJS
ClassJS
Michael Barrett
 
Gtg12
Gtg12Gtg12
Gtg12
Poga Po
 
Why I don’t want to develop iOS apps in Objective C
Why I don’t want to develop iOS apps in Objective CWhy I don’t want to develop iOS apps in Objective C
Why I don’t want to develop iOS apps in Objective C
SeniorDevOnly
 
Using JHipster for generating Angular/Spring Boot apps
Using JHipster for generating Angular/Spring Boot appsUsing JHipster for generating Angular/Spring Boot apps
Using JHipster for generating Angular/Spring Boot apps
Yakov Fain
 
Intro to JavaScript
Intro to JavaScriptIntro to JavaScript
Intro to JavaScript
Yakov Fain
 
Java Intro: Unit1. Hello World
Java Intro: Unit1. Hello WorldJava Intro: Unit1. Hello World
Java Intro: Unit1. Hello World
Yakov Fain
 
Angular 2 Essential Training
Angular 2 Essential Training Angular 2 Essential Training
Angular 2 Essential Training
Patrick Schroeder
 
Apigility introduction v2 (glasgow php)
Apigility introduction v2 (glasgow php)Apigility introduction v2 (glasgow php)
Apigility introduction v2 (glasgow php)
Engineor
 
PuppetConf 2016 Moving from Exec to Types and Provides
PuppetConf 2016 Moving from Exec to Types and ProvidesPuppetConf 2016 Moving from Exec to Types and Provides
PuppetConf 2016 Moving from Exec to Types and Provides
Martin Alfke
 
Behave manners for ui testing pycon2019
Behave manners for ui testing pycon2019Behave manners for ui testing pycon2019
Behave manners for ui testing pycon2019
Panos Christeas
 
Unit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsUnit Testing JavaScript Applications
Unit Testing JavaScript Applications
Ynon Perek
 
Type script for_java_dev_jul_2020
Type script for_java_dev_jul_2020Type script for_java_dev_jul_2020
Type script for_java_dev_jul_2020
Yakov Fain
 
Selenium In The Real World
Selenium In The Real WorldSelenium In The Real World
Selenium In The Real World
iainrose
 
CocoaConf DC - Automate with Swift - Tony Ingraldi
CocoaConf DC -  Automate with Swift - Tony IngraldiCocoaConf DC -  Automate with Swift - Tony Ingraldi
CocoaConf DC - Automate with Swift - Tony Ingraldi
Tony Ingraldi
 
Javascript omg!
Javascript omg!Javascript omg!
Javascript omg!
bwullems
 
Wuff: Building Eclipse Applications and Plugins with Gradle
Wuff: Building Eclipse Applications and Plugins with GradleWuff: Building Eclipse Applications and Plugins with Gradle
Wuff: Building Eclipse Applications and Plugins with Gradle
Andrey Hihlovsky
 
Ebay legacy-code-retreat
Ebay legacy-code-retreatEbay legacy-code-retreat
Ebay legacy-code-retreat
Konrad Malawski
 
Why I don’t want to develop iOS apps in Objective C
Why I don’t want to develop iOS apps in Objective CWhy I don’t want to develop iOS apps in Objective C
Why I don’t want to develop iOS apps in Objective C
SeniorDevOnly
 
Using JHipster for generating Angular/Spring Boot apps
Using JHipster for generating Angular/Spring Boot appsUsing JHipster for generating Angular/Spring Boot apps
Using JHipster for generating Angular/Spring Boot apps
Yakov Fain
 
Intro to JavaScript
Intro to JavaScriptIntro to JavaScript
Intro to JavaScript
Yakov Fain
 
Java Intro: Unit1. Hello World
Java Intro: Unit1. Hello WorldJava Intro: Unit1. Hello World
Java Intro: Unit1. Hello World
Yakov Fain
 
Angular 2 Essential Training
Angular 2 Essential Training Angular 2 Essential Training
Angular 2 Essential Training
Patrick Schroeder
 
Apigility introduction v2 (glasgow php)
Apigility introduction v2 (glasgow php)Apigility introduction v2 (glasgow php)
Apigility introduction v2 (glasgow php)
Engineor
 
PuppetConf 2016 Moving from Exec to Types and Provides
PuppetConf 2016 Moving from Exec to Types and ProvidesPuppetConf 2016 Moving from Exec to Types and Provides
PuppetConf 2016 Moving from Exec to Types and Provides
Martin Alfke
 
Behave manners for ui testing pycon2019
Behave manners for ui testing pycon2019Behave manners for ui testing pycon2019
Behave manners for ui testing pycon2019
Panos Christeas
 
Unit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsUnit Testing JavaScript Applications
Unit Testing JavaScript Applications
Ynon Perek
 
Type script for_java_dev_jul_2020
Type script for_java_dev_jul_2020Type script for_java_dev_jul_2020
Type script for_java_dev_jul_2020
Yakov Fain
 

Similar to Refactor your way forward (20)

Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
Hendrik Ebbers
 
Rubymotion talk
Rubymotion talkRubymotion talk
Rubymotion talk
pinfieldharm
 
Unit testing on mobile apps
Unit testing on mobile appsUnit testing on mobile apps
Unit testing on mobile apps
Buşra Deniz, CSM
 
Objective-C Is Not Java
Objective-C Is Not JavaObjective-C Is Not Java
Objective-C Is Not Java
Chris Adamson
 
Exploring the power of Gradle in android studio - Basics & Beyond
Exploring the power of Gradle in android studio - Basics & BeyondExploring the power of Gradle in android studio - Basics & Beyond
Exploring the power of Gradle in android studio - Basics & Beyond
Kaushal Dhruw
 
iOS for Android Developers (with Swift)
iOS for Android Developers (with Swift)iOS for Android Developers (with Swift)
iOS for Android Developers (with Swift)
David Truxall
 
Titanium Alloy Tutorial
Titanium Alloy TutorialTitanium Alloy Tutorial
Titanium Alloy Tutorial
Fokke Zandbergen
 
React nativebeginner1
React nativebeginner1React nativebeginner1
React nativebeginner1
Oswald Campesato
 
MFF UK - Introduction to iOS
MFF UK - Introduction to iOSMFF UK - Introduction to iOS
MFF UK - Introduction to iOS
Petr Dvorak
 
Dependency Injection and Autofac
Dependency Injection and AutofacDependency Injection and Autofac
Dependency Injection and Autofac
meghantaylor
 
Data Migrations in the App Engine Datastore
Data Migrations in the App Engine DatastoreData Migrations in the App Engine Datastore
Data Migrations in the App Engine Datastore
Ryan Morlok
 
2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie
hcderaad
 
Hotfixing iOS apps with Javascript
Hotfixing iOS apps with JavascriptHotfixing iOS apps with Javascript
Hotfixing iOS apps with Javascript
Sergio Padrino Recio
 
Swift testing ftw
Swift testing ftwSwift testing ftw
Swift testing ftw
Jorge Ortiz
 
Angular4 kickstart
Angular4 kickstartAngular4 kickstart
Angular4 kickstart
Foyzul Karim
 
Twins: OOP and FP
Twins: OOP and FPTwins: OOP and FP
Twins: OOP and FP
RichardWarburton
 
L04 Software Design Examples
L04 Software Design ExamplesL04 Software Design Examples
L04 Software Design Examples
Ólafur Andri Ragnarsson
 
Setting Up CircleCI Workflows for Your Salesforce Apps
Setting Up CircleCI Workflows for Your Salesforce AppsSetting Up CircleCI Workflows for Your Salesforce Apps
Setting Up CircleCI Workflows for Your Salesforce Apps
Daniel Stange
 
Eclipse 40 - Eclipse Summit Europe 2010
Eclipse 40 - Eclipse Summit Europe 2010Eclipse 40 - Eclipse Summit Europe 2010
Eclipse 40 - Eclipse Summit Europe 2010
Lars Vogel
 
Session 3 - Object oriented programming with Objective-C (part 1)
Session 3 - Object oriented programming with Objective-C (part 1)Session 3 - Object oriented programming with Objective-C (part 1)
Session 3 - Object oriented programming with Objective-C (part 1)
Vu Tran Lam
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
Hendrik Ebbers
 
Objective-C Is Not Java
Objective-C Is Not JavaObjective-C Is Not Java
Objective-C Is Not Java
Chris Adamson
 
Exploring the power of Gradle in android studio - Basics & Beyond
Exploring the power of Gradle in android studio - Basics & BeyondExploring the power of Gradle in android studio - Basics & Beyond
Exploring the power of Gradle in android studio - Basics & Beyond
Kaushal Dhruw
 
iOS for Android Developers (with Swift)
iOS for Android Developers (with Swift)iOS for Android Developers (with Swift)
iOS for Android Developers (with Swift)
David Truxall
 
MFF UK - Introduction to iOS
MFF UK - Introduction to iOSMFF UK - Introduction to iOS
MFF UK - Introduction to iOS
Petr Dvorak
 
Dependency Injection and Autofac
Dependency Injection and AutofacDependency Injection and Autofac
Dependency Injection and Autofac
meghantaylor
 
Data Migrations in the App Engine Datastore
Data Migrations in the App Engine DatastoreData Migrations in the App Engine Datastore
Data Migrations in the App Engine Datastore
Ryan Morlok
 
2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie
hcderaad
 
Hotfixing iOS apps with Javascript
Hotfixing iOS apps with JavascriptHotfixing iOS apps with Javascript
Hotfixing iOS apps with Javascript
Sergio Padrino Recio
 
Swift testing ftw
Swift testing ftwSwift testing ftw
Swift testing ftw
Jorge Ortiz
 
Angular4 kickstart
Angular4 kickstartAngular4 kickstart
Angular4 kickstart
Foyzul Karim
 
Setting Up CircleCI Workflows for Your Salesforce Apps
Setting Up CircleCI Workflows for Your Salesforce AppsSetting Up CircleCI Workflows for Your Salesforce Apps
Setting Up CircleCI Workflows for Your Salesforce Apps
Daniel Stange
 
Eclipse 40 - Eclipse Summit Europe 2010
Eclipse 40 - Eclipse Summit Europe 2010Eclipse 40 - Eclipse Summit Europe 2010
Eclipse 40 - Eclipse Summit Europe 2010
Lars Vogel
 
Session 3 - Object oriented programming with Objective-C (part 1)
Session 3 - Object oriented programming with Objective-C (part 1)Session 3 - Object oriented programming with Objective-C (part 1)
Session 3 - Object oriented programming with Objective-C (part 1)
Vu Tran Lam
 
Ad

More from Jorge Ortiz (20)

Tell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature FlagsTell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature Flags
Jorge Ortiz
 
Unit Test your Views
Unit Test your ViewsUnit Test your Views
Unit Test your Views
Jorge Ortiz
 
Control your Voice like a Bene Gesserit
Control your Voice like a Bene GesseritControl your Voice like a Bene Gesserit
Control your Voice like a Bene Gesserit
Jorge Ortiz
 
Kata gilded rose en Golang
Kata gilded rose en GolangKata gilded rose en Golang
Kata gilded rose en Golang
Jorge Ortiz
 
CYA: Cover Your App
CYA: Cover Your AppCYA: Cover Your App
CYA: Cover Your App
Jorge Ortiz
 
201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG
Jorge Ortiz
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & Kotlin
Jorge Ortiz
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
Jorge Ortiz
 
Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive Apps
Jorge Ortiz
 
iOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editioniOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h edition
Jorge Ortiz
 
Android clean architecture workshop 3h edition
Android clean architecture workshop 3h editionAndroid clean architecture workshop 3h edition
Android clean architecture workshop 3h edition
Jorge Ortiz
 
To Protect & To Serve
To Protect & To ServeTo Protect & To Serve
To Protect & To Serve
Jorge Ortiz
 
Clean architecture workshop
Clean architecture workshopClean architecture workshop
Clean architecture workshop
Jorge Ortiz
 
Escape from Mars
Escape from MarsEscape from Mars
Escape from Mars
Jorge Ortiz
 
Why the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureWhy the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID Architecture
Jorge Ortiz
 
Dependence day insurgence
Dependence day insurgenceDependence day insurgence
Dependence day insurgence
Jorge Ortiz
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
Jorge Ortiz
 
TDD for the masses
TDD for the massesTDD for the masses
TDD for the masses
Jorge Ortiz
 
7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS
Jorge Ortiz
 
Building for perfection
Building for perfectionBuilding for perfection
Building for perfection
Jorge Ortiz
 
Tell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature FlagsTell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature Flags
Jorge Ortiz
 
Unit Test your Views
Unit Test your ViewsUnit Test your Views
Unit Test your Views
Jorge Ortiz
 
Control your Voice like a Bene Gesserit
Control your Voice like a Bene GesseritControl your Voice like a Bene Gesserit
Control your Voice like a Bene Gesserit
Jorge Ortiz
 
Kata gilded rose en Golang
Kata gilded rose en GolangKata gilded rose en Golang
Kata gilded rose en Golang
Jorge Ortiz
 
CYA: Cover Your App
CYA: Cover Your AppCYA: Cover Your App
CYA: Cover Your App
Jorge Ortiz
 
201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG
Jorge Ortiz
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & Kotlin
Jorge Ortiz
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
Jorge Ortiz
 
Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive Apps
Jorge Ortiz
 
iOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editioniOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h edition
Jorge Ortiz
 
Android clean architecture workshop 3h edition
Android clean architecture workshop 3h editionAndroid clean architecture workshop 3h edition
Android clean architecture workshop 3h edition
Jorge Ortiz
 
To Protect & To Serve
To Protect & To ServeTo Protect & To Serve
To Protect & To Serve
Jorge Ortiz
 
Clean architecture workshop
Clean architecture workshopClean architecture workshop
Clean architecture workshop
Jorge Ortiz
 
Escape from Mars
Escape from MarsEscape from Mars
Escape from Mars
Jorge Ortiz
 
Why the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureWhy the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID Architecture
Jorge Ortiz
 
Dependence day insurgence
Dependence day insurgenceDependence day insurgence
Dependence day insurgence
Jorge Ortiz
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
Jorge Ortiz
 
TDD for the masses
TDD for the massesTDD for the masses
TDD for the masses
Jorge Ortiz
 
7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS
Jorge Ortiz
 
Building for perfection
Building for perfectionBuilding for perfection
Building for perfection
Jorge Ortiz
 
Ad

Recently uploaded (20)

NYC ACE 08-May-2025-Combined Presentation.pdf
NYC ACE 08-May-2025-Combined Presentation.pdfNYC ACE 08-May-2025-Combined Presentation.pdf
NYC ACE 08-May-2025-Combined Presentation.pdf
AUGNYC
 
Quasar Framework Introduction for C++ develpoers
Quasar Framework Introduction for C++ develpoersQuasar Framework Introduction for C++ develpoers
Quasar Framework Introduction for C++ develpoers
sadadkhah
 
iTop VPN With Crack Lifetime Activation Key
iTop VPN With Crack Lifetime Activation KeyiTop VPN With Crack Lifetime Activation Key
iTop VPN With Crack Lifetime Activation Key
raheemk1122g
 
wAIred_LearnWithOutAI_JCON_14052025.pptx
wAIred_LearnWithOutAI_JCON_14052025.pptxwAIred_LearnWithOutAI_JCON_14052025.pptx
wAIred_LearnWithOutAI_JCON_14052025.pptx
SimonedeGijt
 
AI Agents with Gemini 2.0 - Beyond the Chatbot
AI Agents with Gemini 2.0 - Beyond the ChatbotAI Agents with Gemini 2.0 - Beyond the Chatbot
AI Agents with Gemini 2.0 - Beyond the Chatbot
Márton Kodok
 
Temas principales de GrafanaCON 2025 Grafana 12 y más
Temas principales de GrafanaCON 2025 Grafana 12 y másTemas principales de GrafanaCON 2025 Grafana 12 y más
Temas principales de GrafanaCON 2025 Grafana 12 y más
Imma Valls Bernaus
 
Aligning Projects to Strategy During Economic Uncertainty
Aligning Projects to Strategy During Economic UncertaintyAligning Projects to Strategy During Economic Uncertainty
Aligning Projects to Strategy During Economic Uncertainty
OnePlan Solutions
 
Grand Theft Auto 6 PC Game Cracked Full Setup Download
Grand Theft Auto 6 PC Game Cracked Full Setup DownloadGrand Theft Auto 6 PC Game Cracked Full Setup Download
Grand Theft Auto 6 PC Game Cracked Full Setup Download
Iobit Uninstaller Pro Crack
 
Legacy Code Nightmares , Hellscapes, and Lessons Learned.pdf
Legacy Code Nightmares , Hellscapes, and Lessons Learned.pdfLegacy Code Nightmares , Hellscapes, and Lessons Learned.pdf
Legacy Code Nightmares , Hellscapes, and Lessons Learned.pdf
Ortus Solutions, Corp
 
Logs, Metrics, traces and Mayhem - An Interactive Observability Adventure Wor...
Logs, Metrics, traces and Mayhem - An Interactive Observability Adventure Wor...Logs, Metrics, traces and Mayhem - An Interactive Observability Adventure Wor...
Logs, Metrics, traces and Mayhem - An Interactive Observability Adventure Wor...
Imma Valls Bernaus
 
How to Troubleshoot 9 Types of OutOfMemoryError
How to Troubleshoot 9 Types of OutOfMemoryErrorHow to Troubleshoot 9 Types of OutOfMemoryError
How to Troubleshoot 9 Types of OutOfMemoryError
Tier1 app
 
Best HR and Payroll Software in Bangladesh - accordHRM
Best HR and Payroll Software in Bangladesh - accordHRMBest HR and Payroll Software in Bangladesh - accordHRM
Best HR and Payroll Software in Bangladesh - accordHRM
accordHRM
 
Reinventing Microservices Efficiency and Innovation with Single-Runtime
Reinventing Microservices Efficiency and Innovation with Single-RuntimeReinventing Microservices Efficiency and Innovation with Single-Runtime
Reinventing Microservices Efficiency and Innovation with Single-Runtime
Natan Silnitsky
 
Drawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon Creation
Drawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon CreationDrawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon Creation
Drawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon Creation
Philip Schwarz
 
Troubleshooting JVM Outages – 3 Fortune 500 case studies
Troubleshooting JVM Outages – 3 Fortune 500 case studiesTroubleshooting JVM Outages – 3 Fortune 500 case studies
Troubleshooting JVM Outages – 3 Fortune 500 case studies
Tier1 app
 
Hydraulic Modeling And Simulation Software Solutions.pptx
Hydraulic Modeling And Simulation Software Solutions.pptxHydraulic Modeling And Simulation Software Solutions.pptx
Hydraulic Modeling And Simulation Software Solutions.pptx
julia smits
 
Lumion Pro Crack + 2025 Activation Key Free Code
Lumion Pro Crack + 2025 Activation Key Free CodeLumion Pro Crack + 2025 Activation Key Free Code
Lumion Pro Crack + 2025 Activation Key Free Code
raheemk1122g
 
S3 + AWS Athena how to integrate s3 aws plus athena
S3 + AWS Athena how to integrate s3 aws plus athenaS3 + AWS Athena how to integrate s3 aws plus athena
S3 + AWS Athena how to integrate s3 aws plus athena
aianand98
 
Buy vs. Build: Unlocking the right path for your training tech
Buy vs. Build: Unlocking the right path for your training techBuy vs. Build: Unlocking the right path for your training tech
Buy vs. Build: Unlocking the right path for your training tech
Rustici Software
 
Let's Do Bad Things to Unsecured Containers
Let's Do Bad Things to Unsecured ContainersLet's Do Bad Things to Unsecured Containers
Let's Do Bad Things to Unsecured Containers
Gene Gotimer
 
NYC ACE 08-May-2025-Combined Presentation.pdf
NYC ACE 08-May-2025-Combined Presentation.pdfNYC ACE 08-May-2025-Combined Presentation.pdf
NYC ACE 08-May-2025-Combined Presentation.pdf
AUGNYC
 
Quasar Framework Introduction for C++ develpoers
Quasar Framework Introduction for C++ develpoersQuasar Framework Introduction for C++ develpoers
Quasar Framework Introduction for C++ develpoers
sadadkhah
 
iTop VPN With Crack Lifetime Activation Key
iTop VPN With Crack Lifetime Activation KeyiTop VPN With Crack Lifetime Activation Key
iTop VPN With Crack Lifetime Activation Key
raheemk1122g
 
wAIred_LearnWithOutAI_JCON_14052025.pptx
wAIred_LearnWithOutAI_JCON_14052025.pptxwAIred_LearnWithOutAI_JCON_14052025.pptx
wAIred_LearnWithOutAI_JCON_14052025.pptx
SimonedeGijt
 
AI Agents with Gemini 2.0 - Beyond the Chatbot
AI Agents with Gemini 2.0 - Beyond the ChatbotAI Agents with Gemini 2.0 - Beyond the Chatbot
AI Agents with Gemini 2.0 - Beyond the Chatbot
Márton Kodok
 
Temas principales de GrafanaCON 2025 Grafana 12 y más
Temas principales de GrafanaCON 2025 Grafana 12 y másTemas principales de GrafanaCON 2025 Grafana 12 y más
Temas principales de GrafanaCON 2025 Grafana 12 y más
Imma Valls Bernaus
 
Aligning Projects to Strategy During Economic Uncertainty
Aligning Projects to Strategy During Economic UncertaintyAligning Projects to Strategy During Economic Uncertainty
Aligning Projects to Strategy During Economic Uncertainty
OnePlan Solutions
 
Grand Theft Auto 6 PC Game Cracked Full Setup Download
Grand Theft Auto 6 PC Game Cracked Full Setup DownloadGrand Theft Auto 6 PC Game Cracked Full Setup Download
Grand Theft Auto 6 PC Game Cracked Full Setup Download
Iobit Uninstaller Pro Crack
 
Legacy Code Nightmares , Hellscapes, and Lessons Learned.pdf
Legacy Code Nightmares , Hellscapes, and Lessons Learned.pdfLegacy Code Nightmares , Hellscapes, and Lessons Learned.pdf
Legacy Code Nightmares , Hellscapes, and Lessons Learned.pdf
Ortus Solutions, Corp
 
Logs, Metrics, traces and Mayhem - An Interactive Observability Adventure Wor...
Logs, Metrics, traces and Mayhem - An Interactive Observability Adventure Wor...Logs, Metrics, traces and Mayhem - An Interactive Observability Adventure Wor...
Logs, Metrics, traces and Mayhem - An Interactive Observability Adventure Wor...
Imma Valls Bernaus
 
How to Troubleshoot 9 Types of OutOfMemoryError
How to Troubleshoot 9 Types of OutOfMemoryErrorHow to Troubleshoot 9 Types of OutOfMemoryError
How to Troubleshoot 9 Types of OutOfMemoryError
Tier1 app
 
Best HR and Payroll Software in Bangladesh - accordHRM
Best HR and Payroll Software in Bangladesh - accordHRMBest HR and Payroll Software in Bangladesh - accordHRM
Best HR and Payroll Software in Bangladesh - accordHRM
accordHRM
 
Reinventing Microservices Efficiency and Innovation with Single-Runtime
Reinventing Microservices Efficiency and Innovation with Single-RuntimeReinventing Microservices Efficiency and Innovation with Single-Runtime
Reinventing Microservices Efficiency and Innovation with Single-Runtime
Natan Silnitsky
 
Drawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon Creation
Drawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon CreationDrawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon Creation
Drawing Heighway’s Dragon - Part 4 - Interactive and Animated Dragon Creation
Philip Schwarz
 
Troubleshooting JVM Outages – 3 Fortune 500 case studies
Troubleshooting JVM Outages – 3 Fortune 500 case studiesTroubleshooting JVM Outages – 3 Fortune 500 case studies
Troubleshooting JVM Outages – 3 Fortune 500 case studies
Tier1 app
 
Hydraulic Modeling And Simulation Software Solutions.pptx
Hydraulic Modeling And Simulation Software Solutions.pptxHydraulic Modeling And Simulation Software Solutions.pptx
Hydraulic Modeling And Simulation Software Solutions.pptx
julia smits
 
Lumion Pro Crack + 2025 Activation Key Free Code
Lumion Pro Crack + 2025 Activation Key Free CodeLumion Pro Crack + 2025 Activation Key Free Code
Lumion Pro Crack + 2025 Activation Key Free Code
raheemk1122g
 
S3 + AWS Athena how to integrate s3 aws plus athena
S3 + AWS Athena how to integrate s3 aws plus athenaS3 + AWS Athena how to integrate s3 aws plus athena
S3 + AWS Athena how to integrate s3 aws plus athena
aianand98
 
Buy vs. Build: Unlocking the right path for your training tech
Buy vs. Build: Unlocking the right path for your training techBuy vs. Build: Unlocking the right path for your training tech
Buy vs. Build: Unlocking the right path for your training tech
Rustici Software
 
Let's Do Bad Things to Unsecured Containers
Let's Do Bad Things to Unsecured ContainersLet's Do Bad Things to Unsecured Containers
Let's Do Bad Things to Unsecured Containers
Gene Gotimer
 

Refactor your way forward

  翻译: