не модель

7 апреля 2025, 15:02
Maxim Kuznetsov
3
45

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

----------

Сама по себе таблица - это не модель из MVC, это всего-лишь представление данных. Удобное и привычное.

И оно может (и должно) быть максимально кратким в конкретной реализации.

Тестовый индикатор, в табличном представлении. Из 4-х рассчётных и отображаемых буферов и одним промежуточным вычислением, 

/* тестовый индикатор 
*/
/* имена (индексы) колонок в таблице данных
*/
enum ENUM_MY_COLUMNS {
   HIGH,    // цена открытия 
   LOW,     // цена закрытия 
   MEDIAN,  // медиана
   MA,      // средняя
   INTERM   // тестовый промежуточный рассчёт
};
const string MyColumns[]={"HIGH","LOW","MEDIAN","MA","INTERM"};   // строковые имена колонок (для отчётов и обращений по именам)


/** основная рассчётная функция, 
*/
bool CalcMyColumns(DataTable *table,int column,int row,double &result)
{
   switch(column) {
      case HIGH:  result=iHigh(table.Symbol(),table.Period(),row);break;       // цены открытия/закрытие из iHigh/iLow
      case LOW:   result=iLow(table.Symbol(),table.Period(),row);break;
      case MEDIAN: result=table["INTERM"][row]; break;               // скопируем из промежуточного рассчёта (можно по имени)
      case INTERM: result=(table[(int)HIGH][row]+table[(int)LOW][row])/2.0;break; // промежуточный рассчёт
   }
   return true;
}
DataTable Table(MyColumns,CalcMyColumns); // таблица с данными (результаты вычислений кешируются, взаимозависимости разруливаются)
//DataTable Table(CalcMyColumns);   // можно без имён, но тогда нельзя будет обращаться по строковому имени

int ma_handle=INVALID_HANDLE; // хендл внешнего индикатора 
int OnInit()
{
   Table.SetIndexBuffer(0,HIGH,INDICATOR_DATA);    // буфер 0 - из колонки OPEN
   Table.SetIndexBuffer(1,LOW,INDICATOR_DATA);   
   Table.SetIndexBuffer(2,MEDIAN,INDICATOR_DATA);
   Table.SetIndexBuffer(3,MA,INDICATOR_DATA);      // буфер 3 - из колонки MA
   Table.SetIndicator(MA,iMA(_Symbol,PERIOD_CURRENT,13,0,MODE_SMA,PRICE_OPEN));  // колонку MA ассоциируем с внешним индикатором
   EventSetTimer(15);
   return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   return Table.OnCalculate(rates_total,prev_calculated,time,open,high,low,close,tick_volume,volume,spread);
}
void OnTimer()
{
   Table.Print(5); // по таймеру - печатаем 5 самых актуальных строк
}

не скопипщены #property - итого без них ~50 строк включая форматирование и комментарии. 

И конечно-же оно работает, хоть индикатор и тестовый и ничего толково-осмысленного не рисует :

 

И хотя простыми действиями в конкретном приложении получили о-го-го сколько плюшек:

  • нужный результат - все графики построены и данные посчитаны)
  • декларативный стиль - де-факто ведь просто описали таблицу на этапе OnInit;
  • унифицированный доступ и интроспекцию - к данным обращаемся как к ячейкам таблицы. 
  • даже печать и вывод данных - в тесте выводится в журнал, но можно и в отдельные окна и формы

это всё ещё не табличная модель из MVC. У неё нет ничего для взаимодействий с другими компонентами. Есть интерфейс таблицы данных, но "это другое"