Разработка API для доступа к данным с динамически изменяемой структурой на основе GraphQL

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

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 01.12.2019
Размер файла 2,4 M

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

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

Размещено на http://www.allbest.ru/

Пермский филиал федерального государственного автономного

образовательного учреждения высшего образования

«Национальный исследовательский университет

«Высшая школа экономики»

Факультет экономики, менеджмента и бизнес-информатики

Кетов Дмитрий Константинович

РАЗРАБОТКА API ДЛЯ ДОСТУПА К ДАННЫМ С ДИНАМИЧЕСКИ ИЗМЕНЯЕМОЙ СТРУКТУРОЙ НА ОСНОВЕ GRAPHQL

Выпускная квалификационная работа

По направлению подготовки 09.03.04 Программная инженерия

Образовательная программа «Программная инженерия

Пермь 2019

Аннотация

интерфейс программирование данные динамический graphql

Тема работы: Разработка API для доступа к данным с динамически изменяемой структурой на основе GraphQL.

Автор: Студент НИУ-ВШЭ группы ПИ 15-1 Кетов Дмитрий Константинович.

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

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

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

Работа содержит 43 страницы основного текста, 21 иллюстрацию, 1 таблицу, 3 приложения. Библиография - 15 наименований.

Оглавление

Введение

Глава 1. Анализ существующих подходов к проектированию API

1.1. Особенности корпоративной разработки

1.2. Особенности клиент-серверного взаимодействия

1.3. Анализ существующих подходов к проектированию API

Глава 2. Анализ требований и проектирование

2.1. Общие требования к системе

2.2. Используемые в решении методы и технологии

2.3. Проектирование архитектуры системы

2.4. Проектирование структуры приложения

Глава 3. Реализация приложения

3.1. Реализация основного приложения

3.1.1. Реализация модели

3.1.2. Схема обработки запросов

3.1.3. Упаковка данных

3.3. Тестирование и развертывание

3.4. Результаты разработки

Заключение

Библиографический список

Приложение А. Функциональные диаграммы

Приложение Б. Иллюстрация экспорта

Приложение В

Введение

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

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

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

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

В ходе проведённого анализа существующих подходов к проектированию API с точки зрения решения проблемы over и under fetching, а также поддержки динамической структуры данных были рассмотрены такие API, как REST, RESTfull, CRUD и т. д. Показано, что существующие решения не подходят для решения нашей задачи, с точки зрения перечисленных выше требований.

Для решения поставленных проблем предложено API. Ключевой идеей предложенного решения, является использование динамической схемы GraphQL. Это должно позволить пользователю задавать и менять метаданные для сущностей и далее работать с ними. GraphQL даст возможность получать только те поля сущности, которые нужны пользователю в конкретном запросе, что позволит избежать проблемы over и under fetching при запросах.

Объектами исследования являются существующие подходы к проектированию API, предоставляющего доступ к данным.

Предметом исследования является API доступа к данным на основе динамической схемы GraphQL.

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

Для достижения поставленной цели следует:

1. Изучить и проанализировать существующие принципы построения API.

2. Изучить и сформулировать требования, к разрабатываемому приложению.

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

4. Разработать серверную часть системы.

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

Во второй главе конкретизированы требования к приложению, а также более подробно разобраны его ключевые отличия от существующего решения, основанного на Prognoz Platform. Далее была спроектирована архитектура приложения, а также его основная структура.

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

Обзор существующих подходов к проектированию API выполнен с помощью вектора вариантов. Анализ и проектирование проиллюстрированы в рамках нотации UML. На этапе реализации были использованы алгоритмы кэширования, графов, а также такие технологии как .net Core, GraphQL, Jenkins, Reddis, Oracle и т. д.

Глава 1. Анализ существующих подходов к проектированию API

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

1.1. Особенности корпоративной разработки

Различия между разработкой корпоративного программного обеспечения и разработкой простых программ очень значительны [2]. Эта тема хорошо освещена в разных публикациях. Прежде всего, важно упомянуть, что такое разработка корпоративного программного обеспечения. Корпоративное программное обеспечение - это программное обеспечение для крупных предприятий. Такие проекты зачастую отличаются от обычных проектов масштабами, сложностью, бюджетом и, как следствие, числом задействованных сотрудников.

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

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

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

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

Если есть несколько технологий, которые соответствуют потребностям проекта, целесообразно их сравнение [13]. Это может помочь понять, какая технология больше подходит в конкретном случае. Более того, так мы улучшим понимание потребностей проекта в конкретной области и даже можем прийти к отказу от обеих и выбрать другую.

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

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

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

Вторая проблема разработки программного обеспечения предприятия связана с размером проекта. Из-за большого размера кодовой базы его сложнее поддерживать, поэтому очень важно хорошо организовать её. Существует множество различий в принципах и шаблонах организации кода. Использование этих шаблонов помогает программистам, которые не работали с конкретной частью кода, понимать и обновлять ее [15,9].

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

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

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

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

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

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

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

Но помимо методов, которые уже были рассмотрены, существует методология разработки под названием Agile, которая удовлетворяет этим требованиям [5]. Методология предполагает короткие циклы разработки приложений, которые могут координироваться и проверяться заказчиком. Это позволяет найти большинство проблем и недоразумений при первой возможности.

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

1.2 Особенности клиент-серверного взаимодействия

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

Зачастую, взаимодействие между клиентом и сервером происходит по одному из специальных протоколов: IP, HTTP, WebSocket и т. д. Более того, инициатором данного взаимодействия в большинстве случаев является именно клиент [1].

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

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

2) сервер выполняет какие-то действия на основе этого запроса;

3) сервер отправляет ответ.

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

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

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

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

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

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

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

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

Первыми проблемами являются over и under-fetching. Over-fetching - это ситуация, когда пользователь получает избыточные данные. Например, он получает поля, которые не использует. Under-fetching - это обратная ситуация over-fetching. Так называют ситуацию, когда пользователь получает не все необходимые данные, и должен делать несколько запросов. Например, в первом запросе пользователь узнает Id связанной сущности, а далее по Id получает ее.

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

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

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

И, стоит заметить, что выбранное решение по проектированию API должно помогать структурировать код серверной части приложения, чтобы поддержать maintainability и надежность системы, в ситуации, когда разрабатывается enterprise-приложение.

1.3 Анализ существующих подходов к проектированию API

Для рассмотрения были выбраны следующие подходы: REST-API, Pure JSON API и GraphQL со статической схемой данных.

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

1) возможность избежать over-fetching;

2) возможность избежать under-fetching;

3) структура кода;

4) поддержка данных с динамической структурой.

Стоит отметить, что ни один из подходов сам по себе не поддерживает данные с динамической структурой, но в случае с REST-API и Pure JSON API есть возможность это реализовать, возвращая список полей и их значений на основе метаданных, которые можно менять, но назвать это стандартным использованием REST-API или Pure JSON API нельзя.

REST-API подразумевает использование методов HTTP, таких как GET, POST, PUT, PATCH, DELETE и т.д. и статус-кодов запросов, таких как 200-ok, 500-internal server error, 404-not found и т.д. при взаимодействии [10]. Такой подход предполагает наличие некоторого количества конечных точек серверного API, через которые и происходит взаимодействие с клиентом. Зачастую, REST-API подразумевает реализацию CRUD-интерфейса, используя перечисленный выше протокол. В расширенном REST-API обычно добавляются вспомогательные поля для GET-запросов, такие как фильтр, пейджинг, сортировка и т.д. Стоит отметить, что добавление этих полей позволяет частично решить проблему over-fetching, т.к. клиент может запрашивать только те сущности, которые ему нужны, но при этом не позволяет выбирать поля, нужные клиенту, отправляя вместо этого все. Несмотря на то, что кажется, что этот подход достаточно строгий и структурированный, на самом деле ничего не мешает использовать эти методы и коды не по назначению, не структурировать код.

Pure JSON API намного менее строгий, чем REST. Он также использует методы HTTP. Причем зачастую только один метод, например, HTTP POST и почти не использует статус-коды (в основном только 200 и 500). Вся логика взаимодействия лежит в JSON в телах запросов. Там проходит сообщение об ошибке, или, в случае успеха, вся нужная информация и т. д. Очевидно, подход, который является еще менее строгим не может обеспечить достаточно жесткую структуру кода.

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

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

Сравниваться варианты будут с помощью вектора вариантов. В качестве критериев выбраны следующие пункты:

1) решение проблемы over-fetching;

2) решение проблемы under-fetching;

3) структура кода;

4) поддержка данных с динамической структурой.

Важность критерия будет оценена по 10-балльной шкале.

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

Для under-fetching выбрана оценка 3. Ситуация в целом похожа на over-fetching, только ситуации, когда это критично реже и замедление не столь значительно

Для структуры кода выбрана оценка 6, т. к. она позволяет в случае необходимости вводить оптимизации, которые по производительности значительно превосходят проблему over и under fetching. Также этот параметр достаточно критичен, т. к. если она будет слишком плоха, то система вообще может быть не разработана до конца ввиду невозможности внесения изменений и обеспечения надежности.

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

Оценки и результат сравнения предоставлены на таблице 1.1.

Таблица 1.1. Вектор вариантов

Критерий

Подход

over-fetching (вес 4)

under-fetching (вес 3)

структура (вес 6)

динамические данные (вес 10)

Сумма

REST-API

5

5

6

5

121

Pure JSON API

4

4

4

6

112

GraphQL

10

10

8

3

148

Максимум:

230

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

Глава 2. Анализ требований и проектирование

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

2.1. Общие требования к системе

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

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

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

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

Функциональные диаграммы AS-IS и AS-TO-BE, демонстрирующие отличия новой системы от старой приведены в приложении А.

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

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

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

Для демонстрации этого отличия были построены диаграммы последовательностей AS-IS и AS-TO-BE. Диаграмма последовательностей AS-IS изображена на рисунке 2.2., а диаграмма последовательностей AS-TO-BE изображена на рисунке 2.3. Как видно из диаграмм, группировка данных по связям теперь осуществляется на серверной части, а клиент получает уже сгруппированные и связанные данные, в то время как в предыдущей версии, этим занимался клиент.

Различается два дополнительных параметра для данных: версионность и иерархичность.

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

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

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

Рисунок 2.2. Диаграмма последовательностей AS-IS

Рисунок 2.3. Диаграмма последовательностей AS-TO-BE

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

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

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

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

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

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

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

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

Также необходимо разработать ряд дополнительных сервисов в рамках серверной части государственной автоматизированной системы правовой статистики, а именно: сервис авторизации (а также систему авторизации для всех сервисов), сервис экспорта и сервис ФЛК.

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

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

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

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

Сервис экспорта получает данные через сервис GraphQL

Сервис ФЛК не является специфическим и нужен только в рамках государственной автоматизированной системы правовой статистики. Этот сервис занимается сборкой JS скриптов для автоматизированных рабочих мест. Он должен с помощью данных с GraphQL сервиса собрать JS код на основе нескольких файлов из базы данных в один. При этом метод Main генерируется в зависимости от загруженных скриптов.

2.2 Используемые в решении методы и технологии

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

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

Для собирания скриптов была использована Node.js.

Для организации потока кода во время разработки использовался поток git. Рабочий процесс соответствует потребностям этого проекта, поскольку внутреннее приложение имеет две версии, называемые dev и stable, а git flow предполагает две основные ветви, называемые dev и master. Таким образом, ветвь dev соответствует версии dev бэкэнда, а ветвь master соответствует стабильной версии бэкенд. Более того, рабочий процесс позволяет исправлять мелкие ошибки без изменения кода и быстрого возврата к предыдущим версиям [6].

Обновление веток dev и master pass с помощью pull-запросов с использованием Team Foundation Server.

Версии автоматически обновляются вместе с Jenkins при завершении запроса на получение доступа к dev или master и прохождении всего теста.

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

GraphQL использовался как коммуникация между интерфейсом и интерфейсом API. Это решение позволяет избежать чрезмерной или недостаточной выборки без увеличения сложности API. Разработка схемы GraphQL основана на некоторых рекомендуемых принципах [5] и конкретных потребностях внешнего интерфейса. Также GraqhQL хорошо сочетается с языком C# и его фреймвоком .net Core [11].

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

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

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

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

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

Для организации кодовой базы были использованы принципы SOLID. Эти принципы созданы для повышения удобства сопровождения кодовой базы и уменьшения количества соединений кода [15, 9], что жизненно важно в большой команде программистов с меняющимся составом.

И большинство из этих систем организации работы подключены к сервису Team Foundation Microsoft. Кроме того, отслеживание следования сотрудниками принципов SOLID производится по запросу в сервисе Team Foundation.

2.3 Проектирование архитектуры системы

Архитектура системы выстроена вокруг одного большого сервиса, предоставляющего GraphQL API к данным. Все мутации данных принимаются этим сервисом, но отправляются на исполнение другому сервису, который занимается мутациями. Сервис мутаций закрытый и напрямую обращаться в него с клиентской стороны нельзя. В качестве базы данных используется 32-битный Oracle. Это связано исключительно с требованиями заказчика, на самом деле, с этой версией Oracle возникло множество проблем, т. к. она очень старая и плохо поддерживается. Вся коммуникация с базой данных из сервиса GraphQL и сервиса мутаций происходит через процедуры PL/SQL. С базой данных работают напрямую только эти два сервиса, остальные же сервисы взаимодействуют только с сервисом GraphQL. Таким образом, сервис экспорта получает запросы на экспорт от клиента, а данные получает через GraphQL от сервиса GraphQL, в то время как сервис FLC вызывается и клиентом, и сервисом GraphQL в некоторых частных случаях мутаций скриптов для автоматизированных рабочих мест.

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

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

Рисунок 2.4. Архитектура системы

2.4 Проектирование структуры приложения

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

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

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

Таким образом, упрощенная диаграмма классов проекта выглядит изображена на рисунке 2.5.

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

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

Рисунок 2.5. Упрощенная диаграмма классов

Глава 3. Реализация приложения

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

Также, особое внимание уделено процессу тестирования и развертывания. Эти процессы описываются совместно, т. к. они тесно связаны и процесс тестирования запускается вовремя развертывания, либо опирается на некоторые особенности развертывания.

3.1 Реализация основного приложения

Серверная часть приложения реализовывалась и продолжает реализовываться примерно в течение примерно половины года командой, которая состояла на протяжении этого времени в среднем из 5 программистов.

У основного приложения и окружающих сервисов есть некоторые общие части кода. Это реализовано с помощью системы сабмодулей git. Всего было создано три общих сабмодуля: core, interface и commonApplication. Модуль Core хранит в себе модель и взаимодействие с базой данных, модуль interface хранит в себе эту модель в виде интерфейсов с которыми можно оперировать (стоит отметить, что взаимодействие между классами происходит только на уровне интерфейсов, в том числе если это классы модели, это позволяет сделать систему более гибкой и подменять некоторые классы), а модуль commonApplication содержит в себе некоторый общий код программы, в частности различные middleware по обработке запросов, но о них будет рассказано немного позже.

3.1.1 Реализация модели

Как было показано на этапе проектирования, каждый элемент содержит список его полей вместе со ссылками на информацию об этих полях. Но понятно, что в таком виде работать с этими полями не удобно, а потому был создан интерфейс, возвращающий поле из списка по его названию или ключу. Также на уровне интерфейса элемента были отдельно вынесены стандартные или наиболее распространенные поля, такие как Key (ключ элемента может быть составным, но для оптимизации создания связей и поиска элементов была введена дополнительная индексация), Name, Version, дата начала действия, дата конца действия (если элемент версионный), ord (показывает порядок элемента в списке элементов, если пользователем не была включена другая сортировка), ordinalNumber (порядковый номер элемента в иерархии, элементы образуют вложенный нумерованный список на основе их иерархии и Ord), ParentKey, IsHasChilds, ChildsCount(для иерархических элементов) и т.д.

Далее был написан компонент, который взаимодействует с базой данных. Данные получаются путем вызова PL/SQL процедур и возвращаются в виде Oracle reader. Была написана некоторая абстракция вокруг прямого вызова процедур и считывания с ридера каждого элемента, это помогает проще использовать компоненту взаимодействия с базой данных для получения различных элементов, справочников, атрибутов и т. д. Эта абстракция принимает mapper, который ответственен за получение данных из reader, а также название запроса и входные параметры, а возвращает generic список ответов, либо сообщение о внутренней ошибке при выполнении oracle процедуры.

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

3.1.2 Схема обработки запросов

После этого, когда компоненты, связанные с получением данных, были готовы, была написана основная часть, связанная со схемой и резолверами. В схеме было создано два стандартных типа запроса: mutation и query. Внутри этих mutation и query получался список справочников и на их основе генерировались create, delete, update, modify и get операции. Каждая из этих операций выполняется внутри специального резолвера, который создается на основе описания справочника. Для получения данных резолверы используют ранее написанные компоненты, связанные с данными, а для мутаций вызывают некоторые конечные точки сервиса мутаций, передавая туда всю необходимую информацию, но о сервисе мутаций будет рассказано в следующем параграфе.

3.1.3 Упаковка данных

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

Сортировка осуществляется при помощи интерфейса IComparable, к которому приводятся поля всех возможных типов (большинство приведений автоматическое, но, например, для поля ordinalNumber, который имеет вид 1.1.1. и т. д. был написан свой компаратор, т. к. лексикографическая сортировка в данном случае не подходит. Далее элементы просто сравниваются с помощью функции Compare их полей. В ситуации, когда сортировка происходит по нескольким полям (в случае равенства), просто вызывается несколько стабильных сортировок в порядке их приоритета, заданного пользователем. Для этого был написан класс ChainComparer, который принимает на вход IEnumerable IComparer для generic элемента и вызывает их в том порядке, в котором они заданы на вход. При этом сам ChainComparer реализует интерфейс IComparer и может задаваться в другой объект.

Код компонента выглядит следующим образом:

public class ChainComparer<T> : IComparer<T>

{

private readonly IEnumerable<IComparer<T>> _comparers;

public ChainComparer(IEnumerable<IComparer<T>> comparers)

{

_comparers = comparers;

}

public int Compare(T x, T y)

{

foreach (var comparer in _comparers)

{

var res = comparer.Compare(x, y);

if (res != 0)

return res;

}

return 0;

}

}

Фильтрация осуществляется при помощи генерации и компиляции функции от элемента, возвращающей Boolean. В таком случае достаточно просто реализовать полноту Boolean логики (не, и, или). Для самих значений реализовано несколько условий, основанных на их типе. Таким образом для строковых типов имеются условия equal, contains, less, greater (лексикографически), notEqual, а также флаг ignoreCase, отвечающий за то, нужно ли учитывать регистр букв в строке и условии при фильтрации. Для остальных типов реализованы условия equal, less, greater и notEqual на основе их приведения к интерфейсу IComparable, вызову метода Compare и анализу результата.

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

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

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

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

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

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

Пример запроса к описанию справочников представлен на рисунке 3.1.

Но помимо CRUD - интерфейса к данным, иногда на сервере необходимо выполнять некоторые вычисления. Эти вычисления связаны с предметной областью и выделены в отдельные query или mutation. Например, у каждого отделения внутренних дел есть свой уникальный идентификатор, который необходимо посчитать на основе того округа, где он находится. На самом деле таких специфических query или mutations очень много, но они связаны с предметной областью государственной автоматизированной системы правовой статистики и в этой статье рассматриваться не будут, так как не имеют прямого отношения к API к данным с динамически изменяющейся структурой.

Рисунок 3.1. Запрос описания справочников

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

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

...

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

  • Обзор особенностей производственного процесса швейного предприятия: подготовки материала, пошива и упаковки. Реализация интерфейса доступа к данным с помощью технологии CSP. Создание модели данных в виде ER-диаграммы и выполнение ее нормализации до 3НФ.

    курсовая работа [4,2 M], добавлен 16.08.2012

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

    курсовая работа [129,5 K], добавлен 09.06.2017

  • Модели баз данных. Локальная, файл-серверная, клиент-серверная и распределенная архитектуры. Технология BDE для доступа к данным. Драйверы баз данных. Создание таблицы, интерфейс программы, дерево объектов, инсталлятор. Системы визуальной разработки.

    курсовая работа [989,5 K], добавлен 04.06.2013

  • Задачи системы SQL Server. Организация одновременного доступа к данным большого количества пользователей. Манипуляция информацией в базах данных (БД). Инфологическое, логическое и физическое проектирование БД. Разработка запросов, процедур, триггеров.

    курсовая работа [3,1 M], добавлен 11.05.2012

  • Принципы построения систем с переменной структурой для управления свободным движением линейных объектов с постоянными параметрами. Разработка модели системы с переменной структурой с применением инструментов Model Vision Studium и Simulink пакета MathLab.

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

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

    реферат [27,5 K], добавлен 10.01.2011

  • Средства и технологии разработки приложений баз данных. Компоненты управления доступом к БД. Описание программного окружения доступа к данным. Механизм получения и отправки данных. Специфика связи внутреннего представления с интерфейсом приложения.

    презентация [29,4 K], добавлен 19.08.2013

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

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

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

    лабораторная работа [25,1 K], добавлен 16.01.2015

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

    дипломная работа [1,0 M], добавлен 18.11.2017

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

    контрольная работа [21,5 K], добавлен 07.11.2013

  • Разработка программы, обеспечивающей ввод и редактирование информации (новостей) об объектах в соответствии с заданной предметной областью. ER-модель базы. Исходный код программы. Доступ к данным, осуществляемый с использованием средств JDBC или ODBC.

    лабораторная работа [624,1 K], добавлен 13.11.2014

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

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

  • Обзор существующих технологий широкополосного доступа (xDSL, PON, беспроводной доступ). Описание особенностей технологии PON. Проект по строительству сети абонентского доступа на технологии пассивной оптической сети. Схема распределительных участков.

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

  • Технологии доступа к СУБД. Управление источниками данных. Типовые параметры настройки драйвера. Способы создания таблиц. Запуск и содержание сценария (текстового файла с командами). Автоматизированные инструменты для управления структурой базы данных.

    презентация [18,8 K], добавлен 19.08.2013

  • Создание многоуровневого приложения с Web-интерфейсом выставления оценки фильму и просмотра оценок других пользователей. Клиентская часть приложения. Разработка многопользовательского веб-приложения на ASP.NET MVC 3 с разграничением доступа к данным.

    курсовая работа [949,7 K], добавлен 22.02.2015

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

    курсовая работа [2,2 M], добавлен 06.12.2013

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

    курсовая работа [6,2 M], добавлен 14.11.2011

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

    курсовая работа [45,1 K], добавлен 09.03.2009

  • Организационно-технические и режимные методы защиты информации. Средства обеспечения безопасности Windows. Интерфейс прикладного программирования. Программа администрирования "Net Programm Administrator". Расчет затрат на разработку программного продукта.

    дипломная работа [1,5 M], добавлен 11.11.2012

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