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

 

Содержание


Введение

Раздел 1. Специальный раздел

1.1. Исследовательская часть

1.1.1. Постановка задачи

.1.2. Предварительные НИР

.1.3. Информационные потребности пользователей

.1.4. Требования, предъявляемые к системе

.2. Конструкторская часть

.2.1. Структура входных и выходных данных

.2.2. Общая схема работы модуля

.2.3. Выбор платформы проектирования и его обоснование

.2.4. Проектирование архитектуры модуля

.2.5. Конфигурация технических средств

.2.6. Алгоритмы работы модуля

.2.7. Методика тестирования

.2.8. Результаты экспериментальной проверки

Раздел 2. Технологический раздел

.1. Проектирование на языке UML

.1.1. Концепция Unified Modeling Language

.1.2. Виды диаграмм UML

.1.3. Связь с объектно-ориентированными языками

.2. Идеология STL в применении к архитектуре модуля8

.2.1. Шаблоны в C++

.2.2. Контейнеры

.2.3. Алгоритмы

.2.4. Потоки

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

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

.3.1. Средства работы с zip-архивами

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

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

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

.4.2. Типы тестов

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

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

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

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

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

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

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

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

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

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

.3. Расчет себестоимости VFS

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

.4.1. По стоимости изготовления

.4.2. На основе отчислений с продаж («роялти»)

.4.3. На тиражируемый продукт

.5. Расчет цены VFS

.6. Выводы

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

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

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

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

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

.2.3. Освещение рабочего места

.2.4. Электробезопасность

.2.5. Микроклимат

.2.6. Зашумленность

.3. Инженерный расчет освещенности машинного зала

.4. Экологическая безопасность

.5. Пожарная безопасность

.6. Выводы

Заключение

Список литературы

Приложения


Введение


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

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

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

) Для представления данных в табличном или объектном виде чаще всего нужна их обработка. Сама по себе СУБД - отдельное приложение, с которым нужно устанавливать связь, разделять ресурсы и т.д. Редактирование данных на этапе разработки вызовет сложности. Также тяжело решить некоторые специфичные проблемы, речь о которых пойдет ниже.

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

Чаще всего разработчики реализуют иерархические структуры на диске. В силу внешних причин отдельные части ресурсов могут быть заархивированы и/или зашифрованы. Часть ресурсов может быть оставлена на ключевом носителе (сейчас в этой роли часто выступает оптический диск), который тоже может быть защищен по какой-либо технологии (оптический диск - StarForce, LaserLock и другие). Также ресурсы могут быть размещены на сетевом сервере, что накладывает свои требования к доступу, верификации и иногда к защите. Ситуация в индустрии диктует ещё одно требование: необходима возможность работы с несколькими параллельными версиями ресурсов - это нужно для корректной установки патчей (пакетов исправлений и дополнений) и пользовательских модификаций. В результате разработчики часто оказываются перед распределенным комплексом весьма сложных по структуре хранилищ. Кроме того, необходимость знать о типах хранилищ и особенностях работы с ними, вызывает резкое усложнение кода и затрудняет его повторное использование.

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

) Любые обращения к файловой системе идут по виртуальному «дереву» каталогов, начиная с корня (root).

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

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

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

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

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

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

Модуль реализует работу с алгоритмами архивации zip, шифрованием по алгоритму CRC32, с сетью и с ресурсами исполняемых файлов Win32.

Выбор средств разработки определялся удобством интеграции в существующие проекты, а также быстродействием результирующего модуля. В силу того, что программирование в MiSTland ведется на языке С++, модуль также был реализован на C++ и с использованием идеологии STL. Из инструментальных средств, выбор пал на Microsoft Visual Studio 7.1, STLport, BOOST и zlib. Проектирование велось в Rational Rose, для не-UML схем использовался Microsoft Visio.

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

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

В организационно-экономическом разделе рассчитаны себестоимость разработки модуля и его цена.

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


Раздел 1. Специальный раздел


.1 Исследовательская часть


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


1.1.1 Постановка задачи

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

Большинство модулей, так или иначе нуждающихся в файловом вводе, принимают информацию в виде потока, реализованного силами CRT или STL. В силу широкого использования в индустрии средств STL, решения на базе CRT используются всё реже, поэтому закладываться на их использование я не стал - таким образом, стандартным форматом ввода-вывода де-факто в модуле стали std::basic_istream и std::basic_ostream.

Первой задачей модуля является прозрачность в предоставлении файлового потока по имени. Проблемой является физически разделенное размещение данных - в разных каталогах, на разных носителях, в разных форматах. Модуль должен обеспечивать единое пространство имен, связывающее все разрозненные хранилища, и изолирующее от пользовательского кода реальное размещение данных. Подобное поведение модуля обычно называют «прозрачностью» в отношении пользовательского кода. Естественно, структура имен файлов в модуле должна соответствовать общепринятой (директория/файл), чтобы не усложнять логику работы с ним.

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

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


1.1.2 Предварительные НИР

Из постановки задачи следует, что требуемый модуль является самостоятельной подключаемой библиотекой, поэтому в предварительных НИР следует изучить имеющиеся примеры ПО аналогичного назначения. В силу специфики задачи подобные системы как отдельные программные модули, как правило, реализуются только в стенах софтверных компаний, имеющих в таких модулях необходимость - потенциальный рынок таких систем невелик. Подобные системы были разработаны для внутреннего использования конкурентами MiSTland, а так же самой MiSTland для её ранних проектов. Необходимость в повторной разработке была вызвана недостаточной гибкостью и переносимостью ранее разработанного модуля, а так же трудностью его поддержки. Таким образом, доступными для изучения оказались только свободно распространяемые средства и общеизвестные концепции родом из мира open-source.

BOOST filesystem

Библиотека boost::filesystem является свободно распространяемой в рамках пакета BOOST, продвигаемого комитетом по стандартизации C++. Эта библиотека призвана облегчить «сборку» пути до файла и некоторые операции с путем. Также она делает небольшую обертку (паттерн Wrapper) над стандартными потоками C++, позволяя удобнее указывать путь. Есть возможность обхода файлов внутри директорий при помощи механизма, совместимого с итераторами стандартной библиотеки С++. Работа с различными форматами представления пути успешно инкапсулирована внутри.

Эта библиотека реализует часть требуемого в ТЗ функционала, конкретно - единообразное представление клиентскому коду данных файлов и возможность итерирования файлов. Она никоим образом не решает проблемы распределенных хранилищ, но её код открыт (в соответствии с условиями распространения библиотеки BOOST), поэтому она может служить замечательным образцом внешнего программного интерфейса. Крайне полезны детали её реализации, касающиеся универсального представления пути и конвертирования различных его форматов, а также механизма итерирования веток файловой системы.

UNIX VFS

Задача абстракции от конкретного типа хранилища наиболее полно решена на данный момент в системе Linux (и в большинстве используемых ныне *nix-систем) комплексом под названием VFS (Virtual File System). Аналогичные операции в других доступных для изучения операционных системах - рассматривались системы семейства Windows - производятся не с той гибкостью, которой бы хотелось достичь в проектах MiSTland. Использовать систему VFS непосредственно не представляется возможным, поскольку VFS является неотъемлемой частью ядер операционных систем *nix, однако интерфейс и логика работы VFS, несомненно, являются удачными и проверенными долговременным использованием.

Кратко о VFS в реализации *nix - систем:

Существует виртуальное дерево, каждый «лист» которого является ячейкой, с которой может быть ассоциирован список неких файловых хранилищ - разделов или директорий на диске, съемных носителей, сетевых дисков и т.д. Структура каталогов ассоциированного (в терминологии VFS - замонтированного) хранилища становится для VFS естественным продолжением имен ветки виртуального дерева. Работа с каждым хранилищем на физическом уровне инкапсулирована кодом VFS и может быть изменена или дополнена путем модификации кода, компиляции модуля VFS и интеграции системой патчей в ядро ОС.

Каждому файлу в VFS соответствует идентификатор (в терминологии VFS - «dentry»), по которому VFS определяет, к какому физическому хранилищу принадлежит файл и из которого, соответственно, можно запросить атрибуты, содержимое файла, права доступа, число активных копий и т.п. VFS ведет учет идентификаторов файлов, организуя их в хэш-очереди. Файлом, кстати, в зависимости от реализации хранилища, может быть представлен специальный файл устройства, канал («pipe»), сетевой сокет.

Все файловые операции - чтение, запись, удаление - реализованы на уровне VFS, которая «спускает» вызовы реализациям, предназначенным для работы с конкретными типами хранилищ.


1.1.3 Информационные потребности пользователя

Основные требования, которые предъявлялись к модулю:

) Открытие файлов на чтение и запись. Имена должны быть единообразными согласно принятой в проекте относительной системе именования.

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

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

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

) Контроль исключительных ситуаций в процессе работы. Недопущение аварийного прекращения работы из-за некорректных данных или действий пользовательского кода.

) Как можно более простой и функциональный программный интерфейс.


1.1.4 Требования, предъявляемые системе

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

Состав выполняемых функций

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

) Открытие файла на чтение и предоставление входного потока на него стандартной библиотеки С++, согласно относительной системе именования, принятой в структуре данных проекта.

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

) Перебор файлов внутри директории безотносительно типу файлового хранилища. Механизм должен быть построен по идеологии итераторов стандартной библиотеки С++.

Для эффективного управление списком файловых хранилищ (в дальнейшем - «подсистем») модуль должен обеспечивать следующие операции:

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

) Возможность монтирования подсистемы (дисковой директории, зип-архива, сетевого диска, ресурсного exe/dll) в виртуальную директорию.

) Ручное и автоматическое («сборка мусора») демонтирование и удаление подсистем.

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

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

) Необходимо предоставить инструмент в compile-time для выбора варианта файла по естественным критериям (дата файла, размер и т.п.).

) Необходимо наличие механизма автоматического выбора варианта файла.

Требования к надежности

Для обеспечения стабильности работы модуля необходимо:

) Максимальное применение отработанных стандартных средств и библиотек.

) Анализ действий пользователя на корректность перед совершением операций в ядре модуля.

Требования к информационной и программной совместимости

Реализовывать модуль следует на языке С++. Модуль должен максимально основываться на стандартной библиотеке языка С++ и использовать идеологию STL. В качестве входных и выходных типов данных должны использоваться базовые и стандартные библиотечные типы С++. Для обработки наборов данных необходимо пользоваться алгоритмами стандартной библиотеки С++.

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


1.2 Конструкторская часть


.2.1 Структура входных и выходных данных


Рис. 1.1. Структура входных и выходных данных


На рисунке 1.1. поясняется, что является входными и выходными данными модуля.

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

) Запрос на чтение или запись по имени. Передаваемые данные - имя и желаемые параметры потока. Ядро VFS запустит алгоритм поиска файла с таким именем в виртуальном дереве. Подробно алгоритм будет рассмотрен ниже.

) Запрос на перебор файлов внутри виртуальной директории. Передаваемые данные - путь и маска поиска. Ядро VFS идентифицирует все файлы, чьё имя соответствует маске поиска (считается, что все такие файлы лежат в одной виртуальной директории) и выдаст наружу объект, позволяющий вести перебор аналогично контейнеру STL. Подробно этот алгоритм также будет рассмотрен ниже.

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


1.2.2 Общая схема работы модуля


Рис. 1.2. Диаграмма прецедентов работы модуля


Общая схема работы модуля выглядит следующим образом:

) В случае работы со списком подсистем клиентский код должен создать подсистему, определиться с её виртуальным путем и передать её ядру. Происходит монтирование - включение подсистемы в виртуальное дерево. Работу по «сборке мусора» при завершении работы ядро берет на себя.

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

а) В случае запроса на итерирование виртуальной директории список дескрипторов возвращается клиентскому коду.

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

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

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


1.2.3 Выбор платформы проектирования и его обоснование

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

В качестве операционной системы для платформенно-зависимого кода была выбрана Windows 98/Me/XP, т.к. именно под эти ОС создаются проекты MiSTland. Код дисковой подсистемы базируется на библиотеке CRT, реализация которой существует на большинстве известных программных платформ. На весь остальной код налагалось такое ограничение: модуль должен быть выполнен на языке С++ (ISO/IEC 14882) с использованием идеологии STL, для удобства подключения (весь остальной код также пишется на С++) и для удобства сопровождения любым программистом MiSTland.

В качестве сред разработки были выбраны:

) Microsoft Visual Studio .NET 7.1 - одна из объективно лучших интегрированных сред для Win32, имеющая такие сильные стороны, как:

а) Удобство и гибкость при создании различных приложений под Win32.

б) Её компилятор практически стопроцентно поддерживает стандарт С++, чем не отличаются многие другие компиляторы.

в) Наличие мощного и удобного интегрированного отладчика, поддерживающего, в том числе, удаленную отладку.

г) Наличие удобного и всеобъемлющего справочного руководства - MSDN.

д) Удобный интерфейс, использующий большинство известных наработок в области Win32 GUI.

) Rational Rose - также одна из объективно лучших интегрированных сред по проектированию на языке UML. Её сильные стороны таковы:

а) Полная поддержка стандарта UML 1.3, на котором и велось проектирование.

б) Удобные графические инструменты.

в) Возможность проверять семантическую целостность диаграмм - своего рода компилятор.

г) Возможность экспортировать проекты на UML в код целого ряда целевых ООП - языков, в том числе, конечно же, и в код С++.

Как дополнительные инструменты были задействованы Microsoft Visio - для не-UML схем - и следующие программные библиотеки:

) STLport - одна из реализаций STL, наиболее распространенная в индустрии, свободно распространяемая. Поддерживается силами членов Комитета по стандартизации С++. Платформенно независима. В отличие от реализации Microsoft, поставляемой вместе с MSVS, полностью соответствует стандарту С++.

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

) zlib - свободно распространяемая библиотека, реализующая архивацию и распаковку архивов формата ZIP алгоритмами deflate и inflate (наиболее распространенные, другие сейчас практически не встречаются). Отличается простотой использования и гибким программным интерфейсом.


1.2.4 Проектирование архитектуры модуля

Ниже описаны архитектурные решения, примененные в модуле.


Рис. 1.3. Диаграмма классов VFS


На рисунке 1.3 изображена общая диаграмма классов VFS. На диаграмме не указаны детально члены классов во избежание нагромождения. Здесь прослежены инкапсулированность основных членов классов, основные зависимости с указанием типа связей, их мощности и направлением раскрытия. Интерфейсные классы выделены стереотипом interface. На диаграмме не присутствует никаких вспомогательных классов, прямо не участвующих в основных алгоритмах работы. Ниже детально рассматриваются особенности проектирования каждого из классов-участников диаграммы.


Рис. 1.4. Диаграмма класса fs


На рисунке 1.4 изображена диаграмма интерфейсного класса fs, который является основным программным интерфейсом модуля. Строго говоря, классом fs не является. Реализован он как пространство имен с вложенными в него самостоятельными функциями. Никаких данных за ненадобностью fs не хранит, поэтому его внешние связи ограничены такой их разновидностью, как «зависимость» (dependency).

Зависимость от класса system обусловлена работой алгоритмов get_files, get_descriptor и mount, которым требуется доступ к дереву виртуальных директорий, хранящемуся в system.

Зависимость от классов file_id, io_file и iterator обусловлена использованием их как аргументов и возвращаемых значений.

Рис. 1.5. Диаграмма класса system


На рисунке 1.5 изображена диаграмма класса system, который является ядром VFS. Класс использует несколько модернизированный паттерн «синглетон», или «одиночка». Этот паттерн (устоявшаяся схема проектирования) характерен тем, что на весь проект гарантированно существует только один экземпляр класса. В С++ это реализуется как статический член класса - экземпляр объекта, доступ к которому осуществляется статической же функцией. Инициализация и уничтожение экземпляра происходят как у статической переменной. Конструктор и деструктор такого класса объявляются приватными. Для большей гибкости существует разновидность этой схемы, когда есть открытые статические функции создания и уничтожения единственного объекта, а функция доступа снабжается идентификацией попытки доступа к неинициализированному объекту.

Для облегчения возможной замены реализации класса system, а также для сокрытия некоторой части интерфейса, основные функции-члены system сделаны абстрактными, а реализует их скрытый наследник system_impl.

В качестве контейнера, реализующего дерево, используется шаблонный класс lcrn_tree из внутренней библиотеки MiSTland. В нем определен итератор, используемый в интерфейсе system.

В узлах дерева содержатся объекты типа directory, поэтому system связан с этим классом агрегированием. Также system непосредственно агрегирует объект класса сache.

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


Рис. 1.6. Диаграмма класса directory


На рисунке 1.6 изображена диаграмма класса directory, представляющего виртуальную директорию. Класс предназначен для хранения списка подсистем и манипулирования им. Директория хранит своё имя и собственно список, реализованный контейнером std::list, это обуславливает агрегирование классов std::string, std::list и sub_fs. Как было сказано выше, директория физически хранится в дереве system, поэтому класс directory агрегирован классом system.

Рис. 1.7. Диаграмма класса sub_fs


На рисунке 1.7 изображена диаграмма класса sub_fs, который является интерфейсом хранилища (подсистемы). Класс предоставляет следующий интерфейс:

) Получение физического расположения подсистемы.

) Доступность подсистемы на запись.

) Существование файла в подсистеме.

) Атрибуты файла: размер, доступ, время создания, директория ли он.

) Создать итератор по пути и маске поиска.

) Открыть файл на запись или на чтение.

) Удалить файл.

) Создать реальные директории по пути.

) Как было сказано выше, подсистему агрегирует класс directory. Создаваемый объект sub_fs_iter имеет ссылку на sub_fs.


Рис. 1.8. Диаграмма класса sub_fs_iter

На рисунке 1.8 изображена диаграмма класса sub_fs_iter, который является итератором подсистемы. Объекты данного класса, используются алгоритмами get_files и get_descriptor. Основные методы - получение текущего дескриптора и оператор инкремента. Содержит ссылку на «свою» подсистему.


Рис. 1.9. Диаграмма класса file_id


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

Для полноты картины стоит упомянуть вспомогательные классы io_file и iterator, диаграммы которых помещены на рисунки 1.10 и 1.11. Класс io_file служит для предоставления потока на файл, хранит в себе исходящий либо входящий поток и экземпляр file_id. Класс iterator служит для построения контейнеров дескрипторов в реализации алгоритмов get_files и get_descriptor.


Рис. 1.10. Диаграмма класса io_file

Рис. 1.11. Диаграмма класса iterator


1.2.5 Конфигурация технических средств

Ограничения на конфигурацию технических средств накладываются проектом в целом. В проектах MiSTland, согласно тестированию, VFS никогда не занимала сколько-нибудь значительного объема памяти (это связано с небольшими объемами её собственных данных) и не отбирала сколько-нибудь заметное количество процессорного времени. Наиболее серьезно, как показали тесты, машину нагружает распаковка архива.

Требования к программному обеспечению - наличие Windows 98 и старше в случае использования подсистемы ресурсов исполняемых файлов Win32.


1.2.6 Алгоритмы работы модуля

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

Рис.1.12. Схема алгоритма get_files


Необходимо пояснить работу алгоритма. Клиентский код предоставляет путь до искомой последовательности и маску поиска (допустимо конкретное имя файла), а также осуществляет выбор механизма сортировки дескрипторов файлов с одинаковыми виртуальными именами. Используется идиома «предикат», заимствованная из STL. Может использоваться предикат по умолчанию, либо же предоставленный пользовательским кодом. Потом запрашивается ядро VFS, у ядра запрашивается дерево виртуальных директорий. Дерево обходится начиная от корня, при каждой итерации выделяется текущая директория, в соответствии с ней корректируется путь поиска: путь директории считается виртуальной частью пути поиска, остальная часть - реальной, соответственно реальная часть пути должна быть передана подсистемам. Из директории берется список замонтированных в неё подсистем, к каждой подсистеме формируется запрос на существование файла с именем «реальная часть + маска поиска». Для этого используется собственный итератор подсистемы. Все найденные таким образом дескрипторы сохраняются в контейнер со структурой, несколько напоминающей графический эквалайзер (рис.1.13).


Рис. 1.13. Схема контейнера файлов виртуальной директории


Контейнер является списком, элементами которого являются списки дескрипторов с одинаковыми виртуальными именами, отсортированных в соответствии с переданным предикатом.

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

) В системе существует кэш для одиночных запросов, поэтому перед запуском сканирования дерева проверяется он - в случае совпадения имен искомого и закешированного дескрипторов выдается закешированный.

) Наружу вместо контейнера выдается первый его элемент.

На рисунке 1.15 изображен алгоритм работы кода, монтирующего и демонтирующего подсистемы.

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


Рис. 1.14. Схема алгоритма get_descriptor

Рис. 1.15. Схема алгоритма mount


1.2.7 Методика тестирования

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

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

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

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

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

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

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

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

Модульные тесты были спланированы заранее с помощью предлагаемых методикой модульного тестирования шаблонов:

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

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

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

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

) время для тестирования было выделено из расчета примерно половины времени разработки;

) в качестве системы учета времени и баг-трекера использовались сначала Microsoft Outlook, потом Sirid.

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

Формально в рамках тестирования системы были проведены следующие проверки.

) Общий интерфейс VFS:

а) Открытие файла на чтение и предоставление входного потока на него стандартной библиотеки С++, согласно относительной системе именования, принятой в структуре данных проекта.

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

в) Перебор файлов внутри директории безотносительно типу файлового хранилища.

2)Ядро VFS:

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

б) Монтирование/демонтирование подсистем различных типов в директории.

в) Проверка механизма "сборки мусора".

) Особенности:

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

б) Проверка работы критериев сортировки и выбора предпочтительных вариантов файлов.

) Специализированные модули:

а) Проверка корректности работы шифрования/дешифрования средствами разработанной библиотеки ml_encrypted_zip при заведомо внедренных ошибках шифрации.

5)Надежность:

а) Проверка на недопустимые имена файлов.

б) Проверка на отсутствие запрашиваемых файлов.

в) Проверка на ошибки физического доступа к подсистемам.

Интегральные тесты не проводились, поскольку в них не было необходимости.

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

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


1.2.8 Результаты экспериментальной проверки

Результаты тестирования показали:

) Модуль полностью удовлетворяет функциональным требованиям, перечисленным в ТЗ.

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

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

) Утечек памяти зафиксировано не было, механизм «сборки мусора» функционирует должным образом.

Раздел 2. Технологический раздел


.1 Проектирование на языке UML


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

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

С повсеместным распространением ООП проектировщики всё чаще стали обращаться к понятию «класс» как к универсальной единице структуры программы и как к актеру поведения. Одновременно несколько видных исследователей - Буч, Джекобсон, Румбах и другие - начали разрабатывать концепции языков, которые могли бы описать все аспекты работы программы, и были бы столь же эффективными, как языки программирования. Их работа вылилась в принятый консорциумом OMG стандарт Unified Modeling Language, который на сегодняшний день используется множеством разработчиков по всему миру и продолжает совершенствоваться.


2.1.1 Концепция Unified Modeling Language

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

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

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

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

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


2.1.2 Виды диаграмм UML

Диаграммы UML, как и было сказано выше, являются основным способом представления моделей. Последовательность рассмотрения диаграмм в данном подразделе обусловлена рекомендациями Rational Unified Process и наглядно показывает последовательность моделирования системы.

Диаграмма прецедентов (use case diagram)

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

Каждый прецедент характеризует некую предполагаемую последовательность действий. Актер представляет некую внешнюю по отношению к модели сущность. Существует несколько стандартных видов отношений между актерами и прецедентами:

) ассоциация - указание на семантическую связь актера и прецедента (например, актер инициирует прецедент);

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

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

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


Рис. 2.1. Диаграмма прецедентов


Диаграмма классов (class diagram)

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

Класс в UML является абстрактным описанием свойств множества объектов, обладающих одинаковой структурой, поведением и отношениями с объектами других классов. Класс обладает набором атрибутов или свойств, а также набором операций или методов. Выделяется понятие шаблонного класса, аналогичное одноименному из языка С++.

Между классами могут быть следующие отношения:

) ассоциация - произвольная семантическая связь классов, может иметь кратность (аналогично ER-диаграммам);

) обобщение - отношение между предком и потомком, интерпретация наследования;

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

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

) зависимость - семантическая связь, не являющаяся какой-либо из вышеперечисленных.

Интерфейс в UML - это специальный случай класса, когда специфицируется только его поведение.


Рис. 2.2. Диаграмма классов

Диаграмма кооперации (collaboration diagram)

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

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


Рис. 2.3. Диаграмма коопераций уровня спецификации


Рис. 2.4. Диаграмма коопераций уровня экземпляров


Диаграмма последовательности (sequence diagram)

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


Рис. 2.5. Диаграмма последовательности


Диаграмма состояний (statechart diagram)

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

Диаграмма состояний по существу является графом, представляющим некий конечный автомат.


Рис. 2.6. Диаграмма состояний

Диаграмма деятельности (activity diagram)

Диаграмма деятельности является самым низкоуровневым видом диаграмм UML. Её семантика сродни многократно стандартизованным правилам записи блок-схем алгоритмов.


Рис. 2.7. Диаграмма активностей


Диаграмма компонентов (component diagram)

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

Диаграмма развертывания (deployment diagram)

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

2.1.3 Связь с объектно-ориентированными языками

Некоторые виды диаграмм UML, например диаграммы классов, очень хорошо поддаются обработке генераторами кода. Соответствующие инструментальные средства встроены в большинство мощных CASE-средств, таких как, например, Rational Rose. По данным диаграммы классов такое инструментальное средство способно создать набор файлов со сгенерированными определениями классов, включая их свойства и методы согласно спецификациям диаграммы.


2.2 Идеология STL в применении к архитектуре модуля


Как и многие другие объектно-ориентированные языки, С++ предоставляет широкие возможности по созданию новых типов данных. Библиотека STL призвана предоставить возможность свободно оперировать этими типами.

Библиотека STL (Standard Template Library - стандартная библиотека шаблонов) вводит широкий набор контейнеров для хранения объектов и большое число алгоритмов для манипулирования ими. Благодаря использованию шаблонов, библиотека STL является строго типизированной, что позволяет ей быть крайне гибкой и дает возможность обнаруживать многие ошибки ещё на этапе компиляции.

Библиотека STL является частью стандартной библиотеки языка С++, как это определено в стандарте ISO / IEC 14882 от 1998 года.

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

2.2.1 Шаблоны в C++

Шаблон (template) - параметризированная часть C++-кода. Шаблонными параметрами, как правило, являются имена типов (малоиспользуемый вариант - константы). Единожды описанный в программе шаблон можно инстанцировать (создавать на его основе новые классы или функции) неограниченное число раз. Фактически, шаблон является способом метапрограммирования - для каждого объявления параметризованного класса или функции с известным набором аргументов шаблона компилятором генерируется новый класс или функция обычного вида. Можно сказать, что такое метапрограммирование является вариантом умных макроподстановок. С одной стороны, это увеличивает объем компилируемого кода (часто в разы), но с другой, дает очень большую гибкость в использовании.

Перед макросами с параметрами препроцессора языка C (которые сохраняют в полном объёме свой функционал и в C++) шаблоны имеют следующие преимущества:

)область видимости шаблонов подчиняется стандартным правилам языка C++, в то время как макрос всегда является объектом с глобальной видимостью;

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

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

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


Листинг 2.1. Макрос и шаблон

#define SQR(x) ((x) * (x))

template<typename T> T sqr(const T& x) { return (x * x); }test()

{x = 2;y = 2;= sqr(y);= SQR(x);= sqr(++y);= SQR(++x);// ошибка! Инкремент x произойдет дважды.

}


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


2.2.2 Контейнеры STL

Контейнеры STL - это шаблонные классы, которые предназначены для хранения ряда однотипных объектов. К объектам, хранимым в контейнере, предъявляются следующие требования:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Список целесообразно применять в случаях, когда требуются многочисленные операции вставки и удаления в середине контейнера, и нет необходимости в доступе по индексу. Этот контейнер поддерживает очень быстрые операции слияния и разделения списков (физического копирования элементов при этом не происходит, модифицируются только указатели в управляющих структурах)., 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, также называются объектами-функциями) - объект любого класса, для которого определён оператор вызова функции «()». Следуя определению, любая функция является функтором.

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

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

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

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

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


2.2.4 Потоки

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

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

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

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

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

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

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

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

Замечу, что упомянутые операторы осуществляют форматированный ввод/вывод. Используя такие низкоуровневые средства, как методы 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 было эпизодическим, а в конечной версии исключено за ненадобностью, подробно рассматриваться здесь они не будут.

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

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

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


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 Модульное тестирование

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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


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


2.4.2 Типы тестов

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


Раздел 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 - себестоимость опытного образца;_res - материальные затраты (стоимость материалов и изделий);_coeff - трудоемкость изготовления изделия в нормо-часах;_normhour - цена одного нормо-часа предприятия-изготовителя.


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

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


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

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

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

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

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

) на технику;

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

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


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

Составляющие затратОсновные факторы, влияющие на составляющую затратСтепень влиянияНа непосредственную разработкуОбъем ПСАНадежность ПСАСтепень использования ресурсов ЭВМАДлительность разработки ПСАДлительность цикла жизни ПСАУровень технологии разработки ПСАУровень языка программированияВНа изготовление опытного образца ПСОбъем ПСАУровень технологии разработки ПСАСпособ материализации программВНа технологии и программные средства автоматизации разработкиОбъем ПСАУровень технологии разработки ПСАУровень языка проектирования ПСВДлительность цикла жизни ПСВНа техникуОбъем ПСАУровень технологии разработки ПСАДлительность разработки ПСАСтепень использования ресурсов ЭВМАХарактеристики ЭВМВНа повышение квалификации разработчиковТематическая квалификацияАТехнологическая квалификацияВПрограммистская квалификацияВ

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

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


(3.2)


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


(3.3)


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

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


(3.4)


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


(3.5)


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


(3.6)


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


(3.7)


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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


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

ПараметрМетод1234Трудоемкость разработки ПС-+-+Стоимость ПО, материалов++++Затраты на технику++++Специфика труда программиста---+Язык программирования-+-+Кол-во основных функций разработки--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

) MS Visual C++ .Net Standart

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

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


C_hard = T_work * C_hour


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

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

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


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


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

) стоимость ремонта. Затраты на ремонт в год считаются, как 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.5. Смета затрат на разработку ПС

Статья расходовЗатраты, руб.Непосредственная разработка ПС63818Составление документации19146Содержание и эксплуатация вычислительного комплекса13437Накладные расходы38291Итого134692

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


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

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


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

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

= SC + NP + PP ,(3.8)


где SC (self cost) - себестоимость единицы товара;(normative profit) - нормативная прибыль;(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 от общих на него затрат);_bit - величина прибыли от реализации одного экземпляра тиража. Слагаемое (Replication_cost + Profit_bit) иногда связывают с ценой одной адаптации данного программного продукта.


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


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

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

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


С = SC + NP(3.10)


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

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

= Profitability * C,


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

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

= 0.25 * 134692 = 33673 руб.


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


Cost_total = 134692+ 33673 = 168365 руб.


3.6 Выводы


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

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

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


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


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


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


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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

) двоении;

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


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 Гигиенические требования к видеодисплейным терминалам, персональным электронно-вычислительным машинам и организации работы.

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

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


4.2.3 Освещение рабочего места

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

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

Специфика работы за монитором ПК состоит также в том, что работать приходится с так называемым самосветящимся объектом - об этом упоминалось в разделе «Зрительное утомление».

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

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

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

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

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

) Следует выбирать оптимальную направленность светового потока. Лучше всего иметь так называемый «рассеянный» свет.

Требования к освещенности рабочего места можно сформулировать таким образом:

) наименьшая допустимая освещенность от общего освещения должна составлять 300 люкс;

) освещенность рабочего места не должна превышать 2/3 нормальной освещенности помещения;

) экран монитора не должен быть ориентирован в сторону источников света (окон, настольных ламп и т.п.);

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

) не следует располагать дисплей непосредственно под источником освещения или вплотную с ним;

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

) яркость для блестящих поверхностей более 0.2 кв.м не должна превышать 500 кд/кв.м;

) показатель ослепленности не должен превышать 40 единиц;

) коэффициент пульсаций не должен превышать 20%.


4.2.4 Электробезопасность

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

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

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

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

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

) запрещается разбирать монитор и пытаться самостоятельно устранять неисправности (опасные для жизни высокие напряжения на элементах схемы ЭЛТ-монитора сохраняются длительное время после отключения электропитания);

) повторное включение компьютера рекомендуется производить не ранее, чем через 20 секунд после выключения.

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

ГОСТ 12.2007-75 устанавливает требования безопасности, предотвращающие или уменьшающие до допустимого уровня воздействие на человека электрического тока.

Одной из обязательных мер электробезопасности при работе с компьютером является надежное его заземление. Заземление необходимо для того, чтобы ток шел через цепь наименьшего сопротивления - чем меньше сопротивление заземлителя сопротивления человеческого тела, тем меньший ток пойдет через человека. Потребляемая компьютером мощность в последнее время постоянно растет и сейчас достигает 300-400 ватт. При напряжении в сети ~200 вольт потребляемый компьютером ток заведомо выше порогового (0,5 ампер), поэтому заземление в данном случае необходимо. Для заземления компьютера, в первую очередь, применяются естественные заземлители - любые металлические конструкции, имеющие хорошую связь с землей. Если сопротивление естественных заземлителей больше нормируемого (4 Ом), то необходимо сооружать искусственные заземлители.


4.2.5 Микроклимат

Метеорологическими условиями согласно ГОСТ 12.1.005-88 являются:

1)температура;

2)относительная влажность;

)скорость движения воздуха;

)атмосферное давление.

С целью обеспечения комфортных условий для работающих людей и надежной работы оборудования, необходимо поддерживать следующие метеорологические условия (согласно СН 512-78):

) Атмосферное давление в помещении машинного зала должно быть 1013.25±266 ГПа. При пониженном давлении воздуха ухудшается отвод теплоты от аппаратуры компьютера, снижаются изоляционные свойства воздуха.

) Воздух, используемый для вентиляции машинного зала, должен очищаться от пыли. Запыленность воздуха не должна превышать 1 мг/м³, а размеры пылинок - 3 мкм.

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

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


4.2.6 Зашумленность

Шум оказывает большое влияние на человека и его работоспособность. Уже при уровнях шума выше 40 дБ ослабляется внимание, ухудшается память, появляется быстрая утомляемость, головная боль.

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

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

) Располагать помещение машинного зала вдали от внешних источников шума.

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

) Использовать малошумящую вентиляцию.

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

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

Оптимальные показатели уровня шумов в рабочих помещениях конструкторских бюро, кабинетах расчетчиков, программистов определяются по ГОСТ 12.1.003-83 [16].


.3 Инженерный расчет освещенности машинного зала


Рассчитаем общее освещение в машинном зале ПЭВМ методом коэффициента использования светового потока по уравнению:

Выбираем рекомендованное для машинного зала люминесцентное освещение.


(4.1)


Располагаем светильники рядами вдоль длинной стороны помещения. Будем использовать светильники типа УСП-35 с двумя лампами типа ЛБ-40. Для обеспечения наилучших условий освещения, расстояние между рядами светильников L должно соответствовать отношению:


(4.2.)


Где: h - высота подвеса светильников,= 3.2 м - высота помещения,= 0.2 м - свес светильника,= 0.75 м - высота рабочей поверхности от пола.


(4.3)= 3.0-0.2-0.75 = 2.25 [м] Þ L = ?*h ~= 3.2 [м]


Длина помещения А = 8 м

Ширина помещения В = 6 м

Количество рядов светильников N найдем из уравнения:

* (0.33* 2 + N-1) = B

(4.4)


Количество рядов светильников N = 2 ряда.

Согласно нормам, нормируемая минимальная освещенность при общем освещении: Eн = 200 лк.

Так как запыленность воздуха меньше 1 мг/м³, то коэффициент запаса:


Кз = 1.5.


Площадь помещения

= A*B = 8*6 = 48 [м²].


Так как мы предполагаем создать достаточно равномерное освещение, то коэффициент неравномерности освещения: z = 1.15.

Индекс помещения:


(4.5)


Коэффициенты отражения светового потока принимаем (c учетом наиболее распространенной окраски):

от потолка - ?п = 70%,

от стен - ?с = 50%,

от пола - ?пола = 10%.

Тогда по таблице находим коэффициент использования светового потока:


? = 0.46.


Так как мы не собираемся создавать затенение, то коэффициент затенения считаем ? = 1.

Из данных производителя находим световой поток лампы ЛБ-40:


Фл = 3120 лм.


Световой поток светильника:


Фсв = 2*Фл = 6240 [лм].


Количество светильников в одном ряду:


(4.6)


Расположение светильников:

Длина светильника lсв = 1.3 м

Количество светильников в ряду М = 3 шт

Количество рядов светильников N = 2 шт


Так как А - М*lсв = 4.1<4*L = 12.8 [м]


(где L - рассчитанное минимальное расстояние между светильниками), то расстояние между светильниками в одном ряду L2 можно сделать равным расстоянию от крайнего светильника в ряду до стены. Тогда


(4.7)


Расстояние между рядами L1 при расстоянии крайнего ряда от стены 0.33*L1:


(4.8)


Итак, для нормального освещения машинного зала заданных размеров используем 6 светильников типа УСП-35 с двумя лампами типа ЛБ-40.


4.4 Экологическая безопасность


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


4.5 Пожарная безопасность


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


4.6 Выводы


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

Был выполнен инженерный расчет необходимого освещения машинного зала.

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

Заключение


Модуль, разработанный в ходе выполнения данного дипломного проекта, был успешно внедрен в трех коммерческих программных продуктах компании «МиСТ ленд - ЮГ», один из которых - «Альфа Антитеррор» - поступил в продажу в феврале 2005 года, а остальные в данный момент разрабатываются. Реализация затребованного в техническом задании функционала позволила команде разработчиков безболезненно перейти на завершающей стадии проекта к хранению ресурсов в конечной версии размещения. Вторым по значимости результатом стала возможность быстро менять ресурсы без переупаковки, перераспределения и т.п., что является вариантом пользовательской модификации ресурсов.

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

В специальном разделе были освещены вопросы предварительных исследований, проектирования и тестирования модуля. Большая часть уделена вопросам архитектуры. В технологическом разделе рассмотрены основные средства, которые были использованы при разработке: UML, средства STL, внешние библиотеки, методология модульного тестирования. Экономический раздел посвящен вопросам себестоимости и цены модуля; в разделе производственно-экологической безопасности рассмотрены основные вредности на рабочем месте программиста и выполнен расчет необходимой освещенности машинного зала.

Список литературы


1) Л.Г.Гагарина, Н.Н,Зубов, А.В.Стрижков, Е.Л.Федотова. Методические указания по подготовке дипломного проекта специалистов направления 654600 «Информатика и вычислительная техника». МГИЭТ, 2006.

) Костина Г.Д., Моисеева Н.К. Маркетинговые исследования при создании и использовании программных продуктов: Методические указания длявыполнения курсовых и дипломных работ по специальности «Менеджмент». МИЭТ(ТУ),2006.

) Константинова Л.А., Ларионов Н.М., Писеев В.М. Методические указания по выполнению раздела «Охрана труда» в дипломных проектах для студентов МИЭТ. Под ред. В.И. Каракеяна. М., МИЭТ, 2008.

) Джефф Элджер. С++: Библиотека программиста. «Питер», 2008.

) Бьярн Страуструп. Дизайн и эволюция С++. «ДМК Пресс», 2006

) Эрик Дж. Брауде. Технология разработки программного обеспечения. "Питер", 2006.

) Гради Буч. Объектно-ориентированный анализ и проектирование с примерами приложений на C++. «Невский диалект», 2008.

) Айра Пол. Объектно-ориентированное программирование на С++. «Бином», 2008.

) Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес. Приемы объектно-ориентированного проектирования. Паттерны проектирования. «Питер», 2009.

) Чарльз Петзолд. Программирование для Windows 95. «BHV - Санкт-Петербург», 2007.

) Герб Саттер. Решение сложных задач на С++. «Вильямс», 2008.

) Андрей Александреску. Современное проектирование на С++. «Вильямс», 2007.

) Бьярн Страуструп. Язык программирования С++. Специальное издание. «Бином», 2008.

) Д. Рихтер. Windows 2000 для профессионалов. «Русская редакция», 2007.

) Документация к библиотеке zlib - #"center">Приложение 1


Руководство программиста.

Назначение и условия применения программы.

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

Модуль предназначен для работы в составе проекта, написанного на языке С++. Разработка велась с использованием компилятора из MSVS 7.1, и компиляция более слабыми в плане поддержки стандарта компиляторами не гарантируется. Для некоторого функционала необходимо наличие библиотек MS Windows не ниже версии 98. Аппаратные ограничения накладывает использующий модуль проект.

Характеристика программы.

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

Обращение к программе.

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

<class Pred>std::auto_ptr<i_file> r_open_file (std::string& file_name, pred,


bool seekable = true) - открыть поток на файл по имени с использованием при поиске явно указанного предиката сортировки. Параметр seekable указывает, нужно ли открывать поток с возможностью поиска по нему (сказывается на быстродействии). В случае невозможности выполнения будет сгенерировано исключение.


inline std::auto_ptr<i_file> r_open_file (

const std::string& file_name, seekable = true) - то же самое с использованием предиката по умолчанию.

inline std::auto_ptr<i_file> r_open_file ( file_id &id,

bool seekable = true) - открыть поток на файл по его дескриптору. Наиболее быстрый вариант работы, поскольку поиск не производится.

template <class Pred>

inline file_id file_exists (std::string& file_name, pred) - проверить существование файла по имени.


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


inline file_id file_exists (

const std::string& file_name) - то же самое с использованием предиката по умолчанию.

template <class Pred>std::auto_ptr<o_file> w_open_file (std::string& file_name, pred,

bool seekable = true) - открыть поток в файл на запись по имени. В случае невозможности выполнения будет сгенерировано исключение.

inline std::auto_ptr<o_file> w_open_file (

const std::string& file_name, seekable = true) - то же самое с использованием предиката по умолчанию.

inline std::auto_ptr<o_file> w_open_file (file_id &id,seekable = true, app = 0) - открыть файл на запись по идентификатору. Параметр append - добавлять ли запись в конец файла.

template <class Pred>void delete_file (std::string& file_name, pred) - удалить файл по имени, используя предикат сортировки при поиске.


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


inline void delete_file (

const std::string& file_name) - то же самое с использованием предиката по умолчанию.

inline void delete_file (file_id &id) - удалить файл по его дескриптору.<class Pred>fs_files<Pred> get_files (std::string& file_name, pred,

unsigned param) - получить контейнер с файлами в виртуальной директории по маске с использованием при поиске предиката сортировки.


Параметр param позволяет задать флаги поиска аналогично функциям CRT.


inline fs_files<date_heuristic> get_files (

const std::string& file_name, param) - то же самое с использованием предиката по умолчанию.

inline void make_dir (

const std::string& file_name) - разбор пути и создание реальных директорий по нему там, где подсистемы это позволят сделать.

inline sub_fs_id mount (::auto_ptr<sub_fs> what, std::string& path) - замонтировать подсистему в дерево.


Параметр what - подсистема, параметр path - желаемый виртуальный путь до неё. Система создаст виртуальные директории в необходимом количестве. Удаление подсистемы в конце работы VFS берет на себя объект system. Возвращаемое значение - идентификатор подсистемы, позволяющий выборочно её демонтировать.


inline std::auto_ptr<sub_fs> unmount (_fs_id id) - демонтировать подсистему по её идентификатору.


Внимание! Осмысленность идентификаторов за всё время работы модуля не гарантируется.

Входные и выходные данные.

Входные и выходные данные полностью описаны в «обращении к программе». Ничего другого модуль не использует.

Сообщения.

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

Типы исключений:

) no_file - не найден файл по имени или дескриптору;

) stream_fail - ошибка при создании потока;

) no_mounted - поиск невозможен, нет замонтированных подсистем;

) no_writable - нет возможности открыть поток на запись, все подсистемы помечены как read_only;

) incorrect_path - грубая ошибка в задании имени файла;

) zip_restrictions - неподдерживаемый формат зип-архива.

Приложение 2


Фрагменты исходных текстов.

Ниже представлены интерфейсные классы VFS. Подробности реализации в большинстве случаев опущены, поскольку код имеет большой объем.


Файл fs.hmll

{ fs

{

/////////////////////////////////////////////////////////////////////////

//перечисления для передачи фуцкциям в качестве параметров

enum SearchParams

{= 1<<0,= 1<<1,= 1<<2

};

enum WriteParams

{

append = 1

};

/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//БАЗОВЫЙ ПРЕДИКАТ

//базовая эвристика, определяет файл с большей датой последнего изменения

//как "меньший". Свои предикаты нужно писать "по образу и подобию"

struct date_heuristic

{operator()(const file_id& x, const file_id& y) const

{x_prior = x.sub_fs()->priority();y_prior = y.sub_fs()->priority();(x_prior == y_prior)(x.date() >= y.date());(x_prior > y_prior);

}

};

/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//ПРОВЕРИТЬ ПУТЬ НА ПРАВИЛЬНОСТЬ

//проверить на наличие запрещенных файловой системой символов

inline bool is_path_valid(const std::string& raw_data);

/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//ОТКРЫТЬ ФАЙЛ НА ЧТЕНИЕ

//открыть, используя предикат сортировки

template <class Pred>std::auto_ptr<i_file> r_open_file(const std::string& file_name, Pred pred, seekable = true);

//открыть с использованием стандартного предиката

inline std::auto_ptr<i_file> r_open_file(const std::string& file_name, bool seekable = true);

//открыть по идентификаторуstd::auto_ptr<i_file> r_open_file(const file_id &id, bool seekable = true);

/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//ПРОВЕРИТЬ ФАЙЛ НА СУЩЕСТВОВАНИЕ

//проверить, используя предикат сортировки

template <class Pred>file_id file_exists(const std::string& file_name, Pred pred);

//проверить с использованием стандартного предиката

inline file_id file_exists(const std::string& file_name);

/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//ОТКРЫТЬ ФАЙЛ НА ЗАПИСЬ

//открыть, используя предикат сортировки

template <class Pred>

inline std::auto_ptr<o_file> w_open_file(const std::string& file_name, Pred pred, seekable = true);

//открыть с использованием стандартного предиката

inline std::auto_ptr<o_file> w_open_file(const std::string& file_name, bool seekable = true);

//открыть по идетификатору, параметр - appendstd::auto_ptr<o_file> w_open_file(const file_id &id,seekable = true, bool app = 0);

/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//УДАЛИТЬ ФАЙЛ

//удалить, используя предикат сортировки

template <class Pred>void delete_file(const std::string& file_name, Pred pred);

//удалить с использованием стандартного предикатаvoid delete_file(const std::string& file_name);

//удалить по идентификаторуvoid delete_file(const file_id &id);

/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//ПОЛУЧИТЬ ОБЪЕКТ ДЛЯ ИТЕРИРОВАНИЯ

//получить объект-"переборщик" файлов по маске (path - путь вместе с маской).

//Из него можно получить контейнеры file_id по всем файлам (будет использоваться

//эвристика) и по вариантам каждого отдельного файла

//создать объект, используя предикат сортировки

template <class Pred>

inline fs_files<Pred> get_files(const std::string& file_name, Pred pred, unsigned param);

//создать с использованием стандартного предикатаfs_files<date_heuristic> get_files(const std::string& file_name, unsigned param);

/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//СОЗДАТЬ ФИЗИЧЕСКИЕ ДИРЕКТОРИИ ПО ПУТИvoid make_dir(const std::string& file_name);

/////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////

//МОНТИРОВАНИЕ/ДЕМОНТИРОВАНИЕ ПОДСИСТЕМ

//замонтировать подсистему. Права на удаление будут принадлежать fs.

//Возвращается объект, который нужно передать в unmount() для принудительного

//демонтирования.sub_fs_id mount(std::auto_ptr<sub_fs> what, const std::string& file_name);

//демонтировать подсистему и получить права на её удаление

inline std::auto_ptr<sub_fs> unmount(sub_fs_id id);

/////////////////////////////////////////////////////////////////////////

}

}

Файл system.hmll

{fs

{directory;sub_fs;cache;critical_section;

//=====================================================================================//

// class system //

//=====================================================================================//FILE_SYSTEM_EXPORT system

{::system *m_instance;~system() {}:void make_fs();void destroy_fs();system *instance();:mll::utils::lcrn_tree<directory *> dir_tree;dir_tree::const_iterator const_iterator;dir_tree::iterator iterator;:iterator begin() = 0;iterator end() = 0;const_iterator begin() const = 0;const_iterator end() const = 0;void _create_path(const fs_path &path) = 0;iterator find_dir(const fs_path &where) const = 0;sub_fs_id mount(std::auto_ptr<sub_fs> what, const fs_path &where) = 0;std::auto_ptr<sub_fs> unmount(sub_fs_id id) = 0;mll::fs::cache* cache() = 0;critical_section *get_cs() const = 0;

};

//исключения всякого родаmll::debug::exception_template<struct fs_failure> failure;mll::debug::exception_template<struct fs_no_file,failure> no_file;mll::debug::exception_template<struct fs_stream_fail,failure> stream_fail;mll::debug::exception_template<struct fs_no_mounted,failure> no_mounted;mll::debug::exception_template<struct fs_no_writable,failure> no_writable;mll::debug::exception_template<struct fs_incorrect_path,failure> incorrect_path;mll::debug::exception_template<struct fs_zip_restrictions,failure> zip_restrictions;

}

}

Файл directory.hmll

{fs

{

//=====================================================================================//

// class directory //

//=====================================================================================//directory

{:std::list<sub_fs *> list_t;_t m_list;::string m_name;:list_t::iterator iterator;list_t::const_iterator const_iterator;:(const std::string &name): m_name(name) {}

~directory();mount(sub_fs *what);::auto_ptr<sub_fs> unmount(iterator what);std::string &name() { return m_name; }_iterator begin() { return m_list.begin(); }_iterator end() { return m_list.end(); }size() const { return m_list.size(); }

};

}

}

Файл sub_fs.hmll

{fs

{sub_fs_iter;

//=====================================================================================//

// class sub_fs //

//=====================================================================================//sub_fs

{:priority_handler;: ~sub_fs() = 0 {}

///подцепить объект-приоритет системы

virtual void set_priority_handler(std::auto_ptr<priority_handler> handler) = 0;

///Дисковый путь до объекта подсистемы (каталога, zip-файла etc), со слешем на конце

virtual const std::string& disk_path() const = 0;

/// Возможность изменять файлы внутри подсистемыbool system_readonly() const = 0;

/// Существует ли файл с указанным именем

virtual bool file_exists(const fs_path &name) const = 0;

/// Создать итератор внутри подсистемы по введенному пути

virtual std::auto_ptr<sub_fs_iter> new_iterator(const fs_path &) const = 0;

/// Размер файла с указанным именем в байтах

virtual unsigned file_size(const fs_path &name) const = 0;

/// Возможность писать в файл с указанным именем

virtual bool is_readonly(const fs_path &name) const = 0;

/// Дата последнего изменения файла с указанным именем

virtual time_t date(const fs_path &name) const = 0;

/// Является ли файл с указанным именем директорией

virtual bool is_dir(const fs_path &name) const = 0;

/// Вернуть указатель на поток istream для файла с указанным именем

virtual std::auto_ptr<std::istream> r_open_file(const fs_path &path, seekable = true) const = 0;

/// Вернуть указатель на поток ostream для файла с указанным именем

/** Если указан параметр append, поток должен указывать

на конец файла.*/std::auto_ptr<std::ostream> w_open_file(const fs_path &path,append, bool seekable = true) const = 0;

/// Удалить файл с указанным именемvoid delete_file(const fs_path &name) const = 0;

///Создать директориюvoid make_dir(const fs_path &path) const = 0;://up_to_subsystem_priorityint priority() const = 0;

};

//=====================================================================================//

// class FILE_SYSTEM_EXPORT sub_fs::priority_handler //

//=====================================================================================//sub_fs::priority_handler

{:~priority_handler() {}int priority() const = 0;

};

}

}

Файл sub_fs_iter.hmll

{fs

{

//=====================================================================================//

// class sub_fs_iter //

//=====================================================================================//sub_fs_iter

{: ~sub_fs_iter() = 0 {}

/// Закончились ли файлы по указанному пути

virtual bool is_done() = 0;

/// Смещение на следующий файл

virtual sub_fs_iter &operator++() = 0;

/// Формирует объект file_obj из имеющейся информации о файле

virtual file_id get_id() = 0;

};

}

}

Файл fs_files.hmll

{fs

{

//=====================================================================================//

// template<class T> class reference_container //

//=====================================================================================//<class T>reference_container

{:T container_type;container_type &m_list;:_container(const container_type &list): m_list(list) {}

~reference_container() {}:typename container_type::const_iterator iterator;:

///получить итератор на начало

iterator begin() { return m_list.begin(); }

///получить итератор на конец

iterator end() { return m_list.end(); }

///получить размер контейнераsize() const { return m_list.size(); }

};

//=====================================================================================//

// template<class T> class value_container //

//=====================================================================================//<class T>value_container

{:T container_type;_type m_list;:_container(const container_type &list): m_list(list) {}_container(const value_container &another): m_list(another.m_list) {}

~value_container() {}:typename container_type::const_iterator iterator;:

///получить итератор на начало

iterator begin() { return m_list.begin(); }

///получить итератор на конец

iterator end() { return m_list.end(); }

///получить размер контейнераsize() const { return m_list.size(); }

};std::list<file_id> file_t;reference_container<file_t> file_container;value_container<file_t> id_container;

//=====================================================================================//

// class fs_files //

//=====================================================================================//<class Pred = date_heuristic>fs_files

{:file_t::const_iterator iterator;:::shared_ptr<file_list<Pred> > m_data;::shared_ptr<file_t> m_list;:_files() {}_files(const fs_path &path, unsigned param);_files(const fs_files<Pred> &another);

~fs_files() {}_files<Pred> &operator=(const fs_files<Pred> &);:_container get_file_container() const;_container get_id_container(const file_id &id) const;:

///получить итератор на начало контейнера предпочтительных вариантов фалов

iterator begin() const { return m_list->begin(); }

///получить итератор на конецend() const { return m_list->end(); }

///получить размер контейнераint size() const { return m_list->size(); }

};

}

}

Файл file_id.hmll

{fs

{sub_fs;

//=====================================================================================//

// class file_id //

//=====================================================================================//FILE_SYSTEM_EXPORT file_id

{sub_fs *m_sub_fs;_path m_name;:_id(): m_sub_fs(0) {}_id(const sub_fs *sfs, const std::string &name);_id(const file_id &another);

//~file_id() {}_id& operator=(const file_id& another)

{(this != &another)

{_sub_fs = another.m_sub_fs;_name = another.m_name;

}*this;

}:const void * const () const { return m_sub_fs; }operator !() const { return m_sub_fs == 0; }:

/// Возвратит указатель на sub_fs, к которому принадлежит идентификатор

const sub_fs *sub_fs() const { return m_sub_fs; }

/// Полный виртуальный путь с именем

std::string path() const;

/// Виртуальный путь::string dir() const;

/// Имя файла::string fname() const;

/// Расширение::string ext() const;

///Полное имя с расширением

std::string name() const;

///Полный дисковый путь с именем

std::string disk_path() const;

/// Параметр "только чтение"is_readonly() const;

/// Размер файла в байтахfile_size() const;

/// Время последнего изменения файла

time_t date() const;

/// Директория ли это

bool is_dir() const;

};

}

}

Файл file.hmll

{fs

{

//=====================================================================================//

// class o_file //

//=====================================================================================//

/** \class o_file

\brief Класс - "файл для записи".

*/

/**Класс, содержащий уникальный идентификатор

и указатель на поток ostream.

*/o_file

{_id m_id;::auto_ptr<std::ostream> m_stream;:_file(const file_id &id, std::auto_ptr<std::ostream> stream)

: m_id(id), m_stream(stream) {}

~o_file() {}

/// Возвращает ссылку на уникальный идентификатор

const file_id &id() const { return m_id; }

/// Возвращает ссылку на поток::ostream &stream() const { return *m_stream; }

};

//=====================================================================================//

// class i_file //

//=====================================================================================//

/** \class i_file

\brief Класс - "файл для чтения".

*/

/**Класс, содержащий уникальный идентификатор

и указатель на поток istream.

*/i_file

{_id m_id;::auto_ptr<std::istream> m_stream;:_file(const file_id &id, std::auto_ptr<std::istream> stream)

: m_id(id), m_stream(stream) {}

~i_file() {}

/// Возвращает ссылку на уникальный идентификатор

const file_id &id() const { return m_id; }

/// Возвращает ссылку на поток::istream &stream() const { return *m_stream; }

};

}

}

Файл fs_path.hmll

{fs

{

//=====================================================================================//

// class fs_path //

//=====================================================================================//

/*Служебный класс, призван заменить строку-путь.

При конструировании разбивает строку по слэшам и заносит

в список имена каталогов. Может "превращаться" обратно в строку.

*/FILE_SYSTEM_EXPORT fs_path

{:const_iterator;std::list<int> separators_t;///<позиции, по которым в m_data находятся слеши (считается, чтоо в конце строки тоже есть слеш - для удобства)std::string data_t;:_t m_data;_t m_separators;:_path();_path(const std::string& data);_path(const char* data);_path(const fs_path& another);

~fs_path() {}:_iterator begin() const;_iterator end() const;::string front() const;::string back() const;pop_front();pop_back();length() const;clear();std::string& to_str() const;:_path& operator+=(const fs_path& another);_path& operator=(const fs_path& another);:analyzeRawData();

};

//=====================================================================================//

// fs_path operator+(); //

//=====================================================================================//_path operator+(const fs_path& first, const fs_path& second);

//=====================================================================================//

// class fs_path::const_iterator //

//=====================================================================================//FILE_SYSTEM_EXPORT_path::const_iterator: public std::iterator<std::bidirectional_iterator_tag, std::string>

{:fs_path;::string m_selecting;fs_path::data_t* m_data;fs_path::separators_t* m_separators;m_dataIndex;///<"from" point in controlled sequence_path::separators_t::const_iterator m_sepIt;///<next separator:_iterator();_iterator(const const_iterator& another);

~const_iterator();:operator==(const const_iterator& another) const

{ return ((m_dataIndex == another.m_dataIndex) && (m_sepIt == another.m_sepIt)); }operator!=(const const_iterator& another) const

{ return ((m_dataIndex != another.m_dataIndex) || (m_sepIt != another.m_sepIt)); }_iterator& operator++();_iterator operator++(int);_iterator& operator--();_iterator operator--(int);std::string& operator*() const;std::string* operator->() const;_iterator& operator=(const const_iterator& another);

};

}

}

Файл cache.hmll

{fs

{

//=====================================================================================//

// class cache //

//=====================================================================================//FILE_SYSTEM_EXPORT cache

{:std::deque<file_id> single_query_cache_t;_query_cache_t m_single_query_data;://кэширование данных

///добавить данные последнего запроса на операцию с одним файлом (r_open, w_open, exists)

void add_single_query(file_id id);

///файл удаляется, нужно сбросить его из всех кэшей

void drop_file(file_id id);

///сбросить все кэши (например, обновилась структура подсистем)

void clear_all();://получение данных

/// посмотреть наличие в кэше id, полученного ранее по такому же пути

file_id single_query_stored(const std::string& path);

};

}

}


Содержание Введение Раздел 1. Специальный раздел 1.1. Исследовательская часть 1.1.1. Постановка задачи .1.2. Предварительные НИР .1.3. Инф

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ