|
|
su.dbms- SU.DBMS ---------------------------------------------------------------------- From : Victor Metelitsa 2:5020/400 24 Jul 2001 17:22:45 To : All Subject : Примерчик преимуществ GemStone/S -------------------------------------------------------------------------------- Примерчик преимуществ ОО СУБД GemStone/S Итак, пусть мы "напроектировали" "Отдел Кадров". Кроме всего прочего, там есть сотрудники (экземпляры класса Employee). У сотрудника есть атрибут name (здесь под "атрибутом" я понимаю тройку: get-метод, set-метод и переменную экземпляра). Мы храним в нем строку: "Создали нового сотрудника и дали ему имя" employee := Employee new. employee name: 'Иван Иванович Иванов'. Hаписали также кучу другого кода, и т.д., и т.п., и в конце концов сдали базу в эксплуатацию. Спустя некоторое количество времени мы пришли к выводу, что в проектировании была допущена ошибка. Hа самом деле name должно быть экземпляром не String, а класса Name: "Создали новое имя, нового сотрудника и дали ему имя" name := Name new. name firstName: 'Иван' middleName: 'Иванович' lastName: 'Иванов'. employee := Employee new. employee name: name. Как внести изменения, по возможности не тормозя систему? Smalltalk'ам (и GemStone/S в том числе) совершенно без разницы, что хранится в переменной - строка, число, коллекция или экземпляр какого-либо иного класса. Так что в классе Employee мы только переопределим get-метод и set-метод. Первый проверит, не хранится ли в переменной name строка, и при необходимости конвертирует в экземпляр класса Name. name name isString ifTrue: [name := Name fromString: name]. ^ name Второй то же самое проделает со своим аргументом. name: param param isString ifTrue: [name := Name fromString: param] ifFalse: [name := param]. Остается куча мест в программе, где программист предполагал, что в name находится строка. Тут есть два варианта (которыми можно воспользоваться порознь или одновременно): 1) [Естественное] Просмотреть все методы всех классов такие, где объекту посылается сообщение name, и исправить код. Любой Smalltalk GUI с легкостью предоставит такой список. 2) [Красивое] перекрыть в классе Name обработчик "непонятых" сообщений (#doesNotUnderstand:) Подробней про второе. Пусть, например, где-то в программе, предполагая, что в name находится строка, мы вырезаем из нее кусочек с 1-го по 10-й символ (неважно, зачем); или делаем что-то другое, непонимаемое Name. "Естественно", экземпляр класса Name такое сообщение не поймет. Т.е., когда мы посылаем объекту сообщение с каким-то селектором (на C++ это называется "сигнатура"?), то обычно предполагаем, что оно будет обработано его методом с тем же селектором, но в данном примере такого метода не найдется. В таком случае оно будет обработано методом с селектором #doesNotUnderstand: (который, определенный в корневом классе, просто выбросит исключение). А перекрыв, в этом методе мы просто-напросто сконкатенируем firstName, middleName и lastName (не забыв, конечно, пробелы-разделители) и передадим сообщение полученной строке (т.е. экземпляру класса String), которая его и обработает! Вот так программа и "не догадается" об "обмане" - Name будет вести себя как String, и все это ценой перекрытия одного метода. Последовательность действий: 1. Создать класс Name (с, кроме всего прочего, методом doesNotUnderstand:, о котором я рассказал) 2. Изменить get- и set-методы очевидно, это можно проделать без остановки системы, и никто ничего не заподозрит. Конечно, возможны и более тяжелые случаи, но все равно по сравнению с такими возможностями все RDBMS [вырезано самоцензурой], и, подозреваю, достославная Cache тоже. -- Отправлено через сервер Talk.Ru - http://www.talk.ru --- ifmail v.2.15dev5 * Origin: Talk.Ru (2:5020/400) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /su.dbms/536455a24c9f.html, оценка из 5, голосов 10
|