Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy

33 views

Published on

Quite often when architecting an app or implementing a feature, we don’t really think about the Data itself. Sure, we will handle few network requests or database queries but these things just contain some data, we don’t specifically think about the main character. In this talk I will try to show you why Data itself is important and a few tips and tricks on how to manage it

Published in: Education
  • Be the first to comment

  • Be the first to like this

Mobile Fest 2018. Łukasz Mróz. Let’s make your DATA sexy

  1. 1. LET'S MAKE YOUR DATA LOOK SEXY! sunshinejr thesunshinejr
  2. 2. WHAT IS AN APP?
  3. 3. BEAR
  4. 4. ''APPS ARE JUST PRETTY PICTURES OF JSON'' (ORTA THEROX)
  5. 5. DATA 7b22777764635f73657373696f6e73223a205ba7b226964223a 203432302c20226465736372697074696f6e223a2022496e7472 6f647563696e67204d61727a6970616e2e227d2c207b22696422 3a203432312c20226465736372697074696f6e223a2022576879 206469642077652064656369646520746f2062757920526561637 4204e617469766520616e642063616c6c206974204d61727a6970 616e202d2074686520627573696e657373207065727370656374 6976652e227d2c207b226964223a203432322c20226465736372 697074696f6e223a2022576861742773206e657720696e20456c
  6. 6. JSON {"wwdc_sessions": [ {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."}, {"id": 420, "description": "Introducing Marzipan."}, {"id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective."}, {"id": 422, "description": "What's new in Electron."} ]}
  7. 7. PRETTY PRINTED { "wwdc_sessions": [ { "id": 420, "description": "Introducing Marzipan." }, { "id": 421, "description": "Why did we decide to buy React Native and call it Marzipan - the business perspective." }, { "id": 422, "description": "What's new in Electron." } ] }
  8. 8. ''PRETTY PRINTED JSON IS NOT A PRETTY PICTURE OF JSON'' (ME)
  9. 9. AT LEAST IT'S NOT PRETTY FOR USERS !
  10. 10. WHAT DEVELOPERS SAY ABOUT JSON:
  11. 11. WHAT DEVELOPERS SAY ABOUT JSON: > JSON is awesome boring
  12. 12. WHAT DEVELOPERS SAY ABOUT JSON: > JSON is awesome boring > JSON is increcidbly fast slow as FK
  13. 13. WHAT DEVELOPERS SAY ABOUT JSON: > JSON is awesome boring > JSON is increcidbly fast slow as FK > JSON is a good friend (???)
  14. 14. JSON IS A CHALLENGE!
  15. 15. If you don't love me at my if let jsonResponse = data as? NSDictionary { if let feed = jsonResponse["feed"] as? NSDictionary { if let entry = feed["entry"] as? NSArray { if let firstEntry = entry[0] as? NSDictionary { if let name = firstEntry["name"] as? NSDictionary { if let label = name["label"] as? NSString { println("label: (label)") } } } } } } Then you don't deserve me at my let decoder = JSONDecoder() let product = try decoder.decode(Product.self, from: data) https://twitter.com/harlanhaskins/status/982249952154824704
  16. 16. (140 PAGES) BOOK ABOUT CODABLE
  17. 17. PERFORMANCE OF JSON DECODING https://github.com/bwhiteley/JSONShootout
  18. 18. ''JSON PARSERS'' ???
  19. 19. WE SHOULD CARE MORE ABOUT OUR DATA!
  20. 20. IS YOUR JSON PAYLOAD FROM THE API TOO BIG?
  21. 21. TRY TO CHANGE IT!
  22. 22. TREAT YOUR DATA LIKE A PRINCESS!!
  23. 23. UNDERSTAND HER DOMAIN!
  24. 24. ASK QUESTIONS!
  25. 25. > How do you split the works if you are not working alone?
  26. 26. > How do you split the works if you are not working alone? > When do you migrate dependencies?
  27. 27. > How do you split the works if you are not working alone? > When do you migrate dependencies? > What if one dependency does not work in newer version?
  28. 28. > How do you split the works if you are not working alone? > When do you migrate dependencies? > What if one dependency does not work in newer version? > What if you are 2 major versions behind?
  29. 29. > How do you split the works if you are not working alone? > When do you migrate dependencies? > What if one dependency does not work in newer version? > What if you are 2 major versions behind? > Do you use migrator?
  30. 30. > How do you split the works if you are not working alone? > When do you migrate dependencies? > What if one dependency does not work in newer version? > What if you are 2 major versions behind? > Do you use migrator? > How do you test your app after the migration?
  31. 31. > How do you split the works if you are not working alone? > When do you migrate dependencies? > What if one dependency does not work in newer version? > What if you are 2 major versions behind? > Do you use migrator? > How do you test your app after the migration? > Do you do refactor while migrating the codebase?
  32. 32. HANDLE ALL THE STATES SHE MIGHT BE IN!
  33. 33. func viewDidLoad(animated: Bool) { super.viewDidLoad(animated: animated) loadData() } func loadData() { api.fetchData { [weak self] data in self?.data = data self?.tableView.reloadData() } }
  34. 34. func viewDidLoad(animated: Bool) { super.viewDidLoad(animated: animated) loadData() } func loadData() { tableView.isHidden = true loadingView.isHidden = false api.fetchData { [weak self] data in self?.data = data self?.loadingView.isHidden = true self?.tableView.isHidden = false self?.tableView.reloadData() } }
  35. 35. func viewDidLoad(animated: Bool) { super.viewDidLoad(animated: animated) loadData() } func loadData() { tableView.isHidden = true loadingView.isHidden = false api.fetchData { [weak self] data, error in if let error = error { let alertController = UIAlertController(...) self?.present(alertController, animated: true, completion: nil) } else { self?.data = data self?.loadingView.isHidden = true self?.tableView.isHidden = false self?.tableView.reloadData() } } }
  36. 36. INTRODUCE EXPLICIT STATE!
  37. 37. enum Layout { case empty case loading case content } private func updateLayout(to: Layout) { switch to { case .empty: contentView.alpha = 0.0 loadingView.alpha = 0.0 case .loading: contentView.alpha = 0.0 loadingView.alpha = 1.0 case .content: contentView.alpha = 1.0 loadingView.alpha = 0.0 } }
  38. 38. LET HER KNOW YOU CARE ABOUT HER
  39. 39. LET HER KNOW YOU CARE ABOUT HER EVEN WHEN SHE'S OFFLINE
  40. 40. > caching responses & policies var request = URLRequest(url: url) request.cachePolicy = .reloadIgnoringLocalCacheData > recording & using stubbed responses (OHHTTPStubs/Moya)
  41. 41. DON'T PASS HER TO THE WRONG GUY!
  42. 42. > Intermediate objects like View Model or Redenerable
  43. 43. > Intermediate objects like View Model or Redenerable > Think about who is responsible for the data
  44. 44. HANDLE HER ERRORS PROPERLY!
  45. 45. provider.request(GitHub.repos(repo)) { (result) in if case .success(let response) = result { do { let repos = try response.map(to: [Repository].self) print(repos) } catch let error { print("There was something wrong with the request! Error: (error)") } } }
  46. 46. ???
  47. 47. WE CAN DO BETTER!
  48. 48. SORTED BY EFFORT:
  49. 49. SORTED BY EFFORT: 1. Alert
  50. 50. SORTED BY EFFORT: 1. Alert 2. Smooth UI component that fits the screen
  51. 51. SORTED BY EFFORT: 1. Alert 2. Smooth UI component that fits the screen 3. Silent retries & cache fetching
  52. 52. SORTED BY EFFORT: 1. Alert 2. Smooth UI component that fits the screen 3. Silent retries & cache fetching 4. 2 & 3 at once
  53. 53. AND THE LAST BUT NOT LEAST...
  54. 54. THINK ABOUT HER ALL THE TIME
  55. 55. THANKS SO MUCH! ANY QUESTIONS? sunshinejr thesunshinejr

×