Pull to refresh

Comments 42

UFO just landed and posted this here
UFO just landed and posted this here
Не только «страшненькое», это даже не главное. Здесь у нас сортировка, pagination, поиск, редактирование inline, и прочее. И — самое главное — нет ни сгенерированного View, ни Controller, что очень критично для приложений с сотнями моделей (подробнее про это в моих комментариях ниже).
+ twitter bootstrap = 2 минуты и не такое страшненькое )
UFO just landed and posted this here
Всерьез задумавшись над тем, что вам ответить, я в результате уперся в вопрос о смысле жизни…

Вы, пожалуйста, поосторожнее с такими вопросами! :)
Судя по примеру приложения по ссылке с гитхаба, тут та же беда, что и со многими другими приложениями, которые используют Ext 4+ — пишется куча вьюх/моделей/хранилищ/контроллеров, затем они по мере неоходимости подгружаются с помощью Ext.Loader (или, в данном случае, каким-то его Netzke-аналогом).

В итоге получается — жмем кнопку чтобы вызвать форму редактирования, уходит запрос на сервер, юзер ждет. Через какое-то время (в зависимости от качества интернетов и всякого такого) форма догружается и появляется на экране.

Юзер (и часто разраб, если он не еще не вник в Ext, а только начинает) делает вывод что Ext это медленно и неповоротливо.
В большинстве случаев 4-й экст есть смысл использовать только в связке с Sencha CMD. Ну или руками собирать все в кучу и скармливать в какой-нибудь closure compiler. Но это муторно.
По нажатию на вызов формы редактирования можно мгновенно (ну, или как получится у ExtJS) показывать пустую/полупустую форму и натягивать на неё маску «Loading», попутно отправляя AJAX-запрос за данными (точнее, сконфигурировать запрос данных из нужного хранилища, которое уже само инициирует или AJAX-запрос, или чтение из памяти, или ещё что-то), которые нужно отобразить в этой форме. В принципе, можно сконфигурировать один раз это, и onShow форма будет сразу показывать эту маску с каким-то текстом, а по завершению загрузки данных (или же после их обработки перед показом, тут уж как задумает программист) её убирать.

Если скорость доступа к данным большая, а обработка данных занимает небольшое время, то иногда можно эту маску и не увидеть вообще. А если какие-то проблемы со связью или пересылаются/обрабатываются большие объёмы данных, то пользователь сразу видит, что вот он, интерфейс с нужными полями, но данных там ещё нет, и крутится какое-то изображение, показывающее, что идёт процесс загрузки данных.
А зачем запрашивать данные для формы редактирования у сервера? Они же есть в хранилище грида.
Там даже при нажатии на «Add in form» летит запрос на сервер и приходится ждать подгрузки формы.
Хорошее наблюдение!

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

Однако, запрос на сервер при нажатии Add in form воможно отключить, если указать, что форма должна загружаться eagerly вместе с гридом. Это конфигурируется тоже.
Ну ок, наверное нет смысла развивать дискуссию по этому поводу, хотя я все же остаюсь приверженцем сборки приложения и используемых компонентов экста в один скрипт )

И, конечно, поля в форме и колонки в гриде могут отличаться (часто так и происходит) — это конфигурируется в классе грида.


Колонки грида и поля формы да, могут.
Я люблю толстые модели и тонкие контроллеры, поэтому поступил следующим образом — в базовом классе модели, от которого наследуются все остальные модели, описал метод getEditForm(). Если для модели установлено свойство editForm (например: editForm: 'app.view.User.edit'), то возвращется ее инстанс с загруженным record, иначе — создается и возвращается дефолтная форма редактирования, в которой присутствуют все поля модели, для которых не установлен признак editable: false.

В итоге получается довольно удобно и гибко — по нажатию кнопки в контроллере достаточно дернуть record.processEdit(), который, в свою очередь, сделает нужные проверки, покажет форму и т.д.
Учитывая что я тоже испорльзую кодогенераторы (чаще всего работаю с Yii и просто добавил в gii нужные генераторы), процесс развертки CRUD приложения занимает примерно столько же времени — достаточно натравить эти самые генераторы на БД.

Но это уже в рамках обмена опытом (хотя в формате комментария наверное не очень понятно получилось) — не сочтите за критику. А в это приложение было бы неплохо еще добавить возможность открыть несколько пунктов меню одновременно (например в отдельных табах), их сохранение между перезагрузками страницы, и stateful для гридов.
Обмен опытом всегда интересен!

Похоже, вы нашли вполне интересный и работающий способ отображения форм для моделей.

Против кодогенераторов я выступаю только по той причине, что когда в приложении сотни моделей, кодогенераторы приводят к огромному количеству дуплицированного кода. Чтобы добавить/улучшить фичу во всех 100 гридах в приложении на Нецке, необходимо просто подправить Netzke::Basepack::Grid (или унаследованный от него свой грид, служащий базой для всех остальных гридов). А в случае со сгенерированным кодом — исправлять придется в 100 местах.

возможность открыть несколько пунктов меню одновременно (например в отдельных табах), их сохранение между перезагрузками страницы, и stateful для гридов

Да, все это легко делается с Netzke, см, например, netzke-demo.herokuapp.com или yanit.heroku.com.
А в случае со сгенерированным кодом — исправлять придется в 100 местах.


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

У меня давно назрело желание по этому поводу накатать статью(и), т.к. в рунете не оч много вменяемой инфы по архитектуре экстовых приложений вообще, и Sencha CMD в частности. Да все никак время выбрать не могу. А в комментах, конечно, особо не объяснишь ничего.
Теперь понятнее, и в этом случае мы на одной волне, просто нашли разные подходы, которые было бы интересно сравнить в деталях — с удовольствием бы почитал статью.
Окей, постараюсь не затянуть.
Кстати, JS для класса формы подгружается только первый раз, после чего кэшируется, и с сервера грузится уже только собственно раскладка полей.


В случае фаерфокса, если не включен дисковый кеш, а именно browser.cache.disk.enable в about:config, то этот механизм не работает, фф не шлёт никаких if-modified-since, а простым гетом каждый раз загружает яваскрипты.
Честно говоря, не заметил, когда произошло выключение этой опции, столкнулся совершенно случайно, когда пожаловался клиент что наблюдает значительные тормоза при открытии страницы через gsm модем где-то далеко от цивилизации.
Ещё бы, там почти 4Мб было. После сенча цмд — стало полтора мб, стало лучше, но всё так же неудобно ждать несколько минут. Дальнейший разбор выявил причины.
Я имел в виду механизм кэширования встроенный в Netzke. Работает он так: когда я хочу динамически подгрузить, например, грид — для этого нужен Ext JS код самого класса компонента, плюс конфигурация для создания его образца (например, где будет указано, какие колонки должны быть отображены). И то, и другое, подгружается с сервера. JS эвалюируется, после чего класс оказывается объявлен в браузере. В следующий раз, когда нужен грид (по-другому сконфигурированный — например, привязанный к другой модели), с сервера загружается уже только конфигурация, потому что повторно эвалюировать сам класс необходимости нет.
А, невнимательно прочел. Я о наболевшем (-
Да, это один из воможных вариантов. Я выбрал сделать чуть по-другому: показывать маску Loading в самом гриде, пока загружается и код для формы (только первый раз, после чего кэшируется), и то, что в ней нужно отобразить. Если скорость доступа большая, то маску действительно можно и не увидеть.
пишется куча вьюх/моделей/хранилищ/контроллеров

Именно этого Netzke позволяет избежать. Конечно, создания моделей не избежишь, по-крайней мере в Рельсах, но Views и Controllers становятся не нужны, что освобождает нас от огромного количества не DRY кода. Взгляните, сколько кода нам понадобилось, чтобы создать грид-компонент, который работает с данной моделью — ок 14 строк. Ни одного View или Controller. Как это возможно? Благодаря тому, что вся View/Controller-логика — внутри Netzke::Basepack::Grid. И все, что нам нужно — унаследовать от нее (легко ли унаследовать View в Рельсах?..) и нужным образом сконфигурировать. Вся сортировка, поиск, автоматическое определение полей, даже конфигурация колонок налету (что не попало в этот пост) и т.д. — все это внутри Netzke::Basepack::Grid, и в этом сила компонентного подхода.

Это очень критично для сложных приложений, использующих сотни моделей (смотрите, например, мою заявку на EuRuKo — к сожалению, на английском).

Что касается того, что какие-то части приложения подгружаются динамически — это вовсе не обязательно с Нецке и остается на усмотрении разработчика. Когда в приложении, к примеру, сотни моделей (это не преувеличение, я работал с таким), «просто» сгенерировать Ext JS приложение целиком — это получилось бы очень, очень много кода, загрузка (и выполнение в браузере) которого заняла бы слишком много времени. Нецке же позволяет разработчику решать, что загружается сразу, а что позже, по запросу пользователя. Те же формы — они не обязаны загружаться с сервера каждый раз, я в одном из комментариев ниже подробнее про это написал.

Нецке разрабатывалась как-раз с расчетом делать быстрые Ext JS-приложения — именно этому способствуют встроенные механизмы кэширования JS классов, динамическая подгрузка кода компонентов, мультиплексирование запросов на сервер от нескольких компонент (с помощью Ext.Direct) и др.
Ну я, кажется, понял — тут расчет на быстрое поднятие CRUD-да без необходимости особой переконфигурации/изменения логики приложения.
У меня просто немного другой случай — нужно быстро поднимать морды для работы с данными (например бухгалтерская аналитика, закупки, сметы). Причем у каждого заказчика довольно специфическая логика и бизнес процессы, да и просто, как они это называют — «хотелки», под которые приложения после кодогенераторов нужно нужно подстраивать.

В этом случае отказ от MVC экста сильно чреват — завтра у них будет новая «хотелка» или изменения в бизнес-процессах, и будет армагеддон, если я описывал логику в гридах.
Поэтому поднялся фреймворк приложения — обработка меню, смена языка/тем/ интерфейса, базовые классы, кодогенератор. Приложение генериться, логика/вьюхи подтягиваются, sencha app build — на сервер.
Просто разные сферы применимости.
Грид — это всего лишь пример компонента, и, конечно, в него совершенно неуместно совать бизнес-процессы, не связанные с обработкой конкретной модели.

А вот если создать комплексную компоненту, которую условно назовем Application, которая будет содержать в себе «самый верх» бизнес-логики приложения (например, загрузка других компонент, сравнимо с Views), всевозможные меню, компонент дерево-эксплорер (к примеру), и любое количество других (возможно, также комплексных) компонент, в каждом из которых реализован свой кусок логики приложения — вот тогда и получится гибкое, стройное приложение, для упрощения создания которого я и написал Netzke.

Другими словами: каждый компонент в приложении должен отвечать за четко определенный набор задач, как-можно более изолированный от остального приложения. В этом смысл компонентного подхода к созданию приложений — и это то, чего мне не хватало в Рельсах (повторюсь: когда вопрос касался сложных одностраничных приложений).
Извиняюсь, но слово «компонента» обычно используетя в естественных науках, например в математике, физике. В остальной жизни, в т.ч. и программировании, эта штука мужского рода — компонент.
Действительно! Это открытие для меня, я подправлю пост.
Увы на первый вопрос в списке так ни кто и не ответил, поэтому я продублирую вопрос. А есть ли что то подобное для PHP, или система создания гридов — с возможностью задания фильтров по столбцам, или вообще универсальные фильтры, которые можно выводить перед любой таблицей?
Был опыт нескольких больших проектов с Ext JS, код выглядит жутковато и работает медленно. По возможности, стараюсь избегать этого зверя.
Согласен с оценкой того, как выглядит код. В этом смысле Netzke довольно-таки облегчает жизнь:

1) Netzke-компонент, будучи однажды написанным (для чего наверняка понадобится знание Ext JS), после этого встраивается в Рельсы (или другие компоненты), путем использования преимущественно Руби. Т.е. JS «заворачивается» в компоненту, и основным ее интерфейсом становится ее Руби класс (в Руби происходит, в частности, конфигурация клиентской части компоненты, и код читается достаточно просто). Т.е. необходимость «связываться» с Ext JS значительно снижается, соответственно процент экспертов в Ext JS в команде разработчиков может быть также снижен.

2) Код выглядит более структурировано: github.com/netzke/netzke-core#what-is-a-netzke-component

3) (Тут не именно о качестве кода, но имеет отношение к нему) Разработка, отладка и автоматическое тестирование отдельного компонента, выполняющего конкретную функцию в приложении — намного более приятный процесс, чем отладка монструозного монолитного Ext JS приложения. Конечно, при умелом подходе и Ext JS код можно писать модульно, но преимущество компонента Netzke в том, что он включает в себя и серверную часть кода.

Насчет оценки скорости сложно как-то прокомментировать, потому что скорость сильно зависит и от качества кода тоже, от выбранных подходов в решении разных мини-задач (и в том числе и от серверной части тоже). Если бы было более определенное описание какой-то проблемы с быстродействием Ext JS — тогда было бы возможно ее обсудить.
работает медленно и выглядит жутковат просто от не умения готовить.
Эххх, а потом потребуется сделать, например, галочку, которая связывет нижнюю строку к верхней и начнется то, за что мы реально получаем деньги :)
Спасибо за интересный компонент и интересную статью. А будет ли перевод второй части?
Пытался использовать ExtJS для системы документооборота предприятия. Столкнулся с кучей конкурирующих с RoR особенностей, нафиная с формирования запроса. В некторых случах приходится модифицировать контроллер, к чему ExtJS готов, но по-своему, и его точка зрения не совпадает с точкой зрения RoR.
С другой стороны, RoR разработчикам доступны компоненты, которые сразу дружат с рельсами и друг с другом, это и kaminary, и boootstrap, и ransack, и т.д., которые успешно решают задачи предоставления datagrid, однако уровень абстракции гораздо выше, чем у ExtJS которые скорее диктует RoR что и как нужно делать, и модель conventions over configuration сразу разрушается.
Т.о. мне ExtJS видится подходящим для чего угодно, кроме RoR. Уж лучше тогда backend сразу писать на node.js, потому как в нашем случае, рельсы будут скорее тормозить процесс в виду идеологической несовместимости с ExtJS.
Не очень понял — а в чем у них идеологическая несовместимость? Если речь идет об одностраничном приложении, то просто клиент с сервером меняются, например, json-ом. А какая у кого идеология не особо важно.
В чем, например, разница — будете вы JQuery-вскими $.ajax () на сервер с рельсами ходить, или экстовым прокси?
Ну например в том, что ExtJS 3 был не restfull, возможно что-то изменилось в 4-й версии, но осадочек остался. А если с рельсами общаться не как с REST-сервисом, то нужно оверрайдить кучу рабочего функционала. Если мы любим руби, то удобно воспользоваться каким-то rack-based фреймворком, но не rails(с оговоркой на ExtJS3).
Обещаю попробовать ExtJS в следующем проекте с админкой, добавлю в напоминание перечислить Вам весь список граблей на которые наступлю. Да даже в виде статьи это можно будет изобразить.
Окей, авансировал.
Только при этом постарайтесь в нем разобраться — от обилия возможностей легко самому себе граблей под ноги разложить. По пути можете стучаться в личку/скайп, если что.
Какой неожиданный разворот моего неосторожного комментария :)
Просто слухи о монструозности экста обычно сильно преувеличены )
Но да, у него порог вхождения повыше чем у многого другого, и чтобы сделать что то стоящее нужен некоторый опыт.
Вообще, поддержка REST-архитектуры она скорее на разрабе. Если он сделает restfull — это будет restfull приложение. От экста ту мало что зависит, он для этого давал все возможности.
В рецепте сказано взять чистую кастрюлю, но не сказано где. (из анекдота)
Откуда качать ExtJS и иконки, находится через поисковики, но лучше бы в статье приводились ссылки на их скачивание. Или уточнялось, что ExtJS нужна ровно 4.1.* не больше не меньше.

Для меня оказалось не тривиально найти 4.1.* версию ExtJS, на их сайте www.sencha.com/products/extjs/download/
Version 4.1.3 and Version 3.4.1 are available to Sencha Support subscribers

Минимальная подписка 600$, не наш путь.

4.2.1.883 (Working in Open Source?)

После скачивания, подлинковывания в public/extjs, и при обращении к localhost:3000 получил:
No such file or directory - /home/charger/projects/netzke_task_manager/public/extjs/examples/ux/CheckColumn.js

Related Downloads: Ext JS 4.0.7

получаю белый лист в браузере и ошибку «Netzke: Ext JS 4.1.x required (you have 4.0.7).»

скачал таки 4.1.1а с офф. сайта обнаружив через гугл. Ну и сайт у ExtJS.
В итоге заработало но в 7 минут явно не вложился.
Спасибо за конструктивный отзыв!

Я активно работаю над апдейтом Netzke, который будет работать с последней доступной версией Ext JS. Промежуточный вариант можно найти в ветке ext42 — его должно быть достаточно для данного тюториала.

Насчет линков на скачивание Ext JS и иконок — полностью согласен, исправлю.

Кстати, я только что вручную подправил URL, и попал напрямую на страницу для скачивания 4.1.1a: www.sencha.com/products/extjs/download/ext-js-4.1.1. Сейчас добавлю эту ссылку, если Хабр позволит.
Sign up to leave a comment.

Articles

Change theme settings