ݺߣ

ݺߣShare a Scribd company logo
Кто подставил
Барбару Лисков?
Сергей Крапивенский, Rambler&Co
или Кто кого SOLID?
“Do Not Learn ɴǰ”
Фундаментальные знания
Фундаментальные знания
Язык
Фундаментальные знания
Язык
Фреймворки
Фундаментальные знания
Язык
Фреймворки
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
- 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
AuthServiceMailboxServiceContactService
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
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

More Related Content

Сергей Крапивенский