GDG Firenze - 13 Febbraio 2014 Clean Android Code Fabio Collini
Nov 07, 2014
GDG Firenze - 13 Febbraio 2014
Clean Android CodeFabio Collini
@fabioCollini
linkedin.com/in/fabiocollini
Folder Organizer
Freapp
nana bianca
cosenonjaviste.it
Agenda
Definizione di Clean CodeFormattazione del codiceClean code vs optimizationBest practices JavaGestione delle risorse AndroidTest
"The only way to make the deadline -- the onlyway to go fast -- is to keep the code as clean as
possible at all times."Clean code - Robert C. Martin
Definizione di Clean CodeLeggibileManutenibileEspandibileEspressivoCorrettoTestabile...
Formattazione del codice
Eclipse
Android Studio / IntelliJ
Clean codeVs
optimization
android.view.Viewint mPrivateFlags;
//...
public void setIsRootNamespace(boolean isRoot) { if (isRoot) { mPrivateFlags |= IS_ROOT_NAMESPACE; } else { mPrivateFlags &= ~IS_ROOT_NAMESPACE; }}
public boolean isRootNamespace() { return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;}
Ottimizzazione del codice
la classe View è istanziata molte volte all'interno di ogniactivity di ogni appha senso ottimizzare l'occupazione di memoriama nel codice di una app?
Rules of Optimization:Rule 1: Don't do it.
Rule 2 (for experts only): Don't do it yet.Michael A. Jackson
Enum
storicamente su Android erano sconsigliatecon il JIT compiler la situazione è migliorata
Per evitare creazione di oggetti gli int sono molto usatiTutte le risorse sono int nella classe R
textView.setText(100);
Caused by: android.content.res.Resources$NotFoundException:String resource ID #0x64 at android.content.res.Resources.getText(Resources.java:239) at android.widget.TextView.setText(TextView.java:3844)
textView.setText(Integer.toString(100));
SimpleCursorTreeAdapterContextCursorintString[]int[]intString[]int[]
SimpleCursorTreeAdapter
new SimpleCursorTreeAdapter(this, groupCursor, android.R.layout.simple_expandable_list_item_2, new String[]{"Column1", "Column2"}, new int[]{android.R.id.text1, android.R.id.text2}, android.R.layout.simple_list_item_1, new String[]{"Column3", "Column4"}, new int[]{android.R.id.text1, android.R.id.text2}) { //...};
Usando classi/enumContextCursorLayoutColumn[]ViewId[]LayoutColumn[]ViewId[]
ContextCursorLayoutColumnMappingLayoutColumnMapping
on'tepeatourself
The first time you do something, you just do it.The second time you do something similar, you
wince at the duplication, but you do theduplicate thing anyway. The third time you do
something similar, you refactor.Martin Fowler
riteverythingwice
Coesionee
disaccoppiamento
Activity
classe base da usare per creare una interfaccia graficanei casi semplici contengono tuttopossono diventare molto grandi e difficili da gestire
Fragment
interfacce responsiveciclo di vita complicatoutili ma non semplici da usare
Custom View
classi che estendono una Viewpossono essere usate in un layoutusate per creare componenti nuoviutili anche per raggruppare codice
ButterKnife
injection delle view in una classebasato su annotation processingsemplice da usarerende il codice più leggibile
Flow e Mortar
framework sviluppati da Squarebasati su Daggersostitutivi ai fragment, semplificano il ciclo di vita
Risorse in un progetto Android
<resources> <style name="layoutStyle"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">match_parent</item> <item name="android:orientation">vertical</item> <item name="android:gravity">center</item> </style>
<style name="textViewColor"> <item name="android:textSize">150sp</item> <item name="android:textColor">#515151</item> <item name="android:layout_width">wrap_content</item> <item name="android:layout_height">wrap_content</item> </style></resources>
<resources> <style name="layoutStyle" parent="layoutStyleBase"> <item name="android:orientation">horizontal</item> </style></resources>
<resources> <color name="textColor">#515151</color></resources>
<resources> <dimen name="textSize">150sp</dimen></resources>
<resources> <dimen name="textSize">250sp</dimen></resources>
Include di layout
equivalente di un extract methodutile quando una piccola parte del layout cambia in basealla configurazione
Tipi di risorse disponibili
LayoutDrawableStiliStringAnimazioniColor
Color state listBooleanDimensionIdIntegerArray
Il codice Java dovrebbe essereindipendente dalle configurazioni
Test
Coperto da test Vs TestabileL'architettura dell'app è fondamentale per avere codicetestabile
DaggerA fast dependency injector for Android and Java
Dagger
Object: possono essere singletonModule: classi Java che creano ObjectObjectGraph: creato runtime a partireda più moduli
Scopepublic ObjectGraph plus(Object... modules) {
}
Permette di creare oggetti legati a scope:Application
ActivityFragment
Pro di Dagger
alto disaccoppiamento delle classivalidazione compile time delle dipendenzemoduli di test con stub e mock
EventBus
permette di usare una architettura basata su eventiusando il metodo post vengono invocati i metodionEvent degli oggetti che si sono registrati conregistersimile a Otto ma non basato su annotationgestisce anche i thread in background
Uso di EventBus
Gerarchia di eventi: listener su classi baseGli eventi possono essere ParcelableCiclo di vita Activity/cambio di orientation
Test su Android
JUnitRoboelectricRobotiumEspresso...
Test Driven Development
public void testCalculator() { assertEquals(4, calculator.sum(2, 2)); }
FEST Android
public void testUi() { assertThat(layout).isVisible() .isVertical() .hasChildCount(4) .hasShowDividers(SHOW_DIVIDERS_MIDDLE);}
Quello che servirebbe...
public void testUi() { assertEquals(layout, mockup);}
Test della ui
utili per creare il caso di testaggiungendo uno wait è possibile interagire con il deviceSpoon permette di eseguire i test su più device e salvarescreenshot
Java 8
in uscita a Marzolambda expression e molte altre novitàcambierà il modo di scrivere codice
RiferimentiRobert C. Martin - Clean code
Martin Fowler - Refactoring: Improving the Design ofExisting Code
Simpler Android apps with Flow and Mortargithub.com/JakeWharton/butterknife
github.com/square/daggergithub.com/greenrobot/EventBusgithub.com/square/fest-android
Thanks for your attention!
Questions?
@fabioCollini
linkedin.com/in/fabiocollini