Наиболее неприятный тип ошибок — это неправильные начальные условия для составления программы. В этом случае может получиться, что программа полностью удовлетворяет требованиям, но сами технические требования неправильные. Никакие маленькие коррекции не исправят положения дел. Вот почему мы обязательно должны затратить так много времени на разбор и выработку всех условий работы устройства.
Всеобъемлющее тестирование может использовать технику сверху вниз, когда сначала исследуется общее поведение системы, а затем детали поведения в отдельных режимах. А может наоборот, снизу вверх, когда тестирование начинается с проверки правильного функционирования драйверов периферии. Иногда используется смешанная техника. В любом случае, методика тестирования определяется конкретным проектом. Хороший тест проверяет также живучесть (робастность) программного обеспечения. Под живучестью понимают ситуацию. При которой на вход системы могут поступить не предполагаемые комбинации сигналов, и при этом программное обеспечение должно оставаться работоспособным и формировать сигналы управления, по крайней мере, не создающие аварийной ситуации для исполнительных устройств.
Применение. В процессе тестирования контроллера стереоусилителя были выявлены ситуации, которые не были предусмотрены начальными установками на проектирование программы. Например, если пользователь выбрал устройство для воспроизведения, то предыдущее устройство отключается от входа усилителя, а следующее выбранное подключается. При этом не подумали, а что следует делать контроллеру, если пользователь с пульта управления выбрал то же устройство, которое уже подключено. Контроллер в соответствие со сценарием сначала отсоединял устройство, а затем его же коммутировал опять. Это вызывало неприятные для слуха шумы. Только при тестировании устройства на реальном объекте мы смогли выявить эту неисправность и достаточно просто исправили программу.
Следует заметить, что процесс тестирования занимает много времени, поскольку он многоступенчатый. Если какие либо ошибки обнаружены, то вносятся исправления в исходный текст программы, и все тесты должны быть проведены заново.
Итак, мы закончили свое первое знакомство с методом структурного проектирования. В следующем разделе мы остановимся на вопросах документирования процесса разработки.
2.5.2. Документирование программ
Теория. Многие начинающие программисты уверены, что документирование программного обеспечения проекта — это добавление некоторого количества коротких комментариев к работающей версии программы. Однако хорошее документирование программы значительно важнее самого программного обеспечения. Хорошая документация содержит все разработанные на предыдущих этапах структуры, которые были обсуждены нами в предыдущем разделе. Все эти структуры помогают нам не только закодировать программу, но и содержат информацию о том, как программа работает.
Полная документация на программное обеспечение содержит комментарии, письменное описание принципов построения программы, технические условия на написание программы, исходный текст программы, руководство пользователя, историю разработки программы и ее модификаций. Весь этот набор документов может быть разделен на внешнюю и внутреннюю документацию. Внешняя документация состоит из специально написанного текста, который поясняет, как работает программа. Внутренняя документация включает полный набор читаемых и понимаемых документов, который необходим для легкого исправления кода. Внутренняя документация состоит из комментариев, исходного текста программы, структуры и специальных записей.
Комментарии помогают читателю определить, что программист хотел сделать в любой точке программы. В нашем контроллере стереоусилителя мы имели 4 страницы комментариев, предшествующих программе, которые со всей полнотой описывали работу системы. Мы также написали дополнительные комментарии по алгоритму работы программы, а также описание каждой отдельной функции. Более того, мы комментировали каждую строку исходного текста программы. Это может показаться избыточным. Но чем больше времени затрачено на составление комментариев, тем меньше времени понадобится для поддержания этого кода.
Самодокументирующий код означает, что имена переменных констант и функций выбираются такими, чтобы было интуитивно понятно ее назначение. Например, если функция называется «delay_3ms», то сразу понятно, что функция формирует задержку 3 мс.