Опубликован: 05.11.2013 | Доступ: свободный | Студентов: 542 / 46 | Длительность: 11:51:00
Лекция 9:

Разработка модуля или программы

Проектировщик должен опираться на опыт, на строгое логическое мышление и на педантичную точность.

Никлаус Вирт

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

Добиться этого можно разными путями, но результат всегда должен удовлетворять некоторым критериям, а именно:

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

8.1. проектирование архитектуры

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

Часто удобно вводить условности, отличающие отдельные требования друг от друга и от пояснений. Хорошей практикой будет использование глагола должен (должна, должны) в каждом требовании, например: "Функция деления должна вернуть нуль в случае, если знаменатель или числитель, или они оба равны нулю". При этом требования могут делиться на разделы, которые описывают различные функции программы и форматы ее взаимодействия с окружением.

Одновременно с требованиями к самому ПО на их основе, как уже говорилось ранее, могут разрабатываться тест-требования, в которых отражается то, что надо будет проверить в ходе тестирования, чтобы убедиться, что ПО соответствует разрабатываемым требованиям. Каждое тест-требование выделяет некий класс эквивалентности (или область), в котором надо проверить поведение программы, и обычно начинается со слов "проверить, что". Например, для функциональности, приведенной в предыдущем абзаце, тест-требования можно сформулировать следующим образом:

  • Проверить, что если числитель равен нулю, а знаменатель не равен нулю, то функция возвращает нуль.
  • Проверить, что если числитель не равен нулю, а знаменатель равен нулю, то функция возвращает нуль.
  • Проверить, что если числитель равен нулю и знаменатель равен нулю, то функция возвращает нуль.

Далее по требованиям и тест-требованиям формируют тест-план, а на его основе уже реализуют сами тестовые примеры.

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

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

8.2. Внешнее взаимодействие

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

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

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

Кроме самого обмена данными с пользователем, необходимо всегда учитывать время внешнего "бездействия" программы для пользователя, проявляемое неизменением никаких внешне видимых данных ("зависание" программы). Считается, что время спокойного ожидания пользователя равно примерно двум секундам, далее необходимо изменить что-нибудь на экране, что-нибудь переместить, мигнуть, иначе пользователь начнет сомневаться, что программа работает. Для таких целей часто применяют так называемый "прогресс бар" или процентную шкалу, отображающую степень выполнения программы (алгоритма).

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

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

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

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

Вопросы и задачи для самостоятельного решения

  • Каковы критерии разделения программы на модули?
  • Как следует формулировать требования, чтобы они отличались от пояснений?
  • Как следует формулировать описание тест-требований?
  • Какой документ отвечает на вопрос: "Что должна делать программа?"
  • Какие виды диалогов с пользователем Вам известны?