- •2. По сфере применения
- •2. Разработка пользовательского интерфейса
- •3. Разработка программы
- •4. Отладка
- •5. Внедрение
- •6. Трансляция и интерпретация программ
- •7. Среды и реализации языков программирования
- •9. Теория первичных программ
- •11. Представление алгоритма и псевдокод
- •12. Алгоритм последовательного поиска
- •13. Алгоритм двоичного поиска
- •14. Алгоритм сортировки методом вставки
- •15. Модульное программирование
- •2.1. Нижнюю половину можно одеть в два этапа:
- •2.2. Верхнюю половину можно также одеть в два этапа:
- •20. Принципы объектно-ориентированного программирования
- •5.9. Оптимизация
- •5.3. Ход тестирования
- •5.4. Автономное тестирование модулей программы
- •5.5. Методы тестирования
- •5.6. Аксиомы тестирования
- •5.7. Классификация тестов
5.9. Оптимизация
Обычно программа создается в достаточно жестком временном режиме, что заставляет программиста искать, скорее, более правильные решения, чем более эффективные. Под эффективностью программы понимают, прежде всего, скорость ее выполнения, а также ее объем. Сегодня, когда уделяется особое внимание пользовательскому интерфейсу, в список влияющих на эффективность программы факторов можно, пожалуй, также занести и удобство интерфейса. Таким образом, под оптимизацией понимается процесс улучшения программы.
Оптимизация не является обязательным условием разработки программы. Однако существует целый класс программ, критичных как к скорости выполнения, так и к размеру. Таковыми являются программы графического вывода в силу большого объема вычислений, связанных с графическими преобразованиями.
При проектировании больших систем оптимизация производится в два этапа, Сначала оптимизируют текст программы на языке высокого уровня, а затем наиболее критичные ко времени выполнения процедуры переписывают на язык ассемблера. Существуют следующие способы оптимизации программных кодов.
Разгрузка участков повторяемости. Является способом оптимизации, который чаще всего подразумевает разгрузку циклов путем вынесения из них выражений, которые могут быть вычислены вне циклов.
К этому виду преобразований относятся также «чистки» тел рекурсивных процедур, когда выражения в соответствующем цикле (или теле многократно вызываемой процедуры) выносятся и размещаются перед входом в участок повторяемости — это так называемая чистка вверх.
Иногда применяют чистку вниз, когда соответствующие фрагменты кода помещаются после цикла. При этом нужно обратить внимание на то, что выносить можно только такие выражения, которые обязательно исполняются при каждом прохождении разгружаемого цикла.
Замена сложных операций на более простые. Очень часто одна операция предпочтительнее другой на том основании, что выполняется быстрее, но знание таких нюансов приходит к программисту лишь с опытом.
Например, операция сложения выполняется быстрее операции умножения, а умножение быстрее операции деления. Поэтому один оператор умножения переменной на некоторое небольшое целое число (обычно не более трех) лучше заменить на эквивалентное количество сложений. Выражение:
Total := Summa + Summa + Summa;
эффективнее выражения: Total := 3 * Summa;
а операцию деления Summa := Summa/2; лучше заменить на более быстрое умножение, которое приведет к тому же самому результату Summa := Summa * 0.5;
Чистка программы. Данный способ повышает качество программы за счет удаления из нее ненужных объектов и конструкций. Набор преобразований этого типа включает в себя следующие варианты оптимизации:
удаление несущественных операторов, то есть операторов, не влияющих на результат программы;
удаление бесполезных операторов, вычисляющих вспомогательные переменные, используемые только для подстановки в другие выражения;
удаление объявленных, но неиспользуемых переменных и типов;
удаление идентичных операторов;
удаление процедур, к которым нет обращений.
Необходимость в такого рода чистках возникает потому, что очень часто программист «захлебывается» в общем количестве переменных и процедур одного слишком большого модуля. Подчас он объявляет переменные, которые потом нигде в программе не использует.
Например, программист может объявить целочисленную переменную для организации цикла, а затем, спустя какое-то время, для организации другого цикла объявляет еще одну переменную, забыв о существовании предыдущей и возможности ее повторного использования.
Экономия памяти. Одним из главных ресурсов после процессорного времени, который использует программа, является объем оперативной памяти. Объем памяти зависит как от размера кода самой программы, так и от количества статических и динамических переменных.
Программист должен учиться как можно экономнее использовать память. Каждую структуру следует тщательно продумывать и не требовать, скажем, для переменной, в которой будут храниться координаты текстового экрана, двухбайтового типа.
Это так называемая экономия на типе переменной. Существует и еще ряд способов более экономного расходования памяти:
Глобальная экономия памяти подразумевает совмещение по памяти не существующих одновременно статических переменных. Модульное программирование также подразумевает разнесение объявлений несвязанных переменных в различные модули.
Изменение области существования переменной.
Перемещение оператора объявления переменной (резервирования памяти) ближе к тому участку программы, в котором содержатся операторы, использующие эту переменную, то есть переменную следует объявлять в границах того блока, где она используется.
Экономия стека: при передаче массива в качестве параметра подпрограммы, следует использовать ссылку на массив. Помимо экономии памяти это приводит также и к экономии времени за счет того, что система не создает копии передаваемого массива в стеке.
25. Виды тестирования, разработка и выполнение тестов
Тестирование (testing) - любой вид деятельности, в рамках которого путем реального выполнения каких-либо задач проверяется соответствующая работа либо системы в целом, либо составной ее части.
Тестирование программы (program testing) - проверка, которая проводится в ходе прогона программы с целью убедиться, работает ли она так, как требуется. Это осуществляется при выполнении одного или нескольких тестовых прогонов, при которых в программную систему подаются входные (тестовые данные), а реакция системы фиксируется для последующего анализа. Может осуществляться как с ЭВМ, так и без ЭВМ.
Один из главных законов тестирования гласит: «Тестирование программы или ее отдельных модулей не должен осуществлять программист (группа программистов), создавший эту программу или модуль».
Для обеспечения достаточной степени надежности тестирования должен быть специальный отдел в фирме или привлечены программисты из сторонних организаций. Первоначально разработчик сам устраняет мелкие ошибки. Когда компиляция модуля завершается, и компилятор выдает соответствующее сообщение «Compile successful", программист обычно запускает откомпилированный фрагмент и производит несколько тестов.
После такого поверхностного тестирования разработчиком законченный модуль должен быть протестирован другим программистом. Дело в том, что разработчик изначально настраивается на какой-то один вид возможной ошибки и, не обнаружив ее при предварительном тестировании, не склонен проверять другие участки модуля. Сторонний программист рассматривает модуль, подключенный к программе как своего рода «черный ящик» и пытается запускать его на предельных нагрузках.
Статистика свидетельствует, что стоимость тестирования составляет не менее 50% всей стоимости начальной разработки.
Сколько бы сил, времени и денег не было потрачено на тестирование, один из главных законов программирования действует с неотвратимостью рока: «Тесты могут доказать наличие ошибок в программе, но они не могут доказать их отсутствия» (Э. Дейкстра «Заметки по структурному программированию»).
При тестировании могут возникать следующие вопросы:
Искать все ошибки или грубейшие?
Если не все, то как установить порог допустимости ошибки?
Когда завершать тестирование?
Что делать, если сроки поджимают или нет ресурсов на дальнейшее тестирование?
Где остановиться в документировании тестов?
Ответы на них во многом зависят от того, что считать качественной программой?
Качественная программа - это программа, выполняющая заранее объявленные действия известным способом и не выполняющая никаких необъявленных действий.
Под объявленными действиями понимаются, в том числе, и алгоритмы обработки данных. Таким образом, тестирование должно выполняться до тех пор, пока программа не избавится от всех необъявленных действий (частным случаем которых является неверная обработка, то есть, в сущности, просто порча данных).
