Upload
codefest
View
76
Download
1
Embed Size (px)
Citation preview
Кто подставил Барбару Лисков?
Сергей Крапивенский, Rambler&Co
или Кто кого SOLID?
“Do Not Learn Frameworks”
Фундаментальные знания
Фундаментальные знания
Язык
Фундаментальные знания
Язык
Фреймворки
Фундаментальные знания
Язык
Фреймворки
RayWenderlich - driven development
Senior ReactiveCocoa Developer
Рамблер - секта VIPER
Фундаментальные знания
Язык
Фреймворки
Фундаментальные знания
Язык
Фреймворки
Фундаментальные знания
Язык
Фреймворки
Фундаментальные знания• Структуры данных
• Алгоритмы
• Паттерны
• DRY, KISS, YAGNI
• SOLID
• И многое другое
Single responsibility principle
Open-closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
Single Responsibility Principle
“A class should have only one reason to change”
MassiveViewController
1.Ответственности сильно связаны
2.Класс перестает помещаться в голове
3.Тяжело поддерживать и тестировать
UITableViewController
1.Изменение логики работы с таблицей
2.Поменять иерархию вьюшек
UITableViewController
Решение проблемы: не использовать его
Запуск приложения
Push Notifications
Quick Actions
Уведомления о
состояниях приложенияОткрытие по URL
Фоновая
загрузка данных
AppDelegate
AppDelegate
Запуск приложения Quick Actions
ПоискPush Notifications
Открытие URLСостояния приложения
Загрузка в фоне
Handoff
Extensions
AppDelegate
Запуск приложения Quick Actions
ПоискPush Notifications
Открытие URLСостояния приложения
Загрузка в фоне
Handoff
Extensions
https://github.com/rambler-digital-solutions/RamblerAppDelegateProxy
SRP о снижении сложности
Single responsibility principle
Open-closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
Open-Closed Principle
“Software entities (classes, modules, functions, etc.) should be open for extension, but closed for
modification”
Простой и устойчивый дизайн
Новость
Новость
Новость
Новость
Новость
Новость
Новость
Новость
Новость с фото
Новость с фото
Новость
Новость
Новость
Новость
Новость с фото
Новость с фото
Реклама
Реклама
} 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)
} 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)
} 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)
} 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)
} 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)
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 }
NewsCell PhotoCell AdCell
<ConfigurableCell>
func configure(withObject: CellObject)
News Photo Advert
<CellObject>
func cellClass() -> AnyClass
Когда применять?
Single responsibility principle
Open-closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
Liskov Substitution Principle
“Subtypes must be substitutable for their base types”
Нужен для проверки корректности наследования
func hideViews() { UIView.animate(withDuration: 1.0, animations: { for view in self.animatableViews { view.alpha = 0.5 } }) }
UIView
UIVisualEffectView
Всё ок !
<UIVisualEffectView> is being asked to animate its opacity. This will cause the effect to appear broken until
opacity returns to 1
¯\_(ツ)_/¯
Single responsibility principle
Open-closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
Interface Segregation Principle
“Clients should not be forced to depend on methods that they
do not use”
MailAPIClient
- auth- findContact- getMailboxes- createMailbox- sendMailAuth Contacts Mailboxes Messages
- auth- findContact- getMailboxes- createMailbox- sendMail
- auth- findContact- getMailboxes- createMailbox- sendMail
- auth- findContact- getMailboxes- createMailbox- sendMail
- auth- findContact- getMailboxes- createMailbox- sendMail
AuthServiceMailboxServiceContactServiceMessageService
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
ISP - это не SRP
- sendSelfDestructMessage- deleteBothMessages
ChatChannel
- loadMessages- sendMessage- replyToMessage- forwardMessage
ChannelSecretChat 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
Single responsibility principle
Open-closed principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
Dependency Inversion Principle
“A. High-level modules should not depend on low-level modules. Both
should depend on abstractions”
Dependency Inversion Principle
“B. Abstractions should not depend on details. Details should depend
on abstractions”
func displayNews() { let newsPredicate = NSPredicate(...) let filteredNews = News.findAll() as! [News] // Отображаем новости }
Зависимость от Core Data
NewsViewController MagicalRecord
Realm😓
protocol NewsProvider { func obtainNewsForDate(date: NSDate) -> [News] }
Зависимость от Core Data
func displayNews() { let date = NSDate.init() let filteredNews = self.newsProvider?.obtainNewsForDate(date: date) // Отображаем новости }
protocol NewsProvider { func obtainNewsForDate(date: NSDate) -> [News] }
Зависимость от Core Data
func displayNews() { let date = NSDate.init() let filteredNews = self.newsProvider?.obtainNewsForDate(date: date) // Отображаем новости }
class ViewController: UIViewController { init(newsProvider : NewsProvider) { self.newsProvider = newsProvider super.init(nibName: "ViewController", bundle: nil) }
}
Зависимость от Core Data
NewsViewController <NewsProvider>
MagicalRecord NewsProvider
Зависимости инвертированы #
Серебряной пули нет 😢
- Оноре де Бальзак
“Обстоятельства переменчивы, принципы - никогда”
Спасибо!
serkrapiv
sergey.krapivenskiy
rambler-ios