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

CodeFest 2017, Сергей Крапивенский (Rambler Digital Solutions), Кто подставил Барбару Лисков, или кто кого SOLID

CodeFest
January 31, 2018

CodeFest 2017, Сергей Крапивенский (Rambler Digital Solutions), Кто подставил Барбару Лисков, или кто кого SOLID

https://2017.codefest.ru/lecture/1166

MVVM, VIPER, MVC – очень разные подходы к проектированию архитектуры мобильных приложений. Тем не менее, все они построены на базе гораздо более фундаментальных принципов – SOLID. Зачастую применение таких масштабных паттернов может быть недостаточно оправдано, и следования набору простых и понятных правил будет достаточно для написания чистого и поддерживаемого кода.

Легче всего учиться на ошибках, поэтому все выступление построено на модели "Нарушение принципа -> Обсуждение -> Рефакторинг". В результате доклада у зрителей должно остаться четкое понимание, как принципы SOLID применяются в стандартных задачах iOS разработки.

Тезисы:

Как прокачка фундаментальных знаний помогает нам быстрее становиться сильными разработчиками

Как появился и зачем нужен SOLID

Примеры нарушения каждого из принципов SOLID в реальных проектах

Что делать в случае нарушения принципов и когда их вообще применять

CodeFest

January 31, 2018
Tweet

More Decks by CodeFest

Other Decks in Technology

Transcript

  1. AppDelegate Запуск приложения Quick Actions Поиск Push Notifications Открытие URL

    Состояния приложения Загрузка в фоне Handoff Extensions
  2. AppDelegate Запуск приложения Quick Actions Поиск Push Notifications Открытие URL

    Состояния приложения Загрузка в фоне Handoff Extensions https://github.com/rambler-digital-solutions/RamblerAppDelegateProxy
  3. } else ... return cell } func tableView(_ tableView: UITableView,

    cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SomeIdentifier")! as UITableViewCell let model = self.models[indexPath.row] if (model is News) { let newsCell: NewsCell? = (cell as? NewsCell) newsCell?.setup(withNews: model as! News) } else if (model is Advertisement) { let adCell: AdvertisementCell? = (cell as? AdvertisementCell) adCell?.setup(withAd: model as! Advertisement)
  4. } else ... return cell } func tableView(_ tableView: UITableView,

    cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SomeIdentifier")! as UITableViewCell let model = self.models[indexPath.row] if (model is News) { let newsCell: NewsCell? = (cell as? NewsCell) newsCell?.setup(withNews: model as! News) } else if (model is Advertisement) { let adCell: AdvertisementCell? = (cell as? AdvertisementCell) adCell?.setup(withAd: model as! Advertisement)
  5. } else ... return cell } func tableView(_ tableView: UITableView,

    cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SomeIdentifier")! as UITableViewCell let model = self.models[indexPath.row] if (model is News) { let newsCell: NewsCell? = (cell as? NewsCell) newsCell?.setup(withNews: model as! News) } else if (model is Advertisement) { let adCell: AdvertisementCell? = (cell as? AdvertisementCell) adCell?.setup(withAd: model as! Advertisement)
  6. } else ... return cell } func tableView(_ tableView: UITableView,

    cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SomeIdentifier")! as UITableViewCell let model = self.models[indexPath.row] if (model is News) { let newsCell: NewsCell? = (cell as? NewsCell) newsCell?.setup(withNews: model as! News) } else if (model is Advertisement) { let adCell: AdvertisementCell? = (cell as? AdvertisementCell) adCell?.setup(withAd: model as! Advertisement)
  7. } else ... return cell } func tableView(_ tableView: UITableView,

    cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SomeIdentifier")! as UITableViewCell let model = self.models[indexPath.row] if (model is News) { let newsCell: NewsCell? = (cell as? NewsCell) newsCell?.setup(withNews: model as! News) } else if (model is Advertisement) { let adCell: AdvertisementCell? = (cell as? AdvertisementCell) adCell?.setup(withAd: model as! Advertisement)
  8. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let model: CellObject = self.models[indexPath.row] as! CellObject let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier")! as! ConfigurableCell cell.configure(withObject: model) return cell as! UITableViewCell }
  9. UIView UIVisualEffectView Всё ок ! <UIVisualEffectView> is being asked to

    animate its opacity. This will cause the effect to appear broken until opacity returns to 1
  10. MailAPIClient - auth - findContact - getMailboxes - createMailbox -

    sendMail Auth Contacts Mailboxes Messages - auth - findContact - getMailboxes - createMailbox - sendMail - auth - findContact - getMailboxes - createMailbox - sendMail - auth - findContact - getMailboxes - createMailbox - sendMail - auth - findContact - getMailboxes - createMailbox - sendMail
  11. AuthService MailboxService ContactService MessageServic e Auth Contacts Mailboxes Messages -

    auth - findContact - getMailboxes - createMailbox - sendMail - auth - findContact - getMailboxes - createMailbox - sendMail - auth - findContact - getMailboxes - createMailbox - sendMail - auth - findContact - getMailboxes - createMailbox - sendMail MailAPIClient
  12. - sendSelfDestructMessage - deleteBothMessages ChatChannel - loadMessages - sendMessage -

    replyToMessage - forwardMessage Channel SecretChat Supergroup - banUser Group - loadMessages - sendMessage - replyToMessage - forwardMessage - sendSelfDestruct - deleteBoth - pinMessage - banUser - pinMessage - loadMessages - sendMessage - replyToMessage - forwardMessage - sendSelfDestruct - deleteBoth - pinMessage - banUser - loadMessages - sendMessage - replyToMessage - forwardMessage - sendSelfDestruct - deleteBoth - pinMessage - banUser - loadMessages - sendMessage - replyToMessage - forwardMessage - sendSelfDestruct - deleteBoth - pinMessage - banUser
  13. Dependency Inversion Principle “A. High-level modules should not depend on

    low-level modules. Both should depend on abstractions”
  14. func displayNews() { let newsPredicate = NSPredicate(...) let filteredNews =

    News.findAll() as! [News] // Отображаем новости } Зависимость от Core Data
  15. protocol NewsProvider { func obtainNewsForDate(date: NSDate) -> [News] } Зависимость

    от Core Data func displayNews() { let date = NSDate.init() let filteredNews = self.newsProvider?.obtainNewsForDate(date: date) // Отображаем новости }
  16. protocol NewsProvider { func obtainNewsForDate(date: NSDate) -> [News] } Зависимость

    от Core Data func displayNews() { let date = NSDate.init() let filteredNews = self.newsProvider?.obtainNewsForDate(date: date) // Отображаем новости }
  17. class ViewController: UIViewController { init(newsProvider : NewsProvider) { self.newsProvider =

    newsProvider super.init(nibName: "ViewController", bundle: nil) } } Зависимость от Core Data