Обратная  совместимость
Сергей	
  Константинов	
  
Обратная  совместимость
Жизненный  цикл  любого  проекта
Ваш	
  проект	
  встроен	
  в	
  контекст	
  
и	
  взаимодействует	
  с	
  окружением	
  
Жизненный  цикл  любого  проекта
Однако	
  ваш	
  контекст	
  нестабилен:	
  
меняется	
  платформа,	
  железо,	
  
вкусы	
  пользователей…	
  
Жизненный  цикл  любого  проекта
В	
  какой-­‐то	
  момент	
  вам	
  
приходится	
  чинить	
  то,	
  что	
  
сломалось	
  из-­‐за	
  изменений	
  
в	
  окружающей	
  среде.	
  
	
  
Чем	
  больше	
  проект,	
  чем	
  
нестабильнее	
  контекст	
  –	
  тем	
  
больше	
  затраты	
  на	
  поддержку.	
  
В  один  прекрасный  день  всё  меняется
Представьте,	
  что	
  вы	
  сами	
  стали	
  
предоставлять	
  API	
  
для	
  сторонних	
  проектов.	
  
	
  
И	
  они	
  почему-­‐то	
  перестали	
  
радоваться	
  вашим	
  
рефакторингам	
  и	
  оптимизациям	
  
Обратная  совместимость
Обратная	
  совместимость	
  
означает,	
  что	
  единожды	
  
принятое	
  обязательство	
  
предоставлять	
  какую-­‐либо	
  
функциональность	
  невозможно	
  
отменить,	
  исправить	
  или	
  
перестать	
  поддерживать.	
  
Обратная  совместимость:  бочка  мёда
•  Вы	
  экономите	
  время	
  и	
  деньги	
  своим	
  пользователям	
  
•  Ваша	
  карма	
  остаётся	
  мягкой	
  и	
  шелковистой	
  
•  Сервис,	
  использующий	
  ваше	
  API,	
  не	
  сломается	
  в	
  продакшене	
  
•  Это,	
  чёрт	
  возьми,	
  клиенториентированно!	
  
Обратная  совместимость:  две  бочки  дёгтя
•  Вы	
  будете	
  писать	
  больше	
  кода	
  
•  Вам	
  придётся	
  гораздо	
  больше	
  думать	
  
•  У	
  вас	
  будет	
  гораздо	
  больше	
  интерфейсов,	
  сущностей,	
  накладных	
  
расходов	
  и	
  избыточных	
  конструкций	
  
Обратная  совместимость:  что  нужно  знать
Предполагается,	
  что	
  вы	
  уже	
  
читали	
  "Совершенный	
  код"	
  и	
  
умеете	
  проектировать	
  системы.	
  
	
  
Ваш	
  код	
  должен	
  быть	
  разделён	
  
по	
  уровням	
  абстракции.	
  Пока	
  
это	
  не	
  так	
  –	
  даже	
  не	
  начинайте.	
  

Изображение	
  

Медиатека	
  

Файл	
  

HDD	
  

EXT	
  

Директория	
  

SSD	
  

HFS	
  

Программа	
  

NTFS	
  

Network	
  

SMB	
  

NFS	
  
Обратная  совместимость:  что  нужно  знать
Кроме	
  того,	
  вы	
  должны	
  чётко	
  понимать	
  границы	
  своей	
  
ответственности:	
  
•  То,	
  что	
  однажды	
  было	
  открыто,	
  закрыть	
  уже	
  нельзя;	
  
•  То,	
  что	
  по	
  вашему	
  недосмотру	
  попало	
  в	
  публичную	
  область	
  –	
  
останется	
  там	
  навечно;	
  
•  Если	
  из	
  публичного	
  интерфейса	
  можно	
  получить	
  доступ	
  к	
  
непубличным	
  объектам	
  –	
  считайте,	
  что	
  вы	
  их	
  открыли.	
  
Правило  №1:  больше  интерфейсов
•  В	
  пределе	
  в	
  вашей	
  публичной	
  документации	
  не	
  должно	
  быть	
  ни	
  
одной	
  сигнатуры,	
  принимающей	
  конкретные	
  типы,	
  а	
  не	
  
интерфейсы	
  
•  Исключение	
  может	
  быть	
  сделано	
  для	
  базовых	
  глобальных	
  
классов	
  и	
  явно	
  подчинённых	
  компонент	
  
Правило  №1:  больше  интерфейсов
interface IGeoObject :
IChildOnMap, ICustomizable,
IDomEventEmitter, IParentOnMap {
attribute IEventManager
events;
attribute IGeometry
geometry;
attribute IOptionManager options;
attribute IDataManager
properties;
attribute IDataManager
state;
}
Map getMap();
IOverlay getOverlay();
IParentOnMap getParent();
IGeoObject setParent(IParentOnMap parent)
	
  
Правило  №1:  больше  интерфейсов
Почему	
  это	
  помогает	
  избежать	
  потери	
  обратной	
  совместимости:	
  
•  Если	
  в	
  сигнатуре	
  заявлен	
  интерфейс,	
  у	
  вас	
  не	
  будет	
  проблем,	
  
когда	
  у	
  вас	
  появится	
  вторая	
  (третья,	
  четвёртая)	
  реализация	
  
интерфейса	
  
•  Атомизируется	
  ответственность	
  объектов	
  
•  Интерфейс	
  не	
  накладывает	
  условий,	
  чем	
  должен	
  быть	
  
передаваемый	
  объект:	
  он	
  может	
  быть	
  как	
  наследником	
  
стандартного	
  объекта,	
  так	
  и	
  самостоятельной	
  реализацией	
  
Правило  №1:  больше  интерфейсов
Почему	
  это	
  полезно	
  при	
  проектировании	
  API:	
  
•  Выделение	
  интерфейсов	
  в	
  первую	
  очередь	
  необходимо	
  
разработчику	
  для	
  наведения	
  порядка	
  в	
  голове	
  
•  Если	
  ваш	
  метод	
  принимает	
  в	
  качестве	
  параметра	
  объект	
  с	
  20	
  
полями	
  и	
  30	
  методами	
  –	
  очень	
  рекомендуется	
  задуматься,	
  что	
  
конкретно	
  необходимо	
  из	
  этих	
  полей	
  и	
  методов	
  
Правило  №1:  больше  интерфейсов
Результат:	
  
•  Вы	
  должны	
  получить	
  на	
  выходе	
  много	
  дробных	
  интерфейсов	
  
•  Ваши	
  сигнатуры	
  не	
  должны	
  требовать	
  от	
  входного	
  параметра	
  
больше	
  7±2	
  свойств	
  или	
  методов	
  
•  Вы	
  получите	
  представление	
  о	
  том,	
  какие	
  свойства	
  ваших	
  
объектов	
  важны	
  в	
  контексте	
  общей	
  архитектуры	
  системы,	
  
а	
  какие	
  –	
  нет	
  
•  Как	
  следствие,	
  снизится	
  избыточность	
  интерфейсов	
  
Правило  №2:  иерархия
•  Ваши	
  объекты	
  должны	
  быть	
  
выстроены	
  в	
  иерархию:	
  кто	
  с	
  
кем	
  взаимодействует	
  
•  Объект	
  имеет	
  право	
  знать	
  
только	
  об	
  объектах	
  соседних	
  
уровней	
  
	
  

Изображение	
  

Медиатека	
  

Файл	
  

HDD	
  

EXT	
  

Директория	
  

SSD	
  

HFS	
  

Программа	
  

NTFS	
  

Network	
  

SMB	
  

NFS	
  
Правило  №2:  иерархия
Как	
  этого	
  добиться?	
  
•  Нужные	
  методы	
  и	
  свойства	
  всегда	
  можно	
  пробросить	
  по	
  цепочке	
  
через	
  промежуточные	
  звенья	
  
•  Эта	
  точка	
  расширения	
  вам	
  рано	
  или	
  поздно	
  пригодится	
  
Правило  №2:  иерархия
Почему	
  это	
  помогает	
  избежать	
  потери	
  обратной	
  совместимости:	
  
•  Снижается	
  общая	
  связанность	
  архитектуры,	
  меньше	
  связей	
  –	
  
меньше	
  side-­‐эффектов	
  
•  При	
  изменении	
  какого-­‐либо	
  объекта	
  вы	
  можете	
  задеть	
  только	
  его	
  
соседей	
  по	
  дереву	
  
Правило  №3:  контексты

Рассматривайте	
  любую	
  промежуточную	
  ступень	
  иерархии	
  как	
  
информационный	
  контекст	
  для	
  нижележащей	
  ступени	
  
Правило  №3:  контексты
Пример:	
  
•  Map	
  =	
  картографический	
  контекст	
  (наблюдаемая	
  область	
  карты	
  +	
  
масштаб)	
  
•  IPane	
  =	
  контекст	
  позиционирования	
  в	
  клиентских	
  координатах	
  
•  ITileContainer	
  =	
  контекст	
  позиционирования	
  в	
  тайловых	
  
координатах	
  
Правило  №3:  контексты
•  Ваше	
  дерево	
  объектов	
  можно	
  будет	
  рассматривать	
  как	
  иерархию	
  
контекстов	
  
•  Каждый	
  уровень	
  иерархии	
  должен	
  соответствовать	
  какому-­‐то	
  
уровню	
  абстракции	
  
Правило  №3:  контексты
Почему	
  это	
  помогает	
  избежать	
  потери	
  обратной	
  совместимости?	
  
•  Правильно	
  построенное	
  дерево	
  контекстов	
  практически	
  никогда	
  
не	
  изменится	
  при	
  рефакторинге:	
  потоки	
  информации	
  могут	
  
появляться,	
  но	
  очень	
  вряд	
  ли	
  пропадут	
  
•  Правило	
  контекстов	
  позволяет	
  эффективно	
  изолировать	
  уровни	
  
иерархии	
  друг	
  от	
  друга	
  
Правило  №3:  контексты
Почему	
  это	
  полезно	
  при	
  проектировании	
  API?	
  
•  Держать	
  в	
  голове	
  информационную	
  схему	
  проекта	
  существенно	
  
проще,	
  чем	
  полное	
  дерево	
  
•  Описание	
  объектов	
  в	
  терминах	
  предоставляемых	
  ими	
  контекстов	
  
позволяет	
  правильно	
  выделять	
  уровни	
  абстракции	
  
Правило  №4:  consistency
Любой	
  объект	
  должен	
  предоставлять:	
  
•  Полное	
  описание	
  своего	
  внутреннего	
  состояния	
  в	
  любой	
  момент	
  
времени	
  
•  Полный	
  набор	
  событий,	
  позволяющий	
  отслеживать	
  все	
  
изменения	
  своего	
  состояния	
  
Правило  №4:  consistency
Подобные	
  паттерны	
  нарушают	
  принцип	
  consistency:	
  
obj.name = 'что-то';
// do something
obj.setOptions('что-то');
// do something
obj.update();

В	
  частности,	
  отсюда	
  следует	
  правило:	
  
•  Избегайте	
  методов	
  update,	
  build,	
  apply	
  
Правило  №4:  consistency
Почему	
  это	
  помогает	
  избежать	
  потери	
  обратной	
  совместимости?	
  
•  Внешний	
  наблюдатель	
  всегда	
  может	
  полностью	
  восстановить	
  
состояние	
  и	
  историю	
  объекта	
  по	
  его	
  публичному	
  интерфейсу	
  
•  Такой	
  объект	
  всегда	
  можно	
  подменить	
  или	
  склонировать,	
  не	
  
обладая	
  знанием	
  о	
  его	
  внутреннем	
  устройстве	
  
Правило  №4:  consistency
Почему	
  это	
  полезно	
  при	
  
проектировании	
  API?	
  
•  Номенклатура	
  методов	
  и	
  
событий	
  ваших	
  объектов	
  
становится	
  менее	
  
разнообразной	
  и	
  более	
  
консистентной	
  
•  Вам	
  станет	
  проще	
  выделять	
  
интерфейсы	
  

// object #1
this.setState = function () {
// apply changes
this.events.fire('statechange');
}
this.getState = function () {
// return state
}
// object #2
this.onObject1StateChange = function () {
var state = this.object1.getState();
// apply changes
}
Правило  №5:  события

Организуйте	
  взаимодействие	
  между	
  объектами	
  с	
  помощью	
  
событий,	
  причём	
  в	
  обе	
  стороны.	
  
Правило  №5:  события

addtomap!	
  

Контрол	
  пробок	
  
Правило  №5:  события

select!	
  

Контрол	
  пробок	
  
Правило  №5:  события

expand!	
  

Контрол	
  пробок	
  
Правило  №5:  события
expand!	
  
select!	
  
providerchange!	
  
Контрол	
  пробок	
  
Правило  №5:  события
•  События	
  необязательны	
  к	
  исполнению	
  для	
  обоих	
  объектов:	
  вы	
  
легко	
  сможете	
  поддерживать	
  такие	
  реализации	
  обоих	
  объектов,	
  
которые	
  реагируют	
  только	
  на	
  часть	
  событий	
  и	
  отображают	
  только	
  
часть	
  состояния	
  второго	
  объекта	
  
•  Если	
  у	
  вас	
  появится	
  третий	
  объект,	
  которому	
  необходимо	
  
реагировать	
  на	
  то	
  же	
  действие	
  –	
  у	
  вас	
  не	
  будет	
  проблем	
  
	
  
Правило  №5:  события
•  Взаимодействие	
  на	
  событиях	
  получается	
  нативно	
  при	
  
соблюдении	
  требования	
  consistency:	
  
•  каждый	
  из	
  объектов	
  знает,	
  когда	
  состояние	
  другого	
  объекта	
  изменилось	
  
•  каждый	
  из	
  объектов	
  может	
  полностью	
  выяснить	
  состояние	
  другого	
  

•  Ваша	
  организация	
  взаимодействия	
  между	
  объектами	
  
значительно	
  унифицируется	
  
•  Взаимодействие	
  между	
  объектами	
  таким	
  образом	
  базируется	
  на	
  
общих	
  методах	
  и	
  событиях,	
  а	
  не	
  частных,	
  т.е.	
  будет	
  содержать	
  
гораздо	
  меньше	
  специфики	
  конкретных	
  объектов	
  
Правило  №6:  делегирование
•  Всегда	
  делегируйте	
  максимальный	
  объём	
  ответственности	
  
объектам	
  нижних	
  уровней	
  
•  Поскольку	
  чаще	
  всего	
  изменяется	
  реализация	
  и	
  
функциональность	
  именно	
  нижнего	
  уровня	
  абстракции	
  (верстка,	
  
протоколы	
  взаимодействия,	
  etc),	
  интерфейс	
  к	
  нижнему	
  уровню	
  
абстракции	
  должен	
  быть	
  максимально	
  общим	
  
Правило  №7:  тесты
•  Пишите	
  тесты	
  на	
  интерфейс	
  
Правило  №8:  внешние  источники
•  В	
  абсолютном	
  большинстве	
  случаев	
  самые	
  большие	
  проблемы	
  с	
  
сохранением	
  обратной	
  совместимости	
  возникают	
  вследствие	
  
несохранения	
  обратной	
  совместимости	
  другими	
  сервисами	
  
•  Если	
  вы	
  не	
  контролируете	
  смежный	
  сервис	
  (источник	
  данных)	
  –	
  
заведите	
  к	
  нему	
  версионируемую	
  обёртку	
  на	
  своей	
  стороне	
  
Обратная  совместимость:  
рефакторинг
Полтора	
  соображения	
  про	
  то,	
  как	
  ломаться	
  чуть	
  реже	
  
	
  
Прежде,  чем  приступать
Проясните	
  ситуацию:	
  
•  Если	
  заявленный	
  функционал	
  не	
  работал	
  никогда,	
  вы	
  вольны	
  
принять	
  любое	
  решение:	
  починить,	
  изменить,	
  выкинуть	
  
•  Если	
  что-­‐то	
  выглядит	
  как	
  баг	
  –	
  это	
  ещё	
  не	
  повод	
  бросаться	
  его	
  
чинить	
  
Прежде,  чем  приступать
•  Проверьте	
  тесты	
  на	
  интерфейс	
  объекта,	
  который	
  собираетесь	
  
рефакторить,	
  и	
  связанных	
  объектов	
  
•  Если	
  тестов	
  нет	
  –	
  напишите	
  их	
  
•  Никогда	
  не	
  начинайте	
  никакой	
  рефакторинг	
  без	
  тестов	
  
•  Тестирование	
  должно	
  включать	
  в	
  себя	
  проверку	
  соответствия	
  
поведения	
  старой	
  и	
  новой	
  версии	
  API	
  
Полтора  приёма  рефакторинга
•  Если	
  вы	
  всё	
  сделали	
  правильно	
  и	
  взаимодействие	
  объектов	
  
сделано	
  по	
  схеме	
  "состояние	
  –	
  событие	
  изменения	
  состояния",	
  
то,	
  часто,	
  вы	
  сможете	
  переписать	
  реализацию,	
  оставив	
  старые	
  
поля	
  и	
  методы	
  для	
  обратной	
  совместимости	
  
От  релиза  к  релизу
•  Если	
  вы	
  неправильно	
  назвали	
  
сущность	
  –	
  она	
  будет	
  
неправильно	
  называться	
  до	
  
следующего	
  мажорного	
  релиза	
  
•  Если	
  вы	
  сделали	
  архитектурную	
  
ошибку	
  –	
  она	
  будет	
  существовать	
  
до	
  следующего	
  мажорного	
  
релиза	
  
•  Запишите	
  себе	
  проблему	
  в	
  
блокнотик	
  и	
  постарайтесь	
  не	
  
думать	
  о	
  ней	
  до	
  следующего	
  
мажорного	
  релиза	
  
Вопросы?
twirl@yandex-­‐team.ru	
  
h•p://api.yandex.ru/maps/	
  
h•p://ymapsapi.ya.ru	
  
	
  

Cергей Константинов, Яндекс

  • 1.
  • 2.
  • 3.
    Жизненный  цикл  любого проекта Ваш  проект  встроен  в  контекст   и  взаимодействует  с  окружением  
  • 4.
    Жизненный  цикл  любого проекта Однако  ваш  контекст  нестабилен:   меняется  платформа,  железо,   вкусы  пользователей…  
  • 5.
    Жизненный  цикл  любого проекта В  какой-­‐то  момент  вам   приходится  чинить  то,  что   сломалось  из-­‐за  изменений   в  окружающей  среде.     Чем  больше  проект,  чем   нестабильнее  контекст  –  тем   больше  затраты  на  поддержку.  
  • 6.
    В  один  прекрасный день  всё  меняется Представьте,  что  вы  сами  стали   предоставлять  API   для  сторонних  проектов.     И  они  почему-­‐то  перестали   радоваться  вашим   рефакторингам  и  оптимизациям  
  • 7.
    Обратная  совместимость Обратная  совместимость   означает,  что  единожды   принятое  обязательство   предоставлять  какую-­‐либо   функциональность  невозможно   отменить,  исправить  или   перестать  поддерживать.  
  • 8.
    Обратная  совместимость:  бочка мёда •  Вы  экономите  время  и  деньги  своим  пользователям   •  Ваша  карма  остаётся  мягкой  и  шелковистой   •  Сервис,  использующий  ваше  API,  не  сломается  в  продакшене   •  Это,  чёрт  возьми,  клиенториентированно!  
  • 9.
    Обратная  совместимость:  две бочки  дёгтя •  Вы  будете  писать  больше  кода   •  Вам  придётся  гораздо  больше  думать   •  У  вас  будет  гораздо  больше  интерфейсов,  сущностей,  накладных   расходов  и  избыточных  конструкций  
  • 10.
    Обратная  совместимость:  что нужно  знать Предполагается,  что  вы  уже   читали  "Совершенный  код"  и   умеете  проектировать  системы.     Ваш  код  должен  быть  разделён   по  уровням  абстракции.  Пока   это  не  так  –  даже  не  начинайте.   Изображение   Медиатека   Файл   HDD   EXT   Директория   SSD   HFS   Программа   NTFS   Network   SMB   NFS  
  • 11.
    Обратная  совместимость:  что нужно  знать Кроме  того,  вы  должны  чётко  понимать  границы  своей   ответственности:   •  То,  что  однажды  было  открыто,  закрыть  уже  нельзя;   •  То,  что  по  вашему  недосмотру  попало  в  публичную  область  –   останется  там  навечно;   •  Если  из  публичного  интерфейса  можно  получить  доступ  к   непубличным  объектам  –  считайте,  что  вы  их  открыли.  
  • 12.
    Правило  №1:  больше интерфейсов •  В  пределе  в  вашей  публичной  документации  не  должно  быть  ни   одной  сигнатуры,  принимающей  конкретные  типы,  а  не   интерфейсы   •  Исключение  может  быть  сделано  для  базовых  глобальных   классов  и  явно  подчинённых  компонент  
  • 13.
    Правило  №1:  больше интерфейсов interface IGeoObject : IChildOnMap, ICustomizable, IDomEventEmitter, IParentOnMap { attribute IEventManager events; attribute IGeometry geometry; attribute IOptionManager options; attribute IDataManager properties; attribute IDataManager state; } Map getMap(); IOverlay getOverlay(); IParentOnMap getParent(); IGeoObject setParent(IParentOnMap parent)  
  • 14.
    Правило  №1:  больше интерфейсов Почему  это  помогает  избежать  потери  обратной  совместимости:   •  Если  в  сигнатуре  заявлен  интерфейс,  у  вас  не  будет  проблем,   когда  у  вас  появится  вторая  (третья,  четвёртая)  реализация   интерфейса   •  Атомизируется  ответственность  объектов   •  Интерфейс  не  накладывает  условий,  чем  должен  быть   передаваемый  объект:  он  может  быть  как  наследником   стандартного  объекта,  так  и  самостоятельной  реализацией  
  • 15.
    Правило  №1:  больше интерфейсов Почему  это  полезно  при  проектировании  API:   •  Выделение  интерфейсов  в  первую  очередь  необходимо   разработчику  для  наведения  порядка  в  голове   •  Если  ваш  метод  принимает  в  качестве  параметра  объект  с  20   полями  и  30  методами  –  очень  рекомендуется  задуматься,  что   конкретно  необходимо  из  этих  полей  и  методов  
  • 16.
    Правило  №1:  больше интерфейсов Результат:   •  Вы  должны  получить  на  выходе  много  дробных  интерфейсов   •  Ваши  сигнатуры  не  должны  требовать  от  входного  параметра   больше  7±2  свойств  или  методов   •  Вы  получите  представление  о  том,  какие  свойства  ваших   объектов  важны  в  контексте  общей  архитектуры  системы,   а  какие  –  нет   •  Как  следствие,  снизится  избыточность  интерфейсов  
  • 17.
    Правило  №2:  иерархия • Ваши  объекты  должны  быть   выстроены  в  иерархию:  кто  с   кем  взаимодействует   •  Объект  имеет  право  знать   только  об  объектах  соседних   уровней     Изображение   Медиатека   Файл   HDD   EXT   Директория   SSD   HFS   Программа   NTFS   Network   SMB   NFS  
  • 18.
    Правило  №2:  иерархия Как  этого  добиться?   •  Нужные  методы  и  свойства  всегда  можно  пробросить  по  цепочке   через  промежуточные  звенья   •  Эта  точка  расширения  вам  рано  или  поздно  пригодится  
  • 19.
    Правило  №2:  иерархия Почему  это  помогает  избежать  потери  обратной  совместимости:   •  Снижается  общая  связанность  архитектуры,  меньше  связей  –   меньше  side-­‐эффектов   •  При  изменении  какого-­‐либо  объекта  вы  можете  задеть  только  его   соседей  по  дереву  
  • 20.
    Правило  №3:  контексты Рассматривайте  любую  промежуточную  ступень  иерархии  как   информационный  контекст  для  нижележащей  ступени  
  • 21.
    Правило  №3:  контексты Пример:   •  Map  =  картографический  контекст  (наблюдаемая  область  карты  +   масштаб)   •  IPane  =  контекст  позиционирования  в  клиентских  координатах   •  ITileContainer  =  контекст  позиционирования  в  тайловых   координатах  
  • 22.
    Правило  №3:  контексты • Ваше  дерево  объектов  можно  будет  рассматривать  как  иерархию   контекстов   •  Каждый  уровень  иерархии  должен  соответствовать  какому-­‐то   уровню  абстракции  
  • 23.
    Правило  №3:  контексты Почему  это  помогает  избежать  потери  обратной  совместимости?   •  Правильно  построенное  дерево  контекстов  практически  никогда   не  изменится  при  рефакторинге:  потоки  информации  могут   появляться,  но  очень  вряд  ли  пропадут   •  Правило  контекстов  позволяет  эффективно  изолировать  уровни   иерархии  друг  от  друга  
  • 24.
    Правило  №3:  контексты Почему  это  полезно  при  проектировании  API?   •  Держать  в  голове  информационную  схему  проекта  существенно   проще,  чем  полное  дерево   •  Описание  объектов  в  терминах  предоставляемых  ими  контекстов   позволяет  правильно  выделять  уровни  абстракции  
  • 25.
    Правило  №4:  consistency Любой  объект  должен  предоставлять:   •  Полное  описание  своего  внутреннего  состояния  в  любой  момент   времени   •  Полный  набор  событий,  позволяющий  отслеживать  все   изменения  своего  состояния  
  • 26.
    Правило  №4:  consistency Подобные  паттерны  нарушают  принцип  consistency:   obj.name = 'что-то'; // do something obj.setOptions('что-то'); // do something obj.update(); В  частности,  отсюда  следует  правило:   •  Избегайте  методов  update,  build,  apply  
  • 27.
    Правило  №4:  consistency Почему  это  помогает  избежать  потери  обратной  совместимости?   •  Внешний  наблюдатель  всегда  может  полностью  восстановить   состояние  и  историю  объекта  по  его  публичному  интерфейсу   •  Такой  объект  всегда  можно  подменить  или  склонировать,  не   обладая  знанием  о  его  внутреннем  устройстве  
  • 28.
    Правило  №4:  consistency Почему  это  полезно  при   проектировании  API?   •  Номенклатура  методов  и   событий  ваших  объектов   становится  менее   разнообразной  и  более   консистентной   •  Вам  станет  проще  выделять   интерфейсы   // object #1 this.setState = function () { // apply changes this.events.fire('statechange'); } this.getState = function () { // return state } // object #2 this.onObject1StateChange = function () { var state = this.object1.getState(); // apply changes }
  • 29.
    Правило  №5:  события Организуйте  взаимодействие  между  объектами  с  помощью   событий,  причём  в  обе  стороны.  
  • 30.
    Правило  №5:  события addtomap!   Контрол  пробок  
  • 31.
    Правило  №5:  события select!   Контрол  пробок  
  • 32.
    Правило  №5:  события expand!   Контрол  пробок  
  • 33.
    Правило  №5:  события expand!   select!   providerchange!   Контрол  пробок  
  • 34.
    Правило  №5:  события • События  необязательны  к  исполнению  для  обоих  объектов:  вы   легко  сможете  поддерживать  такие  реализации  обоих  объектов,   которые  реагируют  только  на  часть  событий  и  отображают  только   часть  состояния  второго  объекта   •  Если  у  вас  появится  третий  объект,  которому  необходимо   реагировать  на  то  же  действие  –  у  вас  не  будет  проблем    
  • 35.
    Правило  №5:  события • Взаимодействие  на  событиях  получается  нативно  при   соблюдении  требования  consistency:   •  каждый  из  объектов  знает,  когда  состояние  другого  объекта  изменилось   •  каждый  из  объектов  может  полностью  выяснить  состояние  другого   •  Ваша  организация  взаимодействия  между  объектами   значительно  унифицируется   •  Взаимодействие  между  объектами  таким  образом  базируется  на   общих  методах  и  событиях,  а  не  частных,  т.е.  будет  содержать   гораздо  меньше  специфики  конкретных  объектов  
  • 36.
    Правило  №6:  делегирование • Всегда  делегируйте  максимальный  объём  ответственности   объектам  нижних  уровней   •  Поскольку  чаще  всего  изменяется  реализация  и   функциональность  именно  нижнего  уровня  абстракции  (верстка,   протоколы  взаимодействия,  etc),  интерфейс  к  нижнему  уровню   абстракции  должен  быть  максимально  общим  
  • 37.
    Правило  №7:  тесты • Пишите  тесты  на  интерфейс  
  • 38.
    Правило  №8:  внешние источники •  В  абсолютном  большинстве  случаев  самые  большие  проблемы  с   сохранением  обратной  совместимости  возникают  вследствие   несохранения  обратной  совместимости  другими  сервисами   •  Если  вы  не  контролируете  смежный  сервис  (источник  данных)  –   заведите  к  нему  версионируемую  обёртку  на  своей  стороне  
  • 39.
    Обратная  совместимость:   рефакторинг Полтора  соображения  про  то,  как  ломаться  чуть  реже    
  • 40.
    Прежде,  чем  приступать Проясните  ситуацию:   •  Если  заявленный  функционал  не  работал  никогда,  вы  вольны   принять  любое  решение:  починить,  изменить,  выкинуть   •  Если  что-­‐то  выглядит  как  баг  –  это  ещё  не  повод  бросаться  его   чинить  
  • 41.
    Прежде,  чем  приступать • Проверьте  тесты  на  интерфейс  объекта,  который  собираетесь   рефакторить,  и  связанных  объектов   •  Если  тестов  нет  –  напишите  их   •  Никогда  не  начинайте  никакой  рефакторинг  без  тестов   •  Тестирование  должно  включать  в  себя  проверку  соответствия   поведения  старой  и  новой  версии  API  
  • 42.
    Полтора  приёма  рефакторинга • Если  вы  всё  сделали  правильно  и  взаимодействие  объектов   сделано  по  схеме  "состояние  –  событие  изменения  состояния",   то,  часто,  вы  сможете  переписать  реализацию,  оставив  старые   поля  и  методы  для  обратной  совместимости  
  • 43.
    От  релиза  к релизу •  Если  вы  неправильно  назвали   сущность  –  она  будет   неправильно  называться  до   следующего  мажорного  релиза   •  Если  вы  сделали  архитектурную   ошибку  –  она  будет  существовать   до  следующего  мажорного   релиза   •  Запишите  себе  проблему  в   блокнотик  и  постарайтесь  не   думать  о  ней  до  следующего   мажорного  релиза  
  • 44.