mirror of
https://github.com/twirl/The-API-Book.git
synced 2025-01-05 10:20:22 +02:00
Уровни абстракции и декомпозиция
This commit is contained in:
parent
09cd881333
commit
d5d2f385d3
57
API.ru.html
57
API.ru.html
@ -4,15 +4,35 @@
|
||||
<title>API</title>
|
||||
<style>
|
||||
body {
|
||||
width: 80%;
|
||||
width: 60%;
|
||||
max-width: 1000px;
|
||||
margin: 10px auto;
|
||||
margin: 10px auto 0 300px;
|
||||
font-family: Georgia, serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
body > aside {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
header:after {
|
||||
content: "";
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
padding: 0 0 20px 0;
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
<h1>API</h1>
|
||||
<aside>
|
||||
<img src="Why.jpg" style="width: 275px;"/>
|
||||
</aside>
|
||||
<h1>Сергей Константинов<br/>API</h1>
|
||||
<h2>Об авторе</h2>
|
||||
<h2>Введение</h2>
|
||||
<p>Если мы посмотрим на определение из энциклопедии, то узнаем, что программирование — это что-то вроде преобразования формально проставленной задачи в исполняемый код, как правило, путём имплементации какого-то алгоритма на определённом языке программирования. И действительно, курсы обучения соответствующим дисциплинам большей частью и состоят из инструкций, как перевести словесно поставленную задачу в код и запрограммировать тот или иной алгоритм.</p>
|
||||
@ -151,7 +171,7 @@
|
||||
<ul>
|
||||
<li>GET /weather/temperature/{city_id} - возвращает текущую температуру в городе с указанным идентификатором;</li>
|
||||
<li>GET /weather/temperature/{city_id}/forecast - возвращает прогноз изменения температуры;</li>
|
||||
<li>GET /weather/pressure/{city_id} - возвращает атмосферное давление.<li>
|
||||
<li>GET /weather/pressure/{city_id} - возвращает атмосферное давление.</li>
|
||||
</ul>
|
||||
|
||||
<p>Покрывает ли такой интерфейс наши сценарии использования? С одной стороны кажется, что да - каждый потребитель сможет получить нужный ему набор информации.</p>
|
||||
@ -169,9 +189,36 @@
|
||||
<ul><li>от сценариев использования к их внутренней реализации: высокоуровневые сущности и номенклатура их методов должны напрямую отражать сценарии использования api; низкоуровневый - отражать декомпозицию сценариев на составные части;</li>
|
||||
<li>от терминов предметной области пользователя к терминам предметной области исходных данных - в нашем случае от высокоуровневых понятий "прогноз погоды" и "движение атмосферных фронтов" к базовым "температура", "давление", "скорость ветра";</li>
|
||||
<li>наконец, от структур данных, в которых удобно оперировать пользователю к структурам данных, максимально приближенных к "сырым" - в нашем случае от "атмосферных фронтов" и "магнитных бурь" - к сырым байтовый данным, описывающим поле атмосферного давления или магнитное поле Земли.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>Чем дальше находятся друг от друга программные контексты, которые соединяет наше api - тем более глубокая иерархия сущностей должна получиться у нас в итоге. Обращаю ваше внимание, что иерархия не должна быть самоцелью; цель - введение промежуточных ступеней погружения в тонкости предметной области. Избыточная сложность здесь не менее вредна, чем избыточная простота.</p>
|
||||
|
||||
<h3>Уровни абстракции и декомпозиция</h3>
|
||||
|
||||
<p></p>Приближённость к сценариям использования - не единственная польза правильно построенной иерархии абстракций. Другим критерием качества архитектуры api здесь является снижение связности и декомпозиция объектов api.</p>
|
||||
|
||||
<p>Рассмотрим следующий пример организации функциональности карты атмосферных фронтов.</p>
|
||||
|
||||
<p>Первый способ:</p>
|
||||
|
||||
<ul>
|
||||
<li>GET /map - возвращает множество геометрий атмосферных объектов, попадающих в заданную область;</li>
|
||||
<li>GET /geometry/{geometry_id} - возвращает метаданные о геометрии, в том числе тип объекта, описываемого геометрией (область повышенного или пониженного давления, атмосферный фронт);</li>
|
||||
<li>GET /area/{area_id}, GET /front/{front_id} - возвращает метаданные конечного объекта.</li>
|
||||
</ul>
|
||||
|
||||
<p>Порядок работы, вроде бы, ясен: разработчик получает карту и отрисовывает её, опираясь, если это необходимо, на нужные метаданные.</p>
|
||||
|
||||
<p>Однако, очевидно, с точки зрения иерархии здесь допущена ошибка: высокоуровневые сущности (карта, атмосферные фронты и области повышенного и пониженного давления) связаны посредством технической сущности - визуальной геометрии объекта, которая по всем критериям должна находиться где-то в самом низу иерархии. Чем это может быть плохо для нас?</p>
|
||||
|
||||
<p>Предположим, завтра у нас появится клиент, которого не устраивает векторное описание геометрии, и которому нужна растровая картинка. Мы окажемся в сложном положении: либо мы создаем параллельное api именно для работы с растром, либо клиенту придётся забирать и растровую картинку, и векторную - вторую только для того, чтобы через нее получить идентификаторы погодных объектов. Если бы иерархия была выстроена правильно (карта погоды отдает идентификаторы объектов, а уже по идентификаторам можно получить геометрии) - достаточно было бы добавить режим "растровое изображение".</p>
|
||||
|
||||
<p>Аналогичные проблемы нас ждут, если в какой-то момент появятся объекты, содержащие более одной геометрии - либо, наоборот, несколько объектов научатся делить одну геометрию. В правильной архитектуре мы просто добавим новые типы ресурсов; в неправильной нам вообще не удастся решить эту ситуацию без слома обратной совместимости.</p>
|
||||
|
||||
<p>Оба этих примера эксплуатируют одну и ТЦ же мысль: в иерархии уровней абстракции верхние уровни являются, как правило, более устойчивыми к разного рода изменениям. В самом деле, если объекты верхнего уровня описывают сценарии использования - они гораздо менее вероятно изменятся с развитием технологии. Потребность "мне нужно узнать прогноз погоды на завтра" никак не меняется уже много тысяч лет.</p>
|
||||
|
||||
<p>Чем универсальнее ваше api в смысле широты тех контекстов, которые вы связываете, тем больше альтернативных реализаций одного и того функционала вам придётся реализовать (см. Пример с растровыми и векторными изображениями) и тем "шире" окажется ваша иерархия уровней абстракции: у вас появится множество объектов, принадлежащих одному уровню; в достаточно большом api неизбежно возникнут поддеревья иерархии - каждая реализация будет опираться на свой, полностью или частично, независимый слой логики.</p>
|
||||
|
||||
<!--
|
||||
<h2>О проектировании API</h2>
|
||||
<h3>Архитектура против реализации</h3>
|
||||
|
Loading…
Reference in New Issue
Block a user