"Рекомендации по проектированию api". Марина...
DESCRIPTION
В докладе говорится о проектировании архитектуры API — начиная с того, о ком должен думать разработчик в начале работы, и до секретов «безболезненного» рефакторинга. От общей культуры формирования интерфейсов до правки багов и поддержки обратной совместимости. А также пара слов о документации — фасаде любого API.TRANSCRIPT
1
2
Рекомендации по проектированию API
Степанова Марина
3
– Всем привет! Меня зовут Марина, и я сейчас буду рассказывать, как надо проектировать API.
4
5
Начну заново
6
Меня зовут Марина, и я программист…
7
Меня зовут Марина, и я программист…
…как и моя мама.
8
Я работаю в команде API Яндекс.Карт
9
2013
…
2012
2011
2010
2009
2008 1.0.0
…
…
1.0.8
1.1.0
…
1.1.21
… 2.0.1
…
2.0.33 2.1-beta
10
2013
…
2012
2011
2010
2009
2008 1.0.0
…
…
1.0.8
1.1.0
…
1.1.21
… 2.0.1
…
2.0.33 2.1-beta
Я начала здесь
11
300 000 сайтов используют API 15 000 000 пользователей видят карту через API ежедневно (это каждый 10-й человек в России)
12
Про что я буду рассказывать
! В чем основная проблема разработки API
! Приемы проектирования, которые мы применяем, чтобы с этой
проблемой жить
13
Бонус!
Я буду приводить примеры, когда мы не соблюдали собственные рекомендации и сильно от этого страдали Слайды стыда и позора будут помечены специальным знаком
14
15
16
Корень страданий разработчика API
17
О чем таком особенном должен помнить проектировщик API?
18
Программный код Пользовательский интерфейс
К чему все привыкли
19
Чего хотел пользователь?
Понятно Крутой дизайн
Не глючит
Функциональность
Котики
Няшки
20
Программный код
Программный интерфейс
Пользовательский интерфейс
Все меняется, когда вы делаете API
21
Программный код
Программный интерфейс
Пользовательский интерфейс
Все меняется, когда вы делаете API
22
Мечта каждого программиста – видеть свой код 1 раз в жизни
23
Чего хочет этот пользователь?
API Пользовательский код, работающий с API Проект
Написал, отладил и
забыл
24
Если вы ломаете обратную совместимость, пользователь вынужден вечно переписывать код
1.1.0
1.1.1
1.1.2
Пользовательский код №0
Пользовательский код №1
Пользовательский код №2
Проект
25
Если вы ломаете обратную совместимость, пользователь вынужден вечно переписывать код
И ему это не нравится
26
А чего хотим мы сами?
27
Чего хотим мы, разработчики API?
! Править баги ! Добавлять фичи ! Рефакторить код
28
Мы заморочились и посчитали сколько строк кода мы переписали за год
2.0.7 2.0.31
60% кода поменялось
(без потери обратной совместимости)
29
Итак, причина страданий разработчика API:
Мы должны переписывать свой код, а пользователи должны свой не переписывать
30
Смягчить удар позволяет правильное проектирование системы
31
Наши приемы проектирования
32
Мы разбиваем систему на уровни абстракции
33
Пример абстракций в API
Точка
34
Пример абстракций в API
Геообъект Геометрическая
модель DOM-макет
Точка
35
При формировании уровней абстракции мы следуем некоторым правилам, о которых я и буду говорить
36
Иерархия уровней
37
Иерархия уровней
Геообъект Геометрическая модель
DOM-макет
38
В этом месяце мы должны заработать в
три раза больше
Уровни знают только о своих соседях
39
Уровни знают только о своих соседях С этого дня
работаете в две смены
40
Геообъект Геометрическая модель DOM-макет
Не знает, как будет выглядеть, зато знает свои координаты
Ничего не знает про координаты, зато умеет встраиваться в DOM
Уровни знают только о своих соседях
41
Каждый уровень – это информационный контекст
42
Каждый уровень – это информационный контекст
43
Каждый уровень – это информационный контекст
Геообъект Геометрическая модель DOM-макет
Здесь важны координаты, проекция, зум
Здесь важны пиксельные координаты окна карты
44
Максимальное разграничение обязанностей
45
Максимальное разграничение обязанностей
46
Максимальное разграничение обязанностей
Геообъект Геометрическая модель DOM-макет
Canvas-макет
47
Оценим предусмотрительность нашего старого знакомого
API Пользовательский код, работающий с API Проект
Как знал, что понадобится!
48
Система превращается в большой конструктор, в котором легко заменяются части
49
Части вашей системы должны между собой как-то взаимодействовать
50
Взаимодействие на событиях
«Я подвинулась»
«Карта подвинулась, надо бы перерисоваться»
«Так, говорят надо перерисовываться, двигай наш div»
Геообъект Геометрическая модель
DOM-макет Карта
51
События дают много места для маневра
52
В 2.1-beta мы сделали адаптивный дизайн
53
size = “small” size = “large”
54
«Большой» макет реагирует на все события
Контрол пробок
addtomap!
55
Контрол пробок
select!
«Большой» макет реагирует на все события
56
Контрол пробок
expand!
«Большой» макет реагирует на все события
57
Маленький макет…
select! expand! enable!
providerchange!
Контрол пробок
ЭЭЭ…
58
Маленький макет делает что может
Контрол пробок
59
Плюсы взаимодействия на событиях
! Слабая связанность объектов ! Легко «подцепить» новую сущность ! Абстрагируетесь от соседей ! Можно реагировать на события частично
60
Что мы узнали про уровни абстракции
! Нужно выстроить иерархию взаимодействия ! Уровни знают только о своих соседях ! Уровень – это информационный контекст ! Максимально разграничиваем обязанности ! Взаимодействие уровней через события
61
Мы строили, строили и наконец построили. Наша система состоит из множества небольших сущностей, взаимодействующих между собой.
62
Мы строили, строили и наконец построили. Наша система состоит из множества небольших сущностей, взаимодействующих между собой.
Это надо отметить описать!
63
На арену выходят программные интерфейсы
64
Что такое программный интерфейс?
! Описание функциональности, которую предоставляет компонент. Причем в определенном контексте. !
IChild!!.getParent() // Описание методов.!!.setParent()!!@parentchange // Описание событий. !
!
65
Интерфейсы наследуются
ICustomizable
IChildOnMap
IGeoObject
Объект, у которого есть менеджер опций
Объект, добавляемый на карту
Геообъект (свои методы + композиция более мелких интерфейсов)
66
Какие задачи решают программные интерфейсы?
67
Вспомним пример, в котором мы хотели заменить один из компонентов
Геообъект Геометрическая модель DOM-макет
Canvas-макет
68
Как понять, насколько точно нам надо скопировать заменяемую сущность, чтобы система не рухнула?
DOM-макет
Canvas-макет
69
Если вы описываете интерфейсы, проблем такого рода не возникает
IGeoObject IOverlay ILayout
На это место можно поместить любую реализацию интерфейса
70
Какие задачи решают программные интерфейсы
! Вы получаете формальное описание вашей системы ! Сущности становятся легко заменяемыми (подойдет любая реализация интерфейса)
71
! Когда вы продумываете программные интерфейсы, вы наводите порядок у себя в голове
72
Интерфейсы должны быть дробными
ICollection
IParentOnMap
ymaps.Collection
ymaps.GeoObjectCollection
73
Если в вашем интерфейсе много сущностей - это повод задуматься
setParent() getParent() .options .events
IChild
ICustomizable
IEventEmitter
74
Названия, ключи, алиасы должны быть очень конкретными
75
– Петька, get()! – 32! – Что 32? – А что get()?
76
Грустный пример из реальной жизни www.somesite.ru?%с&%n&%l&%j%s Для расшифровки этого url нужно выучить небольшой нелогичный алфавит: %c – coordinates %l – lang %n – layer (ну потому что %l занято) %j – id (пошло от «jam») %s – timestamp (потому что «stamp»)
77
В какой момент пора выделять программные интерфейсы?
78
Вариант №1 (неправильный)
! Выделяем уровни абстракции ! Пишем код ! Описываем получившиеся интерфейсы
79
Почему этот вариант неправильный?
80
У нас в 2.0 появился кластеризатор
81
Метки собираются в объект-кластер
Кластеризатор
Объект-кластер
82
Кластеризатору для работы нужно знать, сколько меток в каждом кластере
???
83
Кластеризатору для работы нужно знать, сколько меток в каждом кластере
Можно хранить данные у себя
Можно спрашивать у кластера ???
84
Идем по пути наименьшего сопротивления
Кластеризатор
Объект-кластер
cluster.getGeoObjects()
85
Кластеризатор
Объект-кластер
Позже утверждаем интерфейсы
86
IGeoObject
Позже утверждаем интерфейсы
Кластеризатор
Объект-кластер
87
ICollection IGeoObject
Позже утверждаем интерфейсы
Объект-кластер
88
ICollection IGeoObject IGeoObject
Позже утверждаем интерфейсы
89
Подставим интерфейсы в схему
ICollection cluster.getGeoObjects() IGeoObject
IGeoObject IGeoObject
IGeoObject IGeoObject
IGeoObject
IGeoObject
IGeoObject IGeoObject
IGeoObject
90
Подставим интерфейсы в схему
ICollection cluster.getGeoObjects() IGeoObject
IGeoObject IGeoObject
IGeoObject IGeoObject
IGeoObject
IGeoObject
IGeoObject IGeoObject
IGeoObject
Этот метод больше нельзя использовать – он не входит в интерфейс
91
Как реально выглядит процесс
! Выделяем уровни абстракции ! Пишем код ! Описываем получившиеся интерфейсы ! Переписываем код, чтобы все сущности использовали только интерфейсные методы
92
Вариант №2 (правильный)
! Выделяем уровни абстракции ! Описываем интерфейсы ! Пишем код, в котором объекты взаимодействуют через интерфейсные методы, поля, события
93
Интерфейсы изменят ваш проект
94
Подобное станет подобным
Placemark
Polygon
Polyline
IGeoObject
95
Мы не успели отточить интерфейсы контролов при запуске
Контролы писали разные люди, в результате получили немного разные конструкторы
Button(params, options)! TrafficControl(state, options)! SearchControl(options)!
96
Обратная сторона интерфейсов
Из-за того, что объекты станут композициями дробных интерфейсов, конечные объекты могут иметь несколько монструозный и избыточный интерфейс.
97
У нас чудесным, но монструозным вышел IGeoObject
! var myPlacemark = new ymaps.GeoObject({!! !geometry: { ! ! ! !type: “Point”,!! ! !coordinates: [37.61, 55.75] !! !},!! !properties: {!! ! !balloonContent: ‘Hello!’,!! ! !id: 723!! !}!!}, {!! !// Опции.!! !preset: ‘twirl#redIcon’,!! !zIndex: 100!!});!
98
Мы выбрали самые частые варианты использования и сделали для них хелперы
99
Создавать метки стало проще
! !var myPlacemark = new ymaps.Placemark([37.61, 55.75], {!! ! !// Данные.!
! ! !balloonContent: ‘Hello!’,!! ! !id: 723!! !}, {!! ! !// Опции.!! ! !zIndex: 100,!! ! !preset: ‘twirl#redIcon’!! !}); !
!
100
Также вас спасут значения по умолчанию
Программист изучает опции геообъекта только в тот момент, когда они ему понадобятся и не забивает голову ненужным мусором
101
Еще одна военная хитрость
Публичная часть Наше API
102
Все вылизано, документировано, никогда не изменится
Публичная часть Закрытая часть
103
Все вылизано, документировано, никогда не изменится
Публичная часть Закрытая часть
104
Публичная часть Закрытая часть
Таких ситуаций быть не должно
105
Мы открывали сущности постепенно 2.0.14 2.0.33
106
Лучше открыть мало, но хорошо, чем много, но плохо
107
Подведем итоги
108
Мы в ответе за тех, кто пользуется нашим API
Вывод №1
109
Вывод №2
Проектирование большой системы – сложный процесс. Но если заложить верные принципы, все получится.
110
Спасибо за внимание