Структура жизненного цикла программы
I. Организация программного продукта
Технология программирования – это быстро развивающиеся направление в программировании. Интерес к деталям процесса изготовления программного продукта обусловлен увеличением трудоемкости и стоимости изготовления программных систем. Стоимость изготовления программных систем в настоящее время в несколько раз превышать стоимость аппаратуры ЭВМ.
Можно с различной степенью подробности рассматривать весь жизненный цикл программного продукта. Условно он разбивается на 4 больших этапа:
1. проектирование программных продуктов;
2. испытание программных средств;
3. документирование программного обеспечения;
4. сопровождение программного продукта.
Жизненный цикл программного продукта – это период времени, начинающийся с момента принятия решения о необходимости создания программного продукта, и заканчивающийся в момент его полного изъятия из эксплуатации.
Весь жизненный цикл состоит из процессов. Под процессом понимают совокупность взаимосвязанных действий, преобразующих входные данные в выходные. Каждый процесс характеризуется определенными задачами и методами их решения, а также исходными данными полученными от других процессов и результатами.
|
|
В соответствии со стандартом ISO/IEC12207 все процессы жизненного цикла программного продукта разделены на 3 базовые группы:
1. основные
2. вспомогательные
3. организационные
К основным процессам относятся:
· процесс приобретения программного продукта;
· процесс поставки;
· процесс разработки;
· процесс эксплуатации;
· процесс сопровождения.
К вспомогательным процессам относятся:
· документирования;
· управление конфигурацией;
· обеспечение качества;
· верификации;
· аттестации;
· совместной оценки;
· аудита;
· разрешения проблем.
К организационным группам относятся:
· управления;
· создания инфраструктуры;
· усовершенствования;
· обучения.
Можно привести множество различных критериев для оценки качества программного продукта. Обозначим 4 наиболее важных и характерных критерия:
1. надежность
2. использование ОЗУ
3. время выполнения
4. дружественность пользовательского интерфейса
Пример 1. Вычислить на ЭВМ y = x7, не используя операцию возведения в степень.
Начало вещест. х, у, х1, х2, х3, х4, х5, х6;
Ввод (х);
х2: = х* х
х3: = х2*х
х4: = х3*х
х5: =х4*х
х6: = х5*х
у: = х6*х
выход (у)
конец
Не менее вероятно, что программа может выглядеть и следующим образом:
Начало вещест. Х; у;
Ввод (х)
у: = у*х
у: = у*х
у: = у*х
у: = у*х
у: = у*х
вывод (у)
конец
Во-первых, обе программы решают поставленную задачу.
|
|
Во-вторых, вторая программа лучше 1-ой, т.к. она требует только двух ячеек памяти. Во 2-й программе 5 последних команд одинаковы и это наталкивает на еще большие сокращение программы за счет использования операторов – цикла:
Начало вещест. х; у целое i;
Ввод (х);
у: = х*х;
для i: = 1 шаг 1 до 5 цикл
у: = у*х;
вывод (у)
конец
Выводы:
· задача может быть запрограммирована разными способами (одни способы лучше, др. – хуже);
· программы могут отличаться друг от друга сильнее и слабее: 1-ая и 2-ая программы больше похожи друг на друга, чем каждая из них на 3-ю;
· первые две программы настолько похожи, что даже лучше говорить, что это одна и та же программа, только с разными обозначениями для промежуточных величин (в 1-й они все разные, а во 2-й – одни и те же);
· имеет смысл такая проблема: составить программу, используя наименьшее количество обозначений для величин. Это приводит к экономии ОЗУ.
Отправные принципы:
1. При составлении программы из собраний удобства и логичности вводятся различные обозначения для исходных и промежуточных величин задачи и для ее результатов. Если распределить память по принципу: «каждой величине – свою ячейку», то может оказаться, что памяти будет израсходовано больше, чем это на самом деле нужно. Этот факт можно выразить и по-другому: можно переписать программу так, что она будет решать ту же задачу, но содержать меньшее количество обозначений.
2. Сокращать число обозначений в программе можно: имея в команде (или операторе) некоторый результат, не надо торопиться вводить для него новое обозначение, а посмотреть нет ли в данный момент «свободной» переменной, т.е. такой, текущее значение которой больше не потребуется. Если такая переменная есть, то она и берется в качестве обозначения результата.
Пример 2. Вычислить у = х59, не используя операцию возведения в степень. Логично составить программу следующим образом:
Начало вещ. х; у; целое i;
Ввод (х);
у: = х*х;
Для i: = 1 шаг 1 до 57 цикл
у: = у:*х;
Вывод (у);
Конец
Эта программа короткая, но очень долго работает: на решение задачи расходуется по меньшей мере 3*57 действий (умножение, изменение i, сравнение i (57).
В том случае, если бы надо было вычислить х64 (64 = 26), то на это потребовалось бы всего 6 умножений:
у: = х*х; (х2)
у: = у*у; (х4)
у: = у*у; (х8)
у: = у*у; (х16)
у: = у*у; (х32)
у: = у*у; (х64)
Представим, 59 как сумму степеней 2: 59 = 32+16+8+2+1, т.е. х59 = х32 + х16+ х8+ х2+х, тогда программа может выглядеть следующим образом:
Начало вещ. х; у; х2; х4; х8; х8; х16; х32;
х2: = х*х;
х4: = х2*х2;
х8: = х4*х4;
х16 = х8*х8;
х32: = х16*х16;
у: = х*х2;
у: = у*х8;
у: = у*х16;
у: = у*х32;
вывод (у)
конец
В соответствии с принципом б) нет необходимости вводить величину х8, а вместо нее можно использовать х4, на других величинах в этом варианте сэкономить нельзя.
Т.к. мы посчитали сначала все степени 2ки, а после этого начинаем их использовать, то это делает невозможным сэкономить обозначения величин в пяти первых операторах.
Поступим по-другому: получив очередную степень двойки, ее тут же занесем в у, если она является слагаемым нашего показателя; если же нет, то употребим ее на получение следующей степени двойки. Одновременно стараемся соблюдать принцип б).
Начало вещ х; у;
Ввод (х)
у: = х*х; (х2)
х: = х*у; (х = х3)
у: = у*у; (у= х4)
у: = у*у; (у= х8)
х: = х*у; (х= х11)
у: = у*у; (у= х16)
х: = у*х; (х= х27)
у: = у*у; (у= х32)
у: = х*у; (у= х59)
вывод (у);
конец
Вывод: каким бы способом мы не получили программу, если мы хотим получить максимальную экономию памяти, мы должны проверить не содержит ли она лишних величин и постараться найти наилучший вариант алгоритма, чтобы она стала более короткой.
С точки зрения программиста память и время счета – два различных ресурса, и программист (а не система) должен нести ответственность за их распределение, т.е. за разделение между ними необходимой нагрузки.
|
|
Рассмотрим случай, в котором мы имеем дело с вычислением, при котором регулярно требуется значение FUN (arg), где FUN – некоторая функция, определенная для текущих значений одной или нескольких переменных, под общим названием arg.
В одном варианте программы (А) запоминается только значение arg, а значение FUN (arg) вычисляется каждый раз, когда, оно понадобится. В другом варианте (Б) вводится дополнительная переменная, например γ, назначение которой состоит в том, чтобы хранить значение FUN (arg). Т.о., если вариант (А) не содержит оператор arg: = …, то вариант (Б) будет содержать arg: = …, γ: = FUN (arg).
Каждый раз, когда вариант (А) требует вычисления FUN (arg), вариант (Б) обратиться к текущему значению, который значительно быстрее.
Вывод: если значение FUN (arg) пи одних и тех же значениях arg требуется чаще одного раза, то вариант (Б) потребовал бы меньше времени счета. В таких случаях вариант (Б) предпочтительнее варианта (А). Это же относится и к вычислению одного и того же арифметического выражения при одних и тех же значениях переменных.
В случаях, когда приходится делать выбор между экономией ОЗУ и уменьшением времени работы программы, выбирают последнее.