Быстро делать web UI для кровавого энтерпрайза, как?
А так портативность была бы...
Увы, есть требование такое, что строго веб.
Чего-то ничего лучше
http://www.formbreeze.com/freehtmleditor/formbuilder_editor....
http://www.sigmawidgets.com/
не нашёл/
А чем не устраивают автоматически сгенерированные формы во всяких джангах и ASP.NET MVC? CRUD они умеют и пишутся за полчаса-час (который занимает описание профиля БД).
во всяких джангах и ASP.NET MVCгриды в них по умолчанию убогие (по сравнению даже с древней delphi)
гриды в них по умолчанию убогие (по сравнению даже с древней delphi)Гриды - да, я для гридов юзал http://www.datatables.net/
Как делать правильно такие штуки в 2014 году? Есть какой-нибудь набор полуфабрикатов для этого?Есди БД — Oracle, то Oracle APEX.
http://www.curs.ru.. Разрабатываем свою платформу, она бесплатна, решения платны. При этом база данных может быть одной из 4 типов (Orakle, mssql, postgres? mysql это не важно.
Мы занимаемся ровно такими вещами
Ни разу не пользовался, но по обрывочной информации кажется, что вот эта штука специально предназначена для указанной цели: google web toolkit кажется. Но я правда не уверен, что правильно понимаю зачем он.
google web toolkit кажется. Но я правда не уверен, что правильно понимаю зачем он.да gwt. только надо одну хрень предусмотреть, что разрабатывать на нем строго юзая бестпрактики и без сторонних библиотек типа шарана или smartgwt иначе потом эта штука станет не управляемой и проще будет ее выкинуть
без сторонних библиотек типа шарана или smartgwt иначе потом эта штука станет не управляемой и проще будет ее выкинутьлюто плюсую, smartgwt то еще г., не писал, но осуждаю - видел результат использования, который потом пришлось выкинуть и переписать на простом js со всякими либами (kendo, leaflet)
простом jsот gwt вроде многие отказываются
гриды в них по умолчанию убогие (по сравнению даже с древней delphi)Что по-твоему требуется от грида?
а OLAP как поставщик гридов тебе не пойдёт? То что касается отображения, не редактирования, там вроде хорошо поставлено
Это больше похоже на админку, чем на BI, так что нет.
Что по-твоему требуется от грида?одновременно большое кол-во функционала и отсутствие глюков
http://developer.mozilla.org/ru/docs/XUL
Это как раз тулза под те задачи, которые ты описал.
Берёшь, описываешь на xml формочку
<window id="vbox example" title="Example 3">
<vbox>
<button id="yes1" label="Yes"/>
<button id="no1" label="No"/>
<button id="maybe1" label="Maybe"/>
</vbox>
</window>
А он на основе этого генерит тучу html и яваскрипта. Естественно можно создать свой компонент-наследник myButton и т.д...
Тут можно потыркать примеры:
http://www.amplesdk.com/examples/markup/xul/
На нём куча всякого кровавого энтерпрайза написано - например вёбредактор для JBPM.
Но как говориться, не получилось, не взлетело.
<window id="vbox example" title="Example 3">А что делать если набор кнопок должен быть динамическим? В XML нет никаких средств встраивания кода. На джаваскрипте можно сделать так (я воспользуюсь синтаксисом coffeescript чтобы меньше печатать):
<vbox>
<button id="yes1" label="Yes"/>
<button id="no1" label="No"/>
<button id="maybe1" label="Maybe"/>
</vbox>
</window>
А он на основе этого генерит тучу html и яваскрипта. Естественно можно создать свой компонент-наследник myButton и т.д...
window
id: 'vbox example'
title: 'Example 3'
vbox:
button id: 'yes', label: 'Yes'
button id: 'no', label: 'No'
Динамическая генерация кнопок:
window
id: 'vbox example'
title: 'Example 3'
vbox: for i in [1..100]
button id: 'button'+i, label: "Button #"+i
Таким образом, неясно зачем генерить джаваскрипт из XML, в котором нет никаких средств декомпозиции.
Увы, есть требование такое, что строго веб.А что ты бы выбрал если бы не такое требование?
Таким образом, неясно зачем генерить джаваскрипт из XML, в котором нет никаких средств декомпозиции.Блин, двже отвечать не охота.
А что делать если набор кнопок должен быть динамическим? В XML нет никаких средств встраивания кода.Через xml ты определяешь какие компоненты у тебя будут на форме (как в delfi ты в графическом редакторе клепаешь dfm файл). Помимо того поведения, которое имеет каждый экземпляр компоненты определенного типа (например кнопку можно нажать, а грид - отсортировать ты конечно можешь задать и индивидуальное поведение, которое имеет только эта кнопка.
http://github.com/spring-projects/spring-roo
там command line тулза, которая смотрит на базу и сама генерит админку
щупал сам довольно давно и поверхностно
еще думаю всякие RoR тулзы должны уметь
afaik для этого есть вот этот монстрик там command line тулза, которая смотрит на базу и сама генерит админку
щупал сам довольно давно и поверхностно
еще думаю всякие RoR тулзы должны уметь
new Window{{
this.id = "vbox example";
this.title = "Example 3";
this.vbox = new Vbox(
new Button{{this.id = "Save";this.label="Save";}},
new Button{{this.id = "Save";this.label="Save";}},
new Button{{this.id = "Save";this.label="Save";}},
);
}}
Что по синтаксису несильно дерьмовее XML, но зато дает тайпчек и возможность избежать мозгоебства с кодогенератором.
Блин, двже отвечать не охота.
Представь тебе нужна форма, в которой несколько виджетов, при этом один виджет разный в разных местах. С XML ты такое не реализуешь, а с точки зрения нормального языка программирования у тебя просто будет функция принимающая как аргумент этот меняющийся виджет.
Блин, двже отвечать не охота.А ты всё-таки ответь. Вот, например, майкрософт породил из XML монстрика XAML, и многие признают, что XML для этого отстой и нужен нормальный язык. Нормальный язык это либо generic proposal language с синтаксическим сахаром типа groovy-style builders, либо DSL.
Представь тебе нужна форма, в которой несколько виджетов, при этом один виджет разный в разных местах.Говоришь что это не энтерпрайз и не делаешь.
Ну или картинки посмотреть про примеры, которые я приводил (JBPM, Komodo).
Окошко с настройками в фаерфоксе, я так понимаю, тоже на зуле написано. (просто контекстное меню выпилено)
Естественно любой компонент можно и на клиенте создать из яваскрипта.
от gwt вроде многие отказываютсяот него вроде как отказывется гугла, но при этом у них все беки сделаны на нем и работают вполне шустро
но при этом у них все беки сделаны на нем и работают вполне шустроВот это откровение для меня. Вроде сами они GWT почти не пользовались ни для чего. Можно пруф?
консоль разработчика android тоже gwt
Представь тебе нужна форма, в которой несколько виджетов, при этом один виджет разный в разных местах. С XML ты такое не реализуешьПочему это? Реализовать можно:
... <widget_def id="special_button"/> ... <widget id="special_button"/>
новый адмоб бек для монетизатора и рекламодателя сделан на GwtТак вот почему оно так работает!
консоль разработчика android тоже gwt
для JBPM.тк ты под кровавым энтерпрайзом имеешь ввиду распил больших сумм бабла, я то по наивности подразумеваю классическое понятие софта
список :
Да, нагуглился Some Google products that use Google Web Toolkit that you may not know about:
AdWords http://google.com/adwords
AdSense http://google.com/adsense
Flights http://flights.google.com
Hotel Finder http://www.google.com/hotelfinder
Offers http://www.google.com/offers
Wallet http://wallet.google.com
The New Blogger http://www.blogger.com/
Chrome Webstore http://chrome.google.com/webstore (Actually done in Closure, but embeds GWT checkout code)
Product Search http://www.google.com/prdhp?hl=en&tab=mf
Public Data http://www.google.com/publicdata/home
New Google Groups http://groups.google.com
Orkut http://www.orkut.com
Google Health (discontinued)
Google Wave (discontinued)
PlayN (basis of Angry Birds)
Так вот почему оно так работает!не работает скорее всего так из-за того что криво в базу ходит снепшоты с нового адмоба вроде нормально снимаются, старый тормозил вроде сильнее.
кстати ты на новый адмоб перешел?
youtube.com/analytics
new Button{{this.id = "Save";this.label="Save";}}И главное, это должно быть три раза. Три раза, запомни, Ганс, три раза!
new Button{{this.id = "Save";this.label="Save";}}
new Button{{this.id = "Save";this.label="Save";}},
на чем остановились?
ни на чем пока, думаем
Главное, поменьше джавы, побольше джаваскрипта. Ни в коем случае не связывайтесь с GWT или c JSF. Если обязательно надо использовать джаву на бэкенде, то никаких фреймворков, только голый servlet API.
Из того что видел с максимальной скоростью клепания и минимальным порогом вхождения был dhtmlx .
побольше джаваскрипта
Я не люблю все динамические типизированные языки программирования — Python, Perl, JavaScript. У меня очень плохая память, а программы на них требуют, чтобы человек много всего запоминал. Нужно держать в голове какую-то информацию о типах, которой нет в коде. На самом деле, условно говоря, мне с ними совсем тяжело, потому что у меня плохая память. Людям, у которых хорошая память, просто тяжело.
http://habrahabr.ru/company/yandex/blog/230775/
В кровавом энтерпрайзе это уже становится вопросом выживаемости. Держать в голове энтерпрайзную информацию — человек просто не выживет.
Степан Кольцов
Программирует 10 лет. В Яндексе — 7 лет.
Джавист, кстати.
А вот вырезка оттуда же:
Григорий Бакунов
Программирует 25 лет. В Яндексе — 10 лет.
Вопрос, как всегда, очевидный. У меня любимых языков программирования, наверное, много. Больше всего я в последнее время пишу на Питоне — просто в силу того, что это язык, который позволяет мне максимально быстро выразить то, о чем я думаю. Но, конечно, он не единственный, и иногда приходится довольно много писать на JavaScript. Это не самое приятное развлечение в моей жизни. Наверное, больше всего кода и с наибольшим удовольствием я написал на Лиспе.
Так что каждому своё. Но если желаете, лэт зе холивар бегин.
oreodor.com
ана довольно простую форму 727К — в топку
oreodor.com
В кровавом энтерпрайзе это уже становится вопросом выживаемости. Держать в голове энтерпрайзную информацию — человек просто не выживет.На мой взгляд, типизация как в джаве для энтерпрайза хуже, чем динамика. Энтерпрайзная специфика - много кода который перекладывает данные из одного формата в другой (например сделать запрос к базе, сунуть данные в HTML). Приходится описывать типы, которые используются в одной-двух функциях, при этом тип
class User{
String name;
String surname;
Date birthdate;
}
нельзя использовать на том же месте, что и
class User{
String name;
String surname;
}
Для энтерпрайза нужна структурная типизация, которая при наличии вывода типов и типа any строго лучше динамики. Идеальная система типов для энтерпрайза - язык roy:
http://roy.brianmckenna.org
нельзя использовать на том же месте, что иЕсли придерживаться immutable объектов, то проблема только в том, чтобы дать имя классу и написать переливку. В хорошей IDE переливка пишется, не напрягаясь. Переливка, конечно, увеличивает объем кода, но это не критично, при чтении такие фрагменты кода легко пропускаются глазом.
Подозреваю, что корень, тобою описанной проблемы “приходится описывать типы”, кроется в том, что ты пытаешься выражения на компьютерном языке приблизить к выражениям на естественном. Это иногда дает свои плюсы. Но не стоит это переоценивать. Процитирую Дейкстру: On the foolishness of "natural language programming".
Пиши в рамках существующего языка так, как тебе надо, завтра для этого сделают синтаксический сахар, и так будут писать все.
В хорошей IDE переливка пишется, не напрягаясь.в текущих статически-типизированных языках это достаточно геморройно.
например, задача написать(и использовать далее в коде) N-функций, каждая из которых берет произвольный тип и добавляет к нему поле Ni - выглядит на статике ужасно. Это из-за того, что в статитике сейчас нет операции вида: вернуть объект, имеющий те же поля, что и исходный, но с добавлением поля Ni.
например, задача написать(и использовать далее в коде) N-функций, каждая из которых берет произвольный тип и добавляет к нему поле Ni - выглядит на статике ужасно. Это из-за того, что в статитике сейчас нет операции вида: вернуть объект, имеющий те же поля, что и исходный, но с добавлением поля Ni.особой остроты такой проблемы не чувствуется (для immutable)
а так, конечно, языки стоит развивать
в смысле, у тебя такой задачи не возникает? или в смысле, что ты не считаешь, что способ решения получается ужасный?
в смысле, у тебя такой задачи не возникает? или в смысле, что ты не считаешь, что способ решения получается ужасный?В моих задачах эта проблема не стоит остро. В моих задачах решение не могу охарактеризовать словом "ужасное" .
Энтерпрайзная специфика - много кода который перекладывает данные из одного формата в другой (например сделать запрос к базе, сунуть данные в HTML).Да, да, всё именно так! И просто удивительно сколько бабла на это сливается. Я как-то писал вот это:
Во многих корпоративных приложениях используется реляционная модель данных. Реляционная модель имеет крайне простую структуру. Если использовать неформальные термины, то реляционная модель это набор таблиц. Таблица состоит из набора колонок. Как постепенно построить или вырастить реляционную модель? Какие элементарные операции для этого требуются? Создание и удаление таблиц и колонок. Таким образом, добавление (и удаление) колонки является базовой (а значит крайне важной операцией) для построения реляционной модели и, тем самым, всей информационной системы. Удивительно, но часто добавление поля требует от разработчика значительных усилий. Вот, что об этом пишет Фаулер: "Схема расслоения обладает и определенными недостатками. Слои способны удачно инкапсулировать многое, но не все: модификация одного слоя подчас связана с необходимостью внесения каскадных изменений в остальные слои. Классический пример из области корпоративных программных приложений: поле, добавленное в таблицу базы данных, подлежит воспроизведению в графическом интерфейсе и должно найти соответствующее отображение в каждом промежуточном слое."
Т.е. когда-то давно всех обманули, закрыв глаза на проблему добавления колонки. А если иметь механизм program slicing-а по колонке от БД и по всему приложению, то в энтерпрайзе вполне можно жить. Program slicing по колонке базируется на статической типизации. И плевать, что кода много.
class CN1<T>
{
public CN1(T value, string n1)
{
this.Value = value;
this.N1 = n1;
}
public readonly T Value;
public readonly string N1;
}
public CN1 N1<T>(T value)
{
return new CN1<T>(value, bla-bla-зависящее- от-value);
}
class CN2<T>
{
public CN2(T value, int n2)
{
this.Value = value;
this.N2 = n2;
}
public readonly T Value;
public readonly int N2;
}
public CN2 N2<T>(T value)
{
return new CN2<T>(value, bla-bla-зависящее- от-value);
}
и т.д.
//и использование
var x = N2(N3(N5(4;
Console.WriteLine(x.Value.N3);
Console.WriteLine(x.Value.Value.N5);
Приведи пример как улучшить следующий код так, чтобы он не выглядел ужасным.Использовать F# или Roslyn.
Использовать F#там это как будет выглядеть?
например, задача написать(и использовать далее в коде) N-функций, каждая из которых берет произвольный тип и добавляет к нему поле Ni - выглядит на статике ужасно. Это из-за того, что в статитике сейчас нет операции вида: вернуть объект, имеющий те же поля, что и исходный, но с добавлением поля Ni.Это в явах и сишарпах так. Вот пример на языке elm:
assignAge = \person -> {person | age = 20}
bob = {name = "bob", surname = "smith"}
alice = {name = "alice", occupation = "programmer"}
aliceWithAge = assignAge alice
aliceAge = aliceWithAge.age
bobWithAge = assignAge bob
bobAge = bobWithAge.age
Попробовать можно тут http://elm-lang.org/try
У выражения aliceWithAge - тип {name:String, occupation: String,age: Integer}
У выражения bobWithAge - тип {name:String, surname: String,age: Integer}
assignAge = \person -> {person | age = 20}удобно. интересно когда добавят в main-stream (C++, Java, C#)?
Хотя в языках на JVM есть, конечно.
Для безумных педантов: "никогда" в данном контексте есть решение задачи "как быстро они это сделают, поглядев на соседний язык", а не указание срока реализации.
Объектная система on top of встроенной в язык вместе с кодогенерацией творят чудеса.
Вроде, в питоне это уже много-много лет, так что никогда.лямбды тоже давно существуют, но в mainstream их добавили буквально на днях.
так что надежда есть )
Жалобы не "а вот у них это давно есть, а у нас нет", а "а вот пятьдесят лет назад такое вообще придумали, и у них давно есть, а у нас нет".
До того пытались проблему решить анонимными классами. Типа, вот посмотрите, у нас почти такие же замыкания, но Java-way.
Пока не поняли, что херней страдают.
Вроде, в питоне это уже много-много лет, так что никогда.При чем тут питон? Вроде про статически типизированные языки идет речь.
Но вообще, надежда, да, она такая. Мир слишком быстро меняется, и языку просто надо успевать соответствовать надеждам, чтобы не стать мертвым.
Я уже писал, по-моему, тут, что не слежу за дискуссией.
Насчет статических, Scala, поди-ко, наименее статичный.
RoslynКак он тут поможет? Расширять синтаксис языка и допилить самому компилятор?
Вроде, в питоне это уже много-много лет, так что никогда.Питон динамический, обсуждаемые тут языки - статические. Например, в эльме выражение
({a=1, b=2}).c
не компилится
Спасибо, Капитан! Спасибо, Капитан!
Как он тут поможет? Расширять синтаксис языка и допилить самому компилятор?Там уже есть нужный тебе синтаксис. Надеюсь, зарелизят.
Там уже есть нужный тебе синтаксис. Надеюсь, зарелизят.Какой синтаксис? Покажи.
Если ты про primary constructors, то они полностью проблему не решают.
Приведи пример как улучшить следующий код так, чтобы он не выглядел ужасным.
Вот рабочий пример на D. Правильные шаблоны и вывод типов рулят.
import std.stdio;
class Data {
string name;
this(string nm) { name = nm; }
}
class Ext(Old, New, string fldname) {
Old value;
New n;
mixin("New " ~ fldname ~ " { return n; }");
alias value this;
this(Old oldval, New newval) { value = oldval; n = newval; }
}
auto addField(string fldname, Old, NewOld oldval, New newval) {
return new Ext!(Old, New, fldnameoldval, newval);
}
void main(string[] argv) {
auto org = new Data("John");
auto b = org.addField!("surname""Doe");
auto c = b.addField!("age"33);
auto d = org.addField!("height"180).addField!("weight"77.7);
writefln("%s %s aged %s", c.name, c.surname, c.age);
writefln("%s of height %s and weight %s", d.name, d.height, d.weight);
}
Результат запуска:
http://dpaste.dzfl.pl/2836766de1cb
в нюансах - это не совсем то, что хочется.
над типами не выполняется коммутативность и ассоциативность
тип_выражения(org.addField!("age"33).addField!("surname""Doe" не равен типу_выражения(org.addField!("surname""Doe").addField!("age"33
тип выглядит страшновато: type 'f58.Ext!(Ext!(Data, string, "surname" int, "age").Ext'
функции с такими типами замаешься описывать
ps
хочется тип вида structure<field-name-1:field-value-1, field-name-2:field-value-2, ...>
c операцией вида structure<args1> + structure<args2> = structure<args1+args2>, поддерживающей законы коммутативности и ассоциативности
и с возможностью частично конкретизировать такой тип при описании функции
auto F(structure<age:int, name:string, args:...> item)
{
return new structure(age:item.age + (item.name == "Маша" ? 2 : 4 name:item.name, args);
}
и с возможностью вызвать такую функцию для обычных структур
class S
{
public readonly int age;
public readonly string name;
}
auto x = F(new S(10, "Маша";
pps
сам язык ведет себя "странно"
auto org = new Data("John");
auto b = org.addField!("surname""Doe");
auto c = b.addField!("age"33);
c = org.addField!("age"13).addField!("surname2""Doe2"); //*
writefln("%s %s aged %s", c.name, c.surname, c.age);
присваивание со звездочкой не выдает никаких ошибок (ни компиляции, ни runtime-а но при этом c.age остается равным 33, а поля surname2 не появляется. По идее срабатывает какой-то оператор конвертации типов, но ведет себя он очень странно.
над типами не выполняется коммутативность и ассоциативностьА должна?
тип_выражения(org.addField!("age"33).addField!("surname""Doe" не равен типу_выражения(org.addField!("surname""Doe").addField!("age"33
Как сравнить два анонимных типа вообще?
Я уж не говорю, что
struct S1 {}; struct S2 {};
два совершенно разных типа. Надо научиться сперва их сравнивать, прежде чем требовать коммутативности каких-нибудь операций.
Ты хочешь вектор с данными разных типов.
с точки зрения DT типы S1, S2 и structure<> эквиваленты, с классической - типы S1, S2 являеются наследниками structure<> и не эквиваленты между собой
для чистой DT объявления функций эквивалентны между собой: auto F(S1 auto F(S2 auto F(structure<>)
для номинальной системы типов функцию F удобнее записать как:
auto F<T>(T item) where T:structure<>
{
bla-bla;
}
и тогда для каждого типа S1, S2 или structure<> возможен свой вариант перегрузки.
Ты хочешь вектор с данными разных типов.да, но корректность обращения к которому обрабатывается на этапе компиляции
ps
не совсем.
у вектора элементы упорядочены по порядку вставки, а в структуре элементы неупорядочены между собой (или упорядочены по названию полей/хэшу от названия поля)
есть два вида сравнения типов: duck typing и классическая.Называется - структурная и номинальная.
да, но корректность обращения к которому обрабатывается на этапе компиляцииЗачем устанавливать это требование?
чтобы получить все плюсы, которые идут от статически-типизированных языков.
А мы о каких конкретно языках говорим?
в смысле?
Какие элементарные операции для этого требуются? Создание и удаление таблиц и колонок. Таким образом, добавление (и удаление) колонки является базовой (а значит крайне важной операцией) для построения реляционной модели и, тем самым, всей информационной системы. Удивительно, но часто добавление поля требует от разработчика значительных усилий. Вот, что об этом пишет Фаулер: "Схема расслоения обладает и определенными недостатками. Слои способны удачно инкапсулировать многое, но не все: модификация одного слоя подчас связана с необходимостью внесения каскадных изменений в остальные слои. Классический пример из области корпоративных программных приложений: поле, добавленное в таблицу базы данных, подлежит воспроизведению в графическом интерфейсе и должно найти соответствующее отображение в каждом промежуточном слое."Тред начинался с того, что топикстартеру надо было нагенерить интерфейсов для отображения гридов. Как я себе представляю, у него есть много таблиц, надо быстро добавлять просмотр таблиц. Если решать эту задачу в таком стиле, как описываешь ты, то получится миллион прослоек, код, который перекладывает данные из одной прослойки в другую, IDE для написания этого кода, которая тормозит и глючит, application server который долго и мучительно редеплоит это код. Любые попытки облегчить этот процесс будут утыкаться в отсутствие средств метапрограммирования в языках типа C# или Java.
Т.е. когда-то давно всех обманули, закрыв глаза на проблему добавления колонки. А если иметь механизм program slicing-а по колонке от БД и по всему приложению, то в энтерпрайзе вполне можно жить. Program slicing по колонке базируется на статической типизации. И плевать, что кода много.
При этом в изначальной постановке задачи - показать грид с такими-то полями, наполняемый из такой-то таблицы - есть один тип
data Grid = Grid {table::String, columns::[String]}
который не особо тебе облегчает программирование.
На джаваскрипте можно сделать так, что ты описываешь декларативно, какой у тебя грид, из какой таблицы он берется, какие там столбцы, какие права доступа. Этот код у тебя исполняется и в браузере, и на сервере (в джаве есть встроенный высокопроизводительный интерпретатор джаваскрипта сразу давая тебе REST API endpoint для твоего грида, который делает запросы к базе и выдает json, плюс интерфейс для просмотра этого грида. Скрипты перечитываются с диска на каждый запрос, не надо ничего редеплоить и перекомпилировать (в продакшене можно читать их один раз на старте).
В применении к языкам сишного семейства твое "есть" нужно заменить на "а вот хорошо было бы ввести..."
хочется тип вида structure<field-name-1:field-value-1, field-name-2:field-value-2, ...>По-хорошему нужен конечно row polymorphism а-ля Elm или Haxe. А в D для этого есть static duck typing:
и с возможностью частично конкретизировать такой тип при описании функции
и с возможностью вызвать такую функцию для обычных структур
auto f(TT x) {
writefln("f name=%s age=%s", x.name, x.age);
}
или если хочется более культурной проверки наличия нужных полей
auto g(TT x) if (hasFields!(T, "age", int, "name", string {
writefln("g name=%s age=%s", x.name, x.age);
}
где hasFields пишется как-то так:
http://dpaste.dzfl.pl/76384d8570ba
С такими предикатами требования ассоциативности и пр. выполняются автоматически (ибо совпадение типов нужно с точностью до hasFields).
Поменять одно поле, скопировав все остальные неупомянутые, в данной имплементации низя, но если немного репу почесать, то тоже реализуемо.
на сярпе, если не стоит особых ограничений на производительность, можно воспользоваться библиотечками типа AutoMapper. Думаю нечто подобное должно быть и для явы.
application server который долго и мучительно редеплоит это кодэто что-то джававское энтерпрайзное?
в ASP.NET просто билд классов; если правится только вью, то и билдить не надо. А в VS2014 билда вообще не будет, и, говорят, всё в памяти будет делаться.
AutoMapperесть, но пользоваться не надо
есть, но пользоваться не надопочему?
теряется основная фича статической типизации — program slicing по полю, от базы до любого слоя: UI и т.п.
это что-то джававское энтерпрайзное?Расскажи, как выглядит процесс разработки? Сколько требуется времени после сохранения файла, чтобы сделать запрос новой html страницы?
в ASP.NET просто билд классов; если правится только вью, то и билдить не надо. А в VS2014 билда вообще не будет, и, говорят, всё в памяти будет делаться.
Я считаю, что быстрый ребилд/редеплой важнее типизации.
Опишу свой опыт разработки под разные платформы:
1)Java, сервер приложений собранный из open source компонентов (Tomcat, ActiveMQ, JAX-WS). Несколько миллионов строк кода, не считая кода сгенеренного из метаданных (технология генерации - конкатенация строк). Сервер стартует около минуты. Клиент на swing стартует около двух минут. Там в режиме разработки можно было бы загружать не все модули, а только те, которые отлаживаешь, но для этого потребовалось бы рефакторить код инициализации приложения, билд систему, и думать о том, как сынтегрировать билд систему с IDE, на что эффективные менеджеры не могли выделить время.
2)Браузерный джаваскрипт. Максимальный размер одного модуля - около мегабайта минифицированного джаваскрипта. Страница открывается, слава хрому, 2-3 секунды. Модули загружаются лениво, в божественном джаваскрипте это так просто как
button.on 'click', ->
require 'someModule', (module) ->
module.start
3)Хранимые процедуры (plsql, plpgsql). Лучшее, из того что видел. Фактически репл внутрь запущенной СУБД, можно писать и компилировать по одной процедуре за раз.
Тред начинался с того, что топикстартеру надо было нагенерить интерфейсов для отображения гридов. Как я себе представляю, у него есть много таблиц, надо быстро добавлять просмотр таблиц. Если решать эту задачуБля, как же это реально заебало. Вот просто реально это портит мне жизнь. Сейчас есть вменяемый заказчик, готов платить нормальные деньги, только вот в начале проекта был вот такой же горя архитектор что-то там себе представлял и видел задачу. А теперь до продакшена довожу я, и развивать должен я. Было бы написано просто в лоб, без всякой этой декларативности, я был бы сейчас с нормальным проектом и был бы счастливым человеком. Пиши то что есть на текущий момент не надо "представлять себе" и "видеть задачу". Вот статическая типизация и позволяет двигаться спокойной и счастливо в итеративной манере.
...
data Grid = Grid {table::String, columns::[String]}
...
описываешь декларативно,
...
Бля, как же это реально заебало. Вот просто реально это портит мне жизнь. Сейчас есть вменяемый заказчик, готов платить нормальные деньги, только вот в начале проекта был вот такой же горя архитектор что-то там себе представлял и видел задачу. А теперь до продакшена довожу я, и развивать должен я. Было бы написано просто в лоб, без всякой этой декларативности, я был бы сейчас с нормальным проектом и был бы счастливым человеком. Пиши то что есть на текущий момент не надо "представлять себе" и "видеть задачу". Вот статическая типизация и позволяет двигаться спокойной и счастливо в итеративной манере.Ботай convention over configuration
Например, ты пишешь общий файл для браузера и сервера с метаданными
customersGrid =
name: 'customer'
columns: ['firstname','lastname','age']
Теперь ты можешь в коде сервера вызывать функцию
generateRestApi(customersGrid)
которая имплементирвана как-то так:
generateRestApi = (grid) ->
httpServer.route 'GET /api/:name?limit=:limit&offset=:offset', ({name,limit,offset}) ->
# TODO fix sql injections
sqlQueryAsJSON """
select
#{grid.colums.join ' '}
from
#{grid.name}
limit #{limit} offset #{offset}
"""
Тебя никто не заставляет вызывать на сервере функцию generateRestApi для этого грида, ты можешь реализовать rest api сам, к примеру:
httpServer.route 'GET /api/customer', ->
[
{name: 'Bob', lastName: 'Smith', age: 20}
{name: 'Alice', lastName: 'Smith', age: 25}
]
У тебя обычные структуры данных и функции, ты делаешь с ними что хочешь, тем не менее это декларативное программирование в каком-то смысле.
Ботайтак ты еще студент? Тогда это всё объяснит.
Оставить комментарий
psm-home
Есть такой класс веб приложений, которые представляют собой CRUD фронтенд к БД и состоят из большого количества гридов с фильтрами и форм для создания/редактирования записей. Нормальные люди этого всего не видят, а невидимые миру слезы т. н бизнес пользователей мало кого волнуют, поэтому юзабилити может быть скажем так, неидеальным. Зато важно запиливать фичи как можно быстрее (дешевле).Как делать правильно такие штуки в 2014 году? Есть какой-нибудь набор полуфабрикатов для этого?
Раньше было понятно что "накидать формочек и гридов" быстрее всего в Delphi, но это было до эпохи победившего веба, а теперь что взамен?