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

Читать, слущать книги онлайн бесплатно!

Электронная Литература.

Бесплатная онлайн библиотека.

Читать: Дефрагментация мозга. Софтостроение изнутри - Сергей Тарасов на бесплатной онлайн библиотеке Э-Лит


Помоги проекту - поделись книгой:

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

Под эти требования за 10 лет было написано великое множество приложений. А когда пришла пора обновлять браузеры, внезапно выяснилось, что их новые версии далеко не всегда совместимы с находящимися в эксплуатации системами. И по этой причине простое обновление Internet Explorer 6 на 7 вызовет паралич информационных систем предприятия.

Достаточно свежий пример. В одной крупной конторе (более 10 тысяч сотрудников) система учёта рабочего времени из Internet Explorer 7, 8 или 9 на основной странице ввода зацикливалась, эмулируя скриптами щелчки мыши и подвешивая браузер. В Firefox 3 зацикливания не происходило, но не работали всплывающие окна. В более поздних версиях Firefox система не работала совсем, выдавая « browser is not supported ». В Chrome корректно работала предварительная версия, но сданная в эксплуатацию почему-то лишилась этого качества с выдачей сообщения о несовместимости: « The iView is not compatible with your browser, operating system, or device ».

Итого в 2011 году приложение по-прежнему стабильно работало только в Internet Explorer 6 , выпущенном в 2001 году, то есть 10 лет назад.

За эти же 10 лет прошло огромное количество презентаций о том, что инвестиции сделаны не зря, о том, как замечательно работают веб-приложения в интранете и корпоративной среде в целом. На деле же оказалось, что, собрав свои приложения на базе веб-технологии, корпорация оказалась заложником версии и марки конкретного браузера. Даже переход с Internet Explorer 6 на 7, не говоря уже о Firefox или Chrome, оказался катастрофой масштаба предприятия с долгими месяцами миграции и последующей стабилизации. Разумеется, если есть кому стабилизировать, ведь за 5–10 лет сменяются разработчики, уходят с рынка прежние поставщики. Для таких случаев приложение остаётся жить на виртуальной машине под старой версией операционной системы и проводника.

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

Менеджеры другой фирмы стали искать решение проблемы у Google, отдав ему на откуп корпоративный документооборот, групповую работу и почту. Новое обоснование выглядело так: «Уж Google-то обеспечит совместимость приложений со своим браузером!» Не знаю, слышали ли поверившие в такой довод хоть что-нибудь об открытых системах и о печально завершившейся истории с IBM, продававшей свои большие ЭВМ вместе со своим же, привязанным к ним программным обеспечением. Человеческая история имеет свойство повторяться.

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

Факт наличия у большинства корпоративных клиентов только Internet Explorer версии 6 в качестве стандарта не раз оборачивался казусами. Так, обновление нашего внутреннего сервера Microsoft Exchange привело к тому, что веб-почта в Internet Explorer 6 стала работать со множеством ограничений, например, отсутствует разметка текста, нет проверки орфографии, не показывается дерево папок. Чтобы отправить почту, пришлось соединяться с сервером (!), где изначально стоял Internet Explorer 7, и работать оттуда через терминал.

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

Апплеты, Flash и Silverlight

Появившись в 1995 году, технология Java сразу пошла на штурм рабочих мест и персональных компьютеров пользователей в локальных и глобальных сетях. Наступление проводилось в двух направлениях: полноценные «настольные» ( desktop ) приложения и так называемые апплеты [24] , то есть приложения, имеющие ограничения среды исполнения типа «песочница» ( sandbox ). Например, апплет не мог обращаться к дискам компьютера.

Несмотря на значительные маркетинговые усилия корпорации Sun, результаты к концу 1990-х годов оказались неутешительны: на основной платформе пользователей – персональных компьютерах – среда исполнения Java была редким гостем, сами приложения можно было сосчитать по пальцам одной руки (навскидку вспоминается только Star Office), веб-сайтов, поддерживавших апплеты, было исчезающе мало, а настойчивые просьбы с их страниц скачать и установить 20 мегабайтов исполняемого кода для просмотра информации выглядели издевательством при существовавших тогда скоростях и ограничениях трафика. Несомненно, судебная тяжба Sun в 1997 году с Microsoft, тут же прекратившей распространение Java вместе с Windows, также сыграла свою роль. Но основными объективными причинами такого исхода были:

• универсальность и кроссплатформенность среды, обернувшаяся низким быстродействием и невыразительными средствами отображения под вполне конкретной и основной для пользователя операционной системой Windows;

• необходимость установки и обновления среды времени исполнения (Java runtime).

В 2007 году Sun утверждала, что среда исполнения Java установлена на 700 миллионах персональных компьютеров [25] , правда не уточнялась её версия. В декабре 2011 года уже новый владелец – корпорация Oracle – привёл данные о том, что Java установлена на 850 миллионах персональных компьютеров и миллиардах устройств в мире [26] . Но поезд ушёл, развитие приложений на десктопах сместилось далеко в сторону по пути начинённых скриптами веб-браузеров, а рост количества мобильных устройств положил конец монополии «персоналок» в роли основного пользовательского терминала.

Тем не менее необходимость в кросс-платформенных богатых интерактивными возможностями интернет-приложениях [27] никуда не исчезла, поскольку браузеры, нашпигованные скриптовой начинкой, обладали ещё большими техническими ограничениями и низким быстродействием даже по сравнению с апплетами. Эта ниша к началу 2000-х годов оказалась плотно занятой Flash-приложениями, специализирующимися на отображении мультимедийного содержания. Учтя ошибки Java, разработчики из Macromedia сделали инсталляцию среды исполнения максимально лёгкой в загрузке и простой в установке.

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

К решению проблемы подключилась Microsoft. Первым «блином» в 2005 году стала технология ClickOnce развёртывания полноценных WinForms-приложений. По-прежнему клиентское рабочее место требовало предварительно установки среды исполнения. NET версии 2. Но развёртывание и автоматическое обновление приложения и его компонентов было полностью автоматизировано. Первоначально пользователь, не имеющий прав локального администратора, устанавливал необходимую программу, просто щёлкнув по ссылке в браузере, далее запуская её с рабочего стола или из меню. Sun отреагировала молниеносно, добавив аналогичную возможность под названием Java Web Start.

Но «блин» всё-таки вышел комом. По данным AssetMetrix [28] , основной парк корпоративных компьютеров в 2005 году составляли «персоналки» под управлением Windows 2000 (48 %) и Windows XP (38 %). Имея полную возможность предустановить среду. NET 2 на все эти рабочие места вместе с очередным пакетом обновлений, Microsoft не решилась на такой шаг, тем самым фактически похоронив массовое использование новой технологии разработчиками, имевшими неосторожность надеяться на помощь корпорации в развёртывании тяжёлых клиентских приложений.

Возможно, одной из причин стала потеря интереса Microsoft к WinForms, чьё развитие было заморожено, и переход в. NET 3 к более общей технологии построения пользовательских интерфейсов WPF [29] , отличающейся универсальностью и большей трудоёмкостью в прикладной разработке, но позволяющей полностью разделить труд программистов и дизайнеров, что имело смысл в достаточно больших и специализированных проектах. Вот вам очередная иллюстрация к теме прогресса в производительности разработки.

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

В отличие от WPF, Silverlight вызвал больший энтузиазм разработчиков корпоративных приложений. Во-первых, для развёртывания не требовалась вся среда. NET целиком, достаточно было установить её часть, размер дистрибутива которой составлял всего порядка 5 мегабайтов. Поэтому на очередные обещания Microsoft предустановить. NET 3 можно было не полагаться, тем более при уже анонсированном. NET 3.5. Во-вторых, приложение можно было запускать не только в окне браузера, но и автономно.

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

Прежде всего насторожили меня новости про отсутствие в Silverlight отличных от юникода [30] кодировок. Их нет в константах, а Encoding.GetEncoding (1251) выдаёт ошибку. Как корректно импортировать в приложение ASCII [31] -файл? Никак. Из этого вытекала невозможность полноценной работы приложения с обыкновенным текстовым файлом данных, вроде CSV ( comma separated values ).

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

И тут в корпорации, аккурат к октябрьской конференции разработчиков 2010 года, издали новый декрет: «Наша стратегия по Silverlight изменилась» [32] . Сессий по новой версии Silverlight 5 на мероприятии не было вовсе. Снова часы пробили полночь, и карета превратилась в тыкву. Приоритетом стал HTML 5.

Silverlight вырос до вполне взрослой версии 4, уже давно вышла Visual Studio 2010, где встроена поддержка разработки приложений под него. Но зададимся вопросом: «Может ли пользователь установить себе Silverlight-приложение, не будучи администратором на своем компьютере?» Ответ, мягко говоря, разочаровывающий: «Нет, не может».

Это значит, что развёртывать Silverlight-песочницы на машинах пользователей должны сами компании через своих специалистов, ответственных за инфраструктуру. Хотя в соответствующем официальном документе описано много способов облегчения администраторской деятельности, факт остаётся фактом: технология в своей 4-й (!) версии не может быть использована в корпоративной среде без серьёзных накладных расходов.

Итак, итог к 2012 году. Во-первых, «старые» технологии вроде автономного оконного кроссплатформенного приложения на Lazarus/FreePascal, Delphi XE или Qt/C++ по-прежнему позволяют сделать то, что нельзя сделать «новыми и прогрессивными». Во-вторых, ценность Silverlight по сравнению с полноценным. NET на уровне развёртывания практически нулевая. Видимо, по этой причине Microsoft недавно закрыла веб-сайт silverlight.net, в очередной раз оставив разработчиков в интересном положении.

Из продвигаемых Microsoft за последние 10 лет технологий для разработки полноценных пользовательских интерфейсов, не заброшенных на пыльный чердак, остался только WPF, имеющий весьма сомнительную ценность для небольших коллективов и отдельных разработчиков. WPF – это ниша крупных автономных Windows-приложений. Кроме того, сама по себе она невелика, в ней уже есть WinForms – более простой и быстрый в разработке фреймворк, к тому же переносимый под Linux/Mono. Поэтому при соответствующих ограничениях развёртывания выбор по-прежнему лежит между веб-браузером или условным Delphi, хочешь ты этого или нет…

ООП – неизменно стабильный результат

Говоря об объектно-ориентированном подходе и программировании, принято добрым словом вспоминать начало 1970-х годов и язык Smalltalk, скромно умалчивая, что понадобилось ещё почти 15 лет до начала массового применения технологии в отрасли, прежде всего, за счёт появления C++ и позднее – Объектного Паскаля. Потому что фактическим отраслевым стандартом был язык C, а Паскаль широко использовался для обучения и в основном для прикладного программирования, если не рассматривать исключения вроде первой версии Microsoft Windows. Религиозные войны 1970–80-х годов в новостных группах проходили под лозунгом «Си против Паскаля». По этой причине революционный переход сообществ на Smalltalk выглядел маловероятным, тогда как объектно-ориентированные расширения вышеупомянутых языков были восприняты положительно. Немудрено, что многие концепции Smalltalk были в них реализованы.

В начале широкой популяризации ООП, происходившей в основном за счёт языка C++, одним из главных доводов был следующий: «ООП позволяет увеличить количество кода, которое может написать и сопровождать один среднестатистический программист». Приводились даже цифры, что-то около 15 тысяч строк в процедурно-модульном стиле [33] и порядка 25 тысяч строк на C++.

Довод в целом правильный, хотя из него совсем не следовало, что десяти программистам на C++ будет легче сопровождать общую систему, чем десяти программистам на C. Про это как-то забыли, потому что существовало много автономных проектов, управляемых процессом типа бруксовской операционной бригады [34] с главным программистом, отвечающим за всё решение. Собственно, и Бьёрн Страуструп, создатель C++, прежде всего преследовал цели увеличения производительности своего программистского труда.

Как только «главным программистом» стал «коллективный разум» муравейника, неважно мечущийся ли на планёрках «гибкой» ( agile ) разработки, прозаседавшийся ли на совещаниях по тяжёлой поступи RUP [35] , проблема мгновенно всплыла, порождая Ад Паттернов [36] , Чистилище нескончаемого рефакторинга [37] и модульных тестов, недосягаемый Рай генерации по моделям кода безлюдного Ада.

Термин «Ад Паттернов» может показаться вам незнакомым, поэтому я расшифрую подробнее это широко распространившееся явление:

• слепое и зачастую вынужденное следование шаблонным решениям;

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

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

• лоскутная [38] интеграция существующих систем и создание поверх них новых слоёв API [39] .

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

Services.Oragnization.ContainerProvider.ProviderInventory.InventorySectorPrivate. Stacks[0].Code.Equals("S01")

Последствия от создания Ада Паттернов ужасны не столько невозможностью быстро разобраться в чужом коде, сколько наличием многих неявных зависимостей. Например, в рамках относительно автономного проекта мне пришлось интегрироваться с общим для нескольких групп фреймворком ради вызова единственной функции авторизации пользователя: передаёшь ей имя и пароль, в ответ «да/нет». Этот вызов повлёк за собой необходимость явного включения в. NET-приложение пяти сборок. После компиляции эти пять сборок притащили за собой ещё более 30, б€ольшая часть из которых обладала совершенно не относящимися к безопасности названиями, вроде XsltTransform. В результате объём дистрибутива для развёртывания вырос ещё на сотню мегабайтов и почти на 40 файлов. Вот тебе и вызвал функцию…

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

Несомненно, C++ является мощным инструментом программиста, хотя и с достаточно высоким порогом входа, предоставляющим практически неограниченные возможности профессионалам с потребностью технического творчества. Я видел немалое количество примеров изящных фреймворков и прочих «башен из слоновой кости», выполненных одиночками или небольшим коллективом. Но крупные проекты подвержены влиянию уже упоминавшейся гауссианы (см. рис. 1). Нормальное распределение вовлекает в процесс большое количество крепких профессионалов-середняков, которым надо сделать «чтобы работало» с наименьшими телодвижениями во время нормированного рабочего дня. Если Microsoft или Lockheed Martin – подрядчик Министерства Обороны США, имеют возможность растянуть кривую на графике вправо и вложить немалые

средства во внутреннюю стандартизацию кодирования, то в обычной ситуации оказывается, что C++, действительно увеличивавший личную продуктивность Страуструпа и его коллег, начинает тормозить производительность большого софтостроительного цеха где-нибудь в жарком субтропическом опенспейсе [40] площадью в гектар. Помимо общих проблем интеграции, на C++ достаточно просто «выстрелить себе в ногу», и человеческий фактор быстро становится ключевым риском проекта.

Если вернуться к вопросу стандартов кодирования на C++, хорошим примером будет разработка программной начинки нового истребителя F-35 [15]. Объем разработанного кода порядка 10 миллионов строк, это даже больше, чем Windows. Следовательно, стандарт вполне пригоден к практическому использованию. Но имеются ли у вас в проекте ресурсы для того, чтобы не только обучить всех программистов 150-страничному своду правил, но и постоянно контролировать его исполнение?

Поэтому появились новые C-подобные языки: сначала Java, а чуть позже и C#. Они резко снизили порог входа за счёт увеличения безопасности программирования, ранее связанной прежде всего с ручным управлением памятью. Среды времени исполнения Java и. NET решили проблему двоичной совместимости и повторного использования компонентов системы, написанных на разных языках для различных аппаратных платформ.

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

Примерно в то же время в сообществе начались дискуссии, появились первые публикации вроде уже ставшей классической «Почему объектно-ориентированное программирование провалилось?» [41] . Эксперты по ООП в своих книгах стали нехотя писать о том, что технология тем эффективнее, чем более идеален моделируемый ею мир.

Рис. 3. Эмпирическое сравнение производительности процедурно-реляционного и объектно-ориентированного подходов в зависимости от достигнутой степени формализации моделируемого мира

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

Учебники по ООП полны примеров, как легко и красиво решается задачка отображения геометрических фигур на холсте с одним абстрактным предком и виртуальной функцией показа. Но стоит применить такой подход к объектам реального мира, как возникнет необходимость во множественном наследовании от сотни разношёрстных абстрактных заготовок. Объект «книга» в приложении для библиотеки должен обладать свойствами «абстрактного печатного издания», в магазине – «абстрактного товара», в музее – «абстрактного экспоната», в редакции, типографии, в службе доставки… Можете продолжить сами.

Попытки выпутаться из этой ситуации за счёт агрегации приводят к новым дивным мирам, существующим только в воображении разработчиков. Теперь объект «книга» это контейнер для чего-то продающегося, выдаваемого, хранящегося и пылящегося. Необходимо быстро менять контекст: в магазине вкладывать в книгу товар, в библиотеке – печатное издание, в отделе «книга-почтой» – ещё какую-нибудь хреновину. Плодятся новые многоуровневые иерархии, но теперь уже не наследования ( is a ), а вложения ( is a part of ).

Изящнее выглядят интерфейсы. Но если в реальном мире книга, она и в музее – книга, то во вселенной интерфейсов «книга в музее» – неопознанный объект, пока не реализован соответствующий интерфейс «экспонат». Дальше интерфейсы пересекаются, обобщаются, и мы получаем ту же самую иерархию наследования, от которой сбежали. Но теперь это уже иерархия, во-первых, множественная, а во-вторых, состоящая из абстрактных классов без какой-либо реализации вообще (интерфейс, по сути, есть pure abstract class ). Если же мы отказываемся от обобщения интерфейсов, то фактически оказываемся в рамках современных реализаций модульного программирования типа Оберон [42] .

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

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

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

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

Результат неизменно стабильный…

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

Александр Сергеевич Пушкин использовал в своем творчестве порядка 24 тысяч слов. Толковый словарь Ожегова содержит около 70 тысяч слов. Среднестатистический русский человек использует в повседневной жизни от 5 до 10 тысяч слов [43] , из них только 3 тысячи являются общеупотребительными. Получается, что даже наследник гения Пушкина способен охватить менее половины предлагаемой технологии, при том что её словарь сравним с естественным языком!

Надо признать, входной порог использования ООП оказался гораздо выше, чем предполагалось в 1980–90-х гг. С учётом девальвации среднего уровня знаний «прогрессивных технологий», меняющихся по законам бизнеса ква-зимонополий, и прибывающих выпускников трёхмесячных курсов этот порог ещё и растёт с каждым годом.

Практика подтвердила, что технология, будучи обёрнутой в относительно безопасные языковые средства и жёсткие стандарты, допускает применение в больших проектах. С другой стороны, немалое число крупных проектов принципиально не используют ООП, например, ядро операционной системы Linux, Windows API или движок Zend уже упоминавшегося PHP. Язык C по-прежнему занимает первое место согласно статистике активности сообществ программистов [44] , стабильно опережая второго лидера Java – например, индексы ноября 2012 показывают 19 % против 17 %.

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

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

ORM, или объектно-реляционный проектор

Сокрытие базы данных, или Как скрестить ежа с ужом

Упомянув один из крупнейших столпов современного софтостроения – мир ООП, нельзя обойти вниманием и другой – мир реляционных баз данных. Я намеренно вставил прилагательное «реляционные» применительно ко всем основным СУБД [45] , хотя ещё в 1970-х годах такое обобщение было бы неправомерным.

Тем не менее именно реляционным СУБД удалось в 1980-х годах освободить программистов от знания ненужных деталей организации физического хранения данных, отгородиться от них структурами логического уровня и стандартизованным языком SQL [46] для доступа к информации. Также оказалось, что большинство форматов данных, которыми оперируют программы, хорошо ложатся на модель двумерных таблиц и связей между ними. Эти два фактора предопределили успех реляционных СУБД, а в качестве поощрительной премии сообщество получило строгую математическую теорию в основании технологии.

В отличие от реляционного мира, ООП развивалось инженерами-практиками достаточно стихийно, исходя из потребностей программистского сообщества, и потому никакой строгой теории под собой не имело. Имевшие место попытки подвести таковую под ООП задним числом терпели неудачу. Наилучшего результата добились авторы объявленного стандартом UML [47] , который, однако, в основном до сих пор используется в качестве иллюстрирующих код картинок. Но лучше плохой стандарт, чем никакой.

И реляционная и объектная модели относятся к логическому уровню [48] проектирования программной системы. Они ортогональны и по сути представляют собой два взгляда на одну и ту же сущность. Это значит, что вы можете реализовать одну и ту же систему, оставаясь в рамках только одного реляционно-процедурного подхода или же следуя исключительно ООП.

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

Ввиду упомянутого отсутствия под ООП формальной теоретической базы эта задача, в общем случае нерешаемая, выполнима в случаях частных. Компонент программной системы, реализующий отображение, называется ORM [49] , или объектно-реляционный проектор – ОРП. Полноценный ORM может быть весьма нетривиальным компонентом, по сложности превосходящим остальную систему. Поэтому, хотя многие разработчики с успехом пользуются своими собственными частными реализациями, в отрасли за последние 10 лет появилось несколько широко используемых фреймворков, выполняющих в том числе и задачу проекции.

Обзор средств объектно-реляционной проекции выходит за рамки данной книги. Их и так достаточно в Сети, включая небольшой мой собственный [8], сделанный ещё в 2005 году, но не сильно устаревший. Поэтому последующие примеры будут в основном касаться фреймворка NHibernate.

В технологии отображения объектов на РСУБД есть очень важный момент, от понимания которого во многом зависит успех вашего проекта. Я не раз слышал мнение программистов, что для слоя домена [50] генерируемый проектором SQL код является аналогом результата трансляции языка высокого уровня в ассемблер целевого процессора. Это мнение не просто глубоко ошибочно, оно быстрыми темпами ведёт команду к созданию трудносопровождаемых систем с врождёнными и практически неисправимыми проблемами производительности.

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

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

Такая ситуация приводит разработчиков ORM к необходимости создавать собственный SQL-подобный язык для манипуляции объектами и уже его транслировать в сиквел [51] (см. HQL [52] ). Или использовать непосредственно SQL с динамическим преобразованием результата в коллекцию объектов.

В противном случае прикладной программист обречён на извлечение из БД и последующую обработку больших массивов данных непосредственно в своём приложении. Примерно так же обрабатывали табличные данные при отсутствии встроенного SQL разработчики на ранних версиях Clipper в конце 80-х годов. Там это называлось «навигационная обработка». Думаю, термин уместен и здесь.

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

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

Почему? Недостаток знаний РСУБД пытаются возместить дополнительными уровнями абстракций. На деле же выходит обратное: уровни абстракции скрывают не детали слоя хранения объектов от программиста, а, наоборот, его некомпетентность в области баз данных от СУБД. До некоторого времени.

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

Но попытки продолжаются. Одни по-прежнему разрабатывают проекторы для своих внутренних нужд, зачастую очень лёгкие. Другие ищут упрощение и выход в noSQL [53] . Но в выигрыше пока остаются программисты и консультанты, обладающие «базоданными» компетенциями и зарабатывающие на тех, кто ими не обладает.

Как обычно используют ORM

На софтостроительных презентациях часто рисуют красивые схемы по разделению слоёв представления, бизнес-логики и хранимых данных. Голубая мечта начинающего программиста – использовать только одну среду и язык для разработки всех слоёв и забыть про необходимость знаний реляционных СУБД, сведя их назначение к некоей «интеллектуальной файловой системе». Аббревиатура SQL вызывает негативные ассоциации, связанные с чем-то древним, не говоря уже про триггеры или хранимые процедуры. На горизонте появляются добрые люди, с книгами признанных гуру о домен-ориентированной разработке [54] под мышкой, заявляющие новичкам примерно следующее: «Ребята, реляционные СУБД – пережиток затянувшейся эпохи 30-летней давности. Сейчас всё строится на ООП. И есть чудесная штука – ORM. Начните использовать её и забудьте про тяжёлое наследие прошлого!»

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

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

• Начинаем реализовывать модель предметной области. Добавляем классы, свойства, связи. Генерируем структуру базы данных или подключаемся к существующей. Строим интерфейс управления объектами типа CRUD [55] . Все достаточно просто и на первый взгляд кажется вполне сравнимым с манипуляциями над DataSet [56] – тем, кто о них знает, конечно – ведь не все подозревают о существовании табличных форм жизни данных в приложении за пределами сеток отображения DBGrid.

Как только разработчики реализовали CRUD-логику, начинается основное действо. Использовать сиквел напрямую теперь затруднительно. Если не касаться стратегий отображения и проблем переносимости приложения между СУБД, по сути каждый SQL-запрос с соединениями, поднявшись в домен, сопровождается специфической проекцией табличного результата на созданный по этому случаю класс. По этой причине приходится использовать собственный язык запросов ORM. Нестандартный, без средств отладки и профилирования. Если он, язык, вообще имеется в данном ORM. Для поддерживающих соответствующую интеграцию среда. NET предоставляет возможность использовать LINQ [57] , позволяющий отловить некоторые ошибки на стадии компиляции. Сравните выразительность языка на простом примере, который я оставлю без комментариев:

SQL

SELECT *

FROM task_queue

WHERE

id_task IN (2, 3, 15)

AND id_task_origin = 10

NHibernate HQL

IList<TaskQueue> queues = session

CreateQuery("from TaskQueue where Task.Id in (2, 3, 15) and TaskOrigin.Id = 10")

List<TaskQueue>();

NHibernate без HQL с критериями

IList<TaskQueue> queues = session.CreateCriteria()

Add(Expression.In("Task.Id", someTasks.ToArray()))

Add(Expression.Eq("TaskOrigin.Id", 10))

List<TaskQueue>();

LINQ (NHibernate)

IList<TaskQueue> queues = session

Query<TaskQueue>()

Where(q => someTasks.Contains(q.Task.Id) &&

q. TaskOrigin.Id == 10).ToList();

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

Однако запросы типа «выбрать сотрудников, зарплата которых в течение последнего года не превышала среднюю за предыдущий год» уже вызывают проблемы на уровне встроенного языка. Тогда разработчики идут единственно возможным путём: выбираем коллекцию объектов и в циклах фильтруем и обсчитываем, вызывая методы связанных объектов. Или используем тот же LINQ над выбранным массивом. Количество промежуточных коротких SQL-запросов к СУБД при такой обработке коллекций может исчисляться десятками тысяч.

Триггер как идеальная концепция для NHibernate

Обычно разработчикам баз данных я рекомендую избегать необоснованного использования триггеров. Потому что их сложнее программировать и отлаживать. Оставаясь скрытыми в потоке управления, они напрямую влияют на производительность и могут давать неожиданные побочные эффекты. Пользуйтесь декларативной ссылочной целостностью (DRI [58] ) и хранимыми процедурами, пока возможно. А если ваш администратор баз данных склонен к параноидальным практикам «запрещено всё, что не разрешено», избегайте программировать на уровне СУБД, исключая критичные по производительности участки. Приходится говорить это с сожалением…

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

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

Во-вторых, после осознания авторами недостаточности IValidate и ILifeCycle была введена система прерываний ( interceptors ). Это уже больше, чем бесплатный хлеб на завтрак. Однако в обработчиках типа Save или FlushDirty в качестве аргументов используются массивы состояний объекта. То есть изменять сам объект в них напрямую нельзя: в общем случае это просто не срабатывает, но могут быть и побочные эффекты. Нужно, ни много ни мало, поискать индекс элемента в массиве имён свойств объекта, затем по найденному номеру изменить значение в другом массиве текущего состояния объекта. Что-то вроде такого кода:

Изменение свойств объекта в обработчике NHibernate

int index = Array. IndexOf (propertyNames, "PhoneNumber");

if (index!= - 1 )

state[index] = "(123)456789";

Создавать новые, извлекать, изменять или удалять существующие объекты с последующим сохранением внутри обработчика совершенно не рекомендуется. Кроме собственно гонок ( race condition ), когда обработчик одного класса создаёт другой, а тот что-то делает с первым, могут быть и другие эффекты, включая бесконечную рекурсию. Шаг вправо, шаг влево – стреляют боевыми и без предупреждения. Неплохая иллюстрация к теме декларируемой безопасности языка C# или Java. Рекомендуемая практика обхода ловушек такого рода – запрограммировать собственную защищённую ( thread safe ) очередь, куда складывать все созданные или изменённые объекты, а в событиях BeforeCommit или AfterCommit эту очередь обрабатывать.

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

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

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

С точки зрения архитектуры это несомненный плюс, реализацию можно разбить на независимые классы. Однако для снижения побочных эффектов, прежде всего рекурсии и гонок, не сделано ничего. В том же SQL Server, напомню, рекурсия в триггерах отключена по умолчанию, поскольку трудно сходу придумать случай, когда она нужна. А в событиях NHibernate каждый сам себе вредитель. При этом однозначной методики и документации нет, нескольким десяткам типов событий в официальной документации отведено меньше страницы. Существует огромное количество записей в блогах, тиражирующих одни и те же конкретные примеры – аудит, прежде всего. Но однозначной выверенной практики нет, в каждом конкретном случае надо проводить тесты. Например, для манипуляции объектами рекомендуется создавать дочернюю сессию, что также не всегда избавляет от побочных эффектов.

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

ORM на софтостроительной площадке

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

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

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

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

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

Вы резонно спросите: «А где рефакторинг?» Системе на тот момент исполнилось уже 2 года. Рефакторинг проводился раньше, но, в связи с тем, что его стоимость, прежде всего по требуемым срокам поставки, возрастала, количество реструктурируемого кода линейно уменьшалось. Это создало положительную обратную связь: реструктуризация становилась всё дороже.

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

Приведу пример подсистемы, для которой рефакторинг уже стал дороже полной переделки. Имелся модуль экспорта документов в форматы, пригодные для импорта системами клиентов уровня их внутренних АСУП [60] . Коллективная ответственность привела к выбору написания императивного кода в размере 20 тысяч строк вместо разработки нескольких шаблонов XSLT [61] из нескольких сотен строк. Почему? Во-первых, опасались потери производительности, а во-вторых, не имели достаточной компетенции в XSL. Цикломатическая сложность [62] кода в отдельных методах превышала запредельное число 50 при рекомендованном пороге в 10–20. Глубина вложенности вызовов также была больше 10, при цикличности их части: this с верхнего уровня передаётся в качестве параметра, и где-то глубоко внизу дёргают этот this за какой-то метод. Объектно-ориентированная тарелка со спагетти.

О производительности следует сказать отдельно. Загрузка достаточно сложного документа перед его экспортом занимала порядка 30 секунд. Потому что было принято идеологическое решение «ни строчки SQL», несмотря на необходимость поддержи только одной РСУБД. Вся система работала через слой доступа [63] под управлением NHibernate. Это был именно DAL, а не домен, так как парни не использовали всю мощь NHibernate, ограничиваясь отображением, и накручивали сверху слои бизнес-логики. При загрузке сложного документа с проверками подсистемы безопасности было насчитано порядка 20 тысяч (!) коротких SQL-запросов.

Почему именно такое решение? Было сказано некоторое количество красивых слов о чистоте объектной концепции. Это стандартный ответ. Тогда я просто предложил использовать в одном узком месте вместо сотен строк вложенных циклов сишарп-кода относительно короткий рекурсивный запрос из 40 строк сиквел-кода. Вид этого кода вначале вызвал у парней лёгкий ступор, а после совещания через сутки было принято решение отказаться от него. Но надо отдать должное: ребята честно признались, что после моего ухода никто не сможет этот сиквел-код поддерживать и модифицировать. Вот, собственно, и главная причина первоначального выбора. Красноречивое подтверждение тезиса о том, что слой объектной абстракции доступа к реляционной СУБД в большинстве случаев скрывает не базу данных от приложения, а некомпетентность разработчиков приложения в области баз данных.

Долго и неинтересно рассказывать, каким образом система с тремя сотнями таблиц умудрилась обрасти миллионом строк C#-кода, для поддержки которого требуются всё новые разработчики. Клиенты проявляли недовольство, так как сроки срывались, а задержка медленно, но неуклонно росла. Два совещания, на которых генеральный директор, милейший мсьё, пытался реанимировать дух прежнего стартапа [64] , искренне желая, чтобы все, от стажера до его ближайших замов, смело поднимали и доносили проблемы, по всей видимости, прошли впустую. Состояние постоянного стресса передалось даже мне, формально не несущему ответственности за результат. Но ведь ещё есть риски социального капитала, репутации, которая долго зарабатывается и очень быстро может обесцениться. Пришлось даже посидеть с мыслями об оптимальных путях выхода из миссии [65] за бокалом бургундского.

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

Эмпирика

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

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

• Соотношение 1 к 1–2 примерно соответствует тому порогу, за которым начинается так называемый «плохой код».

• 1 к 3–4 – следует серьёзно заняться изучением вопроса переделки частей системы.

• 1 к 5 и более – надеемся, что случай нестандартный (сложные алгоритмы, распределенные вычисления, базовые подсистемы и компоненты реализуются самим разработчиком), либо «врач сказал – в морг».

ВЦКП в облаках

Можете ли вы представить себе личный автомобиль, передвигающийся во время поездок с предусмотренной скоростью лишь 1 час из 10? Именно таков ваш персональный компьютер, планшет или смартфон. Его вычислительная мощность используется в среднем на 5–10 % даже на рабочем месте в офисе. Более пропорционально расходуется оперативная память. Операционная система Windows NT 4 свободно работала на устройстве с ОЗУ [66] объёмом 16 Мбайт. Windows 7 требуется уже минимум 1 Гбайт. Правда, я не уверен, что Windows 7 хотя бы по одному параметру в 60 раз лучше предшественницы.

Широко известный в узких кругах своими несколько провокационными книгами [67] публицист Николас Карр пишет: «Отделы ИТ в компаниях уходят в прошлое, а сотрудники соответствующих специальностей останутся не у дел из-за перехода их работодателей на сервис, предоставляемый по принципу коммунальных услуг»[4].

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

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

На заре массового внедрения АСУ на предприятиях в 1970-х годах советские управленцы и технические специалисты предвидели многое. А именно, сосредоточение ресурсов в вычислительных центрах, где конечные пользователи будут получать обслуживание по решению своих задач и доступ. Доступ по простым терминалам, в ту эпоху ещё алфавитно-цифровым. Такова была концепция ВЦКП – Вычислительного Центра Коллективного Пользования.

В 1972 году впервые прозвучали слова о государственной сети вычислительных центров, объединяющих региональные ВЦКП. Для чего, по большому счёту, и потребовалась унифицированная техническая база в виде ЭВМ ЕС [68] и позднее СМ ЭВМ [69] . Разумеется, подобные проекты существовали и в США, иначе откуда бы взяться IBM System/360. Но, в отличие от советской программы, американцы на той стадии развития рынка и технологий потенциально могли охватить только окологосударственные и государственные структуры. В СССР же, напомню, все предприятия и организации были государственными за редкими формальными исключениями. Охват экономики планировался куда более полный.

Чем занимались тогда проектировщики, техники и организаторы? Примерно тем же самым, чем занимаются сейчас продвигающие на рынок системы «облачных» ( cloud ) вычислений, за исключением затрат на рекламу. Создавали промышленные вычислительные системы, отраслевые стандарты и их реализации. Чтобы предприятия-пользователи, те, кому это экономически нецелесообразно, не содержали свои ВЦ, а пользовались коллективными, ведь пироги должен печь пирожник, а не сапожник. Чтобы легче было собирать статистическую информацию. Чтобы снижать издержки на инфраструктуру, оборудование и эксплуатацию.

Если частично заменить «большие ЭВМ» на «кластеры из серверов», добавить взращенную за последние 10 лет широкую полосу пропускания общедоступных сетей на «последнем километре» [70] , а в качестве терминала использовать веб-браузер или специальное приложение, работающее на любом персональном вычислительном устройстве, от настольного компьютера до коммуникатора, то суть не изменится. Облако – оно же ВЦКП для корпоративного и даже массового рынка.

В чем состояли просчёты советской программы ВЦКП? Их два. Один крупный: проглядели стремительную миниатюризацию и, как следствие, появившееся обилие терминалов. Хотя отдельные центры, как, например, петербургский «ВЦКП Жилищного Хозяйства», основанный в 1980 году, действуют до сих пор, мигрировав в 1990-х от мейнфреймов к сетям ПК. Второй: просчитались по мелочам, не спрогнозировав развал страны с последующим переходом к состоянию технологической зависимости.

Авторам мемуаров о создании в СССР первых ВЦКП [7], возможно, будет не только досадно, но и приятно. Досадно за опередившие время своего технологического воплощения концепции. Приятно за реализацию идеи – лучше поздно, чем никогда.

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

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

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

SaaS и манипуляции терминами

Софтостроение – производственный процесс с высокой долей НИОКР [71] . Наукоемкий процесс, или, как его ещё называют, высокотехнологичный. На выходе – продукт: программа, программный пакет, система или комплекс.

По причине развития общедоступных каналов связи работать с программами можно с удалённого терминала, в роли которого выступает множество устройств: от персонального компьютера до мобильного телефона. Эксплуатацию же программ ведут поставщики услуг в «облаках» – современные ВЦКП. Это и есть «программа как услуга», SaaS [72] .

Значит ли это, что софтостроительные фирмы теперь, как утверждают некоторые маркетологи, «производят услуги»? Разумеется, нет.

Во-первых, услуги не производят, их оказывают. Во-вторых, услуга от продукта, материального товара, принципиально отличается минимум по трём пунктам:

• услуги физически неосязаемы;

• услуги не поддаются хранению;

• оказание и потребление услуг, как правило, совпадают по времени и месту.

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

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

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

От CORBA к SOA

Признаю, что название главы логически не совсем корректно, поскольку CORBA [73] – одна из технологий создания сервис-ориентированной архитектуры, СОА [74] , оно отражает хронологию развития событий. Поскольку маркетинговый шум вокруг СОА стих, жужжащие словечки вроде « loose coupling » подзабылись, а в последние годы стало модным даже говорить о том, что «СОА выдохлась», можно вернуться к сюжету в спокойной обстановке на уровне собственно технологии. Мне слово «СОА» напоминает другое из 1980-х годов, СОИ – Стратегическая Оборонная Инициатива, оказавшаяся пропагандистским пузырём игры в «звёздные войны» администрации американского президента Рейгана. Просто ассоциации, ничего личного.

Предшественником современной СОА на базе веб-служб, с полным правом можно считать CORBA. Это сейчас задним числом обобщают подходы, представляя СОА как набор слабосвязанных сетевых служб, реализовать которые можно по-разному. А тогда, в середине 1990-х, вокруг CORBA стоял достаточно сильный шум продавцов волшебных палочек, но никаких упоминаний СОА ещё не было. Только начинал своё бурное развитие интерактивный веб динамического контента, приём заказов через интернет-магазин считался «крутой фишкой» для компании, а где-то в недрах Microsoft из XML-RPC [75] тихо прорастал SOAP [76] .

CORBA имела очевидные достоинства, прежде всего это интероперабельность [77] и отраслевая стандартизация не только протоколов (шины), но и самих служб и общих механизмов – facilities . Например, служб имён, транзакций, безопасности, хранения объектов, конкурентного доступа, времени и т. п. Однажды реализованный программистами сервис мог использоваться многими системами без какой-либо дополнительной адаптации и ограничений с их стороны. Следует отметить, что фактически проигнорированная отраслью CORBA 1.0 не была интероперабельной и предназначалась только для языка C.

Почему же и CORBA 2, продержавшись несколько лет в основном потоке технологий, была оттеснена на обочину? Причин много, весьма подробный анализ описан в статье одного из разработчиков стандарта [14]. Мне же, как участнику разработки реальной системы на основе технологии, хотелось бы выделить следующие:

• Стандарт поддерживался многими корпорациями, поэтому развитие требовало длительного согласования интересов всех участников. Некоторые из них продвигали свои альтернативы, например Sun Java RMI и Jini, Microsoft DCOM.

• Несмотря на реальную поддержку интероперабельности, множества языков и сред программирования, основным средством разработки оставался C++. Но код на C++, манипулирующий инфраструктурой CORBA и службами, является излишне сложным по сравнению с той же Java или даже Delphi. Практиковавшие подтвердят, остальным будет достаточно взглянуть на примеры в Сети. А Java-программисты не спешили использовать CORBA из-за упомянутых альтернатив.

• Запоздалая (1999 год), объёмная и весьма сложная спецификация компонентной модели. Java-сообщество к тому времени обладало альтернативой в виде EJB [78] с открытыми и коммерческими реализациями.

Кто знает, откажись тогда корпорация Sun от роли единственно правильного хранителя своей технологии, сосредоточься она на интеграции с CORBA и реализации спецификаций, возможно, её история не закончилась бы через 10 лет поглощением со стороны Oracle. Но Sun тогда, на пике бума доткомов [79] , предпочла строить свой собственный мир, планируя накрыть им всю отрасль. Насколько простой оказалась придуманная в корпорации реальность, можно судить по фрагменту из статьи 2002 года «Страдает ли Java от сложности?» [16].



Поделиться книгой:

На главную
Назад