пятница, 21 декабря 2007 г.

Пример техники XML+XSLT+AJAX

Обзор.
Данная техника использует перобразование
данных формата XML в представление HTML
используя JavaScript в браузере клиента.


Как это делается.

1) Данные записываются в файл формата XML.
В нашем случае, это список книг.

2) Способ преобразования XML в HTML записывается
в файл XSLT. То есть делается разделение представления
от данных.

3) На клиент загружается сценарий JavaScript,
который состоит из следующих компонентов:

а) Функция ajax - для получения данных с сервера.
В зависмости от браузера используются различные
объекты для использования AJAX.
Internet Explorer:
xmlDoc = new ActiveXObject("Microsoft.XMLHTTP")
Mozilla/Opera:
xmlDoc = new XMLHttpRequest()
б) Функция xsltProcessor - создает объект разборщика XML
Для разных браузеров различные объекты:
Internet Explorer:
var xsldoc = new ActiveXObject("Microsoft.XMLDOM")
Mozilla/Opera:
var xsltProcessor = new XSLTProcessor()

Причем для доставки XSLT в случае Mozilla/Opera используем
функцию ajax, я для IE метод load объекта Microsoft.XMLHTTP.

По адресу http://www.w3schools.com/xml/xml_parser.asp
можно найти пример другого кросс-браузерного решения.

в) Подфункцию _onXslLoad, которая выполняется после загрузке XSLT.
_onXslLoad применяет правила XSLT к XML и в результате получается
HTML, который размещается на странице.


Рисунок 1 - UML Sequence Diagram

Выводы.
Плюсы:
* Разделение представления с данными и логикой является важным преимуществом.
* Возможность делать преобразования данных в представление на клиенте позволяет
делать динамические станицы без сервера приложений.
* Сокращение объема передаваемых данных.

Минусы:
* Нет "шаблонов" в привычном понимании, т.е. HTML-файлов с какой-либо разметкой для
размещения данных. Для изменения внешнего вида нужен дизайнер со знанием HTML-XML-XSLT,
а в случае традиционных шаблонов возможно использование редактора HTML типа MS FrontPage,
Adobe Dreamweaver и т.д.
* Возрастает нагрузка на браузер клиента.

Файлы:
index.htm
menu.xml
menu.xsl

четверг, 20 декабря 2007 г.

1-2-3 AJAX+DOM+JSON = Web-разботка становится интереснеера

Web-разработчики привыкли, что сценарии JavaScript в web-обозревателе
перегружаются вместе с HTML-документом. А перегрузка происходит
при путешествии по содержимому какого-либо сайта.
Таким образом: объекты, функции, переменные имели такое же время жизни,
как и отображаемый документ. Это делало работу сценариев JavaScript
похожими на сценарии серверной стороны, таких как PHP, Python, Perl.
Правда объекты, функции, переменные вообще живут только во время
исполнения сценария на сервере. А клиентский JavaScript пока отображается
страница способен на "диалог" с пользователем, например, обеспечивает
какой-нибудь визуальный эффект или проверяет поля формы.

1) Применение AJAX, как известно, позволяет делать
запросы к серверу без берегрузки документа, т.е. подкачивать данные.
В этом случае объекты JavaScript могут "жить" до тех пор
пока не будет закрыто окно браузера. Это делает web-страницу
больше похожим на настоящее приложение опереционной системы.
Их так и стали называть - web-приложения.
Иметь постоянно существующие объекты JavaScript на стороне
делает web-разработку гораздо интереснее и, даже, как-то серъезнее (IMG:style_emoticons/default/smile.gif) .

Современные браузеры имеют развитую объектную модель
документа(DOM), позволяющую легко манипулировать содержимым
документа. А формат представления данных JSON обеспечивает
легкий обмен структуированной информацией между клиентом и сервером.

Пример:


I Этап
На клиенскую часть загружается:
1. Объект обеспечивающий коммуникацию(AJAX)
2. Объект умеющий преобразовывать данные в отображаемый HTML
и собирать данные из HTML в JSON

II Этап
1. Дается запрос на получение данных(JSON)
2. Объект-разборщик преобразует JSON в HTML ипользуя
методы DOM(например createElement, createTextNode, appendChild)

||| Этап
После того, как были произведены какие-либо изменения
в отображаемой информации:
1. Производится сборка данных из HTML
и упаковывается в JSON
2. JSON отсылается на сервер

Замечание.
С сервера можно присылать не только какую-нибудь структуру данных,
но и целый объект(без методов конечно). Тогда после манипуляций
с аттрибутами этого объекта его можно отослать на сервер
где его состояние будет сохранено в БД.

Пример техники AJAX+DOM+JSON.

Обзор.
Данная техника использует формат представления
данных JSON, AJAX для доставки данных и
методы DOM при отображении даннх клиенту.

Как это делается.

1) Создается экземпляр объекта-конструктора ajax и с помощью него
посылается запрос на сервер за JSON-данными(файл "menu.js").

2) После загрузки JSON вызывается функция onJsonLoad,
которая преобразует JSON-текст в объект и используя методы
DOM производит отображение данных согласно заданным правилам.

Примечание.
Для преобразования JSON-текста в JSON-объект используется
функция parseJSON из библиотеки проекта json.org.

Выводы.

Плюсы:
* Данные могут закачиваться по требованию.
* Формат JSON очень прост.

Минусы:
* Правила отображения данных жестко "вшиты" в код программы,
для отделения логики от представления необходимо применить
технику шаблонов.

Файлы:
index.html
menu.js

воскресенье, 16 сентября 2007 г.

JavaScript на сервере - возможные перспективы.

Начало: Netscape Enterprise Server

Весной 1996 году компания Netscape Communications Corporation представила
промышленный web-сервер Netscape Enterprise Server (NES)
, первый сервер способный исполнять код Java и JavaScript.
Осенью 1996 года была анонсирована
бета-версия Microsoft Internet Information Server (IIS),
который поддерживал несколько скриптовых языков, в т.ч. и JavaScript.
Т.е. начиная с 1996 была доступна возможность писать на стороне сервера на JavaScript.


JavaScript не для сервера?

Но, NES не стал массово используемым сервером, быть может из-за цены
(цены начинались от 995$). А компания Microsoft всегда продвигала
основным скритовым языком свой продукт - Visual Basic Script(VBScript).
Львиную долю рынка web-серверов тогда и сейчас занимал web-сервер Apache.
Apache поддерживал любые сценарии и исполнение кода на сервере через механизм
CGI.
А так же через модули. Самым популярным серверным скритовым языком
был PERL, а затем им стал PHP.
Так сложилось, что никто не воспринимал возможность написания
сценариев на JavaScript серьезной. JavaScript всегда ассоциировался
с парой функций в браузере, а не как серьезный скриптовый язык.
JavaScript стал основным и единственным языком для написания
сценариев для web-браузера, несмотря на попытки со стороны Microsoft
заменить его на VBScript. И даже после падения Netscape,
JavaScript в браузерах уже невозможно было заменить на что-то другое.

Вернется ли JavaScript на сервер?

Итак, JavaScript стал одним из самых распространенных языков.
Например, в Windows XP мы можем найти поддержку JavaScript,
само собой, в Internet Explorer, еще в Windows Script Host
и в IIS, точнее в ASP.NET.
Что же с серверным JavaScript? Сегодня доступно много
решений. Пока не одно из них не может покол(вырезано антиматом) господство PHP в сфере
Internet-решений и JSP(Java) на корпоративном рынке.
В последнее время набирает популярность техника AJAX,
использование которой подразумевает собой активную манипуляцию DOM и написание более сложных скриптов.
Идея об использовании JavaScript на сервере обретает смысл, так как
открывается возможность использовать один язык для клиента и сервера.

В статье Линды Дейли Полсон
говорится о том, что растет популярность динамических(скриптовых) языков.
Хороший пример этому - PHP, который стал популярен не только
для небольших Internet-решений, но с выходом 5-ой версии,
замахивается на решение более комплексных задач.
Итак, если JavaScript вступает в схватку с PHP, то придется нелегко.
Сейчас у PHP огромная армия программистов,
готовых решений и хостеров. На корпоративном рынке есть надежды
на проект Phobos Glassfish.
Появление этого проекта подталкивает к подозрениям насчет того, что
компания Sun Microsystems планирует внедрить использование JavaScript и
других скриптовых языков в платформе Java, подобно тому,
как .NET позволяет использовать многие языки. Тогда Sun получит
преимущество, так как платформа Java будет поддерживать не только
много ОС, но и много языков, а .NET много языков и только одну ОС - Windows.

вторник, 28 августа 2007 г.

Пример работы замыкания.

На одном из форумов поднята следующая тема:
при использовании объекта XMLHttpRequest нет доступа
к свойствам текущего объекта.
Метод loadXml создаёт объект xmlDoc, который применяется для
получения данных с сервера в технике AJAX.

У xmlDoc есть свойство "onreadystatechange", которое должно быть
функцией. И является блоком кода, который вызывается объектом xmlDoc
при изменении статуса запроса к серверу.

Вопрос в том - Как xmlDoc вызывает эту функцию, как метод текущего объекта xmlTree
или по другому? Судя по тому, что в xmlTree не сохраняется свойство "this.a",
то "this" это не объект xmlTree.
Как выяснилось, в разных браузерах(в связи с разной реализацией объекта xmlHttpReqiest)
запуск кода "onreadystatechange" происходит в разном контексте.

В Mozilla код запускатеся в своём собственном объекте, не связанном
ни с чем. Проверяем дописывая в метод "process":

var s=""; for (i in this) s+=i+"="+this[i]+"\n"
alert(s)


В IE 6 запускается в контексте объекта window:

alert(this == window)

А в IE7 и Opera запускатся как метод объекта xmlHttpReqiest(у нас xmlDoc),
и написав:

alert(this.onreadystatechange)

в "process" можно увидеть код самого же вызвавшего alert метода.

Итого, код запускатся в чём угодно, но не в контексте xmlTree.

Для решения этой проблемы советуют использовать замыкание(closure)
слудующим образом:

function xmlTree()
{
function loadXml(url, parameters)
{
xmlDoc = new ActiveXObject("Microsoft.XMLHTTP")
var x = this
xmlDoc.onreadystatechange = function(){ x.process() }
xmlDoc.open( "GET", url+"?"+parameters, true)
xmlDoc.send( null )
}

function process()
{
if (xmlDoc.readyState!=4) { return }
this.a = 10
}

this.a=0
this.loadXml=loadXml
this.process=process
}


Т.е. переменной "х" присваивают текущий объект,
а свойству "onreadystatechange" присваивают анонимную(без названия) функцию
в которой происходит вызов "process" как метода "x": x.process().
И это действительно помогает!

Что происходит? Почему так работает и теперь "myTree.a" равно "10"?

Попробуем разобрать поподробнее:
1) При выполнении x = this происходит не присваивание x текущего объекта this,
а создаётся ссылка(в JS всё ссылка), то есть "x" не клон объекта-экземпляра
xmlTree, а ссылка на него.

2) Когда xmlDoc вызывает анонимную функцию, то внутри нее присходит
вызов метода process объекта "x". При этом изнутри анонимной функции
"видны" все переменные внешнего контекста, поэтому и возможен вызов "x.process".

3) Во время отработки "process" как метода "х" "this" является ссылкой
на объект "х", который в свою очередь является ссылкой
на объект "xmlTree". Т.е. все изменения сделанные в "х" отражаются
и в "xmlTree".

Рисунок 1

среда, 25 июля 2007 г.

Перевод заметки "Prototype Based Object-Oriented Programming"

Основанное на прототипах программирование может быть описано, как
объектно-ориентированное программирование, но есть еще что-то большее.
Основанные на прототипах языки и системы состоят из объектов, которые
содержат(абстрактно) в себе описания самих себя, в отличии от классических
объектно-ориентированных систем, в которых объекты описываются классами.
Для этого для объектов используются ассоциативные массивы.
Они, конечно, динамически рассширяемые, и вы так же можете добавлять в них
методы. Вы можете делать это так же динамически, что невозможно в
в статических(основанных на классах) ОО языках.

Основанные на прототипах ОО методы концептуально проще, чем основанные на
классах ОО, но и являются более мощными.


Основанное на прототипах программирование - Wikipedia
Прототипно-ориентированное, или чаще: основанное на прототипах
программирование, - это особый стиль объектно-ориентированного
программирования. Первым примером языка основанного на прототипах был язык
Self, наработки которого затем были скопированны в других проектах,
таких как, языки программирования Cecil, JavaScript, NewtonScript, Io и MOO.

Традиционные ОО

В традиционных ОО системах, объекты бывают двух основных типов.
Классы организуют основную структуру и функциональность других объектов,
а экземпляры являются "используемыми" объектами, основанными на образце,
который заложен в конкретный класс. Использование такой системы обычно подразумевает разработку
необходимых классов, а затем написание программы, которая создаёт различные экземпляры этих классов для работы с ними
пользователя.

Если вы посмотрит в внутрь компьютера, то вы быстро сможете увидеть причину этой
дихтомии
Классы, фактически, являются коллекциями кода для объектов, который одинаков
для всех экземпляров, поскольку экземпляры являются коллекциями памяти, в
которых хранятся данные объектов, которые отличают их друг от друга(концепция
известная как состояние). Такая модель в основном работает хорошо с
традиционными компиляторами и языками, когда сначала в основном пишут код и
затем этот код манипулирует данными.

Для примера, скажем, вы делаете приложение-записную книжку, которое сможет
звонить людям. Вы должны иметь класс "Человек" для хранения списка людей.
Люди имеют имена и телефонный номер. Если вы посмотрите на такую программу, то
найдете, что ваш "Человек" представлен блоком памяти с кодом для дозвона по
телефону и различные экземпляры(Боб, Мария и т.д.) являются блоками памяти с именами
и телефонами с указателями на их класс. Когда вы говорите системе
позвонить Бобу, то она посмотрт телефон Боба из данных экземпляра и затем
обратится по указателю к методу дозвона в классе "Человек".

Однако такие системы имеют серьезные проблемы, которые становятся
заметными когда размеры системы начинают расти. Программы редко остаются
статическими и постоянная структура исходного класса становится менее полезной.
В результате этого все больше кода добавлятеся в новые классы, что в большинстве
негативно сказывается на свойствах и ОО систем.

Было бы проще, если бы ваша программа могла изменить описание этих низлежащих
классов, но в большинстве систем они находятся в скомпилированном коде,
что не позволят их изменить.

Прототипные

Прототипные языка избегают этой проблемы обходясь без дуализма
, который рождает проблему. Вместо содержащих данные экземпляров и
содержащих функции классов они имеют только объекты и ничего кроме объектов.

Для того, чтоб получить новый объект вы делаете копию одного из уже
существующих. Все такие системы начинают работу с всего лишь одного загруженнго объекта,
но все они имеют список общеиспользуемых объектов, работа с которыми позволяет их делать более
похожими на традицонные системы. Когда вы копируете какой-либо объект, то вы получаете
совершенно новый объект, который, однако, имеет такие же свойства, как его оригинал. Вместо
указателя на класс, этот новый объект содержит указатель на объект, который создал его.

Фактически новый объект, в большинстве своем, пустой. Он только тогда начинает
расти в памяти, когда программа менят его. Это совершенно отлично от
традиционных ОО систем, где каждый экземпляр класса всегда резервирует
известное количесво памяти. Здест базовый объект состоит только из
одного указателя.

Дополниетльный данные могут быть добавлены в объект в любое время. Если вы
хотите, чтоб ваш новый "Человек" имел имя "Боб", то вам нужно только добавить
его. Объект, начиная с этого действия, начнёт расти для сохранения
требуемых данных.

Есть одно очень важное различее с обычными языками. Объект увеличивается только
тогда, когда необходимо добавление чего-либо в объект. Хотите, чтоб объект
"Боб" имел номер сотового телефона? Сделайте это. Мари имеет номер факса?
Отлично. Фактически каждый объект такой системы стремится стать отличным от
других, не только данными, но и тем как данные в него были записаны.

Также важно рассмотреть то, что правило "добавить что-то" применимо и к методам.
Если объект "Мари" нуждается в методе, котрый никто не имеет, скажем "послать факс",
то вы можете добавить его используя такую же методолгоию. Вот почему многие основанные на
прототипах языки описывают и данные и методы, как "слоты".

Основынные на прототипах языки стремятся начинать с выбора базовых объектов,
которые затем вы сможете копировать. В основном эти объекты имеют тенденцию иметь
только описание методов, полагая, что прграммист добавит нужные данные.
Для примера, объект "Точка", который может помнить координаты на экране, так
же может содержать методы для добавления и стирания точек, но он не будет
содержать значения X и Y, их добавит программист индивидуально для каждой копииобъекта.

Как результат всего этого мы имеем огромную гибкость. Ошибки в методах
существующих объектов могут быть легко исправлены простой посылкой нового кода
(в форме блоков) в соответствующий "слот". Вы можете изменить любой объект в
другой, заменяя методы в такой же манере.

Разработка классов становится более простой задачей, потому, что вы можете легко
изменять описание "класса" в любое время и, что более важно,
из любого приложения( т.е. одно приложение может исправлять ошибки в
конкректном объекте и никому больше не будут видны эти исправления).


Copyright © 1996-2007 by Dr. Nikolai Bezroukov.

вторник, 24 июля 2007 г.

MVC Web-приложения vs. Web публикация БД

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

1) Получить запрос клиента на информацию
2) Составить запрос к БД
3) "Обернуть" ответ в HTML и послать клиенту.


Широко используется процедурный подход: пишутся функции под часто используемые
нужды и т.п.


Можно работать в ООП-стиле: разработать набор классов, отвечающих за
разнообразный функционал: анализатор запросов, генератор SQL-запросов,
обработчик шаблонов и т.п.

В определённый момент развития системы, встаёт вопрос не только разделения
логики от представления, но и применения более многоуровневой архитектуры.
Самая популярная и хорошо себя зарекомендававшая архитектура - это
Модель-Вид-Контроллер(Model-View-Controller) - MVC.
MVC подразумевает создание модели предметной области, т.е.
иерархии классов, соответсвующих реальным обьектам проблемной области.
Т.е. применение ООП.

Представим, что у нас есть система обмена сообщений, что-то типа форума.
Есть пользователи и сообщения. То есть в БД 2 сущности: users, messages
(см. рисунок с ER).

Например, нужно показать сообщение с ID равным "1". В случае публикации БД:
даём запрос по двум таблицам:
SELECT subject, text, user.name, user.surname FROM message
LEFT JOIN user ON message.fk1_login=user.login WHERE message.id=1';
2) Полученный результат в HTML и дело сделано.

В случае с моделью(см. рисунок с диаграммой классов):
1) Создаём экземляр класса сообщения с идентификтором "1"
2) Создаём экземпляр класса пользователя, используя свойство объекта
сообщения

"userLogi_message = new Message(1)
_user = new User(_message.userLogin)n".
Вытаскиваем у объектов _message и _user нужные свойства,
обёртываем в HTML, посылаем клиенту.

При этом при создании экземпляров классов "User" и "Message"
произойдут два запроса(в конструкторах объектов):

1) SELECT subject, text, fk1_login FROM message WHERE id=1;
2) SELECT name, surname, login FROM user WHERE login='soul';

Рисунок 1 - ER-диаграмма

Плюсы и минусы на первый взгляд.

1 случай:
+ высокая скорость(нужен один сложный запрос)
- под каждое представление необходимо формирование своего SQL-запроса

2 случай
+ работаем с объектами модели, а не с БД, что ближе к естественному мышлению
- низкая скорость(происходит несколько простых запросов к БД)


Первый случай, является так называемой публикацией БД в Web,
подходит для небольших задачь.

Второй случай позволяет думать в объектно-ориентированном стиле,
строить более сложные системы.



Рисунок 2 - Диаграмма классов

Добавим в систему возможность объеденения пользователей в группы.
Соотв. в БД появляется сущность "group", а в классовой модели класс "group"
с методами "addUser" и "removeUser" для добавления и удаления
пользователей в группу.

Выводим сообщение c идентификатором "1", а так же
указываем имя, фамилию пользователя и группу, к которой он пренадлежит.

Рисунок 3 - Развитее системы, ER-диагарамма

1. Без объектов модели:
select subject, text, user.name, user.surname, group.name FROM message

LEFT JOIN user ON message.fk1_login=user.login
LEFT JOIN `group` ON user.fk1_group_id=group.id WHERE message.id=1;


2. Через объекты:

_message = new Message(1)
_user = new User(_message.userLogin)
_group = new Group(_user.groupId)


Все нужные нам данные находятся в трёх объектах.

Gри создании экземпляров классов "User", "Group" и "Message"
произойдут три запроса(в конструкторах объектов):

1) SELECT subject, text, fk1_login FROM message WHERE id=1;
2) SELECT name, surname, login FROM user WHERE login='soul';
3) SELECT name FROM `group` WHERE id=1;

Рисунок 4 - Развитее системы, диаграмма классов

Наибольший интерес представляет собой построение самой системы.
На рисунке попытка изобразить из чего состоят разные компоненты системы MVC.

Модель.
Модель содержит в себе так называемую бизнес-логику, то есть логику связанную
с конкретным делом, для которого предназначена программная система.
Логика содержиться в БД(первичные и внешние ключи, триггеры, хранимые процедуры) и
в программных классах, изложенная на каком-либо прикладном языке программирования.

Платформа.
Это может быть созданные разработчиком функции, классы, библиотеки, фреймворки предназнеченные
для решения поставленной задачи согласно выдвинутым требованиям.
Причём разработанная платформа может затем применятся для разработки системы в другой
проблемной области, для которой разрабатывается другая модель.

Рисунок 5 - Архитектура системы

Переход к сервис-ориентированной архитектуре.

Контроллер с моделью можно представить, как службу, обращение к которой происходит
по какому-либо протоколу.
При этом представления могут находится в различных системах(клиентах службы), которые так-же могут иметь свои собственные
контроллеры, какую-либо свою архитектуру.



Рисунок 5 - Сервис-ориентированная архитектура

четверг, 19 июля 2007 г.

Два порта Ruby On Rails на Javascript, для тех, кого не устраивает "R" в RoR

Сотрудник Google Steve Yegge перенёс код фреймворка Ruby on Rails на язык JavaScript.
John Lam на своём сайте сообщает, что Steve Yegge за 6 месяцев сделал
порт RoR, затратив на это 2000 часов.
Steve Yegge хотел использовать RoR в Googe, но Google не хочет увеличивать количиство используемых языков в компании(C++, Java, Python, JavaScript), поэтому Steve принял решение портировать фреймворк на JavaScript - сообщает John Lam.

Это уже второй проект портирования RuR на JavaScript, первым является проект TrimPath Junction сделанный Stive Yen. Проект был начат в 2005 г. и недавно, после большого перерыва, вышла новая версия, в которой серверная часть работает поверх JavaScript фреймворка Helma.

суббота, 19 мая 2007 г.

JavaScript - Корни прототипов

Вычислитеольная модель наследования основана на понятии класса. Однако можно положить
в основу вычислительной модели понятие объекта. Объектно-оринетрированная вычислительная
модель структуирует объекты в виде агрегативных иерархий. Всякий раз, когда составной
объект(внешний объект) не в состоянии выполнить задание самостоятельно, он может вызвать методы
одного из его компонентных объектов(внутренних объектов) - это называется делегированием
(delegation).

При подходе основанном на делегировании, функциональные возможности системы реализуются с
помощью включения (клонирования) функций существующих объектов во вновь требуемые функции.
Существующие объекты трактуются как прототипы для создания новых объектов.
...
Системы, построенные подобным образом из существующих объектов-прототипов, называются
системами-пртотипами.
....
С точки зрения повторного использования делегирование сильно приближено к наследованию.
...
Разница состоит в том, что - в случае наследования - после завершения обслуживания управление
всегда возвращается к объекту, которыы получает исходное сообщение(запрос на обслуживание).

В случае делегирования после того, как управление передано от внешнего объекта внутреннему
объекту, оно остаётся у последнего.

...
В пользу делегирования можно привести тот аргумент, что непредусмотренное
разделение более естественно и ближе человеческому способу мышления.

Из:
Лешек А. Мацяшек "Анализ требований и проектирование систем" изд. "Вильямс", 2002 . - 428 с. М.
стр. 229-230 "Делегирование или наследование"