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

Matthew Liam Healy - Emergent architecture for mobile applications

Matthew Liam Healy - Emergent architecture for mobile applications

Often the first question mobile engineers ask ourselves when sitting down to build an application is what architectural patterns we should use. We try to lay the foundations for our house before we know how many rooms we need to build.

If we want to retain our ability to react to the evolving needs of our users, then we must accept that it’s impossible to know at the beginning of a project what patterns will best suit what is being built. All too often it turns out that the perfect patterns we chose at the beginning don’t work so well with the desired functionality, leading to code that's difficult to understand and maintain, and eventually to expensive rewrites.

So what if we could just... not choose? This talk will outline an incremental approach to application architecture that works in concert with product design, beginning with broad functionality and allowing the design to reveal itself over time as the specifics of our application become clearer.

E07bf3bc75128836c73f39904f0f7cf7?s=128

Turing Fest
PRO

August 29, 2019
Tweet

Transcript

  1. EMERGENT ARCHITECTURE FOR MOBILE APPLICATIONS MATTHEW LIAM HEALY

  2. EMERGENT ARCHITECTURE FOR MOBILE APPLICATIONS HERE’S WHAT WE’RE GOING TO

    COVER ▸ What is emergent architecture? ▸ Being specific ▸ Testing with change in mind
  3. WHAT EVEN IS EMERGENT ARCHITECTURE ANYWAY?

  4. WHAT EVEN IS ARCHITECTURE ANYWAY?

  5. “[ARCHITECTURE IS] THE FUNDAMENTAL STRUCTURES OF A SOFTWARE SYSTEM” Brian

    Wikipedia WHAT EVEN IS ARCHITECTURE ANYWAY?
  6. “ARCHITECTURE IS ABOUT THE IMPORTANT STUFF. WHATEVER THAT IS.” Ralph

    Johnson WHAT EVEN IS ARCHITECTURE ANYWAY?
  7. EMERGENT ARCHITECTURE IS HAVING THE RIGHT AMOUNT OF STRUCTURE WHEN

    YOU NEED IT - AND NOT BEFORE
  8. WHAT EVEN IS ARCHITECTURE ANYWAY? MOBILE APPLICATION ARCHITECTURE ▸ MVC

    (Model-View-Controller) ▸ MVVM (Model-View-ViewModel) ▸ VIPER (View, Interactor, Presenter, Entity, Router)
  9. YOUR UI IS NOT YOUR ARCHITECTURE

  10. WHAT EVEN IS ARCHITECTURE ANYWAY? SOUNDCLOUD USER PROFILE

  11. WHAT EVEN IS ARCHITECTURE ANYWAY? SOUNDCLOUD USER PROFILE (WIP)

  12. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC

  13. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC DRY - DON’T

    REPEAT YOURSELF struct Person {
 let firstName: String
 let lastName: String
 }
  14. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC DRY - DON’T

    REPEAT YOURSELF struct Person {
 let firstName: String
 let lastName: String
 } // In some file:
 let fullName = person.firstName + “ “ + person.lastName // Some other file:
 let userFullName = person.firstName + “ “ + person.lastName
  15. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC DRY - DON’T

    REPEAT YOURSELF struct Person {
 let firstName: String
 let lastName: String
 } // In some file:
 let fullName = person.firstName + “ “ + person.lastName // Some other file:
 let userFullName = person.firstName + “ “ + person.lastName
  16. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC DRY - DON’T

    REPEAT YOURSELF struct Person {
 let firstName: String
 let lastName: String
 
 func fullName() -> String {
 return firstName + “ “ + lastName
 }
 } // In some file:
 let fullName = person.fullName() // Some other file:
 let userFullName = person.fullName()
  17. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC DRY - DON’T

    REPEAT YOURSELF struct Person {
 let firstName: String
 let middleName: String
 let lastName: String
 } // In some file:
 let fullName = person.firstName + “ “ + person.lastName // Some other file:
 let userFullName = person.firstName + “ “
 + person.middleName + “ “ 
 + person.lastName
  18. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC DRY - DON’T

    REPEAT YOURSELF struct Person {
 let firstName: String
 let middleName: String
 let lastName: String
 } // In some file:
 let fullName = person.firstName + “ “ + person.lastName // Some other file:
 let userFullName = person.firstName + “ “
 + person.middleName + “ “ 
 + person.lastName
  19. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC DRY - DON’T

    REPEAT YOURSELF struct Person {
 let firstName: String
 let middleName: String
 let lastName: String
 
 func fullName(shouldShowMiddleName: Bool) -> String {
 return firstName + “ “ 
 + (shouldShowMiddleName 
 ? middleName + “ “ 
 : “”)
 + lastName
 }
 }
  20. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC DRY - DON’T

    REPEAT YOURSELF 
 func fullName(
 shouldShowMiddleName: Bool,
 shouldUseInitials: Bool
 ) -> String {
 // Insert horrible, complex logic here
 }
  21. “EXISTING CODE EXERTS A POWERFUL INFLUENCE” Sandi Metz IF YOU’RE

    DOING SOMETHING SPECIFIC, BE SPECIFIC
  22. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC SOUNDCLOUD USER PROFILE

  23. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC SOUNDCLOUD USER PROFILE

    // In UserProfilePresenter func present(contentBuckets: [ContentBucket]) {
 // some code
 }
 
 // In UserProfileEventController func didTap(item: TrackOrPlaylist, in: ContentBucket) {
 // some code
 }
  24. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC SOUNDCLOUD USER PROFILE

    // In UserProfilePresenter func present(tracks: [Track]) {
 // some code
 }
 
 // In UserProfileEventController func didTap(track: Track) {
 // some code
 }
  25. IF YOU’RE DOING SOMETHING SPECIFIC, BE SPECIFIC SOUNDCLOUD USER PROFILE

    // In UserProfilePresenter func present(tracks: [Track]) {
 // some code
 }
 
 func present(playlists: [Playlist]) {
 // some code
 }
  26. TESTS FOR CHANGE

  27. “HAVE TESTS” Me, just now TESTS FOR CHANGE

  28. “BUT IF I TEST A LOT THEN REFACTORING IS HARDER

    BECAUSE THEY ALL BREAK” Me, earlier in my career TESTS FOR CHANGE
  29. TESTS FOR CHANGE FOCUS ON BEHAVIOUR func test_whenPlaylistIsTapped_opensThatPlaylist() {
 let

    playlistIdentifier = “some-identifier”
 context
 .given().dataHasLoaded(user: userWithOnePlaylist(id: playlistIdentifier)
 .when().itemIsTapped(item: playlistIdentifier, in: .likes)
 .thenPlaylistLauncher().opensPlaylist(id: playlistIdentifier)
 }
  30. TESTS FOR CHANGE FOCUS ON BEHAVIOUR func test_whenPlaylistIsTapped_opensThatPlaylist() {
 let

    playlistIdentifier = “some-identifier”
 context
 .given().dataHasLoaded(user: userWithOnePlaylist(id: playlistIdentifier)
 .when().itemIsTapped(item: playlistIdentifier, in: .likes)
 .thenPlaylistLauncher().opensPlaylist(id: playlistIdentifier)
 }
  31. TESTS FOR CHANGE FOCUS ON BEHAVIOUR func test_whenPlaylistIsTapped_opensThatPlaylist() {
 let

    playlistIdentifier = “some-identifier”
 context
 .given().dataHasLoaded(user: userWithOnePlaylist(id: playlistIdentifier)
 .when().itemIsTapped(item: playlistIdentifier, in: .likes)
 .thenPlaylistLauncher().opensPlaylist(id: playlistIdentifier)
 }
  32. TESTS FOR CHANGE FOCUS ON BEHAVIOUR func test_whenPlaylistIsTapped_opensThatPlaylist() {
 let

    playlistIdentifier = “some-identifier”
 context
 .given().dataHasLoaded(user: userWithOnePlaylist(id: playlistIdentifier)
 .when().itemIsTapped(item: playlistIdentifier, in: .likes)
 .thenPlaylistLauncher().opensPlaylist(id: playlistIdentifier)
 }
  33. TESTS FOR CHANGE INPUT/OUTPUT TESTS Input Output Code under test

  34. TESTS FOR CHANGE USER PROFILE INPUT/OUTPUT TESTS User Profile User

    Profile 
 view model Presenter Track mapper Playlist mapper Tracks Playlists Track view models Playlist view models
  35. EMERGENT ARCHITECTURE FOR MOBILE APPLICATIONS IN SUMMARY ▸ Your UI

    is not your architecture ▸ If you’re doing something specific, be specific ▸ Write tests with change in mind
  36. EMERGENT ARCHITECTURE FOR MOBILE APPLICATIONS THANKS You can message me

    on LinkedIn if you’d like 
 https://www.linkedin.com/in/matthewliamhealy/