Отладка и трассировка
программ
Отладка программ, за исключением
самых простейших, дело далеко не простое. Начальный опыт программирования на любом
языке приходит спустя годы практической работы с ним. Эти сроки намного сокращаются,
если пользователь всерьез знаком хотя бы с одним, а лучше с несколькими языками
программирования.
Но даже такой пользователь нуждается в специальных средствах диагностики и контроля
программ. Чем их больше, тем совершеннее система программирования. При этом пользователь-программист
должен заботиться и о том, чтобы такие средства входили в программные модули,
которые создает он сам.
Некоторые правила культурного программирования
Выше мы описали множество
методов программирования на языке системы Mathematica. Попробуем сформулировать
некоторые общие правила так называемого культурного программирования с учетом
специфики систем Mathematica, позволяющие создавать надежные и эффективные программные
средства:
-
Тщательно продумайте алгоритм решения задачи. Порой выбор лучшего алгоритма позволяет
кардинально повысить скорость вычислений и упростить программу (впрочем, одновременно
это достигается далеко не всегда).
- Используйте прежде всего возможности функционального программирования — из
него родились основы языка программирования систем Mathematica.
- Разделяйте
задачу на малые части и оформляйте их в виде законченных программных модулей —
прежде всего функций.
- Pie скупитесь на программные комментарии — чем
их больше, тем понятнее программа и тем больше шансов, что она заинтересует пользователей
и будет долго жить. Учтите, что ясность программы в большинстве случаев важнее
скорости ее работы.
- Тщательно готовьте сообщения об ошибках и диагностические
сообщения, а также наименования программных модулей и описания их назначения.
- Тщательно производите диагностику программных модулей, в том числе с
самыми безумными значениями и типами параметров — хорошо спроектированный модуль
должен диагностировать любые виды ошибочных ситуаций и реагировать на них адекватным
образом.
- Используйте имена переменных и констант в стиле, принятом в
Mathematica, и обязательно с использованием понятных по смыслу обозначений. По
мере возможности не используйте в именах зарегистрированные идентификаторы команд
и функций.
- Заменяйте циклы функциями обработки списков, например функциями
суммирования и произведения. Применяйте эффективные варианты упрощенных операторов
и функций.
- В максимальной степени используйте функции ядра системы.
Обращайтесь к пакетам расширений только в том случае, когда это действительно
необходимо.
- Проводите тщательное тестирование своих модулей, в том числе
с выполнением их трассировки. Помните, что нет программы, которую нельзя хоть
чуть-чуть, но улучшить и сократить. Однако при этом цените затраченное на это
время!
- По мере возможности используйте готовые апробированные программные
модули — изобретать велосипед и делать то, что уже сделано, неразумно.
-
Обращайте особое внимание на реализацию механизма контекстов, позволяющего избежать
грубых ошибок при модернизации различных объектов программ, прежде всего наборов
функций.
- Не слишком оригинальничайте! Не применяйте программные трюки
и недокументированные приемы программирования. Такие программы в момент создания
могут выглядеть удивительно эффектными и потрясающе оригинальными, но вполне возможно,
что в следующей версии системы они перестанут работать вообще, поскольку разработчики
обычно стараются исключить любые недокументированные трюки в своих программах.
Применение этих рекомендаций
на практике позволит вам создавать программы, которые нужны не только вам, но
и многим пользователям системы Mathematica. Только такие программы могут быть
размещены в Интернете и, вполне возможно, войти в пакеты расширения и электронные
книги системы Mathematica.
[an error occurred while processing this directive]
Трассировка программных модулей
В практике подготовки и отладки
программ важное значение имеет наличие специальных средств отладки программ по
шагам — средств трассировки. Mathematica имеет ряд функций для осуществления трассировки
своих программных конструкций.
Функция Trace [ехрг] позволяет выполнить трассировку выражения ехрг. Возьмем простой
пример — вычисление выражения 2 (3 + 4) 2 /5:
Trace[2 (3 + 4)^2 / 5]
{{{{3+4, 7 },7^2,49}, {1/5,1/5}, 49/5, 49/5}, 249/5, 98/5}
Результат
трассировки представлен вложенными списками, имеющими два элемента — вычисляемое
выражение и результат вычислений. В частности, для приведенного примера отчетливо
видно, что вначале вычисляется выражение в круглых скобках (3 + 4) и получается
результат 7, который затем возводится в квадрат — получается число 49. Затем вызывается
явно не записанная единица для деления на 5, потом 49 умножается на 1/5 и, наконец,
49/5 умножается на 2 и получается конечный результат. Отсюда ясно, что даже равноценные
операции умножения и деления Mathematica разделяет по приоритету — деление выполняется
перед умножением! Символьные операции также могут трассироваться:
Trace[а*а/(b*b)]
{{ {{bb,b^2}, 1/b^2, 1/b^2}, aa/b^2, a^2/b^2}
Можно выполнить
и трассировку рекуррентных вычислений. Ниже представлен пример трассировки вычисления
чисел Фибоначчи:
fib[n_] := fib[n
- 1] + fib[n - 2]
fib[0] = fib[l] = 1
1
Trace[fib[5], fib[n_] -> n]
{5, {4, {3, {2, {!}, {0}}, {!}}, {2, {1}, {0}}},
{3, {2, {!}, {0}},
{!}}}
Trace[fib[3]]
{fib[3], fib[3-l] + fib[3-2] ,
{{3- 1, 2}, fib[2] , fib[2-l] + fib[2- 2] , {{2-1, 1}, fibtl], 11, {{2-2, 0},
fib[0] , 1}, 1+1, 2},
{{3-2, 1}, fib[l], 1}, 2+1, 3}
Функция
TracePrint [expr] дает распечатку последовательности действий при вычислении выражения
ехрг:
TracePrint[a*b/c]
ab/c
Times а b _1 с
Power
1/c
ab/с
Помимо
указанных примеров выполнения трассировки и отладки возможны и иные их варианты,
осуществляемые с помощью ряда функций. Эти функции представлены в приложении.
Надо, однако, отметить, что применение этих функций на современном уровне программирования
ограничено — в подобной трассировке особой необходимости нет, поскольку система
выдачи диагностических сообщений позволяет выполнять отладку более удобными средствами.
[an error occurred while processing this directive]
Что нового мы узнали?
В этом уроке мы научились:
- Работать
с образцами.
- Создавать функции.
- Использовать функции FixedPoint и Catch.
-
Реализовывать рекурсивные и рекуррентные алгоритмы.
- Использовать процедуры.
- Создавать циклы различного типа.
- Использовать условные выражения
и безусловные переходы.
- Работать с контекстами.
- Готовить пакеты
расширений системы Mathematica.
- Создавать простейшие средства визуального
программирования.
- Использовать средства отладки и трассировки программ.