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

Model-View-Presenter @ Scale

Model-View-Presenter @ Scale

Co-presented with Zach Westlake (https://twitter.com/zachwestlake, https://www.linkedin.com/in/zachwestlake/) at Android @ Scale (https://atscaleconference.com/events/android-scale-2018/)

The Pinterest Android app is worked on by over 30 client engineers spread across 7 different product subteams. While this isn’t a huge team, we were experiencing some growing pains due to a 5-year-old codebase and lack of consistent architecture. In order to move faster and promote app stability, the team began a long-term project to incrementally rewrite Pinterest in the Model-View-Presenter (MVP) architecture. In this talk, we’ll walk you through our journey thus far - our initial goals, implementation, and the challenges we faced in porting our app to MVP.

Sam Thompson

January 31, 2018
Tweet

Other Decks in Programming

Transcript

  1. Over Time Android Engineering 0 10 20 30 40 50

    2012 2013 2014 2015 2016 2017 3
  2. 0 10 20 30 40 50 2012 2013 2014 2015

    2016 2017 5 3 Over Time Android Engineering
  3. 0 10 20 30 40 50 2012 2013 2014 2015

    2016 2017 11 5 3 Over Time Android Engineering
  4. 0 10 20 30 40 50 2012 2013 2014 2015

    2016 2017 22 11 5 3 Over Time Android Engineering
  5. 0 10 20 30 40 50 2012 2013 2014 2015

    2016 2017 40 22 11 5 3 Over Time Android Engineering
  6. 0 10 20 30 40 50 2012 2013 2014 2015

    2016 2017 50 40 22 11 5 3 Over Time Android Engineering
  7. Git stats 2012 2013 2014 2015 2016 2017 0 1000000

    2000000 3000000 4000000 Added Removed
  8. MVP

  9. Testing •If your engineering team is only 2 - 3,

    maybe its actually not a high priority right now. •Code coverage can be a useful way to measure progress but be careful, make sure you are testing the right things. It’s very easy to make code coverage go up without testing critical components. •If you have a bigger engineering org (10+) and testing isn’t part of your regular workflow, understand you are going to need to spend a lot of time and investment spinning people up.
  10. Conventions •Do your homework first, not all architectures work greatly

    for every app. •Get opinionated and realize its better to be consistent first the larger you get. •Plan that as you go, you will find better ways to do things. Always add time so you can go back and update the codebase.
  11. Full rewrites vs Piece by Piece •Full rewrites can be

    nice but they require bigger buy in from the company. •They actually can cost you a lot more in time (and money.) •Doing things piece by piece is harder but the progress you get on each piece allows you to get more buy in.
  12. Goals 1. Converting a screen to MVP shouldn’t result in

    metrics movements 2. Baseline code coverage goal of 80% for presenter layer 3. Improve developer satisfaction
  13. “Rules” 1. View layer contains only UI logic 2. Presenter

    layer contains all our business logic, no android dependencies 3. Repository layer handles data loading/ caching/etc. 4. Tests, tests, tests! Our Approach
  14. View interface goes here Contract interface ProfileContract { interface ProfileView

    : View { fun setProfileImage(imageUrl: String); fun setFullName(fullName: String); } }
  15. Business logic Presenter class ProfilePresenter(private val userId: String, private val

    userRepository: UserRepository ) : BasePresenter<ProfileView>(…) { … override fun onBind(view: ProfileView) { disposable = userRepository.getUser(userId) .subscribe( { user -> view.setProfileImage(user.profileImage); view.setFullName(user.fullName); }, … ) } … }
  16. Verifying that the presenter is taking the correct actions on

    the view Unit Tests class ProfilePresenterTest { private val testUser: User = … private val userRepositoryMock: UserRepository = mock { … } private val profileViewMock: ProfileView = mock { … } private val presenter = ProfilePresenter(TEST_USER_ID, userRepositoryMock) @Test fun setsImageAndName() { presenter.bind(profileViewMock) verify(profileViewMock).setProfileImage(testUser.profileImage) verify(profileViewMock).setFullName(testUser.fullName) } }
  17. Render the data in the ui View Implementation class ProfileFragment

    : MvpFragment(), ProfileView { … override fun setProfileImage(imageUrl: String) { Picasso.with(context) .load(imageUrl) .into(profileImageView) } override fun setFullName(fullName: String) { fullNameTextView.text = fullName } }
  18. Let’s sum up what we needed to know about to

    do the previous example: 1. Implementing the view layer 2. Implementing a Presenter 3. The lifecycle of a Presenter/when to clean up resources 4. Repository framework 5. RxJava 6. JUnit 7. Mockito Lots of new concepts introduced Information Overload
  19. Not everyone on the team was familiar with MVP or

    related concepts Wide Distribution of Experience Each developer was in a relatively different boat: •Some had heard of MVP but never used Rx •Some had used Rx with another architecture pattern •Repository pattern was fairly new to everyone •Not everyone had written unit tests or were familiar with the best practices •etc
  20. To help make developers productive in MVP as fast as

    possible, the MVP team: 1. Wrote a lot of docs - 11769 words and 174 presentation slides 2. Held a multi-day on-boarding session 3. Held MVP framework office hours 4. Directly assisted in the conversion of features to MVP Write docs early and often! Onboarding
  21. One of the pros of large teams is that you

    can cover a lot of ground really fast One of the cons is that there are a lot of competing priorities. A large team has pros and cons MVP requires company-wide buy in
  22. Takeaways 1. Do research on best practices, get opinionated and

    pick one 2. Communication becomes easier when everyone is coding using the same pattern 3. Have tests. No seriously, they are great tool in your codebase especially as you grow.