Эффективное связывание формулы во время выполнения
Одним из элементов моего пользовательского интерфейса является таблица, показывающая список элементов, агрегированных по категориям, с некоторыми формулами (см. Целевой вывод ниже).
Как лучше всего связать ячейки с формулами, подобными таблицам?
- производительность: реальные данные часто меняются, таблицы могут быть большими, а формулы сложными, поэтому производительность и использование ЦП являются проблемой.
- простота конфигурирования (при условии, что конфигурация выполняется разработчиком, поэтому она может включать программирование)
- ремонтопригодность конфигурации
Подходы, которые я предусмотрел до сих пор:
- использовать API Java Scripting, но я бы предпочел использовать подход на основе JVM для повышения производительности
- создать
interface Formula { double calculate(); }
и генерировать, компилировать и загружать реализации во время выполнения - это позволяет JIT компилировать сгенерированные методы - то же самое, что и 2, но с использованием другого языка на основе JVM, такого как clojure, который позволяет легко компилировать на лету и имеет хорошо подходящий функциональный подход (например, карта / уменьшение поможет для вычисления средней и суммы ниже) - не уверен о последствиях производительности, хотя.
Какой подход будет иметь больше смысла? Есть ли другие решения или библиотеки, которые я должен рассмотреть?
пример
Чтобы прояснить цель, вот надуманный пример - давайте предположим, что элементы в таблице:
public class Item() {
public String category;
public String name;
public int quantity;
public double price;
}
Целевой выход
Category Name Quantity Price (avg) Value (sum)
All 82 1,090
Bikes 45 650
Bike 1 10 40 400
Bike 2 5 50 250
Cars 120 440
Car 1 3 100 300
Car 2 1 140 140
Конфигурация столбцов
Столбцы могут быть определены следующим образом:
Column # Formula
1 item.name;
2 item.quantity;
3 item.price;
4 Math.abs(column_2 * column_3); //calls a JDK method
Конфигурация агрегации
И категории агрегации и итоговые формулы могут быть определены следующим образом:
AGGREGATION #1: Category cat = item.category();
Column # Formula
1 cat;
2 "";
3 thisColumn.filter(cat).items().average(); //utility method
//this one is more complex
4 { double sum = 0;
for (double value : thisColumn.filter(cat).items())
sum += value;
return sum;
}
1 ответ
Я бы использовал пользовательский язык, специфичный для домена, который могут использовать ваши пользователи, и позволил бы ANTLR генерировать собственный анализатор в Java, который анализирует выражение для исполняемой функции.
См., Например, http://arcanecoder.blogspot.be/2008/04/using-antlr-to-create-excel-like.html для примера, который сделал что-то подобное, или http://www.antlr.org/wiki/display/ANTLR3/Expression+evaluator для более свежего.
Вы можете определить такие функции, как "сумма", "среднее" и т. Д., Сопоставить их с пользовательским кодом Java и использовать, например, $1 или ${имя}, чтобы они могли ссылаться на свойства.
Вы определяете только те функции, которые вы хотите, чтобы ваш пользователь использовал, чтобы они не могли использовать какие-либо вредные функции, которые были бы доступны на универсальном языке сценариев.