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

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

CC BY
701
104
i Надоели баннеры? Вы всегда можете отключить рекламу.
Ключевые слова
КОНЦЕПЦИЯ / СЛОЖНЫХ ИНФОРМАЦИОННЫХ СИСТЕМ АРХИТЕКТУРНАЯ СЛОЖНОСТЬ / ПЛАТФОРМА РАЗРАБОТКИ СИСТЕМ

Аннотация научной статьи по компьютерным и информационным наукам, автор научной работы — Аленичев Виктор Михайлович, Вольман Денис Владимирович

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

i Надоели баннеры? Вы всегда можете отключить рекламу.
iНе можете найти то, что вам нужно? Попробуйте сервис подбора литературы.
i Надоели баннеры? Вы всегда можете отключить рекламу.

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

© В.М. Аленичев, Д.В. Вольман, 2011

В.М. Аленичев, Д.В. Вольман

РАЗРАБОТКА КОНЦЕПТУАЛЬНЫХ ПРИНЦИПОВ И ПРОГРАММНОЙ ПЛАТФОРМЫ СОЗДАНИЯ СЛОЖНЫХ ИНФОРМАЦИОННЫХ СИСТЕМ

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

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

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

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

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

• Поддержка нескольких СУБД.

• Возможность одновременной работы большого числа пользователей.

• Разграничение прав доступа к информации и к элементам пользовательского интерфейса

• Аудит и мониторинг производительности.

• Сохранение работоспособности в случае отсутствия соединения с сервером.

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

• и т.д.

Архитектура информационных систем проектируется с учётом данных требований, только, если требования изначально определе-

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

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

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

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

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

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

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

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

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

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

2. Используя мощный подход Domain Driven Development (разработка, ориентированная на предметную область), бывает удобнее использовать двусторонние ассоциативные зависимости между программными сущностями (например, связь типа один ко многим между классом Подразделение и классом Сотрудник). Как

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

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

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

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

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

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

a. Концепция преодоления архитектурной сложности

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

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

2. Освободить от каких-либо инфраструктурных зависимостей модель предметной области или, как её часто называют, бизнес логика приложения. Все зависимости должны внедряться на этапе конфигурации приложения и применяться исключительно во время исполнения приложения, а не на этапе разработки. Инфраструктурные зависимости делятся на два вида. Во-первых, это зависимости между сервисами. Данные зависимости должны основываться не на реализации, а на абстракции. Принцип Dependency Injection (внедрения зависимостей) декларирует способы внедрения подобного рода зависимостей. Во-вторых, это интерфейсные зависимости, которые необходимы для обеспечения функционирования внешних инфраструктурных компонентов в условиях строгой типизации. Такие зависимости, как правило, внедряются в объекты -сущности. Возможность внедрения интерфейса на этапе конфигурации, а не декларации типа может быть реализована, если отказаться от прямого использования конструкторов объектов. Взамен, можно организовать внешние фабрики объектов, воспользовавшись библиотеками генерации proxy классов во время исполнения

или средствами автоматической кодогенерации, ориентированной на конфигурацию.

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

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

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

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

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

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

7. Спроектировать библиотеку классов, которая бы являлась стандартной интерфейсной прослойкой для взаимодействия с необходимыми внешними программными компонентами (например, объектно-реляционным преобразователем ORM, контейнером инверсии управления Inversion of Control, инфраструктурными библиотеками проверки правил валидации и проверки прав доступа к данным и функциям системы).

Платформаразработки сложных информационных систем

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

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

В настоящий момент создан прототип платформы разработки в виде набора библиотек и программных компонентов. Данный прототип был сконструирован на базе платформы Microsoft .NET Framework на языке C#.

Основные возможности библиотеки:

- Инфраструктура декларации “функциональных действий”, правил проверки прав доступа к ним и правил валидации аргументов.

- Возможность декларации сущностей предметной области и каркасов пользовательского интерфейса в виде интерфейсов;

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

- Стандартная инфраструктура взаимодействия с подсистемой хранения данных, которая может настраиваться на различную архитектуру программного приложения простой заменой одного компонента на другой. Т.е. с помощью такой замены можно перейти от клиент-серверной архитектуре к многослойной архитектуре. А так же можно заменить подсистему хранения, основанной на базе данных, на взаимодействие с Web сервисом или тестовой моделью хранения в оперативной памяти компьютера. В качестве стандартной реализации данной инфраструктуры используется ORM NHibernate. Однако все метаданные, необходимые для отображения программных объектов в модель хранения настраиваются с помощью классов - соглашений. Это означает, что по-умолчанию разработчику достаточно указать строку

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

- Инфраструктура для организации каркасов пользовательского интерфейса и контроллеров каркасов.

- Реализован набор стандартных аспектов и “пересечений”, которые можно повторно использовать при проектировании различных приложений.

На основе данной платформы успешно ведётся разработка нескольких корпоративных информационных систем. Уже сейчас можно уверенно утверждать о значительном снижении трудозатрат на разработку приложения (до 50%). Применение вышеуказанных принципов позволяет масштабировать процесс разработки, позволяя декомпозировать систему на очень небольшие, логически независимые функциональные блоки, за реализацию которых могут отвечать разные сотрудники. Конечным результатом разработки данной платформы планируется публикация её исходных кодов на сайте www.codeplex.com, где располагаются проекты с открытым исходным кодом, написанные под платформу Microsoft .NET Framework, что сделает её доступной для сообщества разработчиков. 1КШ

КОРОТКО ОБ АВТОРАХ -------------------------------------------------------------

Аленичев Виктор Михайлович - доктор технических наук, профессор, главный научный сотрудник ИГД УрО РАН; direct@igd.uran.ru Вольман Денис Владимирович - инженер НПО «Новатор».

i Надоели баннеры? Вы всегда можете отключить рекламу.