SlideShare una empresa de Scribd logo
1 de 44
Device Fragmentation

Clean Code
Iordanis “Jordan” Giannakakis
@iordanis_g
#fragVsCode
Introduction
•
•
•
•

Iordanis “Jordan” Giannakakis
Android Team Lead – Shazam
@iordanis_g
#fragVsCode

@iordanis_g #fragVsCode
How Shazam works

@iordanis_g #fragVsCode
Bad vs. good code

@iordanis_g #fragVsCode
How is fragmentation related to
clean code?

@iordanis_g #fragVsCode
Is fragmentation really a problem?

android.support
@iordanis_g #fragVsCode
Is fragmentation really a problem?

@iordanis_g #fragVsCode
Is clean code really a concern?

@iordanis_g #fragVsCode
Is clean code really a concern?

A couple of months later...
@iordanis_g #fragVsCode
SharedPreferences.Editor

• commit() – slow
• apply() – fast

@iordanis_g #fragVsCode
API example – MainActivity
protected void onResume() {
super.onResume();
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
prefEditor.putBoolean("has_launched_before", true);
// Will only be available for versions after Froyo
if(VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
editor.apply();
} else {
editor.commit();
}
}

@iordanis_g #fragVsCode
Fixed it!

@iordanis_g #fragVsCode
What are the issues?
protected void onResume() {
super.onResume();
SharedPreferences sharedPreferences =
Glue
PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPreferences.edit();
Business
prefEditor.putBoolean("has_launched_before", true);

Logic

// Will only be available for versions after Froyo
if(VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
editor.apply();
} else {
editor.commit();
}

Glue

}

@iordanis_g #fragVsCode
How to unit test?

Good luck!

@iordanis_g #fragVsCode
Dependency Injection

@iordanis_g #fragVsCode
Dependency Injection Framework

@iordanis_g #fragVsCode
New MainActivity

@Override
public void onResume() {
super.onResume();

editor.putBoolean("has_launched_before", true);
preferencesSaver.save(editor);
}

@iordanis_g #fragVsCode
Before & After
protected void onResume() {
super.onResume();
SharedPreferences sharedPreferences =
PreferenceManager
.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor =
sharedPreferences.edit();
prefEditor.putBoolean(
"has_launched_before", true);
// Will only be available for versions
after Froyo
if(VERSION.SDK_INT >=
VERSION_CODES.GINGERBREAD) {
editor.apply();
} else {
editor.commit();
}
}

public void onResume() {
super.onResume();
editor.putBoolean(
"has_launched_before", true);
preferencesSaver.save(editor);
}

@iordanis_g #fragVsCode
New MainActivity – Constructors

// Constructor the system will call to instantiate this activity
public MainActivity() {
this(sharedPreferencesEditor(), preferencesSaver());
}

// Constructor that can be used in production and test code
public MainActivity(Editor editor, PreferencesSaver preferencesSaver) {
this.editor = editor;
this.preferencesSaver = preferencesSaver;
}

@iordanis_g #fragVsCode
Module classes
public class SharedPreferencesEditorModule {
public static SharedPreferences.Editor sharedPreferencesEditor() {
Context context = getApplication().getApplicationContext();
SharedPreferences preferences = getDefaultSharedPreferences(context);
Editor editor = preferences.edit();
return editor;
}
}
public class PreferencesSaverModule {
public static PreferencesSaver preferencesSaver() {
if(VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {

return new ApplyPreferencesSaver();
}
return new CommitPreferencesSaver();
}
}

@iordanis_g #fragVsCode
Application
public class MyCoolApplication extends Application {
private static MyCoolApplication application;
@Override
public void onCreate() {
application = this;
}
public static MyCoolApplication getApplication() {
return application;
}

}

@iordanis_g #fragVsCode
How to unit test?
@Mock Editor editor;
@Mock PreferencesSaver saver;
@Test
public void canSaveLaunchFlag() {
mockery.checking(new Expectations() {{
atLeast(1).of(editor).putBoolean("has_launched_before", true);
oneOf(saver).save(editor);
}});
MainActivity activity = new MainActivity(editor, saver);
activity.onResume();
}

@iordanis_g #fragVsCode
Capabilities example – Google+

@iordanis_g #fragVsCode
Capabilities example
public void onCreate(Bundle savedInstanceState) {
// Set layout
View googlePlus = findViewById(R.id.google_plus);
try {
getPackageManager().getApplicationInfo("com.android.vending", 0);
googlePlus.setVisibility(VISIBLE);
} catch (PackageManager.NameNotFoundException e) {
googlePlus.setVisibility(GONE);
}
}

@iordanis_g #fragVsCode
MVP pattern

@iordanis_g #fragVsCode
The Model
public class GooglePlayAvailability {
private PackageManager packageManager;
public GooglePlayAvailability(PackageManager packageManager) {
this.packageManager = packageManager;
}
public boolean googlePlayIsAvailable() {
try {
packageManager.getApplicationInfo("com.android.vending", 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
}

@iordanis_g #fragVsCode
The View

public interface GooglePlusView {
public void showGooglePlus();

public void hideGooglePlus();
}

@iordanis_g #fragVsCode
Activity as View
public class MainActivity extends Activity implements GooglePlusView {
public void onCreate(Bundle savedInstanceState) {
//Set layout...
googlePlus = findViewById(R.id.google_plus);
//Injected googlePlusPresenter
googlePlusPresenter.setView(this);
googlePlusPresenter.present();

}
public void showGooglePlus() {
googlePlus.setVisibility(VISIBLE);
}
public void hideGooglePlus() {
googlePlus.setVisibility(GONE);
}
}

@iordanis_g #fragVsCode
The Presenter
public class GooglePlusPresenter {
private GooglePlayAvailability googlePlayAvailability;
private GooglePlusView googlePlusView;
public GooglePlusPresenter(GooglePlayAvailability availability) {
googlePlayAvailability = availability;
}

public void present() {
if (googlePlayAvailability.googlePlayIsAvailable()) {
googlePlusView.showGooglePlus();
} else {
googlePlusView.hideGooglePlus();
}
}
}

@iordanis_g #fragVsCode
How to unit test?
@Mock GooglePlayAvailability googlePlayAvailability;
@Mock GooglePlusView googlePlus;
private GooglePlusPresenter presenter;
@Test
public void hidesGooglePlusIfNotAvailable() {
mockery.checking(new Expectations() {{
allowing(googlePlayAvailability).googlePlayIsAvailable();
will(returnValue(false));
oneOf(googlePlus).hideGooglePlus();
}});

presenter.present();
}

@iordanis_g #fragVsCode
Device size diversity

@iordanis_g #fragVsCode
Device size diversity

@iordanis_g #fragVsCode
How about Acceptance Tests?

@iordanis_g #fragVsCode
How about Acceptance Tests?

public class ShazamTest extends
ActivityInstrumentationTestCase2<ActivityUnderTest> {
private static final int TIMEOUT = 5000;
private Solo solo;
protected void setUp() {
solo = new Solo(getInstrumentation());
}
}

@iordanis_g #fragVsCode
How about Acceptance Tests?
public void testCanShazamOnPhone() {
// Action
// User hits the big Shazam button
View shazamButton = solo.getView(R.id.big_button);
solo.clickOnView(shazamButton);
// Assertions
// Track details are showing on full screen
assertThat(solo.waitForCondition(titleShowsOnFullScreen(),
TIMEOUT), is(true));
}

@iordanis_g #fragVsCode
How about Acceptance Tests?
public void testShazamingOnTablet() {
// Action
// Hit small Shazam button and wait for animation to finish
final View shazamButton = solo.getView(R.id.small_button);
solo.clickOnView(shazamButton);
waitForAnimationToFinish();
// Assertions
// Track details are showing on side-panel
assertThat(solo.waitForCondition(titleShowsOnSidePanel(),
TIMEOUT), is(true));

}

@iordanis_g #fragVsCode
Fixed it!

@iordanis_g #fragVsCode
Test frameworks

GWEN

https://github.com/shazam/gwen

@iordanis_g #fragVsCode
New Acceptance Test
protected void setUp() {
solo = new Solo(getInstrumentation());
user = new User(solo);
}
public void testCanShowTrackAfterShazaming() {
when(user).shazams();
then(user).seesDetailsForTrack();
}

@iordanis_g #fragVsCode
User class
public class User implements Actor, Asserter {
private final Solo solo;
public void shazams() {
Action<Solo, Void> action;
if (isTablet()) {
action = new ShazamTabletButtonAction();
} else {
action = new ShazamPhoneButtonAction();
}
action.actOn(solo);
}
public void seesDetailsForTrack() {
Assertion<Solo> assertion;
if (isTablet()) {
assertion = new TabletDetailsAssertion();
} else {
assertion = new PhoneDetailsAssertion();
}
assertion.assertWith(solo);
}
}

@iordanis_g #fragVsCode
Actions
public class ShazamPhoneButtonAction implements Action<Solo, Void> {
public void actOn(Solo solo) {
View bigButton = solo.getView(R.id.big_button);
solo.clickOnView(bigButton);
}
}
public class ShazamTabletButtonAction implements Action<Solo, Void> {
public void actOn(Solo solo) {
View smallButton = solo.getView(R.id.small_button);
solo.clickOnView(smallButton);
}
}

@iordanis_g #fragVsCode
Assertions
public class PhoneDetailsAssertion implements Assertion<Solo>{
public void assertWith(Solo solo) {
assertThat(solo.waitForCondition(titleShowsOnFullScreen(),
TIMEOUT), is(true));
}
}

public class TabletDetailsAssertion implements Assertion<Solo> {
public void assertWith(Solo solo) {
waitForAnimationToFinish();
assertThat(solo.waitForCondition(titleShowsOnSidePanel(),
TIMEOUT), is(true));
}
}

@iordanis_g #fragVsCode
Fixed it!

@iordanis_g #fragVsCode
Hiring...

Questions?
@iordanis_g
#fragVsCode
github.com/iordanis/androidCleanCode

Más contenido relacionado

La actualidad más candente

Testable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVMTestable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVMFabio Collini
 
Android UI Testing with Espresso
Android UI Testing with EspressoAndroid UI Testing with Espresso
Android UI Testing with EspressoGary Cheng
 
Android testing
Android testingAndroid testing
Android testingBitbar
 
A guide to Android automated testing
A guide to Android automated testingA guide to Android automated testing
A guide to Android automated testingjotaemepereira
 
Android testing
Android testingAndroid testing
Android testingJinaTm
 

La actualidad más candente (7)

Testing on Android
Testing on AndroidTesting on Android
Testing on Android
 
Testable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVMTestable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVM
 
Android UI Testing with Espresso
Android UI Testing with EspressoAndroid UI Testing with Espresso
Android UI Testing with Espresso
 
Android testing
Android testingAndroid testing
Android testing
 
Clean Test
Clean TestClean Test
Clean Test
 
A guide to Android automated testing
A guide to Android automated testingA guide to Android automated testing
A guide to Android automated testing
 
Android testing
Android testingAndroid testing
Android testing
 

Similar a Device fragmentation vs clean code

Keeping 100m+ users happy: How we test Shazam on Android
Keeping 100m+ users happy: How we test Shazam on AndroidKeeping 100m+ users happy: How we test Shazam on Android
Keeping 100m+ users happy: How we test Shazam on AndroidIordanis (Jordan) Giannakakis
 
How to build rock solid apps and keep 100m+ users happy
How to build rock solid apps and keep 100m+ users happyHow to build rock solid apps and keep 100m+ users happy
How to build rock solid apps and keep 100m+ users happyIordanis (Jordan) Giannakakis
 
Android the Agile way
Android the Agile wayAndroid the Agile way
Android the Agile wayAshwin Raghav
 
Android Wear 2.0 - New Level of Freedom for Your Action - GDG CEE Leads Summi...
Android Wear 2.0 - New Level of Freedom for Your Action - GDG CEE Leads Summi...Android Wear 2.0 - New Level of Freedom for Your Action - GDG CEE Leads Summi...
Android Wear 2.0 - New Level of Freedom for Your Action - GDG CEE Leads Summi...Constantine Mars
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code lessAnton Novikau
 
Code to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern ApplicationsCode to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern ApplicationsCaleb Jenkins
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesMichael Galpin
 
From Idea to App (or “How we roll at Small Town Heroes”)
From Idea to App (or “How we roll at Small Town Heroes”)From Idea to App (or “How we roll at Small Town Heroes”)
From Idea to App (or “How we roll at Small Town Heroes”)Bramus Van Damme
 
STYLISH FLOOR
STYLISH FLOORSTYLISH FLOOR
STYLISH FLOORABU HASAN
 
Hacking the Codename One Source Code - Part IV - Transcript.pdf
Hacking the Codename One Source Code - Part IV - Transcript.pdfHacking the Codename One Source Code - Part IV - Transcript.pdf
Hacking the Codename One Source Code - Part IV - Transcript.pdfShaiAlmog1
 
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArt
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArtArchitecture components, Константин Марс, TeamLead, Senior Developer, DataArt
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArtAlina Vilk
 
Building a Native Camera Access Library - Part II - Transcript.pdf
Building a Native Camera Access Library - Part II - Transcript.pdfBuilding a Native Camera Access Library - Part II - Transcript.pdf
Building a Native Camera Access Library - Part II - Transcript.pdfShaiAlmog1
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahNick Plante
 
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...Bruno Salvatore Belluccia
 
Alexey Buzdin "Maslow's Pyramid of Android Testing"
Alexey Buzdin "Maslow's Pyramid of Android Testing"Alexey Buzdin "Maslow's Pyramid of Android Testing"
Alexey Buzdin "Maslow's Pyramid of Android Testing"IT Event
 
Customizing Xamarin.Forms UI
Customizing Xamarin.Forms UICustomizing Xamarin.Forms UI
Customizing Xamarin.Forms UIXamarin
 
Refactoring Wunderlist. UA Mobile 2016.
Refactoring Wunderlist. UA Mobile 2016.Refactoring Wunderlist. UA Mobile 2016.
Refactoring Wunderlist. UA Mobile 2016.UA Mobile
 
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)Alina Vilk
 

Similar a Device fragmentation vs clean code (20)

Keeping 100m+ users happy: How we test Shazam on Android
Keeping 100m+ users happy: How we test Shazam on AndroidKeeping 100m+ users happy: How we test Shazam on Android
Keeping 100m+ users happy: How we test Shazam on Android
 
How to build rock solid apps and keep 100m+ users happy
How to build rock solid apps and keep 100m+ users happyHow to build rock solid apps and keep 100m+ users happy
How to build rock solid apps and keep 100m+ users happy
 
Android the Agile way
Android the Agile wayAndroid the Agile way
Android the Agile way
 
Android Wear 2.0 - New Level of Freedom for Your Action - GDG CEE Leads Summi...
Android Wear 2.0 - New Level of Freedom for Your Action - GDG CEE Leads Summi...Android Wear 2.0 - New Level of Freedom for Your Action - GDG CEE Leads Summi...
Android Wear 2.0 - New Level of Freedom for Your Action - GDG CEE Leads Summi...
 
How to code to code less
How to code to code lessHow to code to code less
How to code to code less
 
Ruby conf2012
Ruby conf2012Ruby conf2012
Ruby conf2012
 
Code to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern ApplicationsCode to DI For - Dependency Injection for Modern Applications
Code to DI For - Dependency Injection for Modern Applications
 
Design Patterns for Tablets and Smartphones
Design Patterns for Tablets and SmartphonesDesign Patterns for Tablets and Smartphones
Design Patterns for Tablets and Smartphones
 
From Idea to App (or “How we roll at Small Town Heroes”)
From Idea to App (or “How we roll at Small Town Heroes”)From Idea to App (or “How we roll at Small Town Heroes”)
From Idea to App (or “How we roll at Small Town Heroes”)
 
STYLISH FLOOR
STYLISH FLOORSTYLISH FLOOR
STYLISH FLOOR
 
Hacking the Codename One Source Code - Part IV - Transcript.pdf
Hacking the Codename One Source Code - Part IV - Transcript.pdfHacking the Codename One Source Code - Part IV - Transcript.pdf
Hacking the Codename One Source Code - Part IV - Transcript.pdf
 
Mini curso Android
Mini curso AndroidMini curso Android
Mini curso Android
 
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArt
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArtArchitecture components, Константин Марс, TeamLead, Senior Developer, DataArt
Architecture components, Константин Марс, TeamLead, Senior Developer, DataArt
 
Building a Native Camera Access Library - Part II - Transcript.pdf
Building a Native Camera Access Library - Part II - Transcript.pdfBuilding a Native Camera Access Library - Part II - Transcript.pdf
Building a Native Camera Access Library - Part II - Transcript.pdf
 
Building native Android applications with Mirah and Pindah
Building native Android applications with Mirah and PindahBuilding native Android applications with Mirah and Pindah
Building native Android applications with Mirah and Pindah
 
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
GDG Mediterranean Dev Fest Code lab #DevFestMed15 da android ad android wear ...
 
Alexey Buzdin "Maslow's Pyramid of Android Testing"
Alexey Buzdin "Maslow's Pyramid of Android Testing"Alexey Buzdin "Maslow's Pyramid of Android Testing"
Alexey Buzdin "Maslow's Pyramid of Android Testing"
 
Customizing Xamarin.Forms UI
Customizing Xamarin.Forms UICustomizing Xamarin.Forms UI
Customizing Xamarin.Forms UI
 
Refactoring Wunderlist. UA Mobile 2016.
Refactoring Wunderlist. UA Mobile 2016.Refactoring Wunderlist. UA Mobile 2016.
Refactoring Wunderlist. UA Mobile 2016.
 
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
Встреча Google Post IO ( Владимир Иванов, Катерина Заворотченко и Сергей Комлач)
 

Último

Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 

Último (20)

Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 

Device fragmentation vs clean code

  • 1. Device Fragmentation Clean Code Iordanis “Jordan” Giannakakis @iordanis_g #fragVsCode
  • 2. Introduction • • • • Iordanis “Jordan” Giannakakis Android Team Lead – Shazam @iordanis_g #fragVsCode @iordanis_g #fragVsCode
  • 4. Bad vs. good code @iordanis_g #fragVsCode
  • 5. How is fragmentation related to clean code? @iordanis_g #fragVsCode
  • 6. Is fragmentation really a problem? android.support @iordanis_g #fragVsCode
  • 7. Is fragmentation really a problem? @iordanis_g #fragVsCode
  • 8. Is clean code really a concern? @iordanis_g #fragVsCode
  • 9. Is clean code really a concern? A couple of months later... @iordanis_g #fragVsCode
  • 10. SharedPreferences.Editor • commit() – slow • apply() – fast @iordanis_g #fragVsCode
  • 11. API example – MainActivity protected void onResume() { super.onResume(); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = sharedPreferences.edit(); prefEditor.putBoolean("has_launched_before", true); // Will only be available for versions after Froyo if(VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { editor.apply(); } else { editor.commit(); } } @iordanis_g #fragVsCode
  • 13. What are the issues? protected void onResume() { super.onResume(); SharedPreferences sharedPreferences = Glue PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = sharedPreferences.edit(); Business prefEditor.putBoolean("has_launched_before", true); Logic // Will only be available for versions after Froyo if(VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { editor.apply(); } else { editor.commit(); } Glue } @iordanis_g #fragVsCode
  • 14. How to unit test? Good luck! @iordanis_g #fragVsCode
  • 17. New MainActivity @Override public void onResume() { super.onResume(); editor.putBoolean("has_launched_before", true); preferencesSaver.save(editor); } @iordanis_g #fragVsCode
  • 18. Before & After protected void onResume() { super.onResume(); SharedPreferences sharedPreferences = PreferenceManager .getDefaultSharedPreferences(this); SharedPreferences.Editor editor = sharedPreferences.edit(); prefEditor.putBoolean( "has_launched_before", true); // Will only be available for versions after Froyo if(VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { editor.apply(); } else { editor.commit(); } } public void onResume() { super.onResume(); editor.putBoolean( "has_launched_before", true); preferencesSaver.save(editor); } @iordanis_g #fragVsCode
  • 19. New MainActivity – Constructors // Constructor the system will call to instantiate this activity public MainActivity() { this(sharedPreferencesEditor(), preferencesSaver()); } // Constructor that can be used in production and test code public MainActivity(Editor editor, PreferencesSaver preferencesSaver) { this.editor = editor; this.preferencesSaver = preferencesSaver; } @iordanis_g #fragVsCode
  • 20. Module classes public class SharedPreferencesEditorModule { public static SharedPreferences.Editor sharedPreferencesEditor() { Context context = getApplication().getApplicationContext(); SharedPreferences preferences = getDefaultSharedPreferences(context); Editor editor = preferences.edit(); return editor; } } public class PreferencesSaverModule { public static PreferencesSaver preferencesSaver() { if(VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) { return new ApplyPreferencesSaver(); } return new CommitPreferencesSaver(); } } @iordanis_g #fragVsCode
  • 21. Application public class MyCoolApplication extends Application { private static MyCoolApplication application; @Override public void onCreate() { application = this; } public static MyCoolApplication getApplication() { return application; } } @iordanis_g #fragVsCode
  • 22. How to unit test? @Mock Editor editor; @Mock PreferencesSaver saver; @Test public void canSaveLaunchFlag() { mockery.checking(new Expectations() {{ atLeast(1).of(editor).putBoolean("has_launched_before", true); oneOf(saver).save(editor); }}); MainActivity activity = new MainActivity(editor, saver); activity.onResume(); } @iordanis_g #fragVsCode
  • 23. Capabilities example – Google+ @iordanis_g #fragVsCode
  • 24. Capabilities example public void onCreate(Bundle savedInstanceState) { // Set layout View googlePlus = findViewById(R.id.google_plus); try { getPackageManager().getApplicationInfo("com.android.vending", 0); googlePlus.setVisibility(VISIBLE); } catch (PackageManager.NameNotFoundException e) { googlePlus.setVisibility(GONE); } } @iordanis_g #fragVsCode
  • 26. The Model public class GooglePlayAvailability { private PackageManager packageManager; public GooglePlayAvailability(PackageManager packageManager) { this.packageManager = packageManager; } public boolean googlePlayIsAvailable() { try { packageManager.getApplicationInfo("com.android.vending", 0); return true; } catch (PackageManager.NameNotFoundException e) { return false; } } } @iordanis_g #fragVsCode
  • 27. The View public interface GooglePlusView { public void showGooglePlus(); public void hideGooglePlus(); } @iordanis_g #fragVsCode
  • 28. Activity as View public class MainActivity extends Activity implements GooglePlusView { public void onCreate(Bundle savedInstanceState) { //Set layout... googlePlus = findViewById(R.id.google_plus); //Injected googlePlusPresenter googlePlusPresenter.setView(this); googlePlusPresenter.present(); } public void showGooglePlus() { googlePlus.setVisibility(VISIBLE); } public void hideGooglePlus() { googlePlus.setVisibility(GONE); } } @iordanis_g #fragVsCode
  • 29. The Presenter public class GooglePlusPresenter { private GooglePlayAvailability googlePlayAvailability; private GooglePlusView googlePlusView; public GooglePlusPresenter(GooglePlayAvailability availability) { googlePlayAvailability = availability; } public void present() { if (googlePlayAvailability.googlePlayIsAvailable()) { googlePlusView.showGooglePlus(); } else { googlePlusView.hideGooglePlus(); } } } @iordanis_g #fragVsCode
  • 30. How to unit test? @Mock GooglePlayAvailability googlePlayAvailability; @Mock GooglePlusView googlePlus; private GooglePlusPresenter presenter; @Test public void hidesGooglePlusIfNotAvailable() { mockery.checking(new Expectations() {{ allowing(googlePlayAvailability).googlePlayIsAvailable(); will(returnValue(false)); oneOf(googlePlus).hideGooglePlus(); }}); presenter.present(); } @iordanis_g #fragVsCode
  • 33. How about Acceptance Tests? @iordanis_g #fragVsCode
  • 34. How about Acceptance Tests? public class ShazamTest extends ActivityInstrumentationTestCase2<ActivityUnderTest> { private static final int TIMEOUT = 5000; private Solo solo; protected void setUp() { solo = new Solo(getInstrumentation()); } } @iordanis_g #fragVsCode
  • 35. How about Acceptance Tests? public void testCanShazamOnPhone() { // Action // User hits the big Shazam button View shazamButton = solo.getView(R.id.big_button); solo.clickOnView(shazamButton); // Assertions // Track details are showing on full screen assertThat(solo.waitForCondition(titleShowsOnFullScreen(), TIMEOUT), is(true)); } @iordanis_g #fragVsCode
  • 36. How about Acceptance Tests? public void testShazamingOnTablet() { // Action // Hit small Shazam button and wait for animation to finish final View shazamButton = solo.getView(R.id.small_button); solo.clickOnView(shazamButton); waitForAnimationToFinish(); // Assertions // Track details are showing on side-panel assertThat(solo.waitForCondition(titleShowsOnSidePanel(), TIMEOUT), is(true)); } @iordanis_g #fragVsCode
  • 39. New Acceptance Test protected void setUp() { solo = new Solo(getInstrumentation()); user = new User(solo); } public void testCanShowTrackAfterShazaming() { when(user).shazams(); then(user).seesDetailsForTrack(); } @iordanis_g #fragVsCode
  • 40. User class public class User implements Actor, Asserter { private final Solo solo; public void shazams() { Action<Solo, Void> action; if (isTablet()) { action = new ShazamTabletButtonAction(); } else { action = new ShazamPhoneButtonAction(); } action.actOn(solo); } public void seesDetailsForTrack() { Assertion<Solo> assertion; if (isTablet()) { assertion = new TabletDetailsAssertion(); } else { assertion = new PhoneDetailsAssertion(); } assertion.assertWith(solo); } } @iordanis_g #fragVsCode
  • 41. Actions public class ShazamPhoneButtonAction implements Action<Solo, Void> { public void actOn(Solo solo) { View bigButton = solo.getView(R.id.big_button); solo.clickOnView(bigButton); } } public class ShazamTabletButtonAction implements Action<Solo, Void> { public void actOn(Solo solo) { View smallButton = solo.getView(R.id.small_button); solo.clickOnView(smallButton); } } @iordanis_g #fragVsCode
  • 42. Assertions public class PhoneDetailsAssertion implements Assertion<Solo>{ public void assertWith(Solo solo) { assertThat(solo.waitForCondition(titleShowsOnFullScreen(), TIMEOUT), is(true)); } } public class TabletDetailsAssertion implements Assertion<Solo> { public void assertWith(Solo solo) { waitForAnimationToFinish(); assertThat(solo.waitForCondition(titleShowsOnSidePanel(), TIMEOUT), is(true)); } } @iordanis_g #fragVsCode