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

More Related Content

What's hot

Selenium In The Real World
Selenium In The Real WorldSelenium In The Real World
Selenium In The Real Worldiainrose
 
Roslyn
RoslynRoslyn
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-retreatKonrad 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
 
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
 

What's hot (20)

Selenium In The Real World
Selenium In The Real WorldSelenium In The Real World
Selenium In The Real World
 
Roslyn
RoslynRoslyn
Roslyn
 
Variables in Pharo5
Variables in Pharo5Variables in Pharo5
Variables in Pharo5
 
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
 
Javascript omg!
Javascript omg!Javascript omg!
Javascript omg!
 
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
 
Ebay legacy-code-retreat
Ebay legacy-code-retreatEbay legacy-code-retreat
Ebay legacy-code-retreat
 
El viaje de Angular1 a Angular2
El viaje de Angular1 a Angular2El viaje de Angular1 a Angular2
El viaje de Angular1 a Angular2
 
ClassJS
ClassJSClassJS
ClassJS
 
Gtg12
Gtg12Gtg12
Gtg12
 
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
 
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
 
Intro to JavaScript
Intro to JavaScriptIntro to JavaScript
Intro to JavaScript
 
Java Intro: Unit1. Hello World
Java Intro: Unit1. Hello WorldJava Intro: Unit1. Hello World
Java Intro: Unit1. Hello World
 
Angular 2 Essential Training
Angular 2 Essential Training Angular 2 Essential Training
Angular 2 Essential Training
 
Apigility introduction v2 (glasgow php)
Apigility introduction v2 (glasgow php)Apigility introduction v2 (glasgow php)
Apigility introduction v2 (glasgow php)
 
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
 
Behave manners for ui testing pycon2019
Behave manners for ui testing pycon2019Behave manners for ui testing pycon2019
Behave manners for ui testing pycon2019
 
Unit Testing JavaScript Applications
Unit Testing JavaScript ApplicationsUnit Testing JavaScript Applications
Unit Testing JavaScript Applications
 
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
 

Similar to Refactor your way forward

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
 

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
 
Rubymotion talk
Rubymotion talkRubymotion talk
Rubymotion talk
 
Unit testing on mobile apps
Unit testing on mobile appsUnit testing on mobile apps
Unit testing on mobile apps
 
Objective-C Is Not Java
Objective-C Is Not JavaObjective-C Is Not Java
Objective-C Is Not Java
 
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
 
iOS for Android Developers (with Swift)
iOS for Android Developers (with Swift)iOS for Android Developers (with Swift)
iOS for Android Developers (with Swift)
 
Titanium Alloy Tutorial
Titanium Alloy TutorialTitanium Alloy Tutorial
Titanium Alloy Tutorial
 
React nativebeginner1
React nativebeginner1React nativebeginner1
React nativebeginner1
 
MFF UK - Introduction to iOS
MFF UK - Introduction to iOSMFF UK - Introduction to iOS
MFF UK - Introduction to iOS
 
Dependency Injection and Autofac
Dependency Injection and AutofacDependency Injection and Autofac
Dependency Injection and Autofac
 
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
 
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
 
Hotfixing iOS apps with Javascript
Hotfixing iOS apps with JavascriptHotfixing iOS apps with Javascript
Hotfixing iOS apps with Javascript
 
Swift testing ftw
Swift testing ftwSwift testing ftw
Swift testing ftw
 
Angular4 kickstart
Angular4 kickstartAngular4 kickstart
Angular4 kickstart
 
Twins: OOP and FP
Twins: OOP and FPTwins: OOP and FP
Twins: OOP and FP
 
L04 Software Design Examples
L04 Software Design ExamplesL04 Software Design Examples
L04 Software Design Examples
 
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
 
Eclipse 40 - Eclipse Summit Europe 2010
Eclipse 40 - Eclipse Summit Europe 2010Eclipse 40 - Eclipse Summit Europe 2010
Eclipse 40 - Eclipse Summit Europe 2010
 
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)
 

More from 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
 

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
 
Unit Test your Views
Unit Test your ViewsUnit Test your Views
Unit Test your Views
 
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
 
Kata gilded rose en Golang
Kata gilded rose en GolangKata gilded rose en Golang
Kata gilded rose en Golang
 
CYA: Cover Your App
CYA: Cover Your AppCYA: Cover Your App
CYA: Cover Your App
 
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
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & Kotlin
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
 
Architecting Alive Apps
Architecting Alive AppsArchitecting Alive Apps
Architecting Alive Apps
 
iOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editioniOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h edition
 
Android clean architecture workshop 3h edition
Android clean architecture workshop 3h editionAndroid clean architecture workshop 3h edition
Android clean architecture workshop 3h edition
 
To Protect & To Serve
To Protect & To ServeTo Protect & To Serve
To Protect & To Serve
 
Clean architecture workshop
Clean architecture workshopClean architecture workshop
Clean architecture workshop
 
Escape from Mars
Escape from MarsEscape from Mars
Escape from Mars
 
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
 
Dependence day insurgence
Dependence day insurgenceDependence day insurgence
Dependence day insurgence
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
 
TDD for the masses
TDD for the massesTDD for the masses
TDD for the masses
 
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
 
Building for perfection
Building for perfectionBuilding for perfection
Building for perfection
 

Recently uploaded

Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
Ortus Solutions, Corp
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
Globus
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
Matt Welsh
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
Tendenci - The Open Source AMS (Association Management Software)
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
IES VE
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Natan Silnitsky
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
takuyayamamoto1800
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
AMB-Review
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Shahin Sheidaei
 

Recently uploaded (20)

Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024Globus Compute Introduction - GlobusWorld 2024
Globus Compute Introduction - GlobusWorld 2024
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdfDominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
Dominate Social Media with TubeTrivia AI’s Addictive Quiz Videos.pdf
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 

Refactor your way forward