21.06.2013

Java web frameworks. JSF vs Spring MVC.

Мне хотелось сделать обобщенный и краткий обзор недостатков и плюсов фреймворков для разработки веб-приложений на Java, на примере JSF и Spring MVC. А если точнее - обзор двух концептуально разных подходов к разработке, на примере вышеуказанных фреймворков. Я выбрал Java Server Faces потому что это в своем роде "официальный" стандарт для разработки веб-приложений на Java, и потому что я уже существенное время имею дело именно с этим фреймворком. Spring MVC - исключительно потому что я с ним знаком. И наконец, краткий и обобщенный - потому что это очень обширная и многогранная тема, на которую можно смотреть с разных сторон, оценивать преимущества того или иного фреймворка по очень разным критериям, зачастую субъективно и в зависимости от области использования. В принципе можно было назвать пост "почему JSF не лучший выбор", так как я считаю, что концепция JSF сама по себе не самая удачная, мне видится в ней больше минусов, чем плюсов. Возможно в других фреймворках, ориентированных на работу с компонентами, эта идея реализована удачнее, но из-за того, что я знаком с JSF - я буду говорить о нем.

Итак, сначала я хотел бы уточнить про то концептуальное различие между этими фреймворками, которое я имел ввиду. Оба этих фреймворка реализуют паттерн MVC, но немного по разному. JSF - фреймворк, ориентированный на работу с компонентами. С точки зрения разработчика это должно выглядеть примерно так - вы создаете представление (веб-страницу), пусть это будет XML страница созданная с использованием технологии Facelets. Когда вы работаете со страницей, вы представляете себе страницу набором компонент, которые во многом уже готовы для использования - кнопок, таблиц, всплывающих сообщений и пр. К определенным действиям пользователя - нажатие на кнопку и т.п., "привязаны" события в классе  (backed bean), связанным с данным представлением. Данные на вашей странице также привязаны к данным этого класса. Вопрос, каким образом действия на веб-странице привязаны к методам класса в значительной мере абстрагирован. Для примера: у вас есть на странице указание (action = ...), какой метод класса нужно выполнить при нажатии пользователем на конкретную кнопку. Или: значение конкретного поля ввода привязывается к какому-то полю класса. Примерно вписать в модель MVC это можно так - страница это представление, модель данных это класс, а контроллер "скрыт" от программиста (возможно не все согласятся с таким определением, но мне оно кажется вполне подходящим в данном случае). С другой стороны, у backed bean есть обязанности, присущие контроллеру. Компоненты как правило представляют собой нечто готовое, при работе с JSF зачастую вам не нужно использовать HTML в чистом виде (и Javasсript), для этого используются определенный язык разметки и библиотеки компонентов - PrimeFaces, RichFaces, IceFaces и другие. С помощью них вы можете за несколько строчек кода сделать всплывающее окно, форму для загрузки файлов и прочее. Когда вы работаете с JSF, HTTP запросы в значительной мере скрыты от программиста. Мне кажется, что разрабатывая на JSF, думаешь больше не как веб-разработчик, а как разработчик десктоп-приложения. Есть компоненты, действия, события, а о том что здесь например нужно сделать Ajax запрос - позаботится фреймворк, для программиста - это лишь пара тегов, которые представляют собой некий "компонент, который добавит сюда Ajax". Точно могу сказать, что разрабатывая на JSF и используя Ajax, можно не знать что такое Ajax вообще. Или то, что в таком-то месте - sumbit формы. HTML и Javascript "генерируются" фреймворком. Итак, это фреймворк, ориентированный на использование компонентов, его подход более привычен для разработчиков традиционных, а не веб-приложений. Некоторые из целей такого подхода: упрощение и ускорение процесса разработки; минимизация усилий, которые нужно потратить на верстку. Кроме того, нет необходимости знать Javascript, можно создавать веб-приложения, не написав вручную не строчки на Javascript. Правда это только в теории. Spring MVC - фреймворк, ориентированный на запросы. Например вы создаете страницу используя JSP, она представляет собой обычную веб-страницу с элементами разметки, которые реализуют некоторую логику и связывают представление с моделью данных. Здесь нет никаких компонент - в общем-то традиционная верстка, javascript: когда нужно сделать запрос, вы делаете запрос, понимая что он из себя представляет. И говоря упрощенно, запросы со страницы обрабатываются контроллерами - специальными классами. Разрабатывая с помощью Spring MVC вы думаете как веб-разработчик, понятиями веба. Мне кажется Spring MVC более четко реализует паттерн MVC. Представления, контроллеры и данные строго разделены и полностью подвластны программисту. HTTP запросы полностью во власти программиста. Отмечу, что для сравнения я подразумеваю типичные ситуации при использовании данных фреймворков - использование в качестве технологий представления Facelets для JSF и JSP для Spring MVC.

Преимущества и недостатки - JSF.

К плюсам JSF можно отнести то, что это определенный стандарт, это технология для разработки веб-приложений на Java по умолчанию. Это следует из спецификаций Java EE. А значит - широкая поддержка этой технологии разработчиками спецификаций, поставщиками ПО.JSF действительно может ускорить процесс веб-разработки, особенно когда не требуется чего-то нетривиального. Не обязательно тратить много времени на верстку, более того, необязательно быть "настоящим" веб-разработчиком, чтобы создавать нечто рабочее на JSF. По задумке, можно сосредоточиться на бизнес логике. Поддержка Ajax в JSF разумеется замечательна - достаточно написать пару тегов. Доступно много библиотек компонентов, с помощью которых, не вникая очень глубоко в технические детали веб-разработки, можно создавать красивый и удобный интерфейс.  И если честно, я плюсов больше не вижу. Более того, даже эти плюсы зачастую аннулируются минусами. Пойдем по порядку. JSF это стандарт. Но наверное почти никто не использует фреймворк JSF без всяческих библиотек компонентов (PrimeFaces etc.), а они не представляют из себя никакого стандарта. Я сталкивался с ситуацией, когда из-за выпуска новой версии одной такой библиотеки пришлось потратить много времени на обновление библиотеки. Так как в новой библиотеке были изменены даже некоторые названия тегов (!). Если у вас приложение, в котором есть древняя библиотека компонентов, готовьтесь к тому, что есть вероятность существенной траты времени, или, если приложение действительно большое - попадете в сущий кошмар. По поводу этих библиотек и вообще компонентного подхода. Это плохой подход. Сейчас я скажу, почему я так считаю. Во первых, то что описано выше - про стандартизацию. Ведь никто не будет менять названия HTML тегов каждые пол-года? В Javascript не появились классы и он не изменил свой синтаксис за последние 3 месяца? Это было бы полным бредом, но подобный бред реален при использовании сторонних библиотек компонентов JSF. А уйти с них бывает уже поздно - вы уже зависите от них. Да, компонентный подход упрощает в какой-то мере разработку, но веб не работает как десктоп. Разрабатывая веб-приложение нужно понимать как работает веб и управлять HTTP запросами. При подходе "по умолчанию" данные с клиентской страницы отправляются и сохраняются в объекте, который существует, пока существует HTTP сессия (это упрощенно, в JSF есть различные варианты, но во многих случаях делают именно так). Когда в веб-приложение вводится понятие сохранения состояния на стороне сервера, это усложняет механизм взаимодействия клиент-сервер и этот механизм во многом скрыт от разработчика на JSF. Это усложнение может приводить к неочевидным ошибкам. Иногда это приводит к тому, что ресурсы сервера используются неэффективно. Простая работа с Ajax это хорошо, но это приводит к тому, что ajax используется там где это совершенно не нужно. Кроме того, по умолчанию JSF использует POST запросы для всего, что можно. А как известно - POST запрос выполняется за более длительное время, чем GET, так как POST выполняется в "два захода". Предположим, у вас есть страница со множеством элементов, чуть ли не на каждую кнопку, на выбор элемента, на наведение указателя мыши "повешен аякс", все это генерирует POST. Нет ничего удивительного, что все это будет работать не очень быстро. Тот факт, что HTML код и Javascript генерируется JSF, за счет использования готовых компонентов, иногда приводит к неочевидным ошибкам. И иногда, для того, чтобы исправить эту ошибку уйдет уйма времени, особенно если вы плохо разбираетесь в Javascript и в том, как работает JSF "внутри". Итак, знание Javascript в той или иной мере обязательно и здесь (что естественно). Код большой страницы, который генерируется JSF, может привести в шок "нормального" веб-разработчика, если у него хватит терпения разобраться в "спагетти-коде". Если вам нужно сделать что-то необычное, что нельзя сделать с помощью готовых компонент - вам нужно в любом случае знать Javascript, и более того - как это привязать к тому сделано на JSF. Иногда нужно проявлять "чудеса изобретательности" чтобы сделать что-то необычное. При работе с JSF в итоге придется изучить много вещей, специфичных для JSF. Это как некая "параллельная" веб-разработка. Это аннулирует всю простоту и удобство JSF на первых этапах, если приложение простое.  Если вы начинающий разработчик JSF, который раньше не занимался веб-разработкой, вы будете думать другими категориями, будете изучать другие технологии, у вас будут на слуху другие вещи. Вы будете отрезаны от сообщества веб-разработчиков, потому что вам не нужно знать как сделать Ajax запрос с помощью JQurey, зато вам нужны узкоспециализированные знания и технологии. О которых большинство веб-разработчиков вообще ничего не слышали. И как я уже говорил выше - эти технологии иногда специфичны и могут быстро меняться.

Недостатки и преимущества - Spring MVC.

К преимуществам Spring MVC определенно можно отнести саму концепцию, ориентированность на запросы. Когда разработчик четко понимает, какие запросы и куда отправляются со стороны клиента, это приводит к более рациональному проектированию приложения. К более оптимизированному и быстрому коду. Вероятность неочевидных ошибок, с которыми приходится сталкиваться в работе с JSF, минимальна. Поддерживать приложение на Spring MVC проще, потому что все более прозрачно. Не нужно гадать, почему например не открывается всплывающее сообщение, хотя по всем законам логики оно должно открываться (это JSF). Если используется JSP, то это означает, что никакого сгенерированного Javascript кода не будет. Вся верстка делается обычным образом, визуальные компоненты тоже создаются "традиционным" способом. По умолчанию, контроллеры Spring MVC не сохраняют состояние страницы на стороне сервера, эти классы представляют собой паттерн "одиночка". По моему мнению, не смотря на то, что JSF - стандарт, у Spring MVC более высокий уровень стандартизации. Никакой зависимости от сторонних библиотек компонентов. Для создания визуальных компонентов и реализации определенной логики можно использовать известные всем веб-разработчикам  библиотеки - например JQuery, Twitter Bootstrap и пр. Мне кажется что эти библиотеки, которые используются очень широко - их можно назвать стандартом, в отличие от библиотек компонентов JSF, которые часто сами используют JQuery и являются "дополнительно прослойкой".  Используя Spring MVC придется в обязательном порядке писать вручную Javascript, что мне кажется плюсом и вполне логичной вещью. Любой веб-разработчик должен быть знаком с Javascript, а при работе с JSF это отрицается, но на практике незнание Javascript не приводит ни к чему хорошему. Знания, которые нужно иметь при работе с Spring MVC более общие для всех веб-разработчиков, если говорить о клиентской стороне приложения (интерфейсе). Таким образом вы не отрезаете себя от огромного сообщества. Могу отметить, что когда я столкнулся с Spring MVC я очень быстро решал все проблемы и возникавшие ошибки, даже на первоначальном этапе. В целом Spring MVC гораздо более "прозрачен" для понимания и изучения. К минусам по сравнению с JSF можно отнести разумеется то, что придется потратить больше времени на верстку. Что компенсируется меньшими усилиями при дальнейшей поддержке системы. И что в итоге? Все то, что я написал выше - просто мое мнение, основанное на практическом опыте работы с этими фреймворками. Я не считаю что JSF не нужно использовать всегда, я просто хочу сказать, что если вы решили сделать выбор в пользу JSF для своего проекта - еще раз взвесьте все минусы и плюсы. Иногда, JSF при первом взгляде кажется просто находкой и замечательной вещью, но это не совсем так.  Мне кажется что рационально выбрать JSF для разработки системы не ориентированной на веб, а ориентированной на работу в локальной сети. Например какая-нибудь внутренняя система предприятия. Я считаю что JSF малопригоден для веба по причине нагрузки, которую он создает на сеть и его производительности в целом. Если это веб-приложение не будет содержать в себе чего-то необычного, допустим это какая-нибудь система управления бухгалтерской отчетностью, которая с точки зрения UI тривиальна. И если нужно сделать эту систему в наиболее краткие сроки, можно брать готовые компоненты, и не беспокоиться по поводу дизайна. Тогда вполне можно выбирать JSF. Я думаю, что Spring MVC в целом является в большинстве случаев хорошим выбором, исключение разве что вышеописанная ситуация, когда рационально выбрать JSF. Если нужно создать нетривиальный интерфейс, веб-приложение которое будет работать действительно быстро, в интернет - тогда Spring MVC выигрывает на 100 %.  



Теги: java javaEE

comments powered by Disqus