Не, JavaScript неудобен своей динамической типизированностью. Кроме того, остаётся не совсем ясным, как автоматически вынести логику, реализованную на сервере на javascript, на клиент. В Java есть аннотации и т.п. Можно прочитать байт-код. Можно через reflection API поковыряться к любом классе. А в javascript, где всего этого нет, даже и не знаю как поступить…
Кстати, не такая уж далёкая от практики идея. Я сейчас занимаюсь чем-то похожим (пишу преобразователь байткода в JS) с вполне практической целью. Всё началось, когда я задумался, как в своём фреймворке сделать валидацию форм так, чтобы не надо было дублировать код на сервере (Java) и на клиенте (JavaScript). Всяческие аннотации для типовых случаев не всегда спасают, плюс они как-то плохо сочетались с локализацией. В итоге мысль пошла именно в сторону преобразования байт-кода в JS. И тут открылись ещё несколько интересных вещей:
1. Помимо валидации, на клиент можно тащить ту часть логики, которая не зависит от БД. Например, в форме редактирования статьи есть кнопка «предпросмотр», которая без JS просто отправляет форму на сервер, а сервер формирует ту же страницу редактирования, но уже с предпросмотром статьи. Фактически, от сервера тут требуется распарсить вики-разметку и по ней сгенерировать HTML. Это можно вынести на клиент. Опять же, вынести можно автоматически.
2. Аналогично, научить генерировать JavaScript можно шаблонизатор. Эту возможность я планирую использовать всё для той же обработки форм. На кнопку отправки формы ставится обработчик. Этот обработчик делает AJAX-запрос, который сервер обрабатывает и возвращает параметры, назначенные шаблону, вместо того, чтобы рендерить шаблон. По этим параметрам браузер сам перерисует части страницы, которые изменились. Получаем AJAX, ничего специально для этого не дописывая. При этом можно и отключить JS — в этом случае генерацию страниц возьмёт на себя сервер.
Вообще, странно, что до сих пор такие штуки больше похожи на игрушки. Вон, делают же javascript-бэкэнд для LLVM, а кроме как поиграться никто не рассматривает. Впрочем, с Java всё равно интереснее, так как байт-код можно получить прямо в рантайме.
А никто не отменял XHTML. По сути, HTML5 описывает модель построения документа. Какой синтаксис использовать — XML или SGML — решение уже разработчика. Кстати, проблемы с well-formed XML (как и со всякими детскими уязвимостями, вроде SQL Injection или XSS) из-за неправильных инструментов.
JIT в принципе возможен и для Python и для Javascript (и для последнего есть). Вот только беда в том, что из-за динамической природы языка даже JIT породит не самый эффективный код (я писал об этом выше). Кстати, у дефолтной реализации питона есть ещё одна проблема — подсчёт ссылок. Так что, полагаю, всякие IronPython и JPython должны быть пошустрее, ибо они идут поверх среды, где уже есть и быстрый GC и JIT. А с недавних пор ещё и встроенная поддержка динамических языков.
GWT — это не средство для написания веб-приложений. Это фреймворк для написания RIA. Но не всё есть RIA. И сводить веб к ним — это кощунство. Так вот, GWT только для RIA и предназначен. Он не способен описыват серверную логику, генерацию HTML и т.п. JavaScript в общем случае — это не средство написания RIA. JavaScript позволяет сделать более интерактивным и удобным то, что обычным HTML+CSS сделать таковыми не получается. Скажем, в том же вики-движке можно с помощью JS сделать валидацию форм, кнопки для редактора вики-разметки, более удобный загрузчик картинок. Но это никак не отменяет базового функционала сайта — валидация всё равно делается и на сервере, вики-разметку так же парсит сервер, пусть она даже и набита в обычном text area, а файлы загрузить можно через простой input type=«file». При этом сохраняется главное, на мой взгляд, преимущество веба — за каждой страницей остаётся её адрес. GWT на такое не способен, т.к. в принципе для этого не предназначался. Как я понимаю, Dart выступает заменой JS в его различных сферах применения, а не только как алтернатива GWT.
C другой стороны, проблема дублирования остаётся. Лично у меня появилась идея, как можно её избежать. Ряд действий (валидация, отправка и обновление форм, парсинг вики-разметки при предпросмотре) всё равно делаются сервером. Но на стороне браузера такие вещи обычно оказываются более удобными. Не хотелось бы дублировать код, написанный на Java, ещё и на JS. Идея состоит в том, чтобы автоматически получать JS-версию кода, уже написанного на Java. Для этого можно написать декомпилятор байткода Java в Javascript. Вот каковы варианты использования такой штуки:
1. Валидация форм. Валидацию выполняет контроллер. Если вынести валидацию в отдельный метод контроллера, то этот метод можно преобразовать в JS, который то же самое делал бы на стороне браузера и выдавал бы alert'ы. Это вместо генерирования той же самой страницы, но с сообщениями об ошибках ввода.
2. Частичная перерисовка страниц при отправке формы. Логику генерации разметки так же можно перенести на сторону браузера. Когда пользователь нажимает кнопку отправки формы, очень часто пользователю в ответ выдаётся та же страница по тому же шаблону. Вместо этого браузер мог бы передавать веб-серверу только новые параметры шаблона в ajax-запросе и автоматом перерисовывать часть страницы.
При этом тот же самый функционал остаётся и с выключенным JS. Если же нужно написать что-то более динамическое, работающее именно на клиенте, разработчик может взять в руки JS или GWT — что ему нравится.
Я уже сделал кое-какие наработки в этом направлении. У меня есть свой фреймворк, и в репозитории я выделил ветку, в которой работаю над декомпилятором байт-кода — уже есть первые успехи (почти правильно переписанный на JS метод java.util.ArrayList.indexOf в качестве примера). В перспективе хочется добиться генерации качественного читабельного JS, чтобы не столкнуться с проблемой текучих абстракций, которая присуща GWT.
Например, в Яве крайне неэффективный метод загрузки классов — они загружаются по одному (вдумайтесь!) по мере использования, причем из zip-архивов. Причем для работы даже простой программы нужна куча клакссов из rt.jar. На практике это означает огромное число random access обращений к диску.
Во-первых, курим класслоадеры и вообще подробно изучаем архитектуру загрузки классов в JVM и понимаем, почему так сделаны и откуда вообще могут браться классы. Во-вторых, на практике это ничего не означает. Подобные вещи могут свободно кэшироваться. Если что — можно написать свой мегакласслоадер, который работал бы оптимальнее. Вот только я думаю, что инженеры из Sun Oracle не такие уж дураки и о подобных вещах уже подумали.
Ну не знаю насчёт аренды. У нас на серваке в дисковом массиве один диск стоит моих пары з/п. А так даже не знаю по поводу быдлокодеров. Возможно, если проекты серьёзные, то имеет смысл и высококвалифицированных спецов держать. А то быдлокодер так набыдлокодит, что потом больше потеряешь денег, чем на з/п для спецов.
Или вон фейсбук. Построили же себе датацентр. Тут уже не стоимость аренды. Тут и железо дорогое, и программисты крутые нужны. Которые на C++ пишут.
Что за наглая неправда. Расскажите мне, какой процессор умеет выполнять байт-код явы? Никакой. Потому в реальности перед вызовом самого метода тратится куча инструкций на чтение и разбор байткода, проверку типа объекта, поиск адреса метода.
Вот как раз Ваша реплика содержит неправду. Инструкции разбираются только при первом вызове. Дальше всегда работает только скомпилированный код. Впрочем, там даже всё несколько сложнее на самом деле, и всё только для одного — чтобы получить более быстрый нативный код.
Более того, если мне не изменяет память, кривокодеры из сан в модуле хранят названия методов и классов из других модулей *текстом* а не каким-то идентификатором, так что там еще дополнительные расходы идут на их преобразование в id метода.
Ну и что, что преобразовывать? Один раз ведь! И то, в самом байт-коде хранятся не строковые идентификаторы, а смещения в constant pool. Их вполне можно использовать в качестве идентификаторов. А то, что метаданные вообще хранятся — это правильно, иначе RTTI идёт лесом.
Это, мягко говоря, спорное замечание. Я лично очень слабо себе представляю, как динамическая типизация может существенно уменьшить скорость разработки.
Если нужно вносить изменения в старый код, то статическая типизация порой спасает. Не ото всего, но от многих бед, свойственных тому же Python.
И тем не менее, видал я энтерпрайз, написанный на GWT, который тормозил не на DOM. И даже не на взаимодействии с сервером. Просто мог подвисать секунд на 5 и кушать 100% процессора.
Ну не знаю. Я просто ответил на вопрос. Лично я не считаю, что основное преимущество статической типизации — это быстродействие. Тут важнее скорость разработки. Не скорость выкатывания рабочего прототипа, как на Python, а полноценный жизненный цикл ПО.
Кстати, про серверные. Если нагрузка большая, то никто не мешает купить сервер помощнее, сделать кластер и т.п. А вот у пользователя есть его слабенький нетбук или планшет. Который, заметьте, ещё и батарейку кушает. Так что, быть может, что-то тут есть…
Накладные расходы — из-за того, что язык динамически типизированный. Совокупность методов, которые доступны у объекта, известна только в рантайме. Следовательно, эта совокупность и хранится у самого объекта. У той же Java заранее для каждого типа известен точный набор методов. Это значит, что у объекта хранится только его тип. Теперь что происходит при вызове метода у объекта. В случае JavaScript происходит поиск метода по таблице методов. Это ещё учитывая, что надо перебрать все прототипы. В случае Java заранее известна позиция адреса метода в vtable, так что всё разруливается косвенной адресацией со смещением, которая в том же x86 поддерживается нативно.
Задача анализа кода для динамически-типизированных языков в общем случае алгоритмически неразрешима. Поэтому любые оптимизации работают постольку поскольку и рано или поздно во что-нибудь операции. То же верно относительно IDE. Те, кто говорит «IDE для JavaScript» просто никогда не писали в Eclipse или IDEA на Java. Ну или на C# в VS + Resharper
Во блогозаписях используется один рубленый шрифт (Verdana), а в комментариях — немного другой (Arial)
Пользователи Linux с недоумением смотрят на все эти Arial и Verdana. Тем более, что шрифты внезапно стали с засечками. Наверное, надо было не забыть указать sans и serif в качестве варианта шрифтов для тех, у кого нет Arial и Verdana.
Подозрения в том, что при разработке Хабрахабра не используется DVCS (например, Git или Mercurial) с простым ветвлением кода по мере поступательного внедрения новых функций, а используется простая VCS (например, SVN или даже CVS), так что одни изменения в коде сайта вообще никак нельзя отчленить от других (потому что все изменения, даже сырые, поступательно вносятся в одну и ту же ветку кода, в одну и ту же кучу файлов)
SVN простой? SVN не умеет ветвиться? Да ну, к SVN'у только два крупных нарекания — глючит и тормозит. Просто тут, если действительно SVN используют, его не умеют готовить.
А ещё удручает, что до сих пор абзацы разделяются двумя элементами br а не вносятся внутрь элементов p. Если уж делали изменения, то могли бы и про это вспомнить.
Для своего фреймворка я реализовал похожий мигратор, основанный на fluent-интерфейсе. Для Java есть достаточно известный LiquiBase, но он основан на XML.
Абсолютно всего не знаю. Но вот, скажем, вопрос о типизации языка программирования, на котором я пишу, меня сильно волнует, ибо я знаю, к чему выбор того или иного языка может привести и как с этим потом бороться. А вот без понимания того, что такое асимптотическая сложность, я бы вообще за клавиатуру не пускал. Я никогда не залезал в этих вопросах в дебри, но общее представление получил. Хотя бы из тех же блогов, которые читаю любопытства ради. Подобные вот статьи как раз и пишутся для людей, работающих в совершенно другой области, чтобы они могли получить общее представление — специалистам они ничего нового не рассказывают. Думаю, так же и людям, программирующим микроконтроллеры, будет очень полезно почитать что-нибудь про веб-программирование.
1. Помимо валидации, на клиент можно тащить ту часть логики, которая не зависит от БД. Например, в форме редактирования статьи есть кнопка «предпросмотр», которая без JS просто отправляет форму на сервер, а сервер формирует ту же страницу редактирования, но уже с предпросмотром статьи. Фактически, от сервера тут требуется распарсить вики-разметку и по ней сгенерировать HTML. Это можно вынести на клиент. Опять же, вынести можно автоматически.
2. Аналогично, научить генерировать JavaScript можно шаблонизатор. Эту возможность я планирую использовать всё для той же обработки форм. На кнопку отправки формы ставится обработчик. Этот обработчик делает AJAX-запрос, который сервер обрабатывает и возвращает параметры, назначенные шаблону, вместо того, чтобы рендерить шаблон. По этим параметрам браузер сам перерисует части страницы, которые изменились. Получаем AJAX, ничего специально для этого не дописывая. При этом можно и отключить JS — в этом случае генерацию страниц возьмёт на себя сервер.
Вообще, странно, что до сих пор такие штуки больше похожи на игрушки. Вон, делают же javascript-бэкэнд для LLVM, а кроме как поиграться никто не рассматривает. Впрочем, с Java всё равно интереснее, так как байт-код можно получить прямо в рантайме.
C другой стороны, проблема дублирования остаётся. Лично у меня появилась идея, как можно её избежать. Ряд действий (валидация, отправка и обновление форм, парсинг вики-разметки при предпросмотре) всё равно делаются сервером. Но на стороне браузера такие вещи обычно оказываются более удобными. Не хотелось бы дублировать код, написанный на Java, ещё и на JS. Идея состоит в том, чтобы автоматически получать JS-версию кода, уже написанного на Java. Для этого можно написать декомпилятор байткода Java в Javascript. Вот каковы варианты использования такой штуки:
1. Валидация форм. Валидацию выполняет контроллер. Если вынести валидацию в отдельный метод контроллера, то этот метод можно преобразовать в JS, который то же самое делал бы на стороне браузера и выдавал бы alert'ы. Это вместо генерирования той же самой страницы, но с сообщениями об ошибках ввода.
2. Частичная перерисовка страниц при отправке формы. Логику генерации разметки так же можно перенести на сторону браузера. Когда пользователь нажимает кнопку отправки формы, очень часто пользователю в ответ выдаётся та же страница по тому же шаблону. Вместо этого браузер мог бы передавать веб-серверу только новые параметры шаблона в ajax-запросе и автоматом перерисовывать часть страницы.
При этом тот же самый функционал остаётся и с выключенным JS. Если же нужно написать что-то более динамическое, работающее именно на клиенте, разработчик может взять в руки JS или GWT — что ему нравится.
Я уже сделал кое-какие наработки в этом направлении. У меня есть свой фреймворк, и в репозитории я выделил ветку, в которой работаю над декомпилятором байт-кода — уже есть первые успехи (почти правильно переписанный на JS метод java.util.ArrayList.indexOf в качестве примера). В перспективе хочется добиться генерации качественного читабельного JS, чтобы не столкнуться с проблемой текучих абстракций, которая присуща GWT.
Во-первых, курим класслоадеры и вообще подробно изучаем архитектуру загрузки классов в JVM и понимаем, почему так сделаны и откуда вообще могут браться классы. Во-вторых, на практике это ничего не означает. Подобные вещи могут свободно кэшироваться. Если что — можно написать свой мегакласслоадер, который работал бы оптимальнее. Вот только я думаю, что инженеры из
SunOracle не такие уж дураки и о подобных вещах уже подумали.Или вон фейсбук. Построили же себе датацентр. Тут уже не стоимость аренды. Тут и железо дорогое, и программисты крутые нужны. Которые на C++ пишут.
Ага, и к этому серверу обслуживающий персонал. Которому тоже нужно платить з/п.
Run time type information? А я как бы про compile time говорил.
А как там с параметрическим полиморфизмом aka generics? Например, я хочу вызвать метод, который возвращает список. Как узнать тип элементов списка?
Вот как раз Ваша реплика содержит неправду. Инструкции разбираются только при первом вызове. Дальше всегда работает только скомпилированный код. Впрочем, там даже всё несколько сложнее на самом деле, и всё только для одного — чтобы получить более быстрый нативный код.
Ну и что, что преобразовывать? Один раз ведь! И то, в самом байт-коде хранятся не строковые идентификаторы, а смещения в constant pool. Их вполне можно использовать в качестве идентификаторов. А то, что метаданные вообще хранятся — это правильно, иначе RTTI идёт лесом.
Если нужно вносить изменения в старый код, то статическая типизация порой спасает. Не ото всего, но от многих бед, свойственных тому же Python.
Кстати, про серверные. Если нагрузка большая, то никто не мешает купить сервер помощнее, сделать кластер и т.п. А вот у пользователя есть его слабенький нетбук или планшет. Который, заметьте, ещё и батарейку кушает. Так что, быть может, что-то тут есть…
Задача анализа кода для динамически-типизированных языков в общем случае алгоритмически неразрешима. Поэтому любые оптимизации работают постольку поскольку и рано или поздно во что-нибудь операции. То же верно относительно IDE. Те, кто говорит «IDE для JavaScript» просто никогда не писали в Eclipse или IDEA на Java. Ну или на C# в VS + Resharper
Пользователи Linux с недоумением смотрят на все эти Arial и Verdana. Тем более, что шрифты внезапно стали с засечками. Наверное, надо было не забыть указать sans и serif в качестве варианта шрифтов для тех, у кого нет Arial и Verdana.
SVN простой? SVN не умеет ветвиться? Да ну, к SVN'у только два крупных нарекания — глючит и тормозит. Просто тут, если действительно SVN используют, его не умеют готовить.
А ещё удручает, что до сих пор абзацы разделяются двумя элементами br а не вносятся внутрь элементов p. Если уж делали изменения, то могли бы и про это вспомнить.