Материал: Технол_разраб_прогр_обесп_Гагарина_Кокарева

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

В случае в) отказ называется сбоем, т. е. сбой — это кратковременный самовосстанавливающийся отказ. Остальные отказы называются устойчивыми (по умолчанию отказ устойчивый). В электронной аппаратуре сбои происходят на порядок чаще устойчивых. Их причины — флюктуации питания, ситуации «гонок» сигналов, альфа-частицы и др. В программах аналогично сбоям ведут себя времязависимые ошибки — их иногда называют «мерцающими» (blinking bugs).

Типичный пример восстановления — с помощью резервной (backup) копии данных. Если выполнить восстановление в латентном периоде отказа, то он никогда не проявится вовне — в этом состоит идеальная отказоустойчивость.


5.10.1. Количественные характеристики надежности программ


Надежность нужно оценивать, измерять, предсказывать — обеспечивать заданные требования к надежности в проекте и проверять их выполнение в продукте [3].

«Внутренняя» характеристика надежности — количество оставшихся ошибок в программе — интересна больше разработчикам, чем потребителям. Для последних важны характеристики, традиционные для теории надежности, основанные на предположении о стохастическом (случайном во времени) процессе возникновения отказов: среднее время безотказной работы (MTBF — Mean Time Between Failures) и коэффициент готовности. Третья характеристика, взаимосвязанная с первой, — интенсивность отказов — среднее их количество в единицу времени.

В предположении простейшего потока отказов (отказы независимы, редки и их вероятность неизменна во времени) P(t) — вероятность безотказной работы за время t — подчиняется закону Пуассона (экспоненциальному распределению вероятностей):

ДО = е*,

где X — интенсивность отказов (обычно в 1/час).

Его первый момент — математическое ожидание М(Р) и есть MTBF = 1/Х.

В табл. 5.4 приведены средние значения MTBF для устойчивых отказов.

Рис. 5.4. Зависимость потока отказов от времени

Таким образом, программы вносят наибольший вклад в (не)надежность современных вычислительных систем. Между тем существуют столь ответственные (mission-critical) приложения, где требуется очень малая вероятность отказов. Например, для бортовой системы управления космическим зондом требуется А.= 10"9, чтобы вероятность устойчивого отказа в первые 10 лет работы была не более 10"4 (или вероятность безотказной работы 0,9999), что означает MTBF= 100 тысяч лет!

Вообще говоря, X не постоянна во времени. Для аппаратуры характерна зависимость, представленная на рис. 5.5.

Многие программные продукты (ПП) имеют аналогичный характер изменения надежности: А — период начальной экс-

в

Inf

Рис. 5.5. Типичное изменение X электронной аппаратуры во времени: А — период приработки («выжигание» дефектов); В — полезная жизнь; С — старение, износ

плуатации (расширенного бета-тестирования), С — накопление ошибок из-за модификаций.

Если отказ все же произошел, время восстановления должно быть минимальным. Это характеризуется показателем ремонтопригодности коэффициента готовности (availability):

к=(Т-Тпр)/Т,

где Т — общее время работы, Тпр — время простоя из-за восстановлений. В ответственных системах требуется, чтобы значение к почти не отличалось от 1: для цифровых АТС — 2 часа простоя суммарно за 15 лет; для системы управления воздушным движением — 3 сек за год!


5.10.2. Методы оценки и измерения характеристик надежности


«Внутренняя» характеристика — число оставшихся ошибок — абсолютное или относительное. Считается, что в хорошо отлаженной программе — не более одной ошибки на 1 тыс. строк исходного кода. Для ответственных применений требуется то же на 10 тыс. строк и больше. Например, для СОИ этот показатель был задан как не более 2,5 ошибки на 105 операторов языка Ада.

Как проверить соответствие ПП таким требованиям?

  1. Метод Миллса (IBM, 1972 г.) использует прием биологов, метод «меченых рыб». Группа тестирования засоряет программу искусственно ошибками и, продолжая тестирование, анализирует долю внесенных ошибок среди обнаруженных.

  2. Пусть внесено s ошибок, обнаружено п собственных и v внесенных ошибок. Предполагая, что вероятность обнаружения внесенных и собственных ошибок одинакова, получим первоначальное количество оставшихся ошибок N=sn/v. Проверка гипотезы: осталось меньше к собственных ошибок. Вносится еще s ошибок и тестирование продолжается, пока все они не обнаружены. Пусть к этому моменту найдено п собственных. Тогда уровень значимости гипотезы (т. е. вероятность того, что она истинна, равна 1 при п > к и s/(s + к + 1) при п < к.

  3. В методе Руднера (1977 г.) тестирование осуществляется двумя независимыми группами тестеров параллельно, которые обнаруживают тх и т2 ошибок соответственно, из которых т]2 ошибок — общие. Используя гипергеометрическое распределение, методом максимального правдоподобия может быть найдена оценка числа первоначально содержавшихся в программе ошибок N= mlm2/ml2.

4. Фирма Motorola использует в качестве меры надежности своих ГШ (управляющих программ реального времени) среднее число ошибок на 1000 строк исходного кода. Она разработала метод оценки времени тестирования без отказов (zero-failure method), подтверждающего заданную надежность. Метод основан на известной форме зависимости:

T=f(N, п, 0,

где Т — время окончательного тестирования — испытаний без отказов; TV — допустимое число ошибок в коде; п — общее число ошибок, обнаруженных в ходе тестирования; / — время, потраченное на выявление всех п ошибок.

Если за время Т ни одного отказа не произошло, считается, что в программе не более N ошибок и тестирование можно закончить. Если же отказ произошел через промежуток времени tr< Т, то испытание продолжается, причем функция Гпересчи-тывается заново для п + 1 и / + tr.

Функция Т получена на базе одной из моделей надежности программ на основе оценок функции Ц0, экстраполирующих динамику отладки (для этого и ведутся журналы отладки). Например, модель Джелинского — Моранды (1972 г.), использовавшаяся в ряде ответственных проектов, в том числе Apollo, основана на следующих допущениях:

  1. Интенсивность обнаружения ошибок R(t) пропорциональна текущему числу ошибок в программе, т. е. числу исходных ошибок минус обнаруженные.

  2. Все ошибки равновероятны и их проявление не зависит друг от друга.

3. Ошибки постоянно исправляются без внесения новых.

4. R(t) постоянна в промежутке между двумя смежными мо-
ментами обнаружения
г,- и tM.

Тогда R(t) — ступенчатая монотонно убывающая функция вида (рис. 5.6).

Предполагается, что динамика проявления ошибок во время эксплуатации остается такой же, как при тестировании, т. е. по

t А

'о h

R(t)

Рис. 5.6. Вид ступенчатой монотонно убывающей функции

стулируется тождество функций R(t) и X(t) с тем отличием, что значение \(t) «замораживается» в момент завершения тестирования — прекращается исправление ошибок.

Если / — число ошибок, обнаруженных к моменту времени /, то до следующего обнаружения справедливо R(t) = К{В- /), где В — неизвестное число исходных ошибок; К — неизвестный коэффициент пропорциональности. Полагая ^.= /i+I-/, (/=0, п- 1), можно утверждать, что X { имеют экспоненциальное распределение: ДА]) = exp (-К(В- i)X). Имея набор А] из журнала отладки, можно решать задачу нахождения значений К и В, отвечающих принципу максимального правдоподобия. Однако проще решение для модифицированной модели, где поскольку dN(f)/dt = R(t) (число ошибок, обнаруженных в единицу времени), получаем дифференциальное уравнение с начальными условиями:

^=KdN(t) dR(t) + Km=0 N{0)=0 т = шdt dt dt

Здесь снято допущение 4, и функция R(f) перестает быть кусочно-постоянной: R(t) = К(В- N(t)).

Его решение: R(t) = KBe~Kt Обозначая а = In (KB), b = -К, получаем запись решения в виде: R(t) = exp (я+ bt). Логарифмируя обе части этого равенства и переходя к дискретному времени получаем систему уравнений

In /?(/,) = a + btt\ i= 1, п.

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

5.10.3. Преимущества парного программирования

  1. Парное программирование экономически оправданно. При использовании в организации ХР штат программистов должен возрасти вдвое. Так как квалифицированные кадры являются достаточно дорогими, то, казалось бы, расходы на создание программного обеспечения должны значительно возрасти. И это действительно так — затраты возрастают на 15 %, но в то же время, как доказывают исследования, при парном программировании количество ошибок на 15 % меньше, чем при одиночном. Если учесть стоимость исправления ошибок, обнаруженных на разных стадиях жизненного цикла продукта, включая внедрение, то сэкономленные на этом деньги значительно превосходят затраты на увеличение штата сотрудников.

  2. Быстрая обучаемость. При парном программировании специалисты перенимают приемы работы друг друга, значительно расширяют свои знания и передают свой опыт.

  3. Работая вместе, люди чувствуют себя уверенней, так как каждый из них знает, что партнер контролирует все его действия. При этом увеличивается качество его работы.

  4. В случае выбытия из проекта одного разработчика работавший с ним в паре сможет сразу же продолжить его деятельность, что приведет к экономии дорогого времени и сил второго разработчика.

  5. Работа в паре улучшает коммуникабельность в коллективе, помогает наладить понимание и взаимоотношения, что является крайне важным фактором с точки зрения психологии [14].


5.11. Отладка программ


Локализация и исправление ошибок называется отладкой [3]. Отладка — это процесс обнаружения причин возникновения ошибки и ее последующего исправления (в отличие от тестирования, являющегося процессом обнаружения самого факта существования ошибки).

Отладка включает в себя элементы тестирования и разработки. На некоторых проектах отладка может занимать до 50 % всего времени разработки. Для многих программистов отладка — это самая трудная часть программирования. При соответствующем подходе количество ошибок, требующих отладки, должно

сократиться, и отладка должна стать самой легкой частью; при таком подходе все ошибки сводятся к небольшим недосмотрам или опечаткам.

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


Ошибки синтаксиса языка

Как правило, в абсолютном большинстве случаев ловятся на
стадии компиляции программы, или же, если вы работаете с ин-
терпретируемым языком типа
Perl или PHP, то при первом интер-
претировании программы. Но есть один существенный момент —
когда выражение допустимо, но зависит от конкретного компиля-
тора или интерпретатора. Например, в языке Си вполне допусти-
мыми по синтаксису, но не по смыслу, являются выражения:
s[i++]=i; printf ("%d %d", i++) ;. Результат этих строк

не определен, так как неизвестно, в каком порядке будет инкре-ментироваться и вычисляться значение переменной /. Переменная не может более 1 раза присутствовать в выражении, если ее значение изменяется в ходе вычисления этого выражения.


Ошибки во время выполнения

К ошибкам во время выполнения программы относятся ошибки в логике и алгоритмах программы. Ошибки в логике программы связаны с неправильной записью алгоритма, например, вместо && вы написали || или поставили точку с запятой там, где ее не должно быть. К этому же классу ошибок относится неправильное обращение с памятью. В языке Си неправильное обращение с памятью является наиболее распространенной ошибкой программистов, причем не только новички, но и профессионалы нередко допускают ошибки подобного типа. Для языка Си — это один из самых больных вопросов и больших недостатков. Ошибки в алгоритме связаны с неправильным проектированием программы или же с изначально неправильно заложенной бизнес-логикой и функциональными требованиями. Пользователь ждет от программы то, что изначально от нее не требовалось. Ошибки во время выполнения — наиболее часто встречаемый тип ошибок, и, как правило, устранение таких ошибок не представляется чересчур сложной задачей.


Ошибки логики взаимосвязанных СО-программ

Ошибки данного типа лежат во взаимосвязанных Сопрограммах. Рассмотрим в качестве примера тестовую систему (см. сайт http://test.itsoft.ru). При сдаче теста в цикле работают два скрипта. Первый показывает вопрос, а второй проверяет правильность ответа. Если в тесте 10 вопросов, то эти СвЬскрипты вызываются парно в цикле 10 раз. Но что будет, если пользователь нажмет кнопку «Обновить» в броузере? Скрипт, который показывает вопрос, вызовется повторно. Что будет при разрыве модемного соединения? Отладка в таких системах значительно сложнее, так как вам придется наблюдать за выполнением ряда взаимосвязанных скриптов.


Ошибки многопользовательского доступа

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


Невоспроизводимые ошибки

Невоспроизводимые ошибки представляют собой наиболее сложный тип ошибок. Например, в високосном году 29 февраля ваша система вдруг начала давать сбои, которые сами собой исчезают в невисокосном году. Но бывают ошибки, которые мистическим образом появляются и исчезают. В той же тестовой системе была непонятная ошибка, которая проявлялась 1 раз на несколько сот случаев. Непонятным образом некоторые студен-

ты после сдачи теста получали не результаты, а сбой системы. На исправление этой ошибки ушло два рабочих дня. Оказалось, что проблема в скрипте на JavaScript, который отправлял данные HTML-формы на сервер после истечения допустимого времени ответа на вопрос. Проблема в том, что если время подходило к концу и пользователь нажимал кнопку «Ответить», а в это же время уже начала работать функция JavaScript form.submit(), то отправка данных HTML-формы происходила дважды, т. е. скрипт проверки правильности ответа вызывался 2 раза. А это за собой тянуло ошибку во взаимосвязанных CGI-скриптах, и внешнее проявление сбоя системы мы наблюдали уже при подсчете результатов, а не непосредственно сразу после двойной отправки HTML-формы. Сам код JavaScript был написан верно, и с теоретической точки зрения даже если пользователь нажимает кнопку «Отправить» в последнюю секунду, HTML-форма должна была отправляться только 1 раз. Но на практике все оказалось совсем по-другому. На самом деле ничего мистического нет, или, как говорится, чудес на свете не бывает. Просто невозможно воспроизвести условия, в которых наблюдалась невоспроизводимая ошибка. Надо искать в программе случайности: одновременный доступ к одному ресурсу, генератор случайных чисел, неинициализированные переменные, некорректная работа с памятью или преобразование типов, которые могут проявлять себя не каждый раз.


Ошибки инструментария и других компонентов системы

Ошибки самого компилятора или интерпретатора очень редки, но и такие бывают.

После классификации ошибок давайте рассмотрим методы их поиска. В первую очередь, один простой и, казалось бы, очевидный совет: «надо думать, анализировать, почему программа не работает так, как было задумано, что надо в ней исправить». Никакой самый навороченный отладчик за вас ошибку не найдет. Никакая самая лучшая методика не найдет и не ускорит поиск ошибки, если вы не «включите» мозги по полной программе и не сосредоточитесь целиком и полностью на поимке ошибки. Итак, допустим, вами, пользователем или тестирующим, было зафиксировано некорректное поведение программы. Что делать? Ниже перечислены методы в порядке их приоритетности, которые используют многие программисты.

Локализация ошибки. Программа — это черный ящик, кото-рый что-то принимает на вход и выдает что-то на выходе. Первое, что вам необходимо сделать, — понять, где именно в этом черном ящике происходит сбой. Для этого уменьшайте количество параметров, передаваемых на вход программы. Добейтесь двух малоразличимых наборов входных параметров, чтобы при одном из них программа работала, а при другом нет.

Отключение ненужных модулей программы. Закомментируйте все лишнее. Тем самым вы упростите вашу программу. Имеет смысл комментировать отдельные куски программы до тех пор, пока ошибка не исчезнет.

Использование отладчика. Возможности современных отладчиков перечислены ниже:

  • точки останова на конкретных строчках кода;

  • остановка на п-й итерации цикла;

  • остановка при изменении переменных;

  • остановка при присваивании конкретного значения;

  • прохождение кода строчка за строчкой;

  • откат по программе (далеко не все);

  • исследование всех данных в программе, включая типы, определенные пользователем;

  • присваивание новых значений переменным;

  • продолжение исполнения программы;

  • многоязыковая отладка (язык1, язык2, ассемблер...);

  • запоминание установок.

Контрольные вопросы

  1. Какие виды ошибок существуют?

  2. Что такое тест? Какими свойствами должен обладать тест?

  3. Каковы критерии выбора тестов?

  4. Дайте краткую характеристику каждому критерию выбора теста.

  5. Опишите последовательность разработки тестов.

  6. Что входит в понятие надежности ПО?

  7. Какие виды отказов существуют?

  8. Каковы количественные характеристики надежности программ?

  1. Что представляют собой методы оценки и измерения характеристик надежности ПО?

10. Перечислите достоинства парного программирования.

Глава 6

СОПРОВОЖДЕНИЕ ПРОГРАММ







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

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



6.1. Виды программных документов


К программным относят документы, содержащие сведения, необходимые для разработки, сопровождения и эксплуатации программного обеспечения. Документирование программного обеспечения осуществляется в соответствии с Единой системой программной документации (ГОСТ 19.ХХХ). Так, ГОСТ 19.101—77 устанавливает виды программных документов для программного обеспечения различных типов. Ниже перечислены основные программные документы по этому стандарту и указано, какую информацию они должны содержать.

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

Ведомость держателей подлинников (код вида документа — 05) должна содержать список предприятий, на которых хранятся

Источник: https://files.student-it.ru/previewfile/6671