WWW.DISS.SELUK.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА
(Авторефераты, диссертации, методички, учебные программы, монографии)

 

Pages:     | 1 | 2 || 4 | 5 |   ...   | 8 |

«Краткое оглавление КРАТКОЕ ОГЛАВЛЕНИЕ 1 ПОДРОБНОЕ ОГЛАВЛЕНИЕ 4 ВВЕДЕНИЕ 17 Для кого предназначено настоящее руководство 17 История создания платформы 17 Платформа с открытым кодом 18 Обзор архитектуры 20 УСТАНОВКА И ...»

-- [ Страница 3 ] --

RetailInv Настройки, относящиеся к розничному складу Таблица 0. Предварительное объявление переменных VbScript позволяет работать с необъявленными предварительно переменными. При вводе новой переменной, ей присваивается значение по умолчанию, исходя из контекста. Например:

Summa = Quantity * Price ’Summa = Здесь мы вводим переменную Quantity и инициализируем ее значением 10, затем вводим переменную Summa и инициализируем ее выражением. Однако в выражении присутствует не объявленная ранее переменная Price. Исходя из контекста, она создается как переменная с численным типом и инициализируется нулем. Поэтому мы получим Summa, равную нулю.

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

Вы уже создавали скрипт-объекты и, наверное, замечали что Option Explicit вставляется автоматически.

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

Dim Quantity, Price, Summa Summa = Quantity * Price ’Summa = Разбиение на модули Что такое модуль?

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

Настройка на Гедымине – это объединенные по области использования объекты (скрипт-объекты, объекты БД, формы, пользовательский интерфейс). Загрузка настройки на базу означает модификацию структуры базы данных, создание необходимых скриптов, включение обработчиков событий, создание пользовательских форм, настройку интерфейса пользователя, загрузку определенных данных. Более подробно ознакомится с настройками можно в главе 14.

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

Зачем вообще деление на модули? Куда как проще все объединить в один блок. Здесь мы сталкиваемся с принципом экономии ресурсов, в частности, дискового пространства. Если вам необходимы только платежные документы, то зачем загружать базу лишними объектами ненужных вам аренды, склада, и др.

Чем больше объектов вы создаете на базе, тем больше места она занимает. Чем больше объем базы, тем медленнее работают запросы к ней. Также стоит упомянуть степень простоты работы с базой данных:

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

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

• дополнение существующего модуля своей функциональностью;

• создание нового модуля с установлением зависимости от существующего.

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

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

Как это все реализуется в системе Гедымин, читайте в главе 14.

Высвобождение ресурсов, использование TCreator.

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

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

Итак, что же такое объект? Объект – это совокупность переменных состояния и связанных с ними методов (операций). Эти методы определяют, как объект взаимодействует с окружающим миром.



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

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

Чтобы создать объект недостаточно просто объявить, экземпляром какого класса он является.

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

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

Примерами таких языков являются Object Pascal, С ++. Существуют однако и такие языки программирования, которые освободили программистов от необходимости очищать память. Такие языки имеют встроенный сборщик мусора, который отслеживает неиспользуемые объекты и освобождает занимаемую ими память. Примерами таких языков являются Java, VBScript.

Т.к. Гедымин использует интерпретатор VBScript-а, то остановимся подробнее на этом языке, а также рассмотрим некоторые особенности, характерные только для данной платформы.

Синтаксис создания экземпляра класса в VBScript следующий:

set NewObject = new ClassName Обратите внимание на два ключевых слова: set – говорит интерпретатору о том, что следующая за ним переменная будет объектом, new – вызывает конструктор класса ClassName. Забегая вперед, скажу, что класс, экземпляр которого вы будете создавать, обязательно должен быть зарегистрирован описан ранее при помощи синтаксиса VBScript и загружен в скрипт-контрол, иначе интерпретатор его просто не найдет и выдаст сообщение об ошибке.

VBScript является языком, который сам управляет освобождением памяти. исключением являются объекты, реализующие экземпляры внутренних классов Гедымина. Эти объекты создаются дизайнером Гедымина и нуждаются в принудительном уничтожении. Как обойти данную проблему, используя классические средства VBScript? Выход напрашивается сам собой: необходимо создать обычный VBобъект, который будет содержать ссылки на объекты Гедымина, и в деструкторе класса этого VBобъекта прописать уничтожение объектов Гедымина. Тогда по завершению выполнения скрипта этот VB-объект автоматически уничтожится и уничтожит все содержащиеся в нем ссылки.

Чтобы не изобретать каждый раз велосипед, в настройку «Общие данные» был вставлен глобальный VBкласс TCreator. Загрузив данную настройку на базу, вы получите доступ к этому классу из любого скрипта.

Экземпляр класса TCreator создается как обычный VB-объект, используя оператор new. Класс обладает следующими методами:

• GetObject(Params, ClassName, Name) – создает новый экземпляр класса ClassName Гедымина с именем Name. Params – это параметры, которые передаются в конструктор класса. Чаще всего первый параметр будет nil, а последний – пустая строка. Здесь нужно обратить внимание на два обстоятельства: во-первых, конструкторы классов Гедымина могут иметь входные параметры, в отличие от конструкторов VB-классов; во-вторых метод GetObject можно использовать только для создания объектов Гедымина.

• DestroyObject(Object) – уничтожает указанный объект и убирает ссылку на него из • DestroyAllObjects – уничтожает все объекты, ссылки на которые имеются в объекте Следует заметить, что методы TCreator, вызывающие явное уничтожение объектов, практически никогда не используются.

И в заключение рассмотрим пример.

'Включаем отслеживание необъявленных переменных Option Explicit ‘Создаем макрос, который будет последовательно ‘выводить все товары sub mcr_ShowAllGoods ‘Объявляем переменные ‘Создаем VB-объект класса TCreator ‘Создаем объект Гедымина класса TgdcGood ‘TgdcGood – дает доступ к таблице gd_good, которая 'хранит информацию о товарах set gdcGood = Creator.GetObject(nil, “TgdcGood”, “”) ‘Открываем объект для доступа к записям ‘В цикле пробегаемся по всем записям gdcGood 'и отображаем последовательно название товаров MsgBox gdcGood.FieldByName(“name”).AsString По завершению выполнения данной процедуры VBScript удалит объект Creator. Удаление объекта вызовет деструктор класса TCreator. В деструкторе проверяется, есть ли ссылки на внешние объекты. В данном случае мы имеем ссылку на gdcGood, который и будет уничтожен деструктором объекта Creator.

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

Подробнее про дизайнер и создание объектов читайте в главе 6.

Обработка ошибок Создавая некий программный продукт невозможно полностью избежать ошибок. Ошибки можно разделить на:

• ошибки, вызванные нарушением доступа;

• ошибки, вызванные определенными действиями пользователя.

Синтаксические ошибки отловить легче всего: любой интерпретатор или компилятор просто не пропустит строку, в которой находится синтаксическая ошибка.

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

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

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

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

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

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

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

Здесь мы вплотную подходим к обработке ошибок.

В системе Гедымин существует две возможности обработать возникшую ошибку. Первая возможность реализуется средствами VBScript. VBScript предоставляет программисту конструкцию On Error Resume Next On Error Resume Next включает подавление ошибок. Это значит, что при возникновении ошибки программа не прервет свое выполнение, но продолжит его просто перейдя к следующей операции. При этом во внутренний объект Err будет передана вся информация о возникшей ошибке.

On Error Goto 0 выключает подавление ошибок и сбрасывает объект Err.

Оба выражения действуют только для скрипта, внутри которого они объявлены, и не распространяются на вложенные процедуры и функции.

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

Свойства объекта Err:

• Description – хранит описание возникшей ошибки в текстовом виде.

• HelpContext – хранит идентификатор, указывающий на раздел в файле помощи.

• Number – возвращает код последней возникшей ошибки. Если Number = 0, то значит к текущему моменту выполнение программы шло без ошибок.

• Source – хранит оригинальное название объекта, вызвавшего ошибку.

Методы объекта Err:

• Raise(number, source, description, helpfile, helpcontext) – генерирует ошибку с заданными параметрами. Названия параметров соответствуют свойствам объекта Err.

В качестве примера рассмотрим случай с определением типа переменной.

Option Explicit sub mcr_IsItDate(ByVal AVar) Отметим, что в конце процедуры не обязательно писать выражение On Error Goto 0, т.к. действие конструкции On Error Resume Next прекращается по завершению процедуры.

Однако, чтобы грамотно работать с конструкцией On Error Goto 0, вам придется в критических точках проверять состояние объекта Err. Иногда это удобно, но чаще всего нет. Нередко требуется выполнить какие-нибудь действия при возникновении исключения и прервать выполнение текущей процедуры.

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

Как заставить программу перед прерыванием функции выполнить определенные действия? Для этого используется конструкция Гедымина, не присутствующая в классическом варианте VbScript (все, что указано в квадратных скобках является необязательным):

Except ExcName(argument1 [argumentList]) Оператор Except вызывает процедуру обработки ошибки с наименованием ExcName в случае возникновения исключительной ситуации. Или, проще говоря, если после объявления оператора except и до объявления end except у вас произошла ошибка, то перед прерыванием выполнения функции / процедуры выполнится скрипт с именем ExcName. Скрипт обработки исключительной ситуации обязательно должен иметь хотя бы один входной параметр (argument1).

Замечания • Функция ExcName вызывается с параметрами переданы ей в момент инициализации, т.е., если переменные, переданные функции ExcName, изменились в дальнейшем коде, то, в случае вызова ExcName, в ней будут использаваться переменные со значениями, которые в них были в момент инициализации ExcName. Инициализация обработчика ошибок происходит при считывании оператора Except.

• Каждое следующее объявление оператора Except отменяет действие предыдущего.

• End Except завершает действие всех вышеобъявленных операторов Except данного • Функцию обработки ошибки можно описать, как в том-же скрипт-объекте после основной функции, так и включить по Include • Инструкция Except не поддерживается в функциях, используемых для построения Описание обработки ошибок будет не полным, если не затронуть вопрос о том, как сгенерировать исключение самому. При рассмотрении объекта Err вы наверняка обратили внимание на метод Raise, который генерирует ошибку с переданными параметрами. Однако по такой ошибке тяжело будет проследить историю ее возникновения (см стек вызовов). В системе Гедымин используется глобальный объект Exception, который позволяет генерировать исключения различных типов.

Синтаксис создания исключения следующий:

Exception.Raise, Гедымин позволяет генерировать исключения трех типов:

• Exception – в принципе, это наиболее общий случай, используемый в 99 процентах.

Исключение данного типа останавливает выполнение скрипта и выводит пользователю • EDivByZero – используется для генерации исключения при делении на 0.

• EAbort – это наиболее интересный тип исключений. Он прерывает выполнение программы, но пользователю ничего не говорит. Поэтому параметр «сообщение» может быть любой строкой. Используется обычно для обрыва некоторых действий. Например, вам нужно запретить добавлять новую запись. Тогда на событие BeforeInsert вы пишите исключение с типом EAbort. Пользователь не увидит, что возникло исключение, но и Например, перед сохранением значений, которые ввел пользователь, вы обнаруживаете, что он забыл указать номер документа. Сохранять такой документ некорректно. Поэтому необходимо выдать сообщение пользователю и прервать сохранение документа. Забегая вперед, скажу, что такое исключение лучше создавать в методе DoBeforePost или событии BeforePost бизнес-объекта.

if gdcDocument.FieldByName(“number”).IsNull then Exception.Raise “Exception”, “Укажите номер документа!” Кроме того, существует исключение как объект базы данных. Данный тип исключения (SQLисключения) используется для описания бизнес-логики, используя средства баз данных. Ознакомится более подробно с объектом базы данных «Исключение» можно в главе 8.

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

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

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

Неявное преобразование осуществляется самим компилятором / интерпретатором языка при вычислении каких-либо выражений.

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

Значения, которые может вернуть данная функция приведены в таблице 4.2.

vbSingle 4 Вещественный тип с плавающей точкой обычной точности vbDouble 5 Вещественный тип с плавающей точкой с двойной точностью vbVariant 12 Вариантный тип (используется только с вариантными масивами) Таблица 0. Однако неявное приведение типа может сработать не всегда. Например, если вам необходимо объединить строку и целое число посредством оператора «+», то целое число придется явно привести к строковому типу. Например:

MsgBox “Количество подключенных пользователей: ” + _ Правда, в данном случае можно избежать явного преобразования типа, если использовать вместо оператора «+», оператор «&». Данный оператор не просто сцепляет строки, но и попутно приводит к строковому типу все не строковые операнды выражения.

Так зачем же нужно явное приведение типов? В случае работы с Гедымином явное преобразование типов чаще всего используется для обработки данных, введенных пользователем или для более понятного представления данных. Не секрет, что дата хранится в виде значения вещественного типа.

Чтобы вывести дату в нормальном виде с учетом текущих региональных установок используется функция CDate. Кроме того, явное преобразование типов в VBScript позволяет конвертировать дробные числа в целые с их округлением. Функции, преобразования типов, приведены в таблице 4.3.

CBool Выводит логический результат в виде слов True (истина) и False (ложь) CByte Преобразует число к типу байт. Если число было дробным, то оно округляется, если число превышает допустимые значения (0..255), то возникнет ошибка.

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

CLng Преобразует выражение к длинному целому типу.

CSng Преобразует выражение к вещественному типу с одинарной точностью.

CStr Преобразует выражение к строковому типу.

Таблица 0. Наиболее интересной эта тема является при рассмотрении SQL-запросов. В отличие от VBScript SQL, используемый в Interbase, является жестко типизированным языком. А потому, программисту приходится использовать явное преобразование типов. Для явного преобразования в SQL существует следующая конструкция:

Например, выведем все товары с заголовком. Первое поле используется только для сортировки:

SELECT 1, cast(NULL as integer), cast(‘Все товары’ as varchar(60)) FROM rdb$database Второе приложение. Пишем Тетрис.

Проводя собеседования с кандидатами на вакансии программистов в нашей компании мне часто приходится сталкиваться с такой реакцией: узнав о том, что в качестве основного средства разработки используется Гедымин, человек делает недовольное выражение лица и начинает выяснять почему мы не пишем на C++, Java или хотя бы на Delphi. В его понимании есть «настоящие» языки программирования и, как бы это выразиться по-мягче, «ненастоящие», годные лишь для того, чтобы создавать простенькие программки печати накладных или учета товаров на складе. Наиболее ретивые сразу заявляют, что иметь что-то общее с «низшими» языками для них слишком оскорбительно и их профессиональная гордость просто не позволит им этого. Конечно, настоящий профессионал никогда не позволит себе подобных высказываний. Ведь он знает, что важно не то, на чем написана задача, а как она написана. Тем не менее, после подобного общения всегда остается определенный горький осадок и желание защитить ни в чем не повинный Гедымин, доказать что он ничем не хуже остальных средств разработки. Можно было бы просто сослаться на те задачи, которые уже созданы на нашей платформе, задачи состоящие из сотен тысяч строк кода и эксплуатирующиеся в реальных, что называется, боевых условиях на сотнях больших и малых предприятий. Можно было бы так же упомянуть, что разработчики, использующие Гедымин, часто выходили победителями в заочных дуэлях с конкурирующими компаниями, которые использовали такие известные языки как Delphi, Java, C#. Но, сразу предвижу возражение скептика: опять вы, мол, про склад и бухгалтерию. Скучно. Вот если бы вы могли доказать, что Гедымин способен решать не только экономические задачи. Удивить нас чем нибудь интересненьким. Вот тогда было бы другое дело. Что ж, отложим разработку складских, бухгалтерских задач до следующих глав и покажем на сколько гибки и обширны возможности системы программирования Гедымин. Создадим… игрушку. Конечно, на четвертый Дум мы не посягнем, но логическая головоломка вроде тетриса нам вполне по силам.

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

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

Рис. 28 «Фигуры классического тетриса».

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

Фигура В тетрисе каждая фигура состоит из четырех, прилегающих друг к другу, сегментов. Всего возможно семь различных фигур, отображенных на Рис. 28 «Фигуры классического тетриса». Фигуру можно поворачивать на 90° за один раз, т.е. возможно четыре угла поворота: 0°, 90°, 180°, 270°. Поворот присходит вокруг оси, перпендикулярной плоскости фигурки и проходящей через центр сегмента, помеченного на рисунке крестиком (в дальнейшем мы будем называть этот сегмент «Центральным», хотя он и не соответствует геометрическому центру фигуры). Фигура «Квадрат» не поворачивается вообще, а фигура «Прямоугольник» может принимать только два положения: вертикальное и горизонтальное, т.е. для нее поворот возможет только на 0° и 90°.

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

Угол поворота фигуры будем задавать целочисленным коэффициентом в диапазоне от 0 до включительно. Для того, чтобы получить реальный угол поворота надо данный коэффициент умножить на 90°. Вид фигуры будет также задаваться целым числом в диапазоне от 1 до 7 включительно.

Осталось придумать как задавать конфигурацию фигуры в нашем двумерном пространстве. Координаты фигуры соответствуют координатам центрального сегмента и не меняются при вращении фигуры. Т.е.

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

двумерном пространстве нам надо два числа, для того, чтобы задать координаты объекта. Итого, получим три пары чисел для каждого угла поворота. Всего 24 числа, учитывая, что возможных углов поворота у нас четыре. Эти числа мы разместим в трехмерном массиве, где первый индекс — это угол поворота, второй — номер сегмента, и третий — указывает какая координата хранится в данной ячейке — 0 соответствует координате по оси X, 1 — по оси Y. Данный массив будет заполняться при создании фигуры, в зависимости от ее типа.

Предусмотрим методы для выполнения следующих действий над объектом Фигура:

• Поворот на 90° по часовой стрелке. Данный метод должен инкрементировать на единицу коэффициент, определяющий угол поворота. Если, при этом, значение коэффициента превысило 3, то устанавливать его в 0;

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

• Вернуться к ранее сохраненному положению фигуры;

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

На этом проектирование класса Фигура можно считать законченным и можно приступать к его кодированию. Но перед этим мы сделаем небольшое отступление и познакомимся с тем как в системе Гедымин создаются и используются новые классы.

Синтаксис VB класса VBScript позволяет создавать новые классы, которые в дальнейшем мы будем называть VB классами.

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

Определение класса осуществляется с помощью следующей конструкции:

Class name statements End Class где name — это имя класса, а statements — это одно или несколько определений переменных, свойств, процедур или функций, называемых так же членами класса. Обратите внимание, что в отличие от Delphi, где код определения класса содержит только объявления процедур и функций, в VB классе тексты членов прописываются прямо в тексте класса.

Члены класса могут быть объявлены как Private или Public. Первые видны только внутри кода данного класса, вторые же доступны как для внутреннего кода, так и снаружи. Если переменная или функция (процедура) не содержат явного определения Public или Private, то они считаются общедоступными.

Процедуры или функции объявленные как Public внутри блока класса становятся методами данного класса. Переменные, объявленные как общедоступные, становятся свойствами класса наравне со свойствами объявленными непосредственно с помощью конструкций Property Get, Property Let, Property Set.

Создание и уничтожение экземпляра VB класса Создание экземпляра VB класса осуществляется с помощью оператора New.

Dim X Set X = New classname Уничтожение ранее созданного экземпляра происходит автоматически по завершении блока кода, где была объявлена соответсвующая переменная и при условии, что на нее нет внешних ссылок. Если необходимо уничтожить экземпляр вручную, то необходимо присвоить значение Nothing переменной.

‘ объявление переменной и создание экземпляра класса Dim X Set X = New classname...

‘ использование экземпляра класса...

‘ уничтожение экземпляра класса Set X = Notning...

События Initialize и Terminate Событие Initialize происходит при создании экземпляра класса, а Terminate — при его уничтожении.

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

Class TestClass ' Определение обработчика события Initialize.

Private Sub Class_Initialize MsgBox("TestClass started") ' Определение обработчика события Terminate.

Private Sub Class_Terminate MsgBox("TestClass terminated") End Class ' Создание экземпляра класса TestClass.

Set X = New TestClass ' Уничтожение экземпляра.

Set X = Nothing Класс TCreator Грамотно написанный программный код должен очень бережно относиться к системным ресурсам.

Объекты необходимо создавать непосредственно перед их использованием и удалять как только они перестанут быть нужными. Причем, высвобождение ресурсов должно гарантироваться не только при нормальном выполнении кода, но и при возникновении исключительных ситуаций, ошибок. В Delphi для гарантированного высвобождения ресурсов существует конструкция try…finally…end. Казалось бы, что в VBScript нет необходимости особо беспокоится о высвобождении ресурсов, ведь объекты автоматически удаляются при завершении того блока кода, в котором они были созданы и использовались. Однако при работе с объектами Гедымина существует определенный нюанс. Дело в том, что при создании объекта Гедымина с помощью вызова метода Designer.CreateObject одновременно создаются два объекта. Один — это, собственно, объект указанного класса и второй — это COM объектоболочка поддерживающий интерфейс IDispatch. Объект-оболочка необходим для того, чтобы с объектом Гедымина можно было работать в VBScript. При завершении блока кода объект-оболочка будет автоматически удален, а вот объект Гедымина останется в памяти. Для его удаления необходимо принудительно вызвать метод DestroyObject. Можно, конечно, на каждый созданный объект, где-нибудь в конце процедуры или функции разместить вызов деструктора, однако гарантировать их удаление не удастся — при возникновении ошибки объекты останутся не удаленными. Тут на помощь приходит TCreator — VB класс широко используемый в настройках на платформе Гедымин. Его основное предназначение — помнить список созданных объектов. При удалении экземпляра TCreator вызывается обработчик события Terminate, который автоматически удаляет все созданные с помощью этого объекта объекты.

Использование TCreator выглядит следующим образом:

Sub MySub ‘ Создание экземпляра класса TCreator Dim Creator Set Creator = New TCreator ‘ Создание объекта Гедымина с помощью Creator Dim Obj Set Obj = Creator.GetObject(,, ) ‘ Использование объекта Гедымина ‘ Объект Гедымина удалится автоматически вместе ‘ с Creator, который будет удален по завершении процедуры End Sub VB класс TCreator входит в настройку «Общие данные». Ниже приводится его текст:

'Класс служит для создания объектов методом GetObject.

'Класс гарантирует освобождение объекта по завершению скрипта.

'При использьзовании GetObject освобождение объектов непосредственно в скрипт-функции не требуется, 'оно происходит автоматически при завершению скрипт-функции.

Class TCreator Private FCount Private FObjectArray() Public Sub DestroyAllObjects for I = UBound(FObjectArray) to LBound(FObjectArray) step - if VarType(FObjectArray(I)) = vbObject then FObjectArray(I).DestroyObject FObjectArray(I) = Empty End Sub Public Function GetObject(Params, ClassName, Name) FCount = FCount + if FCount > UBound(FObjectArray) then ReDim Preserve FObjectArray((UBound(FObjectArray) + 1) * 2 - 1) set FObjectArray(FCount) =_ Designer.CreateObject(Params, ClassName, Name) set GetObject = FObjectArray(FCount) End Function 'Используется, в случае необходимости, 'для уничтожения объктов созданных Креатором Public Sub DestroyObject(Object) for I = UBound(FObjectArray) to LBound(FObjectArray) step - if VarType(FObjectArray(I)) = vbObject then if Addr(FObjectArray(I)) = Addr(Object) then FObjectArray(I) = Empty Object.DestroyObject call Exception.Raise("Exception",_ "В списке не найден переданный объект.") End Sub Private Sub Class_Initialize ReDim FObjectArray(7) End Sub Private Sub Class_Terminate DestroyAllObjects End Sub End Class Создание VB классов в Гедымине Для того, чтобы создать VB класс в Гедымине необходимо открыть окно редактора скрипт-объектов, открыть Проводник, установить курсор на раздел VB классы и нажать правую кнопку мыши.

Рис. 29 Раздел VB классы.

В появившмся меню необходимо выбрать команду «Добавить VB класс» в результате чего будет создан новый VB класс, окно с кодом которого откроется справа, на рабочей области редактора скриптобъектов.

Данное окно содержит три вкладки:

• Свойства;

• Зависимость;

Рис. 30 VB класс. Вкладка Свойства.

На вкладке «Свойства» указывается имя класса, имя модуля, которому он принадлежит, произвольный комментарий и локализованное наименование.

При создании нового класса система сама присвоит ему имя. Что-нибудь вроде:

«TVBClass154664603_266640537». Присмотревшись, можно заметить что в сгенерированном имени присутствует префикс «TVBClass» и РУИД класса в базе данных. Если имя, предложенное системой, покажется вам неудобочитаемым (скорее всего, так и будут), то класс можно переименовать. Сделать это необходимо в двух местах: в поле «Наименование класса» на вкладке «Свойства» и, непосредственно, в исходном коде определения класса на вкладке «Скрипт».

Рис. 31 VB класс. Вкладка Скрипт.

На вкладке «Скрипт» располагается, собственно, исходный код класса. При создании нового класса система автоматически сгенерирует пустые обработчики событий создания и уничтожения экземпляра класса.

Не забудьте, что при изменении имени класса, точно такое же имя следует указать и на вкладке «Свойства».

Третья вкладка, «Зависимость», показывает какие скрипт-функции зависят от данного класса. т.е.

включают его по директиве #include, и, в свою очередь, от каких скрипт-функций зависит данный класс.

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

Редактор форм Рис. 32 Редактор форм.

Окно «Редактора форм» содержит список экранных форм, а так же кнопки для вызова команд:

• Создать — вызывает мастер создания новой формы;

• Изменить — открывает выбранную в списке форму для изменения;

• Удалить — удаляет выбранную в списке экранную форму;

• DFM как текст — открывает DFM формы, Обновить — перечитывает список форм12, • Справка — вызавает подсказку по работе с данным окном, • Закрыть — закрывает окно.

Создание новой формы С помощью кнопки «Создать» вызовем мастер создания экранной формы.

Рис. 33 «Мастер создания экранной формы»

Как видно на рисунке, сперва мы должны решить: будем ли мы создавать нашу форму «с нуля» или наследуем ее от одного из предопределенных в Гедымине классов.

В нашем случае нам нужна абсолютно чистая форма, поэтому выбираем «Простая форма» и нажимаем кнопку «Вперед».

Рис. 34 Ввод имени экранной формы.

Введем имя класса формы. Обратите внимание, что все формы имеют префикс “usrf_”, изменить который нельзя.

Нажмем кнопку «Вперед» и затем «Ок» для подтверждения. Новая форма будет создана и открыта в дизайнере.

Дизайнер форм Дизайнер экранных форм системы Гедымин во многом копирует дизайнер среды программирования Delphi.

Когда форма находится в режиме редактирования на экране присутствуют следующие окна:

• Палитра компонентов;

• Инспектор объектов;

Палитра компонентов Если палитра компонентов закрыта, ее можно вызвать на экран воспользовавшись клавишей F10.

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

Рис. 35 Палитра компонентов.

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

• Команда выхода из режима редактирования и сохранения внесенных изменений;

• Команда выхода из режима редактирования без сохранения изменений;

• Команда выхода из режима редактирования и сброс всех сделанных изменений. Возвращение формы в ее первоначальное состояние. Будьте осторожны! Используя данную команду вы рискуете удалить все изменения, в том числе и те, которые вам необходимы. Не забывайте периодически создавать архивную копию базы данных.

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

Рис. 36 Список компонентов.

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

• Выравнивание положения компонентов внутри группы;

• Выравнивание размеров компонентов внутри группы;

• Установка порядка табуляции компонентов на форме.

В правой части палитры компонентов находятся вкладки с пиктограммками компонентов.

Стандартные На данной вкладке находятся основные компоненты для постороения пользовательского интерфейса:

кнопки, списки, закладки, меню, панели, радиокнопки, чекбоксы и т.п.

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

Системные На данной вкладке находятся такие компоненты как: список действий (ActionList), список картинок, таймер и другие.

БД Компоненты На вкладке «БД Компоненты» находятся визуальные компоненты, предназначенные для отображения информации из базы данных.

БД Доступ На данной вкладке находятся компоненты TClientDataSet и TDataSource.

Interbase На вкладке находятся компоненты дял доступа к базе данных на сервере Interbase/Firebird.

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

SynEdit Вкладка содержит четыре компонента для работы с текстовым редактором поддерживающим подсветку синтаксиса.

GDC На вкладке “GDC” находятся все доступные в системе бизнес-объекты.

По правой кнопке мыши можно вызвать контекстное меню, которое содержит единственную команду:

расположить Палитру компонетов поверх всех окон.

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

Рис. 37 Инспектор объектов.

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

Если Инспектор объектов скрыт, вывести его на экран можно с помощью нажатия клавиши F11.

По правой кнопке мыши можно вызвать контекстное меню, которое содержит единственную команду:

расположить Инспектор объектов поверх всех окон.

Создание новой наследованной формы Рис. 38 Выбор базового класса окна.

Конструируем окно тетриса Рис. 39 Окно тетриса.

Исходный код Класс CFigure Class CFigure ' горизонтальная координата фигуры, т.е. координата ' ее центрального сегмента Private FX ' вертикальная координата фигуры, т.е. координата ' ее центрального сегмента Private FY ' конфигурация фигуры задается указанием координат ' трех ее сегментов относительно центрального сегмента ' для каждого из возможных углов поворота ' в массиве FPieces первый индекс -- это угол, ' второй -- номер сегмента и третий указывает по какой ' оси задается координата, 0 -- по Х, 1 -- по У Private FPieces(3, 2, 1) ' текущий угол поворота фигуры Private FAngle ' тип фигуры. Целое число от 1 до Private FType ' три поля используются для сохранения и последующего ' восстановления положения фигуры Private FOldX Private FOldY Private FOldAngle ' конструктор Private Sub Class_Initialize CreateFigure NULL End Sub ' данный метод инициализирует внутренний поля, т.е.

' фактически создает фигуру. Входящий параметр -- это ' другая фигура. Если он указан, то будет создана ' ее копия, если передан NULL, то тип фигуры будет ' определен случайным образом Public Sub CreateFigure(ByRef APeekFigure) FAngle = if IsNull(APeekFigure) then FType = Int(7 * Rnd + 1) else FType = APeekFigure.FigureType end if select case FType ' "палка" FPieces(3, 2, 1) = ' літара Т case ' літара G case ' літара G case ' літара Z case ' літара Z case ' square case end select End Sub ' поворот фигуры на 90 градусов по часовой стрелке Public Sub Rotate FAngle = FAngle + if FAngle = 4 then end if End Sub ' перемещение фигуры на DX, DY относительно текущего положения Public Sub Move(DX, DY) End Sub ' сохранение координат и угла поворота фигуры Public Sub Save FOldX = FX FOldY = FY FOldAngle = FAngle End Sub ' восстановление ранее сохраненных координат и угла поворота Public Sub Restore FX = FOldX FY = FOldY FAngle = FOldAngle End Sub ' отрисовывает фигуру на переданной канве Public Sub DrawFigure(ByRef ACanvas, ByVal AX, ByVal AY,_ ByRef ABmp) if FType = 0 then ' фигура еще не была проинициализирована end if Dim XX, YY, I ACanvas.CopyRect XX, YY, XX + 16, YY + 16, ABmp.Canvas,_ FigureType * 16, 0, FigureType * 16 + 16, XX = AX + PieceCoord(I, 0) * YY = AY + PieceCoord(I, 1) * ACanvas.CopyRect XX, YY, XX + 16, YY + 16, ABmp.Canvas,_ FigureType * 16, 0, FigureType * 16 + 16, next End Sub Property Get X End Property Property Get Y End Property Property Get PieceCoord(APiece, ACoord) PieceCoord = FPieces(FAngle, APiece, ACoord) if ACoord = 0 then PieceCoord = PieceCoord + FX PieceCoord = PieceCoord + FY End Property Property Get FigureType FigureType = FType End Property End Class Класс CWell Class CWell ' калодеж. памеры 10х20. кожная клетка -- цэлы лік.

' 0 -- клетка пустая ' >0 -- клетка занятая. лік паказвае колер клеткі.

Private FTetris Private WellArr Private Sub Class_Initialize ' Setup Initialize event.

Dim Arr(9, 19) WellArr = Arr ResetWell End Sub Private Sub Class_Terminate Set FTetris = Nothing End Sub ' resets well to empty state Public Sub ResetWell End Sub Public Function GetXY(X, Y) if (X >= 0) and (X < 10) and (Y >= 0) and (Y < 20) then GetXY = WellArr(X, Y) End Function Public Sub PutFigure(AFigure) WellArr(AFigure.X, AFigure.Y) = AFigure.FigureType WellArr(AFigure.PieceCoord(I, 0), AFigure.PieceCoord(I, 1)) = AFigure.FigureType End Sub Public Sub DisposeRows(R) for K = LBound(R) to UBound(R) - End Sub Public Sub DrawWell(ByRef ACanvas, AX, AY, ByRef ABmp) ACanvas.CopyRect XX, YY, XX + 16, YY + 16, ABmp.Canvas, GetXY(I, J) * 16, 0, GetXY(I, J) * 16 + 16, if FTetris.Paused then End Sub Public Property Set Tetris(Value) Set FTetris = Value End Property Public Property Get Tetris Set Tetris = FTetris End Property End Class Класс CTetris Public Const sUninitialized = Public Const sPaused = Public Const sInProgress = Public Const sGameOver = class CTetris Public F ' Private F Public Well Private Figure Private PeekFigure Private Bmp Private GameOver Private FPaused Private FState Private DPoints Private DLevel Private DFigures Private DLines Private Sub Class_Initialize ' Setup Initialize event.

set F = GedeminApplication.FindComponent("MyTetrisForm") if not Assigned(F) then set F = Designer.CreateForm(Application, "usrf_Tetris", "MyTetrisForm") set Well = New CWEll set Figure = New CFigure set PeekFigure = New CFigure set DPoints = New CDigits DPoints.SetW F Set Bvl = F.FindComponent("usr_Bevel_Andreik1") DPoints.X = Bvl.Left + DPoints.Y = Bvl.Top + set DLevel = New CDigits DLevel.SetW F Set Bvl = F.FindComponent("usr_Bevel_Andreik4") DLevel.X = Bvl.Left + DLevel.Y = Bvl.Top + set DFigures = New CDigits DFigures.SetW F Set Bvl = F.FindComponent("usr_Bevel_Andreik7") DFigures.X = Bvl.Left + DFigures.Y = Bvl.Top + set DLines = New CDigits DLines.SetW F Set Bvl = F.FindComponent("usr_Bevel_Andreik8") DLines.X = Bvl.Left + DLines.Y = Bvl.Top + set Bmp = Designer.CreateObject(NULL, "TBitmap", "") set TmpStream = Designer.CreateObject(NULL, "TMemoryStream", "") set TmpData = Designer.CreateObject(NULL, "TgdcAttrUserDefined", "") TmpData.SubType = "USR$TETR_DATA" TmpData.SubSet = "All" TmpData.Open TmpData.FieldByName("USR$DATA").SaveToStream TmpStream TmpStream.Position = Bmp.LoadFromStream TmpStream TmpData.Close Designer.DestroyObject(TmpData) Designer.DestroyObject(TmpStream) GameOver = True End Sub Private Sub Class_Terminate ' Setup Terminate event.

set Well = Nothing set Figure = Nothing set PeekFigure = Nothing set DPoints = Nothing Designer.DestroyObject(F) Designer.DestroyObject(Bmp) End Sub Public Sub BindObjects(Value) Set Well.Tetris = Value End Sub Public Sub ShowWindow F.Show Application.ProcessMessages loop while F.Visible End Sub Public Sub Play Randomize GameOver = False FPaused = False do while not GameOver ResetKeys Well.ResetWell DPoints.Value = DLevel.Value = DFigures.Value = DLines.Value = PeekFigure.CreateFigure Null Figure.CreateFigure Null if F.Visible then F.Invalidate Application.ProcessMessages do while F.Visible and (not GameOver) do while not F.Active and F.Visible Application.ProcessMessages WinAPI.Sleep(200) if (WinAPI.GetAsyncKeyState(VK_PAUSE) and 1) 0 then do while FPaused Application.ProcessMessages WinAPI.Sleep(200) if (WinAPI.GetAsyncKeyState(VK_PAUSE) and 1) 0 then FPaused = not FPaused F.Invalidate end if if not F.Visible then FPaused = False end if ResetKeys loop if (WinAPI.GetAsyncKeyState(VK_F2) and 1) 0 then Exit Do end if X= R= if T > ((9 - DLevel.Value) * 60 + 40) then else if (WinAPI.GetAsyncKeyState(VK_F8) and 1) 0 then if DLevel.Value < 9 then DLevel.Value = DLevel.Value + end if if (WinAPI.GetAsyncKeyState(VK_LEFT) and 1) 0 then X=X- end if if (WinAPI.GetAsyncKeyState(VK_UP) and 1) 0 then end if if (WinAPI.GetAsyncKeyState(VK_RIGHT) and 1) 0 then X=X+ end if if (WinAPI.GetAsyncKeyState(VK_DOWN) and 1) 0 then WinAPI.Sleep Delay loop until Figure.Y = end if end if Application.ProcessMessages WinAPI.Sleep(40) GameOver = not F.Visible if F.Visible then set FPlayerName = Designer.CreateForm(F, "usrf_TetrisPlayerName") if (FPLayerName.ShowModal = 1) then set FStat = Designer.CreateObject(NULL, "TgdcAttrUserDefined", "") FStat.SubType = "USR$TETR_STAT" FStat.SubSet = "ByID" FStat.FieldByName("USR$DURATION").AsInteger = FStat.FieldByName("USR$LEVEL").AsInteger = FStat.FieldByName("USR$FIGURES").AsInteger = FStat.FieldByName("USR$POINTS").AsInteger = FStat.FieldByName("USR$LINES").AsInteger = FStat.FieldByName("USR$PLAYERKEY").AsInteger = scrPublicVariables.Value("TetrisPlayerKey") FStat.FieldByName("USR$DATE").AsDateTime = Now Designer.DestroyObject(FStat) Designer.DestroyObject(FPlayerName) End Sub Private Sub ResetKeys WinAPI.GetAsyncKeyState(VK_DOWN) WinAPI.GetAsyncKeyState(VK_UP) WinAPI.GetAsyncKeyState(VK_LEFT) WinAPI.GetAsyncKeyState(VK_RIGHT) WinAPI.GetAsyncKeyState(VK_F2) WinAPI.GetAsyncKeyState(VK_F8) End Sub Public Sub Draw(Wnd) DPoints.Draw DLevel.Draw DLines.Draw DFigures.Draw DrawWell End Sub Private Sub DrawWell Dim I, J, XX, YY Set Bvl = F.FindComponent("usr_Bevel_Andreik2") Call Well.DrawWell(F.Canvas, Bvl.Left + 1, Bvl.Top + 1, Bmp) Call Figure.DrawFigure(F.Canvas, Bvl.Left + 1, Bvl.Top + 1, Bmp) Set Bvl = F.FindComponent("usr_Bevel_Andreik3") F.Canvas.CopyRect XX, YY, XX + SqSize, YY + SqSize, Bmp.Canvas, 0, 0, SqSize, SqSize Call PeekFigure.DrawFigure(F.Canvas, Bvl.Left + 1 - SqSize * 2, Bvl.Top + 1 + SqSize, Bmp) End Sub Private Sub Move(AX, AY, AR) Dim OldA(3, 1), NewA(3, 1) Set Bvl = F.FindComponent("usr_Bevel_Andreik2") Figure.Save OldA(0, 0) = Figure.X OldA(0, 1) = Figure.Y OldA(I + 1, 0) = Figure.PieceCoord(I, 0) OldA(I + 1, 1) = Figure.PieceCoord(I, 1) Call Figure.Move(AX, AY) Figure.Rotate NewA(0, 0) = Figure.X NewA(0, 1) = Figure.Y NewA(I + 1, 0) = Figure.PieceCoord(I, 0) NewA(I + 1, 1) = Figure.PieceCoord(I, 1) Flag = Well.GetXY(Figure.X, Figure.Y) = Flag = Flag and (Well.GetXY(Figure.PieceCoord(I, 0), Figure.PieceCoord(I, 1)) = 0) if Flag then if (OldA(J, 0) = NewA(I, 0)) and (OldA(J, 1) = NewA(I, 1)) then F.Canvas.CopyRect XX, YY, XX + 16, YY + 16, Bmp.Canvas, Figure.FigureType * 16, 0, Figure.FigureType * 16 + 16, F.Canvas.CopyRect XX, YY, XX + 16, YY + 16, Bmp.Canvas, 0 * 16, 0, 0 * 16 + 16, Figure.Restore Well.PutFigure(Figure) Figure.CreateFigure PeekFigure DFigures.Value = DFigures.Value + if (Well.GetXY(Figure.X, Figure.Y) 0)_ or (Well.GetXY(Figure.PieceCoord(0, 0), Figure.PieceCoord(0, 1)) or (Well.GetXY(Figure.PieceCoord(1, 0), Figure.PieceCoord(1, 1)) or (Well.GetXY(Figure.PieceCoord(2, 0), Figure.PieceCoord(2, 1)) 0) then DPoints.Value = DPoints.Value + Figure.FigureType PeekFigure.CreateFigure NULL End Sub Public Sub BurnRows ReDim R(0) if Well.GetXY(J, I) = 0 then ReDim Preserve R(UBound(R) + 1) if UBound(R) > 0 then Set Bvl = F.FindComponent("usr_Bevel_Andreik2") F.Canvas.CopyRect XX, YY, XX + 16, YY + 16, Bmp.Canvas, K * 16, 0, K * 16 + 16, DPoints.Value = DPoints.Value + DPoints.Draw WinAPI.Sleep(200) DLines.Value = DLines.Value + UBound(R) Well.DisposeRows(R) End Sub Public Sub BurnWell Dim Bvl, K, I, J, Q, XX, YY Set Bvl = F.FindComponent("usr_Bevel_Andreik2") F.Canvas.CopyRect XX, YY, XX + SqSize, YY + SqSize, Bmp.Canvas, K * 16, 0, K * 16 + 16, Call WinAPI.Sleep(100) End Sub Public Sub NextLevel if DLevel < 9 then DLevel.Value = DLevel + End Sub Public Property Get Paused Paused = FPaused End Property End Class Заключение Контрольные вопросы • Для чего предназначен VB класс TCreator?

• Чем отличается переменная VB класса, объявленная как Public от Private?

Бизнес-объект Эта глава расскажет о том, что такое бизнес-объект, как он работает, как создавать свои или расширять уже существующие бизнес-объекты. Также здесь мы познакомимся с такими понятиями, как РУИД, идентификатор, и научимся переносить данные между базами.

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

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

Базовым классом, реализующим бизнес-объект, является TgdcBase. Все остальные классы, наследованные от него характеризуются спецификой работы с определенными данными. Например, бизнес-объект для работы с контактами – TgdcBaseContact, для работы с документами – TgdcDocument, всю специфику по работе с товарами взял на себя TgdcGood. Описание специфики бизнес-объектов можно посмотреть в таблице 6.1.

Название класса Описание бизнес-объекта TgdcBase Базовый бизнес-класс, реализующий основу для все остальных бизнес-классов.

TgdcAccount Бизнес-класс для работы с банковскими счетами TgdcAttrUserDefined Бизнес-класс предоставляющий пользователю возможность создавать «с нуля»

TgdcBankStatement Бизнес-класс для работы с выпиской.

TgdcBankCatalogue Бизнес-класс для работы с картотекой.

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

TgdcConst, Этих два бизнес-класса работают в паре. Они позволяют создавать некоторые TgdcConstValue константы, хранящие значения с градацией по времени, активной организации TgdcCurr, TgdcCurrate Данные бизнес-классы предоставляют пользователю интерфейс для работы с TgdcDocument Базовый класс для работы со всеми документами в системе Гедымин. От него наследовано несколько классов, предоставляющих специфичные возможности TgdcInvBaseDocument Предоставляет возможности для создания и обработки складских документов.

TgdcInvBasePriceList Бизнес-класс для работы с прайс-листами.

TgdcUserBaseDocument Базовый класс для создания пользовательских документов.

TgdcDocumentType Позволяет создавать новые типы документов. Это могут быть пользовательские, складские документы, различные прайс-листы.

TgdcGood, Предоставляют доступ к товарам и товарным группам.

TgdcGoodGroup TgdcFunction, Предоставляют доступ к скрипт-объектам. Работа с этими классами напрямую TgdcEvent, TgdcMacros, подразумевает очень глубокие знания работы Гедымина в целом.

TgdcReport TgdcSetting, Эти классы определяют работу настроек системы Гедымин. Понятия TgdcSettingPos, «настройка» мы уже касались в главе 4. Более подробно о настройках можно TgdcSettingStorage узнать в главе 14.

TgdcUser, Данные базовые классы дают доступ к зарегистрированным пользователям TgdcUserGroup, Гедымина, их группам и хранилищу, в котором содержаться специфические TgdcUserStorage установки каждого пользователя.

TgdcValue Базовый класс для работы с единицами измерения.

Таблица 0. В данной таблице предоставлены не все классы, доступные в системе Гедымин. Более подробное их описание с иерархией и расшифровкой доступных методов и свойств смотрите в приложении a (!!!!!).

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

Что такое идентификатор объекта. Понятие РУИД-а Что же такое идентификатор и с чем его едят?

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

Т.е. проще говоря, по идентификатору можно определить о каком объекте идет речь.

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

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

Любые вновь созданные пользователем или системой объекты получают идентификатор в диапазоне 147000000 … 2147483647. Все идентификаторы менее 147000000 являются служебными и зарезервированы системой Гедымин для внутреннего пользования. В любом случае корректный идентификатор будет больше нуля. Если какие либо функции, которые должны возвращать идентификатор записи, возвращают значение меньше или равно нулю, то это значит, что бизнес-объект пустой. Доступ к идентификатору текущей записи бизнес-объекта можно получить, используя свойство ID или напрямую обратившись к ключевому полю. Например, gdcGood.ID или gdcGood.FieldByName(gdcGood.GetKeyField(gdcGood.SubType)). _ AsInteger Во втором случае, мы по подтипу объекта (SubType) берем название его ключевого поля (GetKeyField) и возвращаем его значение. Первый способ обращения к идентификатору записи бизнес-объекта намного короче.

Зачем требуется уникальность идентификаторов именно в пределах базы? В большинстве случаев можно ограничиться уникальностью только внутри таблицы. Здесь мы подходим к понятию РУИД-а. РУИД (RUID – record unique identifier) – уникальный идентификатор записи между базами Гедымина.

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

Затрагивая эту тему, необходимо упомянуть идентификатор базы, который хранится в генераторе GD_G_DBID и создается при первом подключении к базе. Однако если вы делаете копию с базы, желательно обнулить генератор GD_G_DBID, чтобы Гедымин сгенерировал для копии новый идентификатор. Уникальность идентификаторов баз – это необходимое условие для корректного взаимодействия БД.

РУИД формируется как:

Т.е. значение РУИД-а – это строка из двух идентификаторов, разделенных пробелом. За счет уникальности идентификаторов баз и уникальности идентификаторов записей в пределах каждой отдельной базы мы получаем уникальность РУИД-а между базами Гедымина. Что касается служебных идентификаторов (со значениями менее 147000000), то для них идентификатор базы всегда будет 17. Это необходимо для того чтобы РУИД-ы служебных записей были одинаковы между базами.

Например, идентификатор базы равен 1235792, идентификатор администратора – 650002, идентификатор нового клиента – 147000001. Для администратора РУИД будет равен 650002_17, а для нового клиента – 147000001_1235792.

Итак, мы по идентификатору вновь созданной записи можем узнать РУИД. Как узнать идентификатор по РУИД-у? Вовсе не факт, что первое числовое значение перед знаком подчеркивания в РУИД-е является идентификатором (далее ИД) записи в текущей базе. Оно скорее является значением ключевого поля в базе с ИД, равным числовому значению после знака подчеркивания. При переносе данных между базами РУИД-ы сохраняются, а идентификаторы изменяются, т.к. перенос данных – это по сути дела создание новых записей в базе. А как мы помним, при создании новой записи ей присвоится следующий по счету идентификатор из генератора GD_G_UNIQUE.

Чтобы узнать идентификатор по РУИД-у достаточно выполнить маленький запрос к таблице GD_RUID.

SELECT id FROM gd_ruid WHERE xid = :xid AND dbid = :dbid В данный запрос необходимо подставить параметры, которые и являются составляющими РУИД-а. XID – это идентификатор объекта в исходной базе (т.е. в базе, где он изначально был создан), DBID – идентификатор самой исходной базы.

Структуру GD_RUID можно увидеть в таблице 6. Таблица 0. Изменение содержимого таблицы GD_RUID напрямую крайне нежелательно. Ее данные используются при синхронизации различных БД. Гедымин сам добавляет, изменяет или удаляет записи в GD_RUID, если это необходимо.

Для работы с РУИД-ами в глобальном объекте gdcBaseManager существует несколько функций, которые позволяют узнать РУИД по идентификатору и наоборот, не выполняя лишних запросов к базе.

Данный объект создается при загрузке программы и доступен из любого скрипт-объекта.

Функции gdcBaseManager для работы с РУИД-ами:

• GetIDByRUID(XID: Integer; DBID: Integer): Integer – возвращает идентификатор объекта по РУИД-у. РУИД передается как первоначальный идентификатор объекта (XID) и идентификатор базы, в которой был создан объект (DBID) двумя отдельными целочисленными параметрами.

• GetIDByRUIDString(RUIDStr: String): Integer – возвращает идентификатор объекта по РУИД-у.

РУИД передается как строка (RUIDStr).

• GetRUIDByID(ID: Integer; XID: Integer; DBID: Integer) – возвращает РУИД двумя отдельными параметрами (XID, DBID) по переданному идентификатору(ID).

• GetRUIDStringByID(ID: Integer): String – возвращает РУИД строкой по переданному идентификатору (ID).

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

Передавая необходимую вам транзакцию вы сможете узнать текущее значение РУИД-ов даже если транзакция еще не подтверждена. Однако, если транзакция будет откачена, то откатится и создание объектов, а следовательно и созданные РУИД-ы. Ниже приведен список функций gdcBaseManager для работы с РУИД-ами на конкретной транзакции.

• GetIDByRUIDTr(XID: Integer; DBID: Integer; ibtr: TIBTRansaction): Integer • GetIDByRUIDStringTr(RUIDStr: String; ibtr: TIBTransaction): Integer • GetRUIDByIDTr(ID: Integer; XID: Integer; DBID: Integer; ibtr: TIBTransaction) • GetRUIDStringByIDTr(ID: Integer; ibtr: TIBTransaction): String Зачем вообще нужны идентификаторы? Набор из более чем восьми цифр достаточно тяжело читается и не несет практически никакой информации о записи. Куда как понятнее характеризовать запись текстовым полем, которое будет хранить некое смысловое значение. Здесь есть несколько «но»:

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

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

• если рассматривать этот вопрос применительно к Гедымину, то, как было уже сказано выше, платформа поддерживает только простые целочисленные ключи.

Например, вы создали организацию, ссылки на которую есть в банковской выписке, платежных документах, проводках. Затем вы заметили, что в наименовании организации ошибка. Достаточно исправить название в справочнике клиентов, в остальных документах оно автоматически станет отображаться с последней правкой, т.к. идентификатор вы не меняли. Однако имеется и другая сторона медали. Например, организацию переименовали. Т.е. по сути возникло новое юридическое лицо, а старое перестало функционировать. В данном случае нельзя просто исправить название, т.к. во всех документах, которые были выписаны на предыдущее юридическое лицо, станет отображаться новое название. Нужно создать новую запись с новым идентификатором, а старой установить признак «не активна» (в Гедымине для этого служит поле DISABLED).

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

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

SELECT z.name as goodname, v.name as valuename FROM gd_good z LEFT JOIN gd_value v ON v.id = z.valuekey Некоторые дополнительные таблицы, входящие в запрос, играют не только информативную роль, но и роль ограничителей. Так, например, в таблице GD_DOCUMENT регистрируются все документы. Для каждого документа существует еще своя дополнительная таблица, которая хранит специфичную для типа документа информацию. Присоединение такой таблицы по JOIN будет ограничивать выборку из GD_DOCUMENT только ее данными.

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

• GetListTable(const SubType: string): string – возвращает название базовой таблицы бизнесобъекта, исходя из переданного подтипа объекта.

• GetKeyField(const SubType: string): string – возвращает название ключевого поля объекта.

• GetListField(const SubType: string): string – возвращает название поля для отображения.

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

• SubType: string – возвращает подтип бизнес-объекта. Для стандартных бизнес-объектов данное свойство всегда будет возвращать пустую строку. Для бизнес-объектов, созданных пользователем Гедымина, SubType обязательно будет заполнен.

Для работы с базой данный бизнес-объект использует пять видов запросов:

• SelectSQL – запрос на выборку данных из БД.

• InsertSQL – запрос для вставки новой записи в базовую таблицу.

• ModifySQL – запрос для модификации записи в базовой таблице.

• DeleteSQL – запрос для удаления записи из базовой таблицы.

• RefreshSQL – аналогичен SelectSQL, за исключением того, что возвращает только одну запись с заданным ключом. Используется для обновления только что созданной или отредактированной записи. Вызывается после сохранения изменений.

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

Все виды запросов формируются автоматически, исходя из базовой таблицы и подтипа объекта. Таблицы в запросе на выборку обязательно имеют алиас – уникальный в пределах запроса псевдоним. У базовой таблицы алиас всегда будет «z». Кроме того, для всех пользовательских полей-ссылок в запрос на выборку внутренним парсером (разборщиком запросов) добавляются дополнительные таблицы, используя связку по LEFT JOIN, а в SELECT-часть добавляются поля для отображения из этих таблиц.

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

Управлять ссылками в SQL-запросе можно не только через настройки объектов базы данных. В каждом бизнес-объекте есть внутренний настройщик парсера SQL-запросов. Получить к нему доступ можно, используя свойство SQLSetup. Данный настройщик парсера используется чаще всего для указания, какие ссылки при обработке необходимо проигнорировать. Излишнее загромождение запроса дополнительными таблицами и полями ведет к замедлению его работы. Пример использования SQLSetup вы можете увидеть в главе 6.6 «Основные методы и свойства».

Т.к. выше мы коснулись понятия пользовательских объектов базы данных, дадим ему определение.

Пользовательский объект БД – это объект, созданный средствами Гедымина. Наименование любого пользовательского объекта обязательно имеет префикс USR$. Более подробную информацию на эту тему можно получить в главе 8.

Если вас не устраивает автоматически сформированный запрос, вы можете перекрыть соответствующий метод и подкорректировать запрос вручную. О перекрытии методов смотрите ниже.

Итак, наш бизнес-объект имеет пять основных запросов для работы с базой данных. При открытии объекта (метод Open) на сервере выполняется запрос на выборку и на клиентскую машину пересылается некоторое количество записей, которые помещаются в буфер бизнес-объекта. При необходимости записи докачиваются с сервера на клиента. Количество записей, по умолчанию передаваемое сервером, устанавливается сабсетом (или подмножеством) объекта при помощи свойства BufferChunks (определяет размер активного буфера). Подмножество объекта (свойство SubSet класса TgdcBase) задает условия ограничения на выборку записей. Существует несколько стандартных для всех бизнес-объектов сабсетов:

• All – сабсет, устанавливаемый по умолчанию. Означает, что на выборку не наложено никаких дополнительных условий. Количество подкачиваемых записей при этом сабсете • ByID – при данном подмножестве в выборке может быть только одна запись, соответствующая конкретному значению ключа, или же, если запись с таким ключом не найдена, бизнес-объект откроется пустым. Если при данном сабсете количество записей больше одной, то запрос на выборку некорректен.

• ByName – данное подмножество добавляет в WHERE-часть условие, которое ограничивает выборку по заданному значению поля-отображения (GetListField). Количество возвращаемых в сервера записей в этом случае равно 10.

• OnlySelected – данное подмножество работает в паре со свойством бизнес-объекта SelectedID. SelectedID представляет собой сортированный динамический массив целочисленных ключей. Он хранит отмеченные пользователем записи. При установке сабсета OnlySelected в выборке будут только те записи, ключи которых попали в свойство SelectedID текущего бизнес-объекта. При выборе данного подмножества, как и при выборе других подмножеств за исключением трех выше перечисленных, количество подкачиваемых В наследниках класса TgdcBase cуществуют и другие подмножества. Многие из них могут дополнять друг друга, некоторые же являются взаимоисключающими. Например, с сабсетом ByID нецелесообразно использовать другие сабсеты.

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

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

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

Завершение транзакции означает ее закрытие с подтверждением сделанных изменений или их откатом.

В Гедымине поддерживаются следующие уровни изоляции транзакций:

• Транзакция, которая видит записи в том состоянии, в котором они были на момент ее старта.

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

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

Транзакция указывает бизнес-объекту к какой базе подключаться и как работать с данными. Параметры транзакции указывают степень видимости изменений, сделанных другими пользователями на других транзакциях. Как мы уже сказали, бизнес-объект работает с двумя транзакциями. Транзакция на чтение (свойство ReadTransaction класса TgdcBase) позволяет бизнес-объекту подключаться к базе данных и считывать из нее данные. При этом она должна быть настроена таким образом, чтобы видеть подтвержденные изменения других пользователей. По умолчанию каждому бизнес-объекту присваивается транзакция на чтение из свойства ReadTransaction объекта gdcBaseManager. Т.е. по умолчанию все бизнес-объекты системы Гедымин используют одну транзакцию на чтение.

ReadTransaction должна содержать следующие параметры:

• read – разрешает только операции чтения.

• read_committed – возможность видеть подтвержденные изменения других пользователей. Без этого параметра транзакция будет видеть записи в том состоянии, в котором они были на • rec_version – используется вместе с read_committed. Позволяет читать записи, имеющие неподтвержденные версии. Версия записи – это копия записи, которая создается при попытке ее изменить. Эта версия целиком принадлежит транзакции, и все операции в рамках этой транзакции будут производить изменения над версией записи, а не над исходным оригиналом. Данный параметр означает, что при чтении какой-либо записи просто считывается последняя подтвержденная версия записи.

• nowait – при возникновении конфликта немедленно возникает ошибка.

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

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

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

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

Форма просмотра У каждого бизнес-объекта существует своя форма просмотра. Форма просмотра представляет собой немодальное окно, в котором отображается список записей, соответствующих условиям выборки, меню для работы с объектом и панель элементов управления (смотри рисунок 6.1). Базовым классом для всех форм просмотра является класс Tgdc_frmG.

Рисунок 0. Между формой просмотра и бизнес-объектом существует двусторонняя связь: через бизнес-объект мы можем узнать название формы или создать ее, через форму мы можем получить доступ к бизнес-объекту.

Следующие методы бизнес-объекта позволяют напрямую (из скриптов) работать с формой просмотра:

• CreateViewForm(AnOwner: TComponent; AClassName: String; ASubType: String): TForm – создает форму просмотра с переданным классом (AClassName) и сабтайпом (ASubType).

Владельцем формы является AnOwner. Если вы не хотите указывать конкретного владельца, то первым параметром будет nil. CreateViewForm проверяет существует ли переданный класс, если нет, то создается форма с классом, используемым по умолчанию для объекта, вызвавшего метод. Т.е. если вам нужно создать форму просмотра для текущего объекта, то параметр AClassName может быть пустой строкой. Если же вам необходимо создать просмотровую форму для другого объекта, то вы можете просто передать в CreateViewForm необходимый вам класс формы и ее подтип. Кроме того данный метод проверяет, была ли уже создана необходимая форма. Если такая форма действительно уже создана, то метод просто вернет на нее ссылку. В обратном случае, он сначала создаст форму, а затем вернет на нее ссылку. Т.е. данный метод не позволяет создавать несколько форм одного класса и • CreateViewFormNewInstance(AnOwner: TComponent; AClassName: String; ASubType: String;

ANewInstance: Boolean): TForm – данный метод аналогичен CreateViewForm, за исключением того, что он позволяет создавать несколько форм одного класса и сабтайпа.

Для этого необходимо параметр ANewInstance установить в истину. Если этот параметр будет установлен в ложь, то метод будет работать точно так же, как и CreateViewForm. При ANewInstance равным True, метод в любом случае создаст форму указанного класса и • GetViewFormClassName(ASubType: string): string – возвращает название класса формы просмотра для текущего объекта по указанному сабтайпу (ASubType).

Рассмотрим несколько примеров создания форм просмотра из макросов:

‘Создаем бизнес-объект класса «Люди»

set gdcContact = Designer.CreateObject(nil, “TgdcContact”, “”) ‘Создаем форму просмотра, используемую по умолчанию ‘для класса «Люди»

‘Если форма уже создана, то CreateViewForm просто вернет на ‘нее ссылку set frmContact = gdcContact.CreateViewForm(nil, “”, “”) ‘Создаем форму просмотра товаров 'Метод CreateViewFormNewInstance сначала создаст форму, 'и затем вернет на нее указатель set frmGood = gdcContact.CreateViewFormNewInstance(nil, _ “Tgdc_frmMainGood”, “”) Если нам необходимо вызывать форму просмотра из исследователя, то при редактировании ветки исследователя достаточно указать имя бизнес-класса и подтип. Смотри рисунок 6. Рисунок 0. Формы просмотра можно поделить на простые и сложные. Простая форма предоставляет пользователю возможность просматривать один бизнес-объект. Сложные формы отображают связи между несколькими бизнес-объектами. Например, окно для просмотра выписки предоставляет пользователю две взаимосвязанных таблицы: таблицу шапки выписки и таблицу позиций.

Получить доступ к бизнес-объектам, лежащим на форме просмотра можно через свойства формы, такие как:

• gdcObject – дает доступ к главному бизнес-объекту на форме.

• gdcDetailObject – дает доступ к детальному (т.е. зависимому от некоторых свойств главного) бизнес-объекту на форме. Данное свойство доступно только на сложных формах просмотра.

Базовым классом для таких форм является класс Tgdc_frmMDH.

Форма для выбора записей Форма для выбора записей представляет собой разновидность формы просмотра. В принципе она и является формой просмотра бизнес-объекта, только настроенной определенным образом. На форме в режиме выбора становятся доступными панель элементов управления с кнопками «Выбрать все отображенные записи», «Удалить из выбранных все отображенные записи», «Удалить из выбранных все записи»; панель с гридом для выбранных записей и кнопками Ok, Отмена, Удалить; а также в первой колонке грида или в дереве (в зависимости от вида формы и бизнес-объекта, из которого будет идти выбор записей) становятся доступны элементы для выбора записей (checkbox - чекбокс). При выборе записи чекбокс становится отмеченным, а сама запись отображается также в нижнем гриде. Чтобы убрать запись из выбранных, нужно отщелкнуть элемент для выбора записей, или позиционировать курсор на необходимую запись в таблице для выбора на нижней панели и нажать кнопку «Удалить».

Форму в режиме выбора можно увидеть на рис 6.3.

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

Метод ChooseItems используется для вывода формы выбора бизнес-объекта с заданным классом и подтипом. Если пользователь подтвердил выбор записей, то метод вернет Истина, в противном случае (при отмене операции выбора) – Ложь. Синтаксис вызова метода следующий:

ChooseItems(Cl: String; KeyArray: TgdKeyArray;

DoProcess: Boolean; ChooseComponentName: String;

ChooseSubset: String; ChooseSubType: String): Boolean;

Параметры:

Cl - наименование класса объекта, записи которого мы будем выбирать.

KeyArray - список ключей выбранных записей. Если мы передаем непустой список, то на форме выбора записи с переданными идентификаторами будут отмечены "птичками". При закрытии формы с подтверждением выбора KeyArray заполняется ключами вновь выбранных записей.

DoProcess - не используется. Осталось для совместимости с предыдущими версиями. Должно быть False.

ChooseComponentName - наименование компонента на форме из которого будет идти выбор записей.

Если передана пустая строка, то выбор будет идти из датасета, класс и подтип которого наиболее подобны переданным классу и подтипу. Может быть полезен на формах с несколькими датасетами.

ChooseSubset - сабсет(ы), который подставится объекту для выбора записей.

ChooseSubType - сабтайп объекта, записи которого мы будем выбирать.

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

ChooseItemsSelf(DoProcess: Boolean; ChooseComponentName: String;

ChooseSubset: String): Boolean;

Параметры:

DoProcess - не используется. Осталось для совместимости с предыдущими версиями. Должно быть False.

ChooseComponentName - наименование компонента на форме из которого будет идти выбор записей.

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

ChooseSubSet - сабсет(ы), который подставится объекту для выбора записей.

Методы ChooseItems и ChooseItemsSelf возвращают упорядоченные последовательности идентификаторов. Однако иногда полезно вернуть последовательность выбранных записей в том порядке, в котором их отметил пользователь. Для этого используются немного более расширенные методы ChooseOrderItems и ChooseOrderItemsSelf.

Метод ChooseOrderItems аналогичен методу ChooseItems, за исключением того, что его список параметров несколько расширен. Синтаксис вызова следующий:

ChooseOrderItems(Cl: String; KeyArray: TgdKeyArray;

AChosenIDInOrder: VarArray; ChooseComponentName: String;

ChooseSubset: String; ChooseSubType: String;

ChooseExtraConditions: String): Boolean;

Параметры:

AChosenIDInOrder – массив ключей выбранных записей именно в том порядке, в котором их отметил пользователь. Заметим, что в этом варианте команды остался параметр KeyArray, который работает точно также как и в команде ChooseItems.

ChooseExtraConditions – дополнительные условия, накладываемые на бизнес-объект, из которого будет идти выбор. Как мы знаем, ограничить выборку можно используя свойство бизнес-объекта SubSet.

Однако иногда требуется условие не объявленное через подмножества выборки бизнес объекта.

Метод ChooseOrderItemsSelf аналогичен методу ChooseItemsSelf. Его список параметров также расширен. Синтаксис вызова следующий:

ChooseOrderItems(AChosenIDInOrder: VarArray;

ChooseComponentName: String;

ChooseSubset: String; ChooseSubType: String;

ChooseExtraConditions: String): Boolean;

Не используйте методы ChooseItemsSelf и ChooseOrderItemsSelf для выбора записей из объектов класс и подтип которых не совместим с классом и подтипом бизнес-объекта вызвавшего метод.

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

Это становится известно в момент инициализации диалога (метод SetupDialog класса Tgdc_dlgG).

Между диалоговым окном и бизнес-объектом, вызвавшем его, также существует двусторонняя связь. В бизнес-объекте есть несколько методов для работы с диалогами:

• CreateDialogForm – создает форму диалога, заданную для класса по умолчанию.

• CreateDialog(ADlgClassName: string) – переводит бизнес-объект в состояние вставки и выводит на экран модальное окно для редактирования содержимого объекта. Параметр ADlgClassName содержит наименование класса окна для редактирования. Если передана пустая строка, используется окно, заданное для текущего объекта по умолчанию (см.

свойство CreateDialogForm). В свойство BaseState бизнес-объекта добавляется флаг sDialog (sSubDialog - для вложенного диалога). Если в системе Гедымин включена опция "Сохранять значения полей в диалоговых окнах", то полям объекта присваиваются значения предыдущего ввода информации. Затем у диалоговое окно инициализируется (вызывается метод Setup, который передает на диалог ссылку на бизнес-объект, вызвавший метод, и настраивает окно для дальнейшей работы) и выводится на экран. После закрытия диалога, если пользователь подтвердил введенные значения, и в опциях системы установлен флаг "Сохранять значения полей в диалоговых окнах", в пользовательском хранилище сохраняется информация о последнем вводе записи.

• CreateDialogSubType(AClassName: string; ASubType: string) – добавляет запись заданного класса и подтипа и выводит окно для ее редактирования. Используется чаще всего при добавлении новых записей в базовый бизнес-объект. AClassName - наименование класса, запись типа которого будем добавлена. Этот класс должен быть наследником класса бизнесобъекта, вызвавшего метод. ASubType - подтип класса, запись типа которого будет добавлена. CreateDialogSubType создает объект заданного класса и подтипа и вызывает у объекта CreateDialog(""). Затем, если пользователь подтвердил сделанные изменения, происходит синхронизация содержимого созданного объекта и объекта, вызвавшего метод.

• CopyDialog – данный метод копирует текущую запись и выводит диалог для ее редактирования, используя метод EditDialog. Возвращает Истина если копирование произошло без ошибок и пользователь подтвердил его. В обратном случае возвращает Ложь.

• EditDialog(ADlgClassName: string): Boolean - используется для вывода диалога для редактирования текущей записи. Параметр ADlgClassName хранит наименование класса диалога для редактирования записи. По умолчанию передается пустая строка, что означает использование диалога, заданного изначально для текущего объекта. Если передана строка, равная "TGDC_DLGOBJECTPROPERTIES", то вместо диалога редактирования выводится диалог, отражающий свойства текущей записи. При необходимости бизнес-объект переводится в состояние редактирования. После создания диалог инициализируется (вызывается метод Setup) и выводится на экран. Возвращает Истина, если пользователь сохранил изменения, Ложь в случае отмены.

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



Pages:     | 1 | 2 || 4 | 5 |   ...   | 8 |


Похожие работы:

«Форум Петербургский Диалог Программа научно-практической конференции Научные исследования и образование в области логистики и управления цепями поставок: современное состояние и перспективы развития Санкт-Петербургский государственный университет, Высшая школа менеджмента, 14–16 декабря 2011 года, Санкт-Петербург СРЕДА, 14 ДЕКАБРЯ Заезд участников, регистрация и размещение в гостинице 19.00–21.00 Коктейль в ВШМ СПбГУ (Волховский переулок д. 3) 18.00–21.00 Биржа деловых контактов (ауд. 403)...»

«ОГЛАВЛЕНИЕ Раздел 1. Общие положения.. 4 стр. 1.1 Требования к квалификационной характеристике 5 стр. выпускника Раздел 2. Содержание государственной итоговой аттестации. 8 стр. 2.1 Междисциплинарный государственный экзамен по 8 стр. направлению подготовки 030300.62 Психология. 2.2 Выпускная квалификационная работа (бакалаврская 91 стр. работа 3 РАЗДЕЛ 1. ОБЩИЕ ПОЛОЖЕНИЯ Программа государственной итоговой аттестации по направлению подготовки 030300.62 Психология разработана в соответствии с...»

«ПРОБЛЕМА ВОДНОГО БАЛАНСА И ЕГО ПРЕОБРАЗОВАНИЯ Доктор географических наук М. И. ЛЬВОВИЧ Проблема Водный баланс и его преобразование, выдвинутая и разрабатываемая Институтом географии Академии наук СССР, предусматривает комплексное изучение всех источников водных ресурсов страны — речных, подземных вод и почвенной влаги — в их взаимосвязи, обусловленной процессом круговорота воды. Воднобалансовый подход к изучению водных ресурсов позволил обнаружить ряд свойственных им особенностей и...»

«Программа социально-экономического развития Щучанского района на 2012 год и среднесрочную перспективу до 2014 года 1 СОДЕРЖАНИЕ Раздел I. Введение. 3 1. Социально-экономическое положение и основные тенденции развития Щучанского района Курганской области. 3-19 2. Основные проблемы социально-экономического развития Щучанского района Курганской области. 19-20 3. Цели и задачи программы комплексного социально-экономического развития Щучанского района Курганской области, приоритеты социальной и...»

«Тольятти № стр. Разделы Программы п.п. Целевой раздел 1. 3-52 Пояснительная записка 1.1 3 Планируемые результаты освоения обучающимися ООП начального общего образования 1.2 1.2.1. Общие положения 7 1.2.2. Ведущие целевые установки и основные ожидаемые результаты 8 1.2.3. Планируемые результаты освоения учебных и междисциплинарных программ 1.2.3.1. Формирование универсальных учебных действий. 1.2.3.2. Формирование ИКТ-компетентности обучающихся. 1.2.3.3. Основы учебно-исследовательской и...»

«Храни огонь родного очага - краеведческая программа по ознакомлению и сохранению культурного потенциала коренных народов Кольского Заполярья. 1.1.Содержание программы. Краткая аннотация. Поддерживая и развивая инновационные процессы в библиотечном деле, Муниципальное бюджетное учреждение культуры ЗАТО Александровск Централизованная библиотечная система г. Полярный разработала краеведческую программу Храни огонь родного очага по ознакомлению и сохранению культурного потенциала коренных народов...»

«№ 1 (10) Февраль 2010 Дайджест Целевой капитал Содержание Уважаемые коллеги! Клуб Целевой капитал в 2010 году. Представляем вашему вниманию первый (десятый) выпуск Дайджеста Целевой капитал. Новости.3 С января 2010 года в Форуме Доноров началась новая Восьмое заседание Клуба программа - Развитие целевых капиталов в России. Программа Целевой капитал.5 реализуется при поддержке Благотворительного Фонда В. Потанина и является логическим продолжением Клуба экспертов Целевой Восьмое заседание Клуба...»

«Новации в рамках регламента Стала достоянием истории XVIII Ежегодная конференция Российской библиотечной ассоциации, проходившая в Пензе с 12 по 17 мая 2013 г. Её результаты обсуждаются в профессиональных сообществах, что позволяет сделать некоторые наблюдения. Структура ежегодных конференций РБА складывалась с середины 1990-х гг. и в целом сформировалась к началу 2000-х. С тех пор в первый день проводятся предсессионные мероприятия (в Пензе — занятия Школы комплектатора) и собирается Совет...»

«МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ИНФОРМАЦИОННЫХ ТЕХНОЛОГИЙ, МЕХАНИКИ И ОПТИКИ VIII Всероссийская межвузовская конференция молодых ученых Программа 12–15 апреля 2011 года Санкт-Петербург 3 VIII Всероссийская межвузовская конференция молодых ученых. Сессии научных школ. 12–15 апреля 2011 года: Программа. – СПб: СПбГУ ИТМО, 2011. – 75 с. Конференция проводится в рамках реализации программы развития СПбГУ ИТМО на 2009–2018 годы...»

«Государственное бюджетное образовательное учреждение высшего профессионального образования Московской области Международный университет природы, общества и человека Дубна (Университет Дубна) Факультет экономики и управления Кафедра Государственного и муниципального управления Утверждаю проректор по учебной работе С.В. Моржухина _ 2013г. Рабочая программа учебной дисциплины Административное право по направлению (специальности) 081100 Государственное и муниципальное управление Квалификация...»

«Вторая международная конференция разработчиков свободных программ на Протве Тезисы докладов Обнинск 25-27 июля 2005 Оформление и дизайн: Илья Кравец Верстка: Илья Машкин В сборнике представлены тезисы докладов, одобренных Программным комитетом Второй международной конференции разработчиков свободных программ на Протве. Другие материалы конференции можно найти по http://conf.altlinux.ru © Коллектив авторов, 2005 © ALT Linux, 2005 Программа конференции 24 июля 18.00 – 22.00: Регистрация в холле...»

«Министерство общего и профессионального образования Ростовской области ПРИНЯТА: УТВЕРЖДЕНО: Педагогическим советом ГКОУ РО Директор государственного казённого Азовской школы-интерната №10 образовательного учреждения Протокол №1 от 30 августа 2011г. Ростовской области общеобразовательной школы-интерната основного общего образования №10 г. Азова _ Л.В. Деревянко государственного казенного образовательного учреждения ПРОГРАММА РАЗВИТИЯ Ростовской области общеобразовательной школы-интерната...»

«2 ХАРАКТЕРИСТИКА НАПРАВЛЕНИЯ ПОДГОТОВКИ Автоматизация и управление – область науки и техники, которая включает в себя совокупность средств, способов и методов человеческой деятельности, направленных на создание и применение алгоритмического, аппаратного и программного обеспечения систем и средств контроля и управления подвижными объектами, автономными системами, технологическими линиями и процессами, освобождающих человека частично или полностью от непосредственного участия в процессах...»

«Муниципальное общеобразовательное учреждение Бологовская средняя общеобразовательная школа СОГЛАСОВАНО: УТВЕРЖДАЮ: Председатель Совета школы Директор МОУ Бологовской СОШ Е.А. Булкина_ Л.В. Яковлева Протокол № от 28.08.2013г. Приказ № 58/04 от 01.09.2013г ОБРАЗОВАТЕЛЬНАЯ ПРОГРАММА начального общего образования (4 класс), основного общего образования (5-9класс), среднего (полного) общего образования (10класс) на 2013-2014 учебный год 1 п. Бологово, 2013г. СОДЕРЖАНИЕ Введение 3-...»

«Материалы Всероссийской научно-практической конференции ”Начальная школа: современные образовательные стандарты“ Переход на новые федеральные государственные образовательные стандарты второго поколения Зверева С.Н., Москалева Ж.Н., Мушнина С.И. МОУ Лицей №5 г. Губкин, РФ На современном этапе развития общества активизация человеческого фактора выступает как одно из условий общественного прогресса. В связи с этим перед общеобразовательной школой ставится задача подготовки ответственного...»

«Первый и единственный в России Лауреат премии лауреат международной премии Большая цифра в номинации IBС-2009 (Амстердам) в номинации Лучший российский First HD newsroom in Russia информационный канал РЕКЛАМНЫЕ ВОЗМОЖНОСТИ ЭКСПЕРТ-ТВ РОССИЯ И МИР ГЛАЗАМИ РУССКОГО КАПИТАЛА www.tv.expert.ru 123290, г. Москва, 1-й Магистральный проезд, 11, стр. 1, тел.: (495) 651-65- Эксперт-ТВ — это: Канал для бизнес-сообщества Эксперт-ТВ рассказывает и показывает то, что происхои предпринимателей дит в стране и...»

«Организация познавательной деятельности школьников через систему внеклассной работы по математике Мандыбура Любовь Анатольевна, учитель математики МОУ “СОШ № 2” г. Новодвинска Список ИПМ ИПМ 1. Теоретическая интерпретация ИПМ 2. Структура внеклассной работы по математике ИПМ 3. Система развивающих часов по математике в среднем звене ИПМ 4. Декада математики в школе ИПМ 5. Математические профильные отряды ИПМ 6. Этапы организации работы ИПМ 7. Диагностика Библиография Приложение 1. Программа...»

«ВЕДЕНИЕ Генетическое почвоведение – наиболее синтетический и комплексный отраслевой раздел естествознания. Это обусловлено тем, что педосфера - почвенный покров Земли, образуется, существует и развивается во времени на границе раздела атмосферы, гидросферы и литосферы как результата воздействия на них тонкой пленки живого вещества. Каждая из этих геосфер представлена в почвенном покрове материально – почвенным воздухом, почвенной влагой, почвенными минералами, почвенной биотой и поэтому мир...»

«Муниципальное бюджетное общеобразовательное учреждение средняя общеобразовательная школа № 77 г. Липецка. Рассмотрено на заседании МО учителей УТВЕРЖДЕНО естественно-научного цикла приказом МБОУ СОШ№ 77 Протокол № 1 от 28.08.2013 г. Липецка от 29.08.2013 г. Руководитель МО № 108 - о _Т.А.Лосева Рабочая программа по элективному курсу Избранные вопросы физики для 11 Б класса на 2013-2014 учебный год Учитель физики Изьянова Т.А. Пояснительная записка Рабочая программа элективного курса по физике в...»

«ДЕПАРТАМЕНТ ОБРАЗОВАНИЯ ГОРОДА МОСКВЫ ЮГО-ВОСТОЧНОЕ ОКРУЖНОЕ УПРАВЛЕНИЕ ОБРАЗОВАНИЯ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ КАДЕТСКАЯ ШКОЛА-ИНТЕРНАТ №9 МОСКОВСКИЙ ПАНСИОН ГОСУДАРСТВЕННЫХ ВОСПИТАННИЦ РАССМОТРЕНО: СОГЛАСОВАНО: УТВЕРЖДАЮ: на Педагогическом совете с Управляющим советом Директор ОУ / Протокол №1 Протокол В.Т. Силенская от 02 ноября 2012 г. № от _ ноября 2012 г. 10ноября 2012 г. Рабочая программа учебного курса ТЕХНОЛОГИЯ 5-7 класс на 2012-2015 учебный год Составили:...»






 
2014 www.av.disus.ru - «Бесплатная электронная библиотека - Авторефераты, Диссертации, Монографии, Программы»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.