Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Qualidade de código Android

Rafael Araujo
September 16, 2017

Qualidade de código Android

Talk apresentado no Quality Fest 2017 organizado pelo GDG Campinas.

Rafael Araujo

September 16, 2017
Tweet

More Decks by Rafael Araujo

Other Decks in Technology

Transcript

  1. O que será apresentado Técnicas Análise de padrão de código

    Análise de código Análise de projeto Android Integração continua 3
  2. Pair programming #tecnicas Dois desenvolvedores trabalhando na mesma tarefa Ambos

    com o mesmo objetivo Ambos com diferente conhecimento Um executa a tarefa (driver) O outro observa e ajuda de uma forma mais macro (navigator) 5
  3. Vale a pena fazer pair programming? #tecnicas Dois desenvolvedores fazendo

    o trabalho de um desenvolvedor Um desenvolvedor Junior irá diminuir a velocidade do desenvolvedor Sênior Menos trabalho pronto ao mesmo tempo Porque colocar dois desenvolvedores fazendo o trabalho de um? 8
  4. Ganhos do pair programming #tecnicas Minimizar falhas de código e

    de fluxo Manutenibilidade Confiança do código Amadurecimento mútuo Compartilhar conhecimento Aumento de atenção/concentração 9
  5. Code review #tecnicas Um ou mais membros da equipe devem

    aprovar o código gerado Feito através de ferramentas Previne adicionar bugs Disseminar conhecimento entre a equipe Garantir código legível para todos Garantir código familiarizado para todos 15
  6. Como funciona code review #tecnicas Código em review Código aprovado

    Código integrado Código gerado Comentário em review 17
  7. Code review no Gerrit #tecnicas 0 -1 +1 +2 Não

    está OK. Por favor, olhe meus comentários Código enviado. Por favor, revisem Está OK, mas prefiro que mais alguém confirme Está OK, aprovado! 18
  8. Quebrar métodos para melhor leitura #tecnicas private void findJonSnow(List<Person> persons)

    { for (Person person : persons) { if (person.getHouse().getName().equals("Stark")) { if (person.isAlive()) { if (person.getName().equals("Jon Snow")) { Log.i(TAG, "Jon Snow was founded!"); } } } } } 21
  9. Comentários mais compreensiveis #tecnicas private boolean isAlive(Person person) { //

    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do // eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim // ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut // aliquip ex ea commodo consequat. Duis aute irure dolor in // reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla // pariatur. Excepteur sint occaecat cupidatat non proident, sunt in // culpa qui officia deserunt mollit anim id est laborum return person.isAlive(); } 22
  10. JavaDoc auto-explicativo #tecnicas /** * Returns if the person is

    alive. * * @param person Person to check if is alive. * @return <code>true</code> if is alive. <code>false</code> otherwise. */ private boolean isAlive(Person person) { return person.isAlive(); } 23
  11. Soluções melhores #tecnicas int countPersons(List<Person> persons) { int counter =

    0; for (Person person : persons) { counter++; } return counter; } int countPersons(List<Person> persons) { return persons.size(); } 24
  12. Android Studio + Gradle Organizar arquivos de configuração de ferramentas

    Garantir sempre o uso das ferramentas Gradle e amigos 28
  13. project/ ├── app/ (módulo app do projeto) │ └── src/

    │ └── build.gradle (gradle do módulo) │ └── ... ├── build.gradle (gradle do projeto) ├── ... 29
  14. project/ ├── app/ │ └── src/ │ └── build.gradle │

    └── ... ├── config/ (Pasta de configuração) │ └── quality/ (Pasta de configuração) │ └── quality.gradle (gradle da qualidade) ├── build.gradle ├── ... 30
  15. #ferramentas Manter padrão estético do código Deixar a equipe confortável

    com o código O código é da equipe Valida se o código mantem o padrão Java​ Plugin está no Android Studio, porém desabilitado 32
  16. apply from: "../config/quality/checkstyle.gradle" config/ ├── quality/ │ └── checkstyle/ │

    └── checkstyle.xml │ └── checkstyle.gradle ├── quality.gradle #ferramentas 40
  17. apply plugin: 'checkstyle' checkstyle { configFile file("${rootDir}/config/quality/checkstyle/checkstyle.xml") toolVersion = "8.2"

    } task checkstyle(type: Checkstyle) { source 'src/main/java' include '**/*.java' classpath = project.configurations.compile } check.dependsOn 'checkstyle' #ferramentas 41
  18. <!DOCTYPE ...> ​ <module name="Checker"> <module name="NewlineAtEndOfFile"> <property name="severity" value="ignore"/>

    </module> <module name="JavadocMethod"> <property name="scope" value="package"/> <property name="allowMissingParamTags" value="true"/> <property name="allowMissingThrowsTags" value="true"/> </module> </module> #ferramentas 42
  19. #ferramentas public void allAlive(List<Person > pers) { for (Person person

    : pers) if (person.isAlive()) { Log.i(TAG, "Person is alive!"); } else { } } 43
  20. #ferramentas public void allAlive(List<Person > pers) { for (Person person

    : pers) if (person.isAlive()) { Log.i(TAG, "Person is alive!"); } else { } } 46
  21. #ferramentas public void allAlive(List<Person > pers) { for (Person person

    : pers) if (person.isAlive()) { Log.i(TAG, "Person is alive!"); } else { } } /** * Print if anyone is alive. */ public void allAlive(List<Person> pers) { for (Person person : pers) { if (person.isAlive()) { Log.i(TAG, "Person is alive!"); } } } 47
  22. #ferramentas “Pretty Much Done” ou “Project Meets Deadline” Inspeciona o

    código escrito procurando possíveis bugs Código desnecessário, com muita complexidade ou confuso, tamanho de declarações​ , mal uso de memória e processamento, etc Plugin está no Android Studio, porém desabilitado 51
  23. apply from: "../config/quality/checkstyle.gradle" apply from: "../config/quality/pmd.gradle" config/ ├── quality/ │

    └── checkstyle/ │ └── checkstyle.xml │ └── checkstyle.gradle │ └── pmd/ │ └── pmd-ruleset.xml │ └── pmd.gradle ├── quality.gradle #ferramentas 52
  24. #ferramentas apply plugin: 'pmd' task pmd(type: Pmd) { ignoreFailures =

    false ruleSetFiles = files("${project.rootDir}/config/quality/pmd/pmd-ruleset.xml") ruleSets = [] source 'src' include '**/*.java' exclude '**/gen/**' reports { html.enabled = true html { destination "${project.buildDir}/reports/pmd/pmd.html" } } } check.dependsOn 'pmd' 53
  25. <ruleset ...> <exclude-pattern>.*/R.java</exclude-pattern> <exclude-pattern>.*/gen/.*</exclude-pattern> <rule ref="rulesets/java/android.xml"/> <rule ref="rulesets/java/controversial.xml"> <exclude name="AtLeastOneConstructor"/>

    </rule> <rule ref="rulesets/java/braces.xml"/> <rule ref="rulesets/java/strings.xml"/> <rule ref="rulesets/java/basic.xml"/> <rule ref="rulesets/java/naming.xml"/> </ruleset> #ferramentas 54
  26. #ferramentas private boolean isMelisandre(Person p) { Boolean result = new

    Boolean(false); String melisandre = new String("Melisandre"); if (p.getName().equals(melisandre.toString())) { result = true; } return result; } 55
  27. #ferramentas private boolean isMelisandre(Person p) { Boolean result = new

    Boolean(false); String melisandre = new String("Melisandre"); if (p.getName().equals(melisandre.toString())) { result = true; } return result; } 58
  28. #ferramentas private boolean isMelisandre(Person person) { Boolean result = Boolean.FALSE;

    String melisandre = "Melisandre"; if (person.getName().equals(melisandre)) { result = true; } return result; } private boolean isMelisandre(Person p) { Boolean result = new Boolean(false); String melisandre = new String("Melisandre"); if (p.getName().equals(melisandre.toString())) { result = true; } return result; } 59
  29. #ferramentas Similar ao PMD, porém atua direto no bytecode Além

    de bugs busca potenciais problemas de segurança Plugin está no Android Studio, porém desabilitado 62
  30. apply from: "../config/quality/checkstyle.gradle" apply from: "../config/quality/findbugs.gradle" apply from: "../config/quality/pmd.gradle" #ferramentas

    config/ ├── quality/ │ └── checkstyle/ │ └── checkstyle.xml │ └── checkstyle.gradle │ └── pmd/ │ └── pmd-ruleset.xml │ └── pmd.gradle │ └── findbugs/ │ └── findbugs-filter.xml │ └── findbugs.gradle ├── quality.gradle 63
  31. apply plugin: 'findbugs' task findbugs(type: FindBugs, dependsOn: "assembleDebug") { ignoreFailures

    = false effort = "max" reportLevel = "low" excludeFilter = new File("${project.rootDir}/config/quality/findbugs/findbugs-filter.xml") classes = files("${project.rootDir}/app/build/intermediates/classes") source 'src' include '**/*.java' exclude '**/gen/**' reports { html.enabled = true html { destination "${project.buildDir}/reports/findbugs/findbugs.html" } } classpath = files() } check.dependsOn 'findbugs' #ferramentas 64
  32. <?xml version="1.0" encoding="UTF-8"?> <FindBugsFilter> <Match> <Class name="~.*\.R\$.*"/> </Match> <Match> <Class

    name="~.*\.Manifest\$.*"/> </Match> <!-- All bugs in test, except for JUnit-specific bugs --> <Match> <Class name="~.*\.*Test"/> <Not> <Bug code="IJU"/> </Not> </Match> </FindBugsFilter> #ferramentas 65
  33. #ferramentas private void persons() { Person arya = new Person("Arya

    Stark"); Person jaqen = new Person("Jaqen H'ghar"); whoAreYou(arya); whoAreYou(null); } private void whoAreYou(Person person) { Log.d(TAG, "Who are you?" + person.getName()); } private void isNoOne(Person person) { } 66
  34. #ferramentas private void persons() { Person arya = new Person("Arya

    Stark"); Person jaqen = new Person("Jaqen H'ghar"); whoAreYou(arya); whoAreYou(null); } private void whoAreYou(Person person) { Log.d(TAG, "Who are you?" + person.getName()); } private void isNoOne(Person person) { } 71
  35. #ferramentas private void persons() { Person arya = new Person("Arya

    Stark"); Person jaqen = new Person("Jaqen H'ghar"); whoAreYou(arya); whoAreYou(null); } private void whoAreYou(Person person) { Log.d(TAG, "Who are you?" + person.getName()); } private void isNoOne(Person person) { } private void persons() { Person arya = new Person("Arya Stark"); Person jaqen = new Person("Jaqen H'ghar"); whoAreYou(arya); whoAreYou(jaqen); } private void whoAreYou(Person person) { Log.d(TAG, "Who are you?" + person.getName()); } 72
  36. #ferramentas Analisa todo o projeto, não só o código Possíveis

    bugs, resources não utilizados, segurança e performance Checagens tem prioridade, gravidade e categoria Plugin está no Android Studio, porém desabilitado Lint 76
  37. #ferramentas config/ ├── quality/ │ └── checkstyle/ │ └── pmd/

    │ └── findbugs/ │ └── lint/ │ └── lint.xml │ └── checkstyle.gradle │ └── findbugs.gradle │ └── lint.gradle │ └── pmd.gradle ├── quality.gradle Lint 77
  38. android { compileSdkVersion 26 buildToolsVersion "26.0.1" defaultConfig { ... }

    lintOptions { apply from: "${rootDir}/config/quality/lint.gradle", to: it lintConfig file("${project.rootDir}/config/quality/lint/lint.xml") htmlOutput file("${project.buildDir}/reports/lint/lint-result.html") xmlOutput file("${project.buildDir}/reports/lint/lint-result.xml") } } #ferramentas Lint 78
  39. #ferramentas Lint @SuppressLint("NewApi") private void isNull(String name) { Objects.requireNonNull(name, "Name

    is null"); } <EditText android:id="@+id/main_user_password" android:layout_width="match_parent" android:layout_height="match_parent" tools:ignore="TextFields"/> 90
  40. #ferramentas Roda Checkstyle Roda PMD Roda FindBugs Roda Lint Roda

    Testes Unitários Code Review Código gerado Código integrado 96