1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-04-11 11:02:05 +02:00

Информационные контексты

This commit is contained in:
Sergey Konstantinov 2015-07-05 21:54:14 +03:00
parent a889de9151
commit aaf6bf6d91

View File

@ -352,6 +352,29 @@
<p>В пределе в сложном api должна сложиться ситуация, при которой все объекты взаимодействуют друг с другом только как интерфейсы — нет ни одной публичной сигнатуры, принимающей конкретный объект, а не его интерфейс. Разумеется, достичь такого уровня абстракции практически невозможно - почти в любой системе есть глобальные объекты, разнообразные технические сущности (имплементации стандартных структур данных, например); наконец, невозможно «спрятать» за интерфейсы системные объекты.</p>
<h3>Информационные контексты</h3>
<p>При выделении интерфейсов и вообще при проектировании api бывает полезно взглянуть на иерархию абстракций с другой точки зрения, а именно: каким образом информация протекает через нашу иерархию.</p>
<p>Вспомним, что одним из критериев отделения уровней абстракции является переход от структур данных одной предметной области к структурам данных другой. В рамках нашего примера через иерархию наших объектов происходит трансляция данных реального мира - географическое положение и реальные свойства транспортного средства - через добавление высокоуровневых опций (вид иконки этого транспортного средства) в графические примитивы конкретной платформы (svg-оверлей, заданный в пиксельных координатах сцены).</p>
<p>Мы уже отмечали, что одним из недостатков нашей первой "наивной" реализации api была необходимость объекту source "знать" о том, как осуществляется преобразование данных (геокоординат в пиксели). Если это правило обобщить, оно будет выглядеть следующим образом:</p>
<ul>
<li>каждый объект в иерархии абстракций должен оперировать данными согласно своему уровню иерархии;</li>
<li>Преобразованием данных имеют право заниматься только те объекты, в чьи непосредственные обязанности это входит.</li>
</ul>
<p>Из этих правил явно следует, что в нашей системе source имеет право оперировать только географическими координатами, а оверлей - только пиксельными. Оперировать и теми, и другими имеет право только объект, реализующий оба интерфейса IGeoContext и IGraphicalContext, то есть Map. Аналогично, source имеет право оперировать только свойствами реальных транспортных средств (идентификационный номер), оверлей - только свойствами их графического представления (иконка, её размер), и только Vehicle может связать идентификатор объекта со свойствами его графического представления.</p>
<p>Достаточно внимательный читатель в этом месте может заметить, что правило информационной иерархии всё равно нарушается: объект высшего уровня Map оперирует данными низшего уровня абстракции - пикселями сцены, и будет совершенно прав. Конечно, в нашем умозрительном примере это совершенно излишне, но в реальном "большом" api карту от этого знания необходимо избавить.</p>
<p>Для этого необходимо ввести некоторую промежуточную сущность, которая, с одной стороны, будет следить за изменением области картографирования и предоставлять методы трансляции геокоординат в пиксели сцены; с другой - предоставлять графическим примитивам холст для рисования - родительский svg-элемент в нашем случае.</p>
<p>Назовем такую сущностью, скажем, IRenderingEngine; в нашей иерархии это. Интерфейс займёт промежуточное положение между картой и графическими объектами. Тогда ответственностью карты как IGraphicalContext будет предоставление доступа к своему rendering engine; соответственно, оверлей будет работать уже не с IGraphicalContext, а именно с engine; связывание же оверлея с его графическим контекстом должен произвести тот, кто оверлей инстанцирует - в нашей системе это может быть либо vehicle, либо сам графический контекст, либо какая-то третья сущность, которую мы выделим специально для этого.</p>
<p>Дерево информационных контекстов (какой объект обладает какой информацией, и кто является транслятором из одного контекста в другой), по сути, представляет собой "срез" нашего дерева иерархии интерфейсов; выделение такого среза позволяет проще и удобнее удерживать в голове всю архитектуру проекта.</p>
<!--
<h2>О проектировании API</h2>
<p><em>Зачем</em> такому сервису API?</p>