Данный раздел адресован разработчикам алгоритмов. Его цель — объяснить существующие в maCom ограничения и сформулировать некоторые правила обращения с maCom.

# maCom не даёт готовых алгоритмов

Основная задача стандарта maCom — унификация интерфейсов разработки алгоритмов. Не надо ждать от него большего. Он не предоставляет готовых функций, компонентов и структур данных для эффективной реализации всевозможных алгоритмов. Например, если разработчику понадобилось бинарное дерево, он должен реализовать его сам. Стандарт не может предусмотреть всё на все случаи жизни.

# maCom работает только с оперативной памятью

Стандарт maCom предназначен для реализации сложных алгоритмов, многократно обращающихся к данным. Поэтому он должен работать с данными, находящимися в оперативной памяти. В то же время, источником данных вполне могут быть базы данных или другие долговременные хранилища информации. Предварительная подготовка сырых данных, связанная с обработкой информации на медленных носителях, должна выполняться средствами СУБД или OLAP.

# maCom не всегда заботится об эффективности

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

Во-первых, доступ к элементам матриц осуществляется через интерфейсные функции, что замедляет работу, даже если они хранятся в оперативной памяти. Был проведен эксперимент с методом наименьших квадратов. Первая версия была реализована целиком на maCom-овских матрицах. В следующей версии промежуточные матрицы были заменена на обычные массивы `double**`. Скорость работы возросла в 3.2 раза.

Во-вторых, матрицы не обязательно располагаются в оперативной памяти. maCom может напрямую подключаться к базе данных, ассоциируя входную матрицу с таблицей или результатом запроса.

# maCom запрещает движение данных против течения

Это означает, что алгоритм не имеет права записывать во входные матрицы и считывать из выходных матриц. Разработчик алгоритма не должен делать собственных предположений о реализации объектов с интерфейсом ImaMatrix. Входная матрица вполне может оказаться функцией, которая умеет только вычислять данные, но ей некуда их сохранять. Также и выходная матрица может оказаться функцией, которая может только записать данные в базу или передать их по сети. Типичная ошибка новичков — забыть про запрет чтения из выходной матрицы.

# maCom заставляет хранить параметры в дереве Param

Тем самым обеспечивается важное свойство открытости алгоритмов. Параметры из дерева Param могут считываться и записываться внешними приложениями. Методы алгоритма могли бы обмениваться данными через закрытые члены самого компонента. Однако в этом случае общие для всех алгоритмов функции визуализации данных, записи в файл и чтения из файла не гарантировали бы корректного восстановления внутреннего состояния алгоритма.

# maCom требует игры по правилам!

maCom освобождает разработчика алгоритма от многих рутинных забот: проверки правильности аргументов, записи и считывания алгоритмов в файлы, организации структуры данных для хранения параметров, и т.д.

Взамен maCom требует некоторого количества дополнительной работы, напрямую не относящейся к программированию вычислительных методов. Далее перечисляются важные детали реализации, о которых не следует забывать.

# Сообщение текущего состояния вычислений

Механизм ImaProgressHandler позволяет во время долгих вычислений сообщить пользователю, сколько ещё осталось ждать, и при необходимости прервать вычисление. Алгоритм должен сам оценивать время своего выполнения и периодически вызывать функцию ядра Progress, передавая ей процент сделанной работы. Кстати, это крайне полезное упражнение, заставляющее лишний раз скрупулёзно проанализировать эффективность вычислительного метода.

В момент вызова этой функции происходит обработка системной очереди операционной системы, что позволяет приложению не выглядеть «зависшим». Если функция Progress возвращает код MA_ERR_INTERRUPT, алгоритм должен корректно прервать работу, освободив память и восстановив корректные значения всех параметров алгоритма.

# Использование отладочного вывода Debug

В maCom имеется соглашение, что параметр с именем Debug содержит поток вывода отладочной информации. Разработчику не нужно задумываться, существует ли этот поток и куда реально будет направлен вывод. Если поток не был создан вне алгоритма, вывод в него будет просто проигнорирован.

Пример:

    CmaStream Debug = Param[L"Debug"];
    Debug << L"Vector V=" << V;

# Сохранение побочных результатов

В maCom имеется соглашение, что параметр с именем Result содержит поддерево временных параметров и побочных результатов, носящих справочный характер. При сохранении настроенного алгоритма в файле поддерево Result не сохраняется.

# Измерение времени выполнения

В maCom имеется соглашение, что параметр с именем Result.TimeTotal содержит общее время выполения метода в секундах. Могут быть и другие параметры, измеряющие время выполения отдельных этапов.

Пример:

    clock_t cstart = clock();
    	...
    Param[L"Result"][L"TimeTotal"] = (clock()-cstart)/double(CLOCKS_PER_SEC);

# Разработка документации

Каждый алгоритм документируется в процессе создания. Для включения алгоритма в общую документацию по библиотекам достаточно записать HTML-файл c описанием алгоритма в директорию doc/maLibs и добавить одну строку в скрипт menu.js (по образу и подобию). Все алгоритмы описываются по единой форме, см. «Библиотеки алгоритмов»:

- Назначение алгоритма
- Методы алгоритма (включая спецификацию)
- Параметры алгоритма
- Результаты алгоритма (параметры Result.*)
- Теория
- Литература
- Пример(ы) использования
- Разработчик

Шаблон документации алгоритма находится в файле

    doc/maLibs/_alg.html.

Шаблон головного файла библиотеки находится в файле

    doc/maLibs/_lib.html.

# Разработка тестовых модулей

Для каждого алгоритма в процессе создания разрабатывается тестовый модуль, демонстрирующий типовой порядок работы с алгоритмом. Обычно это решение некоторой модельной задачи, данные для которой генерируются в этом же тестовом модуле. Исходный код тестового модуля должен быть максимально лаконичным и не содержать ничего лишнего, чтобы его можно было целиком включить в раздел документации «Примеры использования».

Шаблоны тестовых модулей для C++ и Delphi входят в состав шаблонов библиотеки алгоритмов, которые находятся в директориях

    src/Lib_Template_cpp
    src/Lib_Template_pas