Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

VPS в России, Европе и США

Бесплатная поддержка и администрирование

Оплата российскими и международными картами

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

2009 г.

Манифест систем объектно-ориентированных баз данных

М. Аткинсон, Ф. Бансилон, Д. ДеВитт, К. Диттрих, Д. Майер, С.Здоник
Перевод: М.Р. Когаловский

Источник: журнал Системы Управления Базами Данных # 4/1995, издательский дом «Открытые системы»
Новая редакция: Сергей Кузнецов, 2009 г.

Оригинал: Malcolm Atkinson, Francois Bancilhon, David DeWitt, Klaus Dittrich, David Maier, Stanley Zdonik. The Object-Oriented Database System Manifesto. Proc. 1st International Conference on Deductive and Object-Oriented Databases, Kyoto, Japan (1989). New York, N.Y.: Elsevier Science (1990). Текст доступен здесь.

Содержание

1. Введение
2. Обязательные свойства: золотые правила
3. Необязательные возможности: конфетки
4. Открытые возможности
5. Заключительные замечания
Благодарности
Литература

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

Мы разделяем эти характеристики на три группы:

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

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

1. Введение

В настоящее время объектно-ориентированных системам баз данных (ООСБД) уделяется много внимания как с теоретической, так и с практической точек зрения, и ведутся жаркие споры об определении таких систем.

Можно выделить три характерные черты современного состояния дел:

  1. отсутствие общепринятой модели данных,
  2. отсутствие формального базиса и
  3. активная экспериментаторская деятельность.

В то время как в классической статье Кодда [Codd 70] была предоставлена отчетливая спецификация систем реляционных баз данных (модель данных и язык запросов), для систем объектно-ориентированных баз данных подобная спецификация отсутствует [Maier 89]. Мы вовсе не хотим сказать, что не существует ни одной полной модели объектно-ориентированной базы данных. На самом деле, в литературе можно найти множество соответствующих предложений (см., например, [Albano et al. 1986], [Lecluse and Richard 89], [Carey et al. 88]), но отсутствует общее согласие по поводу какой-нибудь одной из предложенных моделей. Постепенно складывается общая точка зрения по поводу основных характеристик семейства объектно-ориентированных систем, однако в настоящее время отсутствует единое мнение о том, что из себя представляет объектно-ориентированная система, не говоря уже о системе объектно-ориентированных баз данных.

Второй чертой является отсутствие надежного теоретического базиса. В объектно-ориентированном программировании по сравнению с логическим программированием нет такой программной статьи, как [Van Emdem and Kowalski 76]. Необходимость в основополагающей теории очевидна: семантика таких понятий, как типы или программы, зачастую часто является плохо определенной. Отсутствие надежного теоретического базиса делает практически невозможным достижение единого мнения о модели данных.

Наконец, ведутся многочисленные экспериментальные разработки: люди реально строят системы. Некоторые из этих систем являются только прототипами [Bancilhon et al. 88], [Nixon, et al. 87], [Banerjee et al. 87], [Skarra et al. 86], [Fishman et al. 87], [Carey et al. 86], а некоторые – уже коммерческими продуктами [Atwood 85], [Maier, et al. 84], [Caruso and Sciore 87], [G-Base 88]. Как кажется, интерес к объектно-ориентированным базам данным вызван потребностями систем поддержки проектирования (например, CAD, CASE, офисные информационные системы). Для этих приложений требуются базы данных, которые могут справляться с очень сложными данными, которые способны развиваться, и которые обеспечивают высокую производительность, требуемую интерактивным системам.

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

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

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

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

Мы разделяем характеристики систем объектно-ориентированных баз данных на три категории:

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

Статья организована следующим образом: в разд. 2 описываются обязательные свойства ООСБД, в разд. 3 – необязательные свойства, и в разд. 4 перечисляются степени свободы, которые предлагается оставить проектировщику системы.

2. Обязательные свойства: золотые правила

Система объектно-ориентированных баз данных должна удовлетворять двум критериям: она должна быть СУБД и при этом являться объектно-ориентированной системой, т.е. в максимально возможной степени находиться на уровне современных объектно-ориентированных языков программирования. Первый критерий означает пять свойств: стабильность (persistence), управление вторичной памятью, параллелизм (concurrency), восстанавливаемость (recovery) и средства обеспечения незапланированных (ad hoc) запросов. Второй означает восемь свойств: сложные объекты, идентифицируемость объектов (object identity), инкапсуляцию, типы или классы, наследование (object identity), перекрытие методов (overriding) совместно с отложенным связыванием (late binding), расширяемость и вычислительную полноту.

2.1. Сложные объекты

Следует поддерживать сложные объекты

Сложные объекты строятся из более простых путем применения конструкторов. Простейшими являются такие объекты, как целые числа, символы, символьные строки произвольной длины, булевские значения и числа с плавающей точкой (можно было бы добавить другие атомарные типы). Имеются различные конструкторы сложных объектов: примерами могут служить кортежи (tuple), множества (set), мультимножества (bag), списки (list), массивы (array). Минимальный набор конструкторов, который должна иметь система, – это множества, списки и кортежи. Множества необходимы, потому что они обеспечивают естественный способ представления коллекций реального мира. Кортежи необходимы, потому что они представляют естественный способ представления свойств сущностей. Конечно, важны и множества, и кортежи, поскольку они получили широкое распространение в качестве конструкторов объектов благодаря реляционной модели. Списки или массивы важны потому, что они сохраняют порядок, который имеет место в реальном мире, а также потому, что они присутствуют во многих научных приложениях в виде матриц или временных рядов.

Конструкторы объектов должны быть ортогональными: любой конструктор должен быть применим к любому объекту. Конструкторы реляционной модели не являются ортогональными, потому что конструкция множества может быть применена только к кортежам, а конструкция кортежа – только к атомарным значениям. Другими примерами являются реляционные модели с не первой нормальной формой (non-first normal form), в которых конструкцией верхнего уровня всегда должно быть отношение.

Отметим, что для поддержки сложных объектов необходимы соответствующие операции для работы с такими объектами (как бы они не были устроены). То есть операции со сложным объектом должны транзитивно распространяться на все его компоненты. Примерами могут быть выборка или удаление сложного объекта целиком или создание "глубокой" ("deep") копии (в отличии от "поверхностной" ("shallow") копии, в которой компоненты не копируются: в копии корня объекта указываются ссылки на компоненты копируемого объекта). Конечно, пользователь должен иметь возможность определять дополнительные операции со сложными объектами (см. ниже правило расширяемости). Однако для реализации этой возможности необходимы некоторые обеспечиваемые системой средства, такие как два различаемых типа ссылок ("является частью" ("is-part-of") и "общая" ("general")).

2.2. Идентифицируемость объектов

Следует поддерживать идентифицируемость объектов

Идентифицируемость объектов давно поддерживается в языках программирования. Для баз данных эта концепция сравнительно нова, см., например, [Hall и др. 76], [Maier и Price 84], [Khoshafian и Copeland 86]. Идея состоит в следующем: в модели с идентифицируемостью объектов объект существует независимо от его значения. Таким образом, имеется два понятия эквивалентности объектов: два объекта могут быть идентичны (они представляют собой один и тот же объект) или они могут быть равны (они имеют одно и тоже значение). Это влечет две следствия: первое – разделение объектов, а второе – изменения объектов.

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

(peter, 40, {(john, 15, {})}),

а Сьюзен как:

(susan, 41, {john, 15, {})}).

Таким образом, нет никакой возможности выразить, являются ли Питер и Сьюзан родителями одного и того же ребенка или разных детей. В модели с идентифицируемостью объектов эти две структуры либо имеют общую часть (john, 15, { }), либо не имеют ее, так что поддерживаются обе ситуации.

Изменения объектов: предположим, что Питер и Сьюзан действительно являются родителями мальчика по имени Джон. В этом случае все исправления, касающиеся сына Сьюзан, будут производиться с объектом Джон, а следовательно, и с сыном Питера. Идентифицируемость объектов, кроме того, обеспечивает мощный примитив манипулирования данными, который может служить основой для манипулирования множествами, кортежами или рекурсивными сложными объектами [Abiteboul and Kanellakis 89].

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

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

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

2.3. Инкапсуляция

Объекты следует инкапсулировать

Идея инкапсуляции происходит

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

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

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

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

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

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

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

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

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

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

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

2.4. Типы и классы

Следует поддерживать типы или классы

Это весьма деликатный вопрос: имеются две основные категории объектно-ориентированных систем – те, которые поддерживают классы, и те, которые поддерживают типы. К первой категории относятся такие системы, как Smalltalk [Goldberg and Robson 83], Gemstone [Maier, et al. 84], Vision [Caruso and Sciore 81], все системы семейства Smalltalk: Orion [Banerjee et al. 87], Flavors [Bobrow and Steifik 81], G-Base [G-Base 88], Lore [Caseau 89] и, вообще говоря, все системы, ведущие свое происхождение от языка Lisp. Представителями второй категории являются такие системы, как C++ [Stroustrup 86], Simula [Simula 67], Trellis/Owl [Schaffert, и др. 86], Vbase [Atwood 85] и O2 [Bancilhon et al. 88].

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

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

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

Понятие класса отличается от понятия типа. Его спецификация совпадает со спецификацией типа, но это понятие является более динамическим. Класс характеризуется двумя аспектами: фабрика объектов (object factory) и склад объектов (object warehouse). Фабрика объектов может быть использована для создания новых объектов посредством выполнения операции new данного класса или клонирования некоторого объекта-прототипа, являющегося представителем данного класса. Склад объектов означает, что к классу присоединяется его расширение (extension), т.е. множество объектов, которые являются экземплярами класса. Пользователь может манипулировать складом, применяя операции ко всем экземплярам класса. Классы используются не для проверки правильности программы, а скорее для создания и манипулирования объектами. В большинстве систем, которые используют механизм классов, классы являются "гражданами первого сорта" и, как таковыми, ими можно манипулировать во время выполнения, т. е. изменять их и передавать как параметры. В большинстве случаев это делает невозможным проверку типов во время компиляции, но придает системе большую гибкость и однородность.

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

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

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

2.5. Иерархии классов или типов

Для классов или типов следует поддерживать наследование

Наследование обладает двумя достоинствами:

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

Следующий пример иллюстрирует потребность наличия в системе наследования. Допустим, что мы имеем дело со Cлужащими и Студентами. Каждый Cлужащий имеет имя, возраст более 18 лет и оклад, он или она может умереть, выйти замуж или жениться или получить зарплату (как скучна жизнь Cлужащего!). Каждый Студент имеет имя, возраст и множество оценок. Он или она может умереть, выйти замуж или жениться, и для него или нее может быть вычислен GPA (Grade Point Average, средний академический балл).

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

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

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

Имеется по крайней мере четыре типа наследования:

  1. наследование через подстановку (substitution inheritance),
  2. наследование путем включения (inclusion inheritance),
  3. наследование через ограничение (constraint inheritance) и
  4. наследование через специализацию (specialization inheritance).

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

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

Наследование через ограничение является частным случаем наследования путем включения. Тип t является подтипом типа t', если к нему относятся все объекты типа t', которые удовлетворяют данному ограничению. Примером такого наследования является класс подросток как подкласс класса человек: объекты класса подросток не имеют дополнительных полей или операций по сравнению с объектами класса человек, но они удовлетворяют более специфичным ограничениям (возраст подростков ограничен снизу 13, а сверху 19 годами).

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

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

2.6. Перекрытие, перегрузка и позднее связывание

Не следует производить преждевременное связывание

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

В приложениях, использующих традиционные системы, мы имели бы три операции: отобразить объект человек (display-person), отобразить растровое изображение (display-bitmap) и отобразить граф (display-graph). Программист проверил бы тип каждого объекта, входящего во множество, и использовал бы соответствующую операцию отображения. Это обязывает программиста знать все возможные типы объектов, которые могут входить в заданное множество, а также соответствующие им операции отображения, и использовать их согласованным образом.

for x in X do 
  begin
    case of type(x)
      person: display(x);
      bitmap: display-bitmap(x); 
      graph: display-graph(x);
  end
end

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

for x in X do display(x)

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

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

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

2.7. Вычислительная полнота

Следует поддерживать вычислительную полноту

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

Мы не призываем проектировщиков объектно-ориентированных систем баз данных к созданию новых языков программирования: вычислительной полноты можно добиться, разумным образом опираясь на существующие языки программирования. И на самом деле, в большинстве систем используются уже существующие языки программирования [Banerjee et al. 87], [Fishman et al. 87], [Atwood 85], [Bancilhon et al. 88]; обсуждение этой проблемы см. в [Bancilhon and Maier 88].

Заметим, что вычислительная полнота – это не то же самое, что ресурсная полнота (resource completeness), т.е. возможность доступа ко всем ресурсам системы (например, к экрану и удаленным ресурсам) с использованием внутренних средств языка. Поэтому система, даже будучи вычислительно полной, может быть не способна выразить полное приложение. Тем не менее, такая система является более мощной, чем система баз данных, которая только хранит и извлекает данные, а также выполняет простые вычисления с атомарными значениями.

2.8. Расширяемость

Cледует поддерживать расширяемость

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

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

2.9. Стабильность

Данные не должны забываться

Это требование очевидно с точки зрения баз данных, но является новым с точки зрения языков программирования [Atkinson et al. 83]. Стабильность (persistence) означает возможность программиста обеспечить сохранность данных после завершения выполнения процесса с целью последующего использования в другом процессе. Свойство стабильности должно быть ортогональным, т.е. для каждого объекта вне зависимости от его типа должна иметься возможность сделать его стабильным (т.е. без какой-либо явной переделки объекта). Стабильность должна быть неявной: чтобы сделать данные стабильными, пользователь не должен быть обязан явно перемещать их или копировать.

2.10. Управление вторичной памятью

Следует уметь управлять очень большими базами данных

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

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

2.11. Параллелизм

Следует поддерживать параллельную работу нескольких пользователей

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

2.12. Восстановление

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

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

2.13. Средства обеспечения незапланированных запросов

Следует обеспечивать простой способ запросов данных

Здесь основной проблемой является обеспечение функциональности языка незапланированных (ad hoc) запросов. Мы не призываем к тому, чтобы это обязательно было реализовано в виде языка запросов, а только к тому, чтобы была такая услуга существовала. Например, для обеспечения этой функциональной возможности вполне достаточна графическая программа просмотра. Услуга состоит в том, что пользователь может без затруднений сделать простой запрос к базе данных. Очевидной мерой являются, конечно, реляционные системы. Поэтому проверка наличия средства незапланированных запросов состоит в том, чтобы взять на пробу несколько реляционных запросов и проверить, можно ли их сформулировать с теми же трудозатратами. Заметим, что это средство могло бы поддерживаться языком манипулирования данными или его подмножеством.

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

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

Этим исчерпывается список обязательных характеристик. Надеемся, что нам удалось прояснить различия между системами традиционными и объектно-ориентированными системами баз данных. Реляционные системы баз данных не удовлетворяют правилам с первого по восьмое. Системы баз данных CODASYL частично удовлетворяет правилам 1 и 2. Некоторые люди придерживаются того мнения, что объектно-ориентированные системы баз данных есть ни что иное, как системы CODASYL. Следует отметить, что

  1. системы CODASYL не удовлетворяют полностью этим двум правилам (конструкторы объектов не являются ортогональными, и не обеспечивается однородная идентифицируемость объектов, поскольку допускаются только связи 1:n), и
  2. эти системы не удовлетворяют правилам 3, 5, 6, 8 и 13.

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

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

3. Необязательные возможности: конфетки

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

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

Другие возможности являются просто возможностями систем баз данных (например, управление проектными транзакциями). Эти характеристики обычно улучшают функциональные возможности систем баз данных, но не относятся к ключевым требованиям, предъявляемым к таким системам, и они не связаны с аспектом объектной-ориентированности. В действительности, многие из этих возможностей предназначены для обслуживания "новых" приложений (CAD/CAM, CASE, офисная автоматизация и т. д.) и являются более ориентированными на приложения, чем на технологии. Так как многие системы объектно-ориентированных баз данных нацелены на эти новые приложения, то существует некоторая путаница между этими возможностями и объектно-ориентированной природой системы.

3.1. Множественное наследование

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

3.2. Проверка и вывод типов

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

3.3. Распределенность

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

3.4. Проектные транзакции

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

3.5. Версии

Большинство новых приложений (CAD/CAM и CASE) предполагает проектную деятельность, и для этого требуется какая-либо поддержка версий. Поэтому многие ООСБД поддерживают версии. И в этом случае обеспечение механизма поддержки версий не является ключевым требованием к системе.

4. Открытые возможности

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

4.1. Парадигма программирования

Мы не видим причины, по которой одной парадигме программирования следует отдать предпочтение перед другой: в качестве парадигмы программирования можно выбрать стиль логического программирования [Bancilhon 86], [Zaniolo 86], стиль функционального программирования [Albano et al. 1986], [Banerjee et al. 87] или стиль императивного программирования [Stroustrup 86], [Eiffel 87], [Atwood 85]. Другим решением может быть независимость системы от стиля программирования и поддержка нескольких парадигм программирования [Skarra и др. 86], [Bancilhon и др. 88].

Конечно, каждый волен свободно выбирать синтаксис, и программисты будут вечно спорить, правильнее ли писать john hire, john.hire, hire john, или hire(john).

4.2. Система представления

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

4.3. Система типов

Также остается свобода в выборе формирователей типов. Единственным средством формирования типов, наличия которого мы требуем, является инкапсуляция. Возможны другие формирователи типов, такие как родовые типы или генераторы типов (например, set[T], где T может быть произвольным типом), ограничение, объединение или стрелка (функции).

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

4.4. Однородность

Ведутся жаркие споры о степени однородности таких систем. Является ли тип объектом? Является ли метод объектом? Следует ли эти три понятия рассматривать отдельно? Эту проблему можно рассматривать на трех разных уровнях: уровне реализации,

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

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

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

    5. Заключительные замечания

    Некоторые авторы [Kim 88] и [Dittrich 1986] придерживаются той точки зрения, что ООСБД есть СУБД, основанная на объектно-ориентированной модели данных. Если использовать понятие модели данных в широком смысле, учитывая, в частности, дополнительные аспекты, выходящие за рамки ориентированности на работу с записями, то эта точка зрения, несомненно, согласуется с нашей. В [Dittrich 1986] и [Dittrich 1988] вводится классификация объектно-ориентированных моделей данных (и, следовательно, ООСБД): модель называется структурно объектно-ориентированной, если она поддерживает сложные объекты; модель называется поведенчески объектно-ориентированной, если она обеспечивает расширяемость; для того чтобы модель была полностью объектно-ориентированной, она должна обладать обоими свойствами. В соответствии с определением требуется также поддержка свойства стабильности, управления дисками, параллелизма и восстанавливаемости; определение, по крайней мере, неявно, подразумевает наличие большинства других свойств (в тех случаях, где они применимы в зависимости от класса системы); в целом, это определение является более либеральным, чем наше. Однако, поскольку большинство систем и прототипов все равно не удовлетворяют всем требованиям, которые налагает наше определение, эта классификация предоставляет основу для сравнения выполненных и продолжающихся работ.

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

    Ставьте под сомнения "золотые" правила

    Благодарности

    В заключении мы хотели бы выразить признательность Филиппу Брайдону (Philippe Bridon), Джильберту Харрусу(Gilbert Harrus), Парису Канеллакису (Paris Kanellakis), Филиппу Ричарду (Philippe Richard) и Фернандо Велецу (Fernando Velez) за предложения и замечания, высказанные ими по поводу статьи.

    Литература

    1. [Abiteboul and Kanellakis 89] S. Abiteboul and P. Kanellakis, "Object identity as a query language primitive", Proceedings of the 1989 ACM SIGMOD, Portland, Oregon, June 89
    2. [Albano et al. 1986] A. Albano, G. Gheli, G. Occhiuto and R. Orsini, "Galileo: a strongly typed interactive conceptual language", ACM TODS, Vol 10, No. 2, June 1985.
    3. [Atkinson et al. 83] M. Atkinson, P.J. Bayley, K. Chilsom, W. Cockshott and R. Morrison, "An approach to persistent programming", Computer Journal, 26(4), 1983, pp 360-365.
    4. [Atwood 85] T. Atwood, "An object-oriented DBMS for design support applications", Ontologic Inc. Report.
    5. [Bancilhon 86] F. Bancilhon, "A logic programming object oriented cocktail", ACM SIGMOD Record, 15:3, pp. 11-21, 1986.
    6. [Bancilhon and Maier 88] F. Bancilhon and D. Maier, "Multilanguage object-oriented systems: new answer to old database problems", in Future Generation Computer II, K. Fuchi and L. Kott editors, North-Holland, 1988.
    7. [Bancilhon et al. 88] F. Bancilhon, G. Barbedette, V. Benzaken, C. Delobel, S. Gamerman, C. Lecluse, P. Pfeffer, P. Richard et F. Velez, "The design and implementation of O2, an object-oriented database system", Proceedings of the ooDBS II Workshop, Bad Munster, FRG, September 1988.
    8. [Banerjee et al. 87] J. Banerjee, H.T. Chou, J. Garza, W. Kim, D. Woelk, N. Ballou and H.J. Kim, "Data model issues for object-oriented applications", ACM TOIS, January 1987.
    9. [G-Base 88] "G-Base version 3, Introductory guide", Graphael, 1988.
    10. [Bobrow and Steifik 81] D. Bobrow and M. Steifik, " The Loops Manual", Technical Report LB-VLSI-81-13, Knowledge Systems Area, Xerox Palo Alto Research Center, 1981.
    11. [Carey et al. 86] M. Carey, D. DeWitt, J.E. Richardson and E.J. Shekita, "Object and file management in the EXODUS Extensible Database System", Proceedings of the 12th VLDB, pp 91-10, August 1986.
    12. [Carey et al. 88] M. Carey, D. DeWitt and S. Vandenberg, "A Data Model and Query Language for EXODUS", Proceedings of the 1988 ACM SIGMOD Conference, Chicago, June 1988.
    13. [Caruso and Sciore 87] "The VISION Object-Oriented Database Management System", Proceedings of the Workshop on Database Programming Languages, Roscoff, France, September 1987
    14. [Caseau 89] "A model for a reflective object-oriented language", Sigplan Notices, Special issue on Concurrent Object-Oriented Programming, March 1989.
    15. [Codd 70] E. F. Codd, "A relational model for large shared data banks", Communication of the ACM, Volume 13, Number 6, (June 1970), pp 377-387.
    16. [Dittrich 1986] K.R. Dittrich, "Object-Oriented Database System : The Notions and the issues", in : Dittrich, K.R. and Dayal, U. (eds): Proceedings of the 1986 International Workshop on Object-Oriented Database Systems, IEEE Computer Science Press
    17. [Dittrich 1988] K. R. Dittrich, "Preface", In : Dittrich, K.R. (ed): Advances in Object-Oriented Database Systems, Lecture Notes in Computer Science, Vol, 334, Springer-Verlag, 1988
    18. [Eiffel 87] "Eiffel user"s manual", Interactive Software Engineering Inc., TR-EI-5/UM, 1987.
    19. [Fishman et al. 87] D. Fishman et al, "Iris: an object-oriented database management system", ACM TOIS 5:1, pp 48-69, January 86.
    20. [Hall et al. 76] P. Hall, J. Owlett, S. Todd, "Relations and Entities", in "Modeling in Data Base Management Systems", G.M. Nijssen (ed.), pp 201-220, North-Holland, 1976.
    21. [Goldberg and Robson 83] A. Goldberg and D. Robson, "Smalltalk-80: the language and its implementation", Addison-Wesley, 1983.
    22. [Kim 88] W. Kim, "A foundation for object-oriented databases", MCC Technical Report, 1988.
    23. [Khoshafian and Copeland 86] S. Khoshafian and G. Copeland, "Object identity", Proceedings of the 1st ACM OOPSLA conference, Portland, Oregon, September 1986
    24. [Lecluse and Richard 89] C. Lecluse and P. Richard, "The O2 Database Programming Languages", Proceedings of the 15th VLDB Conference, Amsterdam, August 1989.
    25. [Maier and Price 84] D. Maier and D. Price, "Data model requirements for engineering applications", Proceedings of the First International Workshop on Expert Database Systems, IEEE, 1984, pp 759-765
    26. [Maier 89] D. Maier, "Why isn"t there an object-oriented data model?" Proceedings IFIP 11th World Computer Conference, San Francisco, CA, August-September 1989.
    27. [Maier, et al. 84] D. Maier, J. Stein, A. Otis, A. Purdy, "Development of an object-oriented DBMS" Report CS/E-86-005, Oregon Graduate Center, April 86
    28. [Nixon, et al. 87] B. Nixon, L. Chung, D. Lauzon, A. Borgida, J. Mylopoulos and M. Stanley, "Design of a compiler for a semantic data model", Technical note CSRI-44, University of Toronto, May 1987.
    29. [Simula 67] "Simula 67 Reference Manual"
    30. [Schaffert, et al. 86] C. Schaffert, T. Cooper, B. Bullis, M. Kilian and C. Wilpolt, "An introduction to Trellis/Owl", Proceedings of the 1st OOPSLA Conference, Portland, Oregon, September 1986
    31. [Skarra et al. 86] A. Skarra, S. Zdonik and S. Reiss, "An object server for an object oriented database system," Proceedings of the 1986 International Workshop on Object Oriented Database System, Computer Society Press, IEEE, pp. 196-204, 1986
    32. [Stroustrup 86] B. Stroustrup, "The C++ programming language", Addison-Wesley, 1986.
    33. [Van Emdem and Kowalski 76] M. Van Emdem and R. Kowalski, "The semantics of predicate logic as a programming language", JACM, Vol 23, No. 4, pp. 733-742, October1976.
    34. [Zaniolo 86] C. Zaniolo, "Object-oriented programming in Prolog ", Proceedings of the first workshop on Expert Database Systems, 1985.
    Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

    Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

    Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

    Виртуальные VPS серверы в РФ и ЕС

    Dedicated серверы в РФ и ЕС

    По промокоду CITFORUM скидка 30% на заказ VPS\VDS

    VPS/VDS серверы. 30 локаций на выбор

    Серверы VPS/VDS с большим диском

    Хорошие условия для реселлеров

    4VPS.SU - VPS в 17-ти странах

    2Gbit/s безлимит

    Современное железо!

    Новости мира IT:

    Архив новостей

    IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
    тел. +7 495 7861149
    Пресс-релизы — pr@citforum.ru
    Обратная связь
    Информация для авторов
    Rambler's Top100 TopList This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2019 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...