Pull to refresh

XML, RDF и Я.

Reading time 5 min
Views 1.9K
В своем скромном блоге я примерно обрисовал свое отношение к XML-based языкам и DOM. Если вкратце, то после почти года работы с ними в вебе, я пришел к некоторым выводам. В частности что DOM для отображения сложного содержимого веб-страницы подходит как нельзя лучше, но XML, из которого строится эта модель, сам по себе слишком сложен и избыточен. Исходя из подобных заметок, так считаю не только я, но и другие разработчики, а также сам великий и ужасный W3C.


О RDF, я возможно напишу позже. Сейчас я хочу больше заострить внимание на идее неэффективности XML-подобных языков в вопросе представления данных. Эта тема плотно пересекается с преимуществами RDF. Поэтому, как я думаю, эту заметку можно считать иллюстрацией к применению оного.


Начнем с простого примера. Карта с адресами. Ничего сложного в этом нет.
Стандартная реализация представляет собой или XML-дерево, JSON-хэш или банальный JavaScript c координатами на карте, названиями, адресами и прочей информацией. Живые примеры можно увидеть на http://mirtesen.ru/ (здесь используется JSON) или на http://adresa.yandex.ru/ (а здесь JavaScript)


Все это замечательно работает, пока записей у нас немного. Но если количество записей становится большим — у нас тратится время сначала на загрузку файла, а потом на его интерпретацию. Проблема как JSON, так и XML, в том, что они должны быть загружены полностью, прежде чем они смогут пройти валидацию, дабы браузер корректно разобрал их и использовал по прямому назначению. С загружаемым JavaScript-ом дело обстоит несколько радужней, поскольку каждый последующий вызов функции не зависит от предыдущих и в теории может выполнятся в тот момент, пока идет передача файла, не дожидаясь ее окончания. Но, согласитесь, такой способ совсем неизящен, и требует множество лишних телодвижений. Хотя, стоит заметить, он сейчас единственный может использоваться для решения подобного рода задач. По крайне мере по моей информации это так.


При на уровне DOM-а мы без проблем можем обрабатывать входящий поток данных, генерируя их отображение прямо во время передачи. Единственное что нам мешает — невозможность читать построчно ответ сервера :(. Но это обходится увеличением числа последовательных запросов. (Сначала получаем первые 20 записей, потом получаем записи с 21-й по 40-ю и т.д.). Распространенные форматы передачи данных справляются с этой задачей не так уж и плохо: мы получаем полностью первую двадцатку записей, отрисовывем их полностью, получаем вторую двадцатку, отрисовываем их. И так пока мы не изобразим все записи. Неплохо? Не совсем. Чем больше информации нам надо отобразить — тем хуже мы получаем ситуацию. Почему? Попробую объяснить на примерах.


Обычное XML дерево
выглядит следующим образом:
<root>
	<element>
		<parameter>
			<name>ID</name>
			<value>1</value>
		</parameter>
		<parameter>
			<name>Title</name>
			<value>Первый элемент</value>
		</parameter>
		<parameter>
			<name>Xcoord</name>
			<value>100</value>
		</parameter>
		<parameter>
			<name>Ycoord</name>
			<value>100</value>
		</parameter>
		<parameter>
			<name>Description</name>
			<value><![CDATA[ ... ]]></value>
		</parameter>
		...
	</element>
	<element>
		<parameter>
			<name>ID</name>
			<value>2</value>
		</parameter>
		<parameter>
			<name>Title</name>
			<value>Второй элемент</value>
		</parameter>
		...
	</element>
	<element>
		...
	</element>
...
</root>

Возможно я его чересчур усложнил, но мне кажется так оно лучше передаст мою мысль. (Заранее прошу простить меня за возможные очепятки и ошибки. Я RDF на практике еще не использовал. Вместо него у меня имеется убогая самописная функция, что по лаконичности не может сравнится с синтаксисом третьей нотации, но использует аналогичные идеи.) Теперь переведем его в третью нотацию RDF:

@prefix : <#> .

:element_1 a :Element .
	:element_1 :ID 1 . 
	:element_1 :Title "Первый элемент" .
	:element_1 :Xcoord 100 .
	:element_1 :Ycoord 100 .
	:element_1 :Description " ... " .
:element_2 a :Element
	:element_2 :ID 2 .
	:element_2 :Title "Второй элемент" .
	...
:element_3 a :Element
...

Или, если записать более лаконично:

@prefix : <#> .

:element_1 a :Element ; :ID 1 ; :Title "Первый элемент"; :Xcoord 100 ; :Ycoord 100 ; :Ycoord 100 ; :Description " ... " .
:element_2 a :Element ; :ID 2 ; :Title "Первый элемент"; :Xcoord 200 ; :Ycoord 200 ; :Ycoord 100 ; :Description " ... " .
:element_3 a :Element ; :ID 3 ; :Title "Первый элемент"; :Xcoord 300 ; :Ycoord 300 ; :Ycoord 100 ; :Description " ... " .

Также вы можете посмотреть другие примеры синтаксиса третьей нотации, дабы убедится, что я вас не обманываю или почерпнуть что-нибудь для себя.

Я хочу обратит внимание, что в записи нет упоминания корневого элемента, без которого не обходится ни один XML-файл. На более лаконичный синтаксис, наверное можно не обращать внимания. При желании XML тоже можно утрамбовать. Одно из отличий — уникальное название элементов. Это важно, несмотря на то, что с первого взгляда никаких принципиальных отличий нет. Ну, может, стало чуть читабельнее, расположно по-другому, ну и все. Ан нет. Уникальные имена элементов позволяют нам сделать один фокус — мы теперь можем отсортировать все выражение в нужном нам порядке. К примеру:

@prefix : <#> .

:element_1 a :Element ; :ID 1 ; :Xcoord 100 ; :Ycoord 100 .
:element_2 a :Element ; :ID 2 ; :Xcoord 200 ; :Ycoord 200 .
:element_3 a :Element ; :ID 3 ; :Xcoord 300 ; :Ycoord 300 .
...
:element_1 :Title "Первый элемент" .
:element_2 :Title "Второй элемент" .
:element_3 :Title "Третий элемент" .
...
:element_1 :Description " ... " .
:element_2 :Description " ... " .
:element_3 :Description " ... " .
...


Что нам дает подобный финт ушами? Почти ничего при использовании его с небольшими объемами данных. Но если данных много, то веб-приложение (на примере той-же карты с метками), начинает себя вести иначе. Вместо того чтобы полностью отображать метку за меткой, как в случае загрузки данных с помощью JSON или XML? оно получает возможность сначала отрисовать все метки, привязать к ним события и выделить место в памяти для других данных, после чего постепенно наполнить их данными. Показать названия, затем описания, после чего подгрузить картинки… список можно продолжать долго. При этом веб-приложению никто не мешает форсировать получение данных по произвольному объекту, если пользователь проявил к нему интерес, запросив во второй поток данные по какому-то конкретному элементу, ибо ID у нас загружается в первую очередь. Если интерполировать подобный пример на большое действующее приложение, мы увидим возможность получить последовательную детализацию практически для любых задач — пользователь может начать взаимодействовать с веб-приложением, не дожидаясь окончательной загрузки данных. И при этом продолжать взаимодействие, не запрашивая данные на каждый чих. Неплохо, не так ли?

Тем кого я не убедил во всей прелести подобных фишек, я приведу еще пару доводов. Во первых несмотря на то, что подобная система вполне может быть реализована и без введения всяких RDF-ов, все равно придется использовать или скрипты в ответе сервера для эмуляции чего-то подобного, или делать несколько последовательных запросов. Во-вторых синтаксис RDF очень похож на вывод результата из баз данных и позволяет не привязываться к контексту. На практике это может породить такую ситуацию, что результаты первого запроса уже будут обработаны в браузере, пока последний запрос к базе еще не закончил свое выполнение. Разве не прелестно?


ЗЫ Если я в чем не прав — поправте меня, буду признателен.
ЗЫЫ а оригинал лежит здесь

Tags:
Hubs:
+8
Comments 23
Comments Comments 23

Articles