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

Multiple Developers, One App: How to Not Break Everything

E0ac1256093c733a5d5a26085b90966f?s=47 Andy Dyer
October 22, 2016

Multiple Developers, One App: How to Not Break Everything

Most of us started developing mobile apps individually and many work professionally as the lone Android engineer on an app. But as the saying goes, “If you want to go fast, go alone. If you want to go far, go together.”

In this talk, we’ll explore what it takes to share a large mobile app codebase with a team of developers without breaking everything. From laying a solid foundation, to ensuring code quality, and automating things nobody wants to do, we’ll learn how to manage the increasing complexity of today’s Android apps as a team.


Andy Dyer

October 22, 2016


  1. Mul$ple Developers, One App How to Not Break Everything by

    Andy Dyer #babbq16
  2. #babbq16

  3. #babbq16

  4. #babbq16

  5. #babbq16

  6. #babbq16

  7. How to Not Break Everything • Laying the founda/on •

    Ensuring code quality • Automa5ng things no one wants to do #babbq16
  8. Laying the Founda/on - Organiza/on • Ver%cal, feature focused teams

    • Agile Stuff™ • Weekly pla<orm team Hangout • Lots of chat and ad hoc screen share sessions #babbq16
  9. Laying the Founda/on - Project Structure • Separate repos for

    core business logic and apps • Package per feature • Feature flags to enable/disable func9onality #babbq16
  10. Laying the Founda/on - Build Types productFlavors { alpha {

    // Upload to Crashlytics for QA testers } beta { // Upload to Crashlytics for beta testers } prod { // Release to Google Play } } #babbq16
  11. How to Not Break Everything • Laying the founda0on •

    Ensuring code quality • Automa0ng things no one wants to do #babbq16
  12. Ensuring Code Quality - Common Style #babbq16

  13. Ensuring Code Quality - Code Reviews • Pull requests with

    at least one reviewer before being merged into develop branch • Mul9ple reviewers for significant changes #babbq16
  14. Ensuring Code Quality - Automated Tes6ng • Architect for tes-ng

    • Dependency injec-on to group & isolate related components • MVP or similar pa=ern • Unit test as much as possible, Espresso for UI tests • Con-nuous integra-on server for building latest source and running tests #babbq16
  15. Ensuring Code Quality - Alpha & Beta Tes9ng • QA

    team runs automated integra1on tests and performs targeted manual tests as necessary • Beta testers help iden1fy any cri1cal bugs prior to release • Staged rollout on Google Play for final release #babbq16
  16. git rebase develop Early and o*en #babbq16

  17. How to Not Break Everything • Laying the founda0on •

    Ensuring code quality • Automa'ng things no one wants to do #babbq16
  18. Automa'ng Things No One Wants to Do - Git Hooks

    • Ensure code compiles before each commit • Ensure unit and instrumenta5on tests pass before each push #babbq16
  19. Automa'ng Things No One Wants to Do - GitHub Hooks

    • Change Jira ,cket status to "Next Build" when pull request is merged • No,fy chat room when a pull request is opened, merged, etc. #babbq16
  20. Automa'ng Things No One Wants to Do - Gruel Plugin

    • No$fy a HipChat channel with a specific message • Transi$on Jira issues matching a JQL filter to another status and update fields • Increment version numbers in a gradle.proper$es file • Specify a naming paDern for *.jar and *.apk files • Upload an *.apk file to Crashly$cs #babbq16
  21. Gruel Plugin - No.fy HipChat hipchat { auth_token = '{AUTH

    TOKEN}' } task notifyHipchat( type: com.glasstowerstudios.gruel.tasks.hipchat.HipChatNotificationTask) { // Can be one of: ['purple', 'red', 'green', 'yellow', 'gray', 'random'] color = 'yellow' message = "Your message here. You can include simple html" channelName = "Name of channel to notify" } #babbq16
  22. Gruel Plugin - Transi/on Jira Issues task jiraUpdate( type: com.glasstowerstudios.gruel.tasks.jira.JiraTransitionTask)

    { userName = JIRA_USERNAME password = JIRA_PASSWORD jiraRootUrl = 'https://COMPANY.atlassian.net' jql = 'project = "PROJECT_NAME" AND status = "CURRENT_STATUS"' toStatus = 'NEW_STATUS' fieldUpdates = ['customfield_123': 'Updating a custom field', 'customfield_456': 'Updating another custom field'] } #babbq16
  23. Gruel Plugin - Increment Version // Specifies an integer that

    is monotonically increasing with each // new version. PROJECTNAME_VERSION_CODE // Specifies a human-readable string that is used to represent a // version number to users (e.g. "3.0.0"). PROJECTNAME_VERSION_NAME #babbq16
  24. Gruel Plugin - Naming APK Files apply plugin: 'gruel' gruel

    { archiveName "%appName%", "%version%", "%codeName", "%buildType%", "%commitHash%" version android.defaultConfig.versionName commitHash gitSha() } #babbq16
  25. Gruel Plugin - Crashly1cs Upload android { productFlavors { alpha

    { gruel.uploadUsing 'crashlytics', 'alpha-testers', 'release', delegate } } } #babbq16
  26. Links • Gruel Plugin: github.com/jwir3/gruel • Slides: andydyer.org • Twi2er:

    @dammitandy • Google Plus: +AndrewDyer #babbq16