Разработка программного модуля для компьютерной игры

Основные стадии разработки, принципы тестирования и отладка программного модуля "VFS". Особенности проектирования на языке UML. Методы "грубой силы" и их применение при отладке программы. Вредные факторы, присутствующие на рабочем месте программиста.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 07.03.2012
Размер файла 827,0 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

1) доступный конструктор копирования;

2) доступный оператор присваивания;

3) доступный деструктор.

Все контейнеры поддерживают базовый функционал:

1) набор конструкторов; среди них: конструктор по умолчанию, конструктор копирования, конструктор, заполняющий контейнер элементами из последовательности и ряд других;

2) деструктор; при уничтожении контейнера вызываются деструкторы всех содержащихся в нём объектов, а всё память освобождается;

3) функции begin(), end(), rbegin(), rend() - возвращают итераторы на начало и конец последовательности объектов, содержащихся в контейнере, в прямом и, соответственно, обратном порядке; как и всюду в STL, итератор на начало указывает на первый элемент последовательности, а итератор на конец - на место в памяти за последним;

4) функция size(), возвращающая количество элементов в контейнере.

В разработке VFS контейнеры применялись как основной способ хранения данных. Все предоставляемые интерфейсом модуля последовательности объектов являются контейнерами STL. Ниже перечислены основные использовавшиеся контейнеры.

vector - контейнер, являющийся динамическим массивом. Используется для организации редко редактируемых списков. Контейнер vector эффективно реализует следующие операции:

1) добавление и удаление элементов в конце массива;

2) доступ к элементу с произвольным номером;

3) возможность интерпретировать список элементов как традиционный массив C.

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

Доступ к элементам контейнера реализуется с помощью random-access итераторов и оператора [] (аналогично массивам С).

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

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

set, multiset, map, multimap - ассоциативные контейнеры, предназначенные для хранения упорядоченных последовательностей элементов с возможностью быстрой вставки и удаления.

По затратам памяти и отношению к указателям ассоциативные контейнеры похожи на list (в большинстве реализаций для представления этих контейнеров используются бинарные деревья). Не стоит использовать эти контейнеры, если в этом нет необходимости.

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

string - формально можно рассматривать как частный случай контейнера vector, содержащего символы. Использовать string гораздо удобней, чем пользоваться строками в стиле C. Для string определены такие операции, как конкатенация (сцепление), преобразование к традиционной C-строке, присваивание, сравнение и ряд других.

Кроме того, string является контейнером, а значит к нему применим весь набор стандартных алгоритмов STL.

Итераторы

Итератор (iterator) - специализированный объект, предназначенный для доступа к элементам последовательностей, в частности к элементам контейнеров. По своему поведению итератор напоминает указатель на элемент данных: к нему можно применить оператор разыменования «*» или оператор выбора члена класса через указатель «->».

Рис. 2.8. Иерархия итераторов в STL

Иерархия итераторов STL представлена на рис. 2.8. Это не диаграмма наследования классов. Категория итераторов - это характеристика типа, основанная на том, какие операции он обеспечивает. Существует известная идиома на этот счет: «всё, что ведет себя как итератор, является итератором».

Итератор ввода позволяет только считывать значения и поддерживает операцию инкрементации «++». Итератор вывода позволяет только записывать значения и поддерживает операцию инкрементации «++». Однонаправленный итератор является итератором ввода и вывода одновременно. Итераторы этих трёх типов в основном применяются потоками ввода вывода и стандартными шаблонными алгоритмами. Двунаправленный итератор подобен однонаправленному, но кроме операции инкрементации поддерживает ещё и операцию декремента «--». Все контейнеры поддерживают двунаправленные итераторы. Итератор со случайным доступом поддерживает операции сдвига на целое число элементов и, подобно обычному указателю C++, разыменование с помощью оператора индексации. Кроме того, можно вычесть один итератор с произвольным доступом из другого и узнать, сколько элементов их разделяет.

Среди контейнеров, vector и string поддерживают итераторы со случайным доступом. Обычный указатель C++ в большинстве случаев может играть роль итератора со случайным доступом, но пользоваться этим категорически не рекомендуется.

2.2.3 Алгоритмы STL

Библиотека STL содержит развитые средства по управлению контейнерами. Благодаря использованию идеологии итераторов, эти средства не зависят от типа используемого контейнера. Они используют только тип итератора и основываются на операциях, которые он предоставляет.

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

Ниже приведены некоторые особенно популярные алгоритмы STL, которые я использовал при разработке VFS.

copy - осуществляет копирование из последовательности, заданной итераторами [First; Last) (используются стандартное математические обозначение полуоткрытого интервала), в последовательность, начинающуюся итератором Dest. Возвращает итератор на элемент, следующий за последним скопированным элементом.

fill - заполняет диапазон [First; Last) значением Val. Все контейнеры имеют специальный конструктор с аналогичным функционалом.

find - ищет в диапазоне [First; Last) значение Val. Возвращает итератор на первое встретившееся значение. Если значение не найдено, возвращает итератор Last. У этого алгоритма есть мощные расширения, использующие поиск в подпоследовательностях.

for_each - для каждого элемента из диапазона [First; Last), вызывает функтор, передавая ему в качестве параметра текущий элемент (полученным разыменовыванием итератора).

replace - заменяет в диапазоне [First; Last) все элементы, для которых унарный предикат истинен, значением Val.

sort - осуществляет сортировку элементов в диапазоне [First; Last). Передаваемый бинарный предикат имеет смысл оператора сравнения «<». В случае, если сортируемые объекты поддерживают сравнение с использованием оператора «<», можно воспользоваться упрощённой формой.

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

Функтор (functor, также называются объектами-функциями) - объект любого класса, для которого определён оператор вызова функции «()». Следуя определению, любая функция является функтором.

Перегрузка оператора «()» в классе позволяет одновременно решить две задачи:

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

2) предоставить функции накапливать сведения от вызова к вызову без использования глобальной области видимости.

Предикат (predicate) - это функтор, возвращающий логическое (bool) значение. Различают унарные (принимающие один параметр) и бинарные (принимающие два однотипных параметра) предикаты.

Предикаты активно используются в STL. Практически все стандартные алгоритмы и контейнеры, сравнивающие элементы, позволяют задать произвольный предикат в качестве оператора сравнения (по умолчанию для элементов используются операторы «==» и «<», в зависимости от алгоритма).

2.2.4 Потоки

В языке C++ отсутствуют встроенные средства ввода/вывода. Они предоставляются программисту различными библиотеками, в том числе STL. В STL реализован гибкий объектно-ориентированный подход, названный «потоки» (streams).

Центральным понятием библиотеки iostream является поток (stream). Поток можно представить себе как источник и/или приёмник последовательности байт. Переопределяя операции записи и чтения потока («сдвиг»), можно заставить поток быть источником и/или приёмником объектов некого класса.

Примечательно, что несмотря на большую гибкость, базовый интерфейс всех потоков предельно прост: он включает в себя возможность последовательно читать байты данных (для потоков ввода istream) и последовательно записывать их (для потоков вывода ostream). При этом для потоков допускается буферизованный вывод (т.е. ситуация, когда оправленные на вывод данные временно хранятся в некотором буфере). Для незамедлительной отправки данных все потоки вывода поддерживают метод flush. Подобная универсальность выгодно отличает библиотеку iostream от альтернативных решений.

Использование потоков ввода/вывода распадается на две стадии: формирование и закрытие потока и собственно ввод/вывод.

Ввод/вывод в потоки осуществляется с помощью перегруженных операторов сдвига «<<» (вывод) и «>>» (ввод). Как указывалось выше, программист имеет возможность перегрузить эти операторы для своих классов обеспечив простой и удобный способ взаимодействия их с внешним миром. При этом необходимо иметь о потоке самые общие сведения:

1) тип потока (ввода, вывода, ввода/вывода);

2) тип символов потока;

3) наличие или отсутствие буферизации;

Замечу, что упомянутые операторы осуществляют форматированный ввод/вывод. Используя такие низкоуровневые средства, как методы put, write, get, read и им подобные, можно посимвольно манипулировать потоками, но эти возможности, как правило, используются при написании высокоптимизированного кода.

В модуле VFS потоки были использованы как одна из основных составных частей: согласно ТЗ, модуль обязан предоставлять данные любого файла как поток. Используя стандартные интерфейсы потоков STL и их буферов, были реализованы потоки, осуществляющие архивирование/распаковку и шифрацию/дешифрацию «на лету».

2.2.5 Умные указатели

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

Библиотека STL, предоставляя мощные средства управления памятью, тем не менее не избавляет программиста от возможных ошибок. Частая ошибка - возврат адреса локальной переменной - контролируется только компилятором. Широкое использование механизма исключений и вообще, любой развитый механизм обработки ошибок, требует, чтобы все динамические объекты удалялись вовремя.

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

Рассмотрим использованные при разработке проекта умные указатели. Это шаблон auto_prt из стандартной библиотеки языка C++ и шаблоны weak_prt и shared_prt из библиотеки boost.

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

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

Шаблоны weak_ptr и shared_ptr библиотеки boost являются довольно мощными реализациями указателей с подсчетом ссылок. Поскольку их применение в VFS было эпизодическим, а в конечной версии исключено за ненадобностью, подробно рассматриваться здесь они не будут.

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

1) множественные ссылки (один умный указатель уже удалил объект, а какой-то другой указатель продолжает ссылаться на него); чаще всего проблема возникает при одновременном использовании простых и умных указателей;

2) циклические связи; возникают только при использовании умных указателей с счётчиками ссылок; приводят к невозможности корректного уничтожения контролируемых объектов и, как следствие, к утечкам памяти.

2.3 Специализированный инструментарий

Разработка VFS, кроме решения архитектурных задач, потребовала работы над задачами прикладными, такими как шифрование, архивирование и работа с ресурсами исполняемых фалов win32.

2.3.1 Средства работы с зип-архивами

В качестве базовой библиотеки для работы с зип-архивами была выбрана open-source разработка zlib. Эта библиотека работает на уровне последовательностей байт и реализует наиболее простые и распространенные алгоритмы deflate и inflate. Средства этой библиотеки были использованы при написании специфических потоков, позволяющих «на лету» архивировать и распаковывать данные.

2.3.2 Шифрация по алгоритму CRC32

Шифрация по алгоритму CRC32 была выполнена самостоятельно, поскольку средства, имевшиеся, например, в zlib, в разумные сроки задействовать не удалось. Алгоритм был реализован по описанию в источнике [16] и снабжен известным набором контрольных сумм.

2.4 Тестирование

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

2.4.1 Модульное тестирование

Цели тестирования

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

Время, затраченное на тестирование, стоит достаточно дорого, и необходимо получить от этих затрат наибольшую отдачу. Ниже приведены «золотые правила» тестирования:

1) цель: максимизировать количество и важность обнаруженных дефектов на каждый рубль затрат;

2) поэтому: нужно начинать тестирование рано;

3) ограниченность: тестирование может установить только наличие дефектов и никогда - их отсутствие;

4) для доказательства отсутствия дефектов нужно использовать доказательства корректности.

Рис. 2.9. Типы тестирования

Значение модульного тестирования

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

Типичный план модульного тестирования.

Типичный план, основанный на стандарте IEEE 1008-1987, показан на рис. 2.10. Далее поясняются основные шаги:

1) входными данными для планирования теста являются требования и детальный проект; выходными - модульный план тестирования;

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

3) исполнение тестов.

Рис. 2.10. План модульного тестирования

2.4.2 Типы тестов

«Черный ящик», «серый ящик» и «прозрачный ящик»

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

Целью тестирования «прозрачного ящика» является нахождение наиболее ненадежных путей программы. Для этого программа подвергается декомпозиции до получения путей управления и данных.

Тестирование «серого ящика» подразумевает нечто среднее между перечисленными методами или их комбинацию.

Разбиение равнозначности для «черного ящика»

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

Анализ граничных требований для «черного ящика»

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

Утверждения и решения для тестирования «прозрачного ящика»

Каждое утверждение в программе должно быть проверено хотя бы одним тестом. Анализ каждого утверждения обязателен. Обзор решений гарантирует, что программа выполняет каждую ветвь алгоритма. То есть, необходимо построить такое множество тестов, чтобы каждое «да» и «нет» блок-схемы можно было получить каким-либо тестом из набора.

Тестирование на основе инвариантов

Инварианты - это утверждения, связывающие переменные. Это своего рода выражение состояний, которое можно использовать как ограничение множества значений параметров. Это значит, что в некоторых случаях мы можем положить, что некоторые сочетания значений переменных не встретятся в программе никогда.

Использование случайных величин

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

2.4.3 Планирование модульных тестов

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

1) определить принципы модульного тестирования:

а) назначить ответственным разработчика;

б) поручить тестирование другим;

в) поручить другим и проектирование, и проверку;

2) определить, что, где и как документировать:

а) индивидуальная документация;

б) как и где внедрять в другие типы тестирования;

в) внедрять ли в формальные документы;

г) использовать ли специальный инструментарий;

3) определить объемы заранее:

а) не тестировать «пока время не кончится»;

б) расставить приоритет тестов;

4) определить, где и как получить входные данные;

5) оценить необходимые ресурсы:

а) по возможности, воспользоваться статистикой;

6) организовать учет времени и выполнения задач.

2.4.4 Примеры тестирования

Пример теста метода

1) проверить работу при допустимых значениях параметров (метод «черного ящика», основанный на требованиях);

2) проверить работу на граничных значениях параметров («черный ящик»);

3) проверить работу на значениях вне разрешенного диапазона;

4) убедиться, что выполняются все инструкции (рассмотрение утверждений);

5) проверить все пути, в том числе ветви каждого узла (рассмотрение решений);

6) проверить использование всех вызванных объектов;

7) проверить обработку всех структур данных;

8) проверить обработку всех файлов;

9) проверить нормальное завершение всех циклов (часть доказательства корректности);

10) проверить аварийное завершение всех циклов;

11) проверить нормальное завершение всех рекурсий;

12) проверить аварийное завершение всех рекурсий;

13) проверить обработку всех условий ошибок;

14) проверить синхронизацию и расчет времени;

15) проверить аппаратные зависимости.

Пример теста класса

1) испытывать комбинации методов:

а) обычно 2-5;

б) сначала выбрать наиболее общие последовательности;

в) учесть последовательности, заведомо приводящие к ошибке;

г) попытаться вручную подсчитать значения результатов;

2) фокусировать модульные тесты на каждом атрибуте:

а) инициализировать его, а потом запускать последовательности методов, изменяющих его;

3) проверять, что инвариант каждого класса не меняется:

а) проверить истинность инварианта на начальных условиях;

б) выполнить последовательность;

в) ещё раз проверить инвариант;

4) проверить ожидаемость изменения состояний объектов:

а) спланировать последовательность переходов;

б) установить объект в начальное состояние;

в) обеспечить появление первого события и протестировать переход, и так далее.

2.4.5 Методы “грубой силы” и их применение при отладке программы

Практически все виды тестов - и модульные, и интегральные, и системные - необязательно проводить в отладчике. Для того, чтобы убедиться в результате выполнения функции, достаточно вставить пару строк кода для вывода необходимой информации куда-либо на экран. При отладке VFS использовались вывод в консольное окно тестового приложения и в окно output MSVS. Для вывода в консоль тестового проекта использовался стандартный потока std::cout, для вывода в окно output студии использовались встроенные функции из библиотеки msvcrt. Для более удобного вызова эти библиотечные функции были обернуты в поток.

Раздел 3. Организационно-экономический раздел

3.1 Цели определения себестоимости и цены модуля

Любой крупный программный продукт состоит из множества отдельных модулей. Это - правило, продиктованное современным менеджментом разработки программного обеспечения. Оно позволяет эффективно разделить труд разработчиков, уменьшить риски, облегчить сопровождение. Каждый модуль делают по возможности независимым от остальных, и в каждом конкретном случае руководитель должен принимать решение: делать модуль своими силами, купить его коммерческий аналог или воспользоваться аутсорсингом. Ярким примером подобного подхода в игровой индустрии является участившееся использование коммерческих библиотек физики (Havok, Meqon).

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

3.2 Методы определения себестоимости

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

3.2.1 Метод калькуляции

Калькуляция осуществляется по заранее составленному списку статей расходов, приведенному в источнике [2]. Типовая схема калькуляции рассмотрена там же.

3.2.2 Расчет на основе нормо-часа

Определение себестоимости изделия на основе цены нормо-часа проводится по формуле:

С_testsample = C_res + Work_coeff * C_normhour (3.1)

где C_testsample - себестоимость опытного образца;

C_res - материальные затраты (стоимость материалов и изделий);

Work_coeff - трудоемкость изготовления изделия в нормо-часах;

C_normhour - цена одного нормо-часа предприятия-изготовителя.

3.2.3 Метод удельных показателей

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

3.2.4 Метод коэффициентов

Совокупные затраты труда HR (human resources) на создание ПС включают ряд составляющих, которые могут становиться доминирующими в зависимости от различных факторов. Наибольшее значение в составе HR при разработке сложных комплексов программ имеют следующие составляющие:

1) на непосредственное проектирование, программирование, отладку и испытание программ в соответствии с требованиями заказчика или пользователей;

2) на сборку опытного образца ПС как продукции производственно-технического назначения;

3) на разработку, подготовку и применение технологий и программных средств, в случае автоматизации разработки программ;

4) на технику;

5) на повышение квалификации специалистов.

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

Таблица 3.1. Основные составляющие затрат в процессе разработки

Составляющие затрат

Основные факторы, влияющие на составляющую затрат

Степень влияния

На непосредственную разработку

Объем ПС

А

Надежность ПС

А

Степень использования ресурсов ЭВМ

А

Длительность разработки ПС

А

Длительность цикла жизни ПС

А

Уровень технологии разработки ПС

А

Уровень языка программирования

В

На изготовление опытного образца ПС

Объем ПС

А

Уровень технологии разработки ПС

А

Способ материализации программ

В

На технологии и программные средства автоматизации разработки

Объем ПС

А

Уровень технологии разработки ПС

А

Уровень языка проектирования ПС

В

Длительность цикла жизни ПС

В

На технику

Объем ПС

А

Уровень технологии разработки ПС

А

Длительность разработки ПС

А

Степень использования ресурсов ЭВМ

А

Характеристики ЭВМ

В

На повышение квалификации разработчиков

Тематическая квалификация

А

Технологическая квалификация

В

Программистская квалификация

В

Степени влияния: А > 30%, B <= 30%

1) Затраты на разработку программного продукта определяются как частное от деления объема кода программного продукта Code(Кбайт) и производительности труда Eff, коррелируемое на произведение коэффициентов изменения трудоемкости (КИТ) в зависимости от ряда факторов

(3.2)

В состав коэффициентов входят:

(3.3)

- изменение трудоемкости при увеличении объема программы

_ изменение трудоемкости при изменении базы данных

(3.4)

- учет надежности функционирования ПС, где T - наработка на отказ в часах.

(3.5)

_ ограничение ресурсов производительности и оперативной памяти реализующей ЭВМ, где - реальная загрузка (относительные единицы).

(3.6)

- длительность предполагаемой эксплуатации, где - время эксплуатации

(3.7)

- предполагаемый тираж ПС N.

2) Затраты на изготовление опытного образца ПС определяются необходимостью обеспечить отчуждение всего комплекса программ от его первичных разработчиков. Удельный вес этих затрат находится в пределах 10-15% от общих затрат на разработку. Затраты на изготовление опытного образца включают в себя:

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

б) затраты на создание комплекта документации, обеспечивающей квалифицированную эксплуатацию продукта.

3) Затраты на технологии и программные средства автоматизации разработки ПС. Объем и сложность создаваемого ПС значительно влияют на выбор уровня автоматизации технологии и долю затрат в общих затратах на разработку.

Затраты на технологии включают в себя:

а) затраты на создание технологии и приемлемой системы автоматизации разработки программ;

б) затраты на внедрение и освоение технологии и средств автоматизации;

в) затраты на эксплуатацию системы автоматизации разработки программ.

4) Затраты на ЭВМ определяются как сумма затрат, в составе которых:

а) затраты на машинное время в процессе разработки программ;

б) первичные затраты на приобретение ЭВМ;

в) затраты на моделирующие ЭВМ.

5) Затраты на эксплуатацию программ включают в себя:

а) затраты на непосредственную эксплуатацию(зависят от стоимости эксплуатации вычислительных средств и затрат на контроль состояния и возобновления программ);

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

в) затраты из-за потери эффективности при эксплуатации программ вследствие их отказов. Эти потери характеризуют устойчивость ПС к различного рода внешним возмущениям. Интенсивность отказовых ситуаций зависит от уровня отлаженности программ, отказов в аппаратной части ЭВМ и интенсивности искажения исходной информации.

6) Затраты на сопровождение программ включают:

а) затраты на обнаружение и устранение ошибок в каждой версии ПС;

б) затраты на доработку и совершенствование программ, формирование и испытание новых версий ПС;

в) затраты на тиражирование каждой новой версии ПС и ее внедрение в эксплуатируемых и новых системах.

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

3.3 Расчет себестоимости VFS

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

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

Таблица 3.2. Сравнение методов расчета стоимости нового продукта

Параметр

Метод

1

2

3

4

Трудоемкость разработки ПС

-

+

-

+

Стоимость ПО, материалов

+

+

+

+

Затраты на технику

+

+

+

+

Специфика труда программиста

-

-

-

+

Язык программирования

-

+

-

+

Кол-во основных функций разработки

-

-

1

все

Исходя из расчета затрат, приведенного в теоретической части, определим себестоимость разрабатываемого программного продукта как:

С = С_base + C_overheads,

где C_base - затраты на разработку ПС,

C_overheads - накладные расходы.

Затраты на разработку определим как суммарные затраты на непосредственную разработку ПС (C_code), затраты на составление документации (C_doc), затраты на ЭВМ (C_hard) и затраты на технологию и средства автоматизации разработки ПС (C_soft) :

C_base = C_code + C_doc + C_hard + C_soft.

Затраты на непосредственную разработку ПС рассчитаем по формуле, приведенной в теоретической части работы.

Объем программного продукта

Code = a * (1+b) * N_str,

где «a» характеризует относительную сложность программы по отношению к так называемой типовой задаче, реализующей стандартные методы решения, сложность которой принята равной единице (величина a лежит в пределах от 1,25 до 2). Для разрабатываемого программного продукта коэффициент сложности a = 1,5.

Коэффициент коррекции программы b - увеличение объема работ за счет внесения изменений в алгоритм или программу по результатам уточнения постановок. Примем b = 0.1, т.к. изменения вносились.

Ниже приведены исходные данные, которые используются в расчетах.

Таблица 3.3. Исходные данные для расчета затрат на разработку программного комплекса

Наименование характеристики

Количество

Число строк (N_str)

5000

Количество программистов (N)

1

Заработная плата программиста

12000 рублей

Часов наработки на отказ (T)

24 часа

Длительность эксплуатации ПС (t)

2 года

Получаем Code = 1,5 * 1,1 * 5000 = 8250 (инструкций).

Найдем значения коэффициентов изменения трудоемкости:

Изменение трудоемкости при увеличении объема программы

Надежность функционирования ПС

Длительность предполагаемой эксплуатации

Относительное быстродействие ЭВМ:

.

Относительный объем памяти ЭВМ: если его недостаточно, то возможно снижение производительности труда на 10-20%. Но в нашей ситуации такой проблемы не возникло:

.

Современные методы разработки:

Уровень языка проектирования:

Таблица 3.4 Изменение трудоемкости в зависимости от уровня языка программирования

Характеристика языка программирования

Коэффициент изменения трудоемкости

Покомандный автокод-Ассемблер

1

Макроассемблер

0,95

Алгоритмические языки высокого уровня

0,8 - 0,9

Алгоритмические языки сверхвысокого уровня

0,7 - 0,8

Выбранный для проектирования программы язык C++ относится к языкам высокого уровня, поэтому, по данным табл.5, примем

.

Квалификация разработчиков: сильно влияет на производительность тематическая квалификация разработчиков и их опыт программирования. Коэффициент квалификации разработчика С51 определяется в зависимости от стажа работы и составляет: для работающих до двух лет - 1.6; от двух до трех лет - 1.4; от трех до пяти лет - 1,2; от пяти до семи - 1,0; свыше семи лет - 0.8. Исходя из этих характеристик, примем

Ориентировочная производительность труда программиста на языке С++ составляет

(инструкций/чел./день)

Теперь определяем

(чел./день)

В разработке программного комплекса участвовал один инженер-программист (N=1), заработная плата составляла 12000 рублей (з/п).

Таким образом, непосредственные затраты на разработку продукта составили:

(руб.)

Любой программный продукт должен сопровождаться документацией, оформленной в соответствии с ГОСТом. В состав документации входит руководство программиста. Написание документации я оценил в 30% времени программиста, поэтому

C_doc = 0,30 * C_code = 19145,5 (руб.)

Затраты на технологию и средства автоматизации включают в себя установку программных продуктов:

1) MS WinXP Pro

2) MS Visual C++ .Net Standart

Общая стоимость этих продуктов составила 10367 рублей.

Затраты на ЭВМ определяются следующим образом :

C_hard = T_work * C_hour

где T_work - время эксплуатации ЭВМ, C_hour - стоимость машинного времени.

Стоимость машинного времени формируется из следующих составляющих:

1) стоимость электроэнергии. Стоимость 1 КВт/час электроэнергии составляет: 0,844 руб. Один компьютер потребляет около 400 Вт/час (использовалась мощная техника). За время разработки программного комплекса отчисления за электроэнергию потребляемую ЭВМ составляет:

1*8 ч. * 117 дней * 0,4 КВт/ч* 0,844 руб.* ч. /КВт = 71 руб.

2) стоимость амортизации. Амортизация ВТ считается, как 50% балансовой стоимости ВТ (50000 руб.) и за год составляет: 50000руб. * 0,5 = 25000 руб. Амортизация программного обеспечения (ПО) с условием, что срок морального старения составляет 4 года, считается, как 25% от его балансовой стоимости (10367) и за год составляет 10367*0,25=2591 руб. Общая амортизация за год составляет: 25000 руб. + 2591 руб. = 27591 руб.

3) стоимость ремонта. Затраты на ремонт в год считаются, как 4% от стоимости комплекса ВТ, и составляют: 50000*0,04 = 2000 руб.

Действительный фонд времени работы вычислительного комплекса рассчитываем по следующей формуле:

F = F_nom - F_prof,

где F_nom - номинальный фонд времени работы вычислительного комплекса,

F_prof - годовые затраты времени на профилактические работы (принимаются 15% от F_nom).

Фонд работы вычислительного комплекса составляет

F = 2462 * 0,85 = 2094,4 ч.

Получаем, что стоимость машинного времени равна 14.36 (руб./час).

Исходя из расчета того, что время эксплуатации ВТ в основном складывается из времени, которое потребовалось программистам на разработку продукта, его отладку и тестирование, а также написание документации, то Т = 936 (ч.)

Таким образом получаем общие затраты на ЭВМ:

(475+27591+2000)/2094,4*936=13436,7 (руб)

Накладные расходы рассчитываются, как 60% от суммарной основной заработной платы исполнителей и составляет:

C_overhead = 63818,2 руб. * 0,6 = 38291 руб.

Накладные расходы, в том числе, включают в себя:

1) приобретение специальной литературы;

2) хозяйственные нужды;

3) аренду помещения;

4) транспортные расходы;

5) оплата Интернета.

Смета затрат на разработку программного продукта приведена в таблице Х.

Таблица 3.5. Смета затрат на разработку ПС

Статья расходов

Затраты, руб.

Непосредственная разработка ПС

63818

Составление документации

19146

Содержание и эксплуатация вычислительного комплекса

13437

Накладные расходы

38291

Итого

134692

3.4 Методы расчета цены

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

Не секрет, что основные затраты в бизнесе производства программных продуктов приходятся на разработку и (не всегда) на поддержку. Для программного обеспечения тяжело определить понятие амортизации. Устаревание может быть только моральным и устареванием вследствие устаревания программных и/или аппаратных платформ. Затраты на тиражирование в случае распространения «коробочных» версий, как правило, не идут ни в какое сравнение с затратами на разработку, поскольку тиражирование представляет из себя технически несложное копирование носителей (сейчас - штамповка оптических дисков) и документации.

3.4.1 Расчет цены по стоимости изготовления

Цена программной продукции (C) формируется на базе экономически обоснованной (нормативной) себестоимости ее производства и прибыли:

C = SC + NP + PP , (3.8)

где SC (self cost) - себестоимость единицы товара;

NP (normative profit) - нормативная прибыль;

PP (prolonged profit) - надбавка к цене в случае продолжительного использования ПС.

3.4.2 Расчет цены на основе роялти

Данный подход применяется, когда цена программного продукта возмещается собственнику не сразу, а по мере получения потребителем дополнительного дохода. Тогда цена данного программного продукта складывается из ежегодных отчислений от дохода потребителей в течение периода действия соглашения, т.е. роялти. Для программных разработок роялти чаще всего составляет 3-5%. Цена программного продукта часто складывается из выплат целого ряда потребителей и распределяется между собственниками этого продукта в соответствии с количеством заключенных ими сделок, их длительностью и величиной роялти.

3.4.3 Расчет цены на тиражируемый продукт

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

Price = Inputs/n + Profit/n + Replication_cost +Profit_bit. (3.9)

где Peplication_cost - затраты на копирование, сопровождение и маркетинг (затраты на маркетинг могут относиться ко всему тиражу, тогда в цене учитывается 1/n от общих на него затрат);

Profit_bit - величина прибыли от реализации одного экземпляра тиража. Слагаемое (Replication_cost + Profit_bit) иногда связывают с ценой одной адаптации данного программного продукта.

3.5 Расчет цены VFS

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

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

Будем формировать цену программного продукта ЦПС на базе экономически обоснованной (нормативной) себестоимости его производства и прибыли без учета экономического эффекта от эксплуатации:

С = SC + NP (3.10)

где SC - себестоимость программы, NP нормативная прибыль.

Нормативная прибыль определяется по [4]:

NP = Profitability * C,

Где Profitability - рентабельность данной продукции по отношению к полной себестоимости SC (берем как 25%).

Определим нормативную прибыль:

NP = 0.25 * 134692 = 33673 руб.

Таким образом, по формуле (2) договорная цена разрабатываемого программного комплекса составит:

Cost_total = 134692+ 33673 = 168365 руб.

3.6 Выводы

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

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

Цена на программную библиотеку «Виртуальная файловая система», сформированная на основе себестоимости производства ПС и прибыли, составляет: 168365 руб.

Раздел 4. Раздел производственно-экологической безопасности

4.1 Производственная безопасность

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

4.2 Анализ работы за компьютером с точки зрения производственной безопасности

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

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

1) системный блок, включающий в себя основную аппаратную логику;

2) монитор, являющийся основным средством вывода информации, через который выдается подавляющее количество всей выводимой информации;

3) клавиатуру как основное средство ввода;

4) манипулятор (мышь и/или планшет).

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

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

1) психофизиологические факторы:

а) утомление, связанное с монотонностью работы;

б) статические физические перегрузки;

в) зрительное утомление;

2) электромагнитные излучения;

3) опасность поражения электричеством;

4) зашумленность.

К факторам, влияющим на общее для работающих программистов место, - машинный зал - можно отнести следующие:

1) освещение (общее и рабочих мест);

2) микроклимат;

3) общая зашумленность.

Факторы, связанные с сильными внешними воздействиями, - например, сильные внешние электромагнитные поля - в данной работе не рассматриваются.

4.2.1 Психофизиологические факторы

Монотонность работы

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

Статические физические перегрузки

Рабочая поза оказывает значительное влияние на эффективность работы человека. Основные требования к рабочим местам при выполнении работы сидя приведены в ГОСТ 12.2.033-78 "ССБТ. Рабочее место при выполнении работ сидя. Общие эргономические требования". Согласно этому стандарту, при организации рабочего места программиста необходимо придерживаться следующих рекомендаций:

1) рабочее место должно быть оборудовано так, чтобы исключать неудобные позы и длительные статические напряжения тела;

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

При организации взаимного расположения элементов рабочего места должны учитываться следующие моменты:

1) рабочая поза программиста;

2) пространство для размещения программиста, позволяющее осуществлять все необходимые движения;

3) физические, зрительные и слуховые связи между программистом и программистом;

4) возможность обзора пространства за пределами рабочего места;

5) возможность ведения записей, размещения документации и материалов, используемых программистом.

Зрительное утомление

Уже в первые годы компьютеризации было отмечено специфическое зрительное утомление у пользователей дисплеев, получившее общее название "компьютерный зрительный синдром" (CVS - Computer Vision Syndrome). Причин его возникновения несколько. И прежде всего - сформировавшаяся за миллионы лет эволюции зрительная система человека, которая приспособлена для восприятия объектов в отраженном свете (картин природы, рисунков, печатных текстов и т.п.), а не для работы с дисплеем. Изображение на дисплее принципиально отличается от привычных глазу объектов наблюдения. Оно - изображение - светится, состоит из дискретных точек; оно мерцает, т. е. эти точки с определенной частотой зажигаются и гаснут (в случае CRT мониторов); цветное компьютерное изображение не соответствует естественным цветам (спектры излучения люминофоров отличаются от спектров поглощения зрительных пигментов в колбочках сетчатки глаза, которые ответственны за наше цветовое зрение). Но не только особенности изображения на экране вызывают зрительное утомление. При работе на компьютере часами у глаз не бывает необходимых фаз расслабления, глазные мышцы напрягаются, их работоспособность снижается. Большую нагрузку орган зрения испытывает при вводе информации, так как пользователь вынужден часто переводить взгляд с экрана на текст и клавиатуру, находящиеся на разном расстоянии и по-разному освещенные.

Зрительное утомление выражается в:

1) затуманивании зрения;

2) трудности при переносе взгляда с ближних на дальние и с дальних на ближние предметы;

3) кажущемся изменении окраски предметов;

4) двоении;

5) неприятных ощущениях в области глаз (чувства жжения, "песка"), покраснении век, боли при движении глаз.

4.2.2 Электромагнитные излучения

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

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

Наиболее опасным с точки зрения электромагнитных излучений является ЭЛТ-монитор. Наиболее активное и результативное участие в решении проблемы достижения экологически приемлемых условий, связанных с эксплуатацией устройств визуального отображения информации, приняли шведские научные и общественные организации, так или иначе связанные с безопасностью производственных процессов и здравоохранением. В 1990 году результаты их исследований с учетом накопленного опыта были оформлены Управлением SWEDАC в виде двух документов: справочника для пользователя по оценке устройств визуального отображения (МРR 1990:8) и методов проверки устройств визуального отображения (МРR 1990:10), которые получили широкую известность.

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

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

В России два основополагающих стандарта (гармонизированные с МРR 1990:8 и МРR 1990:10) введены в действие в 1997 году. Это ГОСТ Р 50948-96 “Средства отображения информации индивидуального пользования. Общие эргономические требования и требования безопасности” и ГОСТ Р 50949-96 “Средства отображения информации индивидуального пользования. Методы измерений и оценки эргономических параметров и параметров безопасности”. С учетом данных стандартов Госсанэпиднадзор России разработал и с 1-го января 1997 года ввел в действие обязательные санитарные правила и нормы - СанПиН 2.2.2.542-96 “Гигиенические требования к видеодисплейным терминалам, персональным электронно-вычислительным машинам и организации работы”.

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


Подобные документы

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

    курсовая работа [215,3 K], добавлен 01.09.2010

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

    курсовая работа [146,6 K], добавлен 01.09.2010

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

    курсовая работа [872,3 K], добавлен 10.06.2014

  • Сравнительный анализ технологий тестирования. Разработка программного модуля "Интеллектуальная обучающая система для широкого перечня курсов". Обоснование необходимости и важности этапа отладки в процессе разработки данного программного обеспечения.

    дипломная работа [101,2 K], добавлен 17.06.2011

  • Реализация программного средства "Действия над матрицами". Разработка кода программного продукта на основе готовой спецификации на уровне модуля. Использование инструментальных средств на этапе отладки программного модуля. Выбор стратегии тестирования.

    отчет по практике [296,1 K], добавлен 19.04.2015

  • Методика разработки программного модуля для нахождения методом хорд корня уравнения x3-x-0,3=0 с точностью до 0,001 на языке программирования Visual Basic for Application. Схема программного модуля и описание процедуры обработки кнопки "Найти корни".

    курсовая работа [394,0 K], добавлен 08.09.2010

  • Создание программного модуля, выполненного на языке программирования VBA (Visual Basic for Applications) и позволяющего во введенном массиве символов удалить все повторные вхождения этих символов. Разработка пользовательского интерфейса. Код программы.

    курсовая работа [317,4 K], добавлен 11.10.2012

  • Анализ правил выбора хода на шахматной доске К. Шеннона. Характеристика программного модуля искусственного интеллекта для игры в шахматы. Контроль времени, поиск лучшего хода в шахматных алгоритмах. Разработка программы для игры с компьютерным оппонентом.

    дипломная работа [3,7 M], добавлен 07.07.2012

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

    курсовая работа [648,4 K], добавлен 27.05.2015

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

    отчет по практике [203,8 K], добавлен 12.04.2015

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.