Juri Shutenko Personal Homepage. Visual FoxPro.

Глобализация. Часть 1.

"Нехорошее это слово!" - считают некоторые, и не предпринимают никаких действий. "Нехорошая эта тенденция!" - считают другие и устраивают акции, потасовки и прочие нехорошие действия, сами, порой, не зная против кого... Ну, а что скажете по этому поводу вы, дрессировщики Лисы? По моему скромному убеждению, глобализация, это совсем не плохо, если вести речь об объекто-ориентированном программировании. Вернее не о всем ООП, а только его основе - объектах. Глобальные smart-объекты - это хорошо или плохо?

Начнем с родителя объекта - класса. Три кита ООП - они же три базовых принципа - инкапсюляция, наследование и полиморфизм.

Напомню кратенько, что эти три концепиции означают

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

Наследование - представляет собой концепцию повторного использования. Класс представляет собой описание объекта, который может быть создан с помощью специальных функций, типа "СreateObject" или "NewObject", которым вы указываете из какого класса создать объект. Базовый класс в VFP представляет собой суперкласс, из которого могут быть созданы новые классы или субклассы.
Если мы создаем новый класс из базового класса, он наследует все его свойства и методы, за исключением одного - имени. Вы не можете описать субкласс, один к одному, с тем же именем, что и базовый или суперкласс. Вы можете переписать значения его свойств или процедурный код в методах субкласса, добавить свои пользовательские свойства и методы. Затем вы на основе этого субкласса можете создать новый субкласс, который унаследует неизмененные свойства базового суперкласса, а также все изменения, которые вы произвели при создании субкласса первого уровня.

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

Ну а теперь, вернемся в нашему барану - глобальному smart-объекту. И рассмотрим очень простой его вариант.

Представим себе фирму, продающей компьютеры своей сборки. В эту фирму пришел покупатель с желанием приобрести компьютер за 8000 крон. В фирме, имеющей установленную 1С, продавец создаст новый инвойс или предложение и начнет носиться по дереву каталогов, подбирая компоненты и меняя их, время от времени, с целью обеспечения желаемой пользователем цены. Даже великий спец потратит на это немало времени. (Я сам часто являюсь покупателем и знаю, что на оформление заказа уходит минимум - 10 минут.) А что если вы просто напечаете команду Do constructor with "computer","8000EEK"? Что может произойти в результате? Мой командный файл, обеспечивающий такую функциональность выглядит так:

LPARAMETERS lpcGlobalClass,lpuAttribute
LOCAL loGObject
loGObject=CREATEOBJECT(lpcGlobalClass,lpuAttribute)
loGObject.ShowMe()

Давайте составим описание компьютера. Из чего состоит физический объект "компьютер"?

  • Материнская плата
  • Процессор
  • Память
  • Жесткий диск
  • Видеокарта (может быть встроенной в "маму")
  • CD-Rom
  • Корпус
  • Блок питания (может поставляться вместе с корпусом)

Приведенный список можно охарактеризовать выражением "must have". То есть, включает в себя минимально необходимую конфигурацию, после обретения которой железный ящик может обрести жизнь. Поскольку есть список "must have", то напрашивается список "may have". Что может содержать такой список.

  • Сетевая карта(может быть встроенной в "маму")
  • Звуковая карта (может быть встроенной в маму)
  • Флоппи-диск
  • DVD-Rom
  • Беспроводная сетевая карта
  • Считыватель медиа-карт

Разумеется, здесь упрощение, с целью облегчения понимания смысла. Возможен и третий список "should be have", который может содержать вариации первого и второго списка. Например - CD-ROM может быть пищущим, а может быть и комбинированным устройством - чтение DVD/чтение+запись CD.

Если еще раз взглянуть на текст программы, то команда loGObject.ShowMe() подразумевает по смыслу ее имени какой-то интерфейс. Однако сразу должен оговориться, что глобальный объект не предсталяет собой объект формы или прочего визуального класса, который будет помещен на форму. Отнюдь. Глобальный объект создается на базе невизуального класса - Custom, и при необходимости создаст интерфейс сам.

Что необходимо этому глобальному объекту для успешной работы? Описание структуры будущего объекта, вроде той, что приведена выше и складские таблицы.

Как описать структуру? Разумеется парами - параметр:значение. Тогда, например, слегка упрощенная структура комьютера могла бы выглядеть так.

computer {
   motherboard:mustHave;
   processor:mustHave;
   memory:mustHave;
   harddisk:mustHave;
   videocard:mustHave;
   cdrom:mustHave;
   case:mustHave;
   powersupply:mustHave;
   networkcard:mayHave;
   soundcard:mayHave;
   floppydrive:mayHave;
   wifinetworkcard:mayHave;
   mediacardreader:mayHave;
}

Что должен сделать глобальный smart-класс?

  • Во-первых, найти описание структуры требуемого объекта (в нашем случае это "компьютер") в таблице описания структур.
  • Во-вторых, по именам параметров найти в таблице описаний базы данных складские таблицы (таблицу), содержащие информацию о компонентах компьютера.
  • В третьих, определить смысл параметра "8000EEK". В качестве второго параметра, например, может быть предпочтение - Intel/AMD, или марка брэнда или даже просто "multimedia".
  • В-четвертых, составить варианты конфигураций в виде объектов конфигураций, на основе складских данных с первичным допуском +/- 10% от запрашиваемой цены, для нашего рассматриваемого случая.
  • В-пятых, обозначить имена конфигураций и вывести их в список, при прохождении которого необходимо будет вывести параметры каждой конфигурации, то есть создать интерфейс применительно к этой задаче.
  • В-шестых, интерфейс предусматрвает создание инвойса по сформированной конфигурации и его печать. Кроме того, в интерфейсе будут созданы объекты с аттрибутом AskUser, которые могут быть оформлены в виде комбинаций чек-боксов с комбобоксами (или со списками, или с радиокнопками - в зависимости от числа возможных вариантов), с целью обработки списков "may have" и "should be have".

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

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

А что, если описание требуемого объекта отсутствует? В глобальном классе предусмотрен метод AskStructure(), который будет формировать вопросы пользователю и на основании его ответов формировать структуру. Задачка, кажущаяся, на первый взгляд, достаточно сложной на самом деле решается достаточно просто и позволяет вам создавать весьма сложные приложения, потратив при этом минимум времени. Работа с глобальным объектов показано в демо-файле. Для отображения демо-файла в браузере требуется наличие установленного проигрывателя flash-файлов.

Я думаю, что глобализация - удачный термин, да и "usability" здесь идет с ним рука об руку.

Если идея понятна, то вперед и с песней "Мы рождены, что сказку сделать былью"!

Cелектор для быстрого перехода на сайты, связанные с Visual FoxPro.