Pull to refresh
134.4
JUG Ru Group
Конференции для Senior-разработчиков

Блеск и нищета джавовых веб-фреймворков

Reading time8 min
Views38K

Привет, Хабр! Помоги выбрать веб-фреймворк? Требования: модный, молодежный, популярный, качественный фреймворк для соло-технономада.


Надо ли нам каждый месяц читать очередной пост про это?



Несколько лет участия в проектах на границе энтерпрайза и системщины окончательно отбили нюх. Чтобы разобраться в вопросе, я заглянул в топ гугла и обнаружил там кучу однобоких рейтингов. Наверное, самым лучшим оказался Java Web Frameworks Index от ZeroTurnaround.


Хорош он тем, что


  • создатели основательно погулили, а также притащили туда статистику StackOverflow, LinkedIn, GitHub — примерно то же самое, что сделали бы и мы;
  • очевидно, что для ZeroTurnaround верное понимание расклада по фреймворкам — это основа для зарабатывания бабла.

Вот как рейтинг выглядит на момент написания статьи:


Rank Framework Popularity
1 Spring MVC 28.82
2 JSF 15.2
3 Spring Boot 13.35
4 GWT 7.74
5 Grails 6.35
6 Struts 5.4
7 Dropwizard 4.9
8 Play framework 3.26
9 JHipster 2.49
10 JAX-RS 2.44
11 Vaadin 2.15
12 Seam 1.94
13 Wicket 1.91
14 Tapestry 1.9
15 Sparkjava 0.77
16 Vert.x 0.76
17 Rapidoid 0.25
18 Lagom 0.24
19 Ratpack 0.13

Стойте, там Struts в первой десятке? Серьезно? Кажется, я ничего не потерял за эти несколько лет. Точнее, даже начиная с раннего средневековья.


Давайте пробежимся по списку.


Оу, Spring MVC и Spring Boot — это два разных элемента списка? Наверное, это можно понять и простить? (напишите в комментариях!). Не имеет смысла спрашивать, при чем тут Spring — он, как и Docker, всегда при чем.



Кстати, к нам на JPoint 2018 Moscow собрался Юрген Хеллер — это главный спринговец. Вот его можно дрючить вопросами типа "при чём тут спринг" по полной программе.


Но что действительно страшно, это то, что между ними (то есть по сути, на первом месте) находится JSF. Когда-то я делал на ЛОРе несколько обсуждений на тему, какой шаблонизатор для Java лучший. Годы шли, но всегда находилась половина треда с универсальным ответом: зачем тебе шаблонизатор, когда есть JSF? Вначале был просто JSP/JSTL, но потом они потихоньку сдали позиции, и остался один JSF.


Давайте глянем, что есть нового в JSF. Да, теперь мы можем больше не писать FacesContext facesContext = FacesContext.getCurrentInstance();. Можно сделать @Inject FacesContext facesContext;. Или если ты EL-камикадзе, то можно даже #facesContext. В нужных местах можно навешать @FlowMap или достать настроечку через @ManagedProperty ("#{bean.property}") private String stringProperty; Имхо, всё это совершенно очевидные рефакторинги, в соответствии с текущей модой на синтаксис. То же касается валидации в форме <f:convertDateTime type="localDate" pattern="MM/dd/yyyy"/> — ну запилили в Восьмерке Date-Time API, пришлось отреагировать, чтобы люди не писали бесконечных конвертеров самостоятельно. Список можно продолжить. Так и представляешь, как архитекторы Oracle пилили эти фичи за один вечер, батон колбасы и бутылку водки.


Интересная фича — это тэг <f:websocket>, который можно юзать вот так:


<h:body> 
   <f:websocket channel="jaxArticle"
    onmessage="function(message){alert(message)"} /> 
</h:body> 

В целом, прогресс с 2009 года (наш эквивалент «XV века») не перестает поражать воображение.


Дальше по рейтингу — Grails и PlayFramework. Grails — это, строго говоря, вообще не Java, а JVM. C PlayFramework под Java API не встречался со времен Play 1, поэтому — можете рассказать об этом в комментариях? Пока условно будем считать PlayFramework вторым годным фреймворком из списка, просто по причине наличия чудесного Scala API (за который можно простить ему историю с ORM и прочие мелкие ляпы).


Grails. Ну, допустим. Закроем глаза, тем более что Барух обещал, что Groovy — это круто. Но у них до сих пор открыты тикеты против Java 9! Ничего личного, чуваки, но это никуда не годится. В самом Groovy тоже какая-то фигня творится с поддержкой модулей и Java 9: насколько понял, --add-opens=java.base/* с нами навечно.


Wicket, Vaadin и GWT хотелось бы выделить в отдельную группу. С Vaadin и GWT я встречался только в смысле правки багов в чужих проектах. Но с Wicket у меня давний и болезненный опыт. Не знаю, кто первый притащил Wicket в Новосибирск, но он как эпидемия прошелся по нашим Java-компаниям. Мы писали на Wicket систему для управления профсоюзами в США. Мы писали мобильную MMO-игру. И для российских государственных компаний тоже писали разное, так что если заходите вылечиться от насморка в соседнюю больницу — осторожней, возможно, там в компьютерах полный неоперабельный Wicket. Каждый раз меня не оставляло ощущение, что Wicket не нужен вообще никогда и нигде. Может быть, про это стоит написать отдельную статью или даже целую книгу?


Давайте посмотрим еще раз на стартовую картинку. (Не знаю, кто настоящий автор, я ее нагуглил вот здесь).



Wicket появился в том же году, что и термин AJAX. В свою очередь, AJAX спас веб, благодаря этому мы все с вами такие богатые и знаменитые, хе-хе. В свою очередь, Wicket появился как средство управления Аяксом и как эксперимент был очень удачным. Потом он пошел в продакшн, и это история, полная боли и фейлов. С точки зрения архитектуры, он так никогда и не стал кластерным, и в некоторых компаниях стал причиной полного отсутствия горизонтального масштабирования. С перфомансом у него очень плохо — просто гляньте, сколько он весит в памяти и как медленно отвечает на запросы. Ну или просто откройте wicket.apache.org и посчитайте, за сколько загрузится страница.


С AJAX у него тоже так и не вышло: в 2017 году нас все еще преследуют оптимизации в названиях параметров. Пожалуйста, поднимите руки все, кто с первого раза догадается о назначении следующих параметров запроса: m, mp, e, f, sc, dt, wr, ch, bh, pre, bsh, ah, sh, fh, coh, ep, dep, rt, ad, sp, tr.


Ответы на задачку находятся здесь. Спойлер: АД расшифровывается как «allow default». Это булевский флаг, который показывает, разрешать ли исполнение поведения по умолчанию для того элемента HTML, который слушает данное событие.


Да, многие из нас работают в банках, и там всё на GWT. Но, оглядываясь назад на этот долгий-долгий путь, давайте честно признаем: управлять JavaScript из Java — наиболее дурацкая и деструктивная идея, которая когда-либо приходила в голову.


Если посмотреть на репозиторий Wicket, становится очевидно, что в период с 2007 по середину 2010 он был скорее мертв, чем жив, и далее возродился силами всего одного пользователя GitHub — Martin Grigorov, который сделал туда около четырех тысяч коммитов.



Картинка хороша, но давайте обратим внимание на конкретные циферки.
git clone https://github.com/apache/wicket.git
cd ./wicket


И теперь долбанём адским однострочником:


git log --shortstat --pretty="%cE" | sed 's/\(.*\)@.*/\1/' | grep -v "^$" | awk 'BEGIN { line=""; } !/^ / { if (line=="" || !match(line, $0)) {line = $0 "," line }} /^ / { print line " # " $0; line=""}' | sort | sed -E 's/# //;s/ files? changed,//;s/([0-9]+) ([0-9]+ deletion)/\1 0 insertions\(+\), \2/;s/\(\+\)$/\(\+\), 0 deletions\(-\)/;s/insertions?\(\+\), //;s/ deletions?\(-\)//' | awk 'BEGIN {name=""; files=0; insertions=0; deletions=0;} {if ($1 != name && name != "") { print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net"; files=0; insertions=0; deletions=0; name=$1; } name=$1; files+=$2; insertions+=$3; deletions+=$4} END {print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net";}'

Или можно получить еще более подробную кумулятивную статистику:


sudo gem install git_fame
git fame

Более подробная статистика займет минут 30 (на SSD, на новеньком макбуке с мобильным i7).


Statistics based on master
Active files: 5,407
Active lines: 578,441
Total commits: 15,600

name loc commits files distribution (%)
martin-g 161,089 98 2,898 27.8 / 0.6 / 53.6
Igor Vaynberg 67,983 2,872 1,993 11.8 / 18.4 / 36.9
Juegen Donnerstag 66,234 1,867 2,250 11.5 / 12.0 / 41.6
andrea del bene 58,583 5 654 10.1 / 0.0 / 12.1
Eelco Hillenius 30,287 2,932 1,051 5.2 / 18.8 / 19.4
svenmeier 28,504 307 1,130 4.9 / 2.0 / 20.9
Martijn Dashorst 22,470 1,089 727 3.9 / 7.0 / 13.4
Frank Bille Jensen 19,854 235 1,403 3.4 / 1.5 / 25.9
Johan Compagner 17,637 1,484 1,503 3.0 / 9.5 / 27.8
Jonathan Locke 14,257 1,321 437 2.5 / 8.5 / 8.1
Jean-Baptiste Quenot 14,022 277 448 2.4 / 1.8 / 8.3
Gerolf Seitz 13,189 205 1,041 2.3 / 1.3 / 19.3
Matej Knopp 8,565 963 291 1.5 / 6.2 / 5.4
Peter Ertl 8,281 354 417 1.4 / 2.3 / 7.7
Pedro Henrique Oliveira d... 7,474 98 169 1.3 / 0.6 / 3.1
Tobias Soloschenko 6,373 100 161 1.1 / 0.6 / 3.0
Emond Papegaaij 4,624 168 207 0.8 / 1.1 / 3.8
Alastair Maw 3,257 422 172 0.6 / 2.7 / 3.2
Carl-Eric Menzel 2,338 36 112 0.4 / 0.2 / 2.1
Jesse Long 2,230 12 261 0.4 / 0.1 / 4.8
Jeremy Ryan Thomerson 2,146 51 84 0.4 / 0.3 / 1.6
Andrea Del Bene 1,999 46 450 0.3 / 0.3 / 8.3
bitstorm 1,972 14 116 0.3 / 0.1 / 2.1
Michael Mosmann 1,397 43 31 0.2 / 0.3 / 0.6
Felipe Campos de Almeida 1,396 4 24 0.2 / 0.0 / 0.4
klopfdreh 1,329 39 27 0.2 / 0.2 / 0.5
Janne Hietamaki 996 218 46 0.2 / 1.4 / 0.9
Timo Heikki Rantalaiho 883 42 105 0.2 / 0.3 / 1.9
Maurice Marrink 784 12 28 0.1 / 0.1 / 0.5
Bertrand Guay-Paquet 773 1 3 0.1 / 0.0 / 0.1
John Sarman 767 8 21 0.1 / 0.1 / 0.4
Maxim Solodovnik 716 26 38 0.1 / 0.2 / 0.7
sourceforge-skipoles 605 40 42 0.1 / 0.3 / 0.8
manuelbarzi 476 2 5 0.1 / 0.0 / 0.1
Domas Poliakas 432 9 9 0.1 / 0.1 / 0.2
Alexander Morozov 412 4 16 0.1 / 0.0 / 0.3
Thomas Götz 403 1 13 0.1 / 0.0 / 0.2
Martin Funk 313 3 20 0.1 / 0.0 / 0.4
Gwyn Richard Evans 249 62 67 0.0 / 0.4 / 1.2
admin 247 3 13 0.0 / 0.0 / 0.2
kensakurai 208 5 3 0.0 / 0.0 / 0.1
Michael Haitz 207 1 2 0.0 / 0.0 / 0.0
Guillaume Smet 204 3 7 0.0 / 0.0 / 0.1
Cedric Gatay 185 9 13 0.0 / 0.1 / 0.2
Thomas Matthijs 185 3 12 0.0 / 0.0 / 0.2
Roman Grigoriadi 169 1 12 0.0 / 0.0 / 0.2
Artur Michałowski 156 4 6 0.0 / 0.0 / 0.1
Martin Grigorov (Netwalk) 149 4 12 0.0 / 0.0 / 0.2
Robert Gruendler 127 6 8 0.0 / 0.0 / 0.1
Matthias Metzger 122 5 2 0.0 / 0.0 / 0.0
René Dieckmann 119 1 3 0.0 / 0.0 / 0.1
Ate Douma 114 14 15 0.0 / 0.1 / 0.3
Pedro Santos 110 2 4 0.0 / 0.0 / 0.1
Sebastien Briquet 110 3 3 0.0 / 0.0 / 0.1
Manuel Barzi 105 5 6 0.0 / 0.0 / 0.1
jac-czerwinski 94 4 4 0.0 / 0.0 / 0.1
Sven 82 1 8 0.0 / 0.0 / 0.1
ozeray 79 1 11 0.0 / 0.0 / 0.2
Thomas Heigl 75 1 4 0.0 / 0.0 / 0.1
Sebastien 71 2 4 0.0 / 0.0 / 0.1
Fridolin Jackstadt 42 2 6 0.0 / 0.0 / 0.1
meno 37 3 8 0.0 / 0.0 / 0.1
Thibault Kruse 33 2 2 0.0 / 0.0 / 0.0
Vit Rozkovec 24 1 1 0.0 / 0.0 / 0.0
Tim Fleming 16 2 5 0.0 / 0.0 / 0.1
Luke Niesink 13 2 4 0.0 / 0.0 / 0.1
Jan Blok 10 8 1 0.0 / 0.1 / 0.0
Nils Schmidt 9 1 1 0.0 / 0.0 / 0.0
Nick Pratt 9 1 2 0.0 / 0.0 / 0.0
slowery 8 1 2 0.0 / 0.0 / 0.0
astrapi69 4 5 2 0.0 / 0.0 / 0.0
Jezza 3 1 1 0.0 / 0.0 / 0.0
tatjana19 3 1 1 0.0 / 0.0 / 0.0
robert mcguinness 3 1 1 0.0 / 0.0 / 0.0
Peter Dave Hello 3 1 1 0.0 / 0.0 / 0.0
barney2k7 2 1 2 0.0 / 0.0 / 0.0
bsaad 1 1 1 0.0 / 0.0 / 0.0
Sander Evers 1 1 1 0.0 / 0.0 / 0.0
Yoann Rodière 1 1 1 0.0 / 0.0 / 0.0
Jeremy Thomerson 1 4 1 0.0 / 0.0 / 0.0
Peter Lamby 1 3 1 0.0 / 0.0 / 0.0
Dan Retzlaff 0 2 0 0.0 / 0.0 / 0.0
Jared Renzullo 0 1 0 0.0 / 0.0 / 0.0
Joe Schaefer 0 1 0 0.0 / 0.0 / 0.0
Leonid Bogdanov 0 3 0 0.0 / 0.0 / 0.0
Yoshiki Higo 0 1 0 0.0 / 0.0 / 0.0
cvs2svn 0 1 0 0.0 / 0.0 / 0.0

В любом случае, мы увидим, что Wicket, по сути, разрабатывается не более чем десятью людьми. Если кто-то из этих десяти человек навернется (особенно Мартин), то вашему свободному времени настанет неминуемый капец — придется вечерами и ночами сидеть и осознавать баги в рендеринге страницы.


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


Совсем недавно было такое время, когда мы возмущались «программистами на фреймворках». «Как же так, — говорили мы на собеседовании, — ты умеешь использовать Spring, но понятия не имеешь, как работает изнутри HashMap! Что за дичь!» В еще больший ужас мы приходили, когда человек начинал рассказывать о десятках различных фреймворков, ни один из которых он не знал даже приблизительно, но все успешно применял на практике. Совсем ужасно, когда человек сам написал пять веб-фреймворков и даже в них не разбирался!


Ну что ж, если долго жечь поляну, то в конце концов травы на ней не останется. В результате своих возмущений мы получили ситуацию, когда JavaScript-проекты растут как грибы после дождика, а вот создание новых фреймворков для Java оказалось не такой уж популярной задачей. Теперь вы легко найдете того самого Senior Framework Coder (если этот фреймворк — Spring Boot, JSF и Play), который назубок расскажет про устройство табличных компонентов и внутреннюю кухню хэшмапы, но вряд ли сможет написать пять своих фреймворков и десять вариантов хэшмапы. И ни одного такого, кто сможет написать нечто лучшее, чем Spring Boot.


Возможно, вот прямо сейчас стоит остановиться и начать раздувать большущий такой фреймворк-хайп. Что думаете?


И возвращаясь к стартовому вопросу. Эй, читатель! Помоги выбрать веб-фреймворк? Требования: модный, молодежный, популярный, качественный фреймворк, и чтобы им кто-то действительно пользовался в проде, а не как Vert.x.


UPD: если кто-то из новосибирцев пишет на Wicket и не согласен с написанным выше, предлагаю встретиться на JBreak и перетереть за всю хурму. Как раз будет несколько месяцев, чтобы подготовиться к защите любимого фреймворка — готовьтесь тщательней :-)

Tags:
Hubs:
+42
Comments155

Articles

Information

Website
jugru.org
Registered
Founded
Employees
51–100 employees
Location
Россия
Representative
Алексей Федоров