Текущее время: Вс, авг 03 2025, 16:46

Часовой пояс: UTC + 3 часа


Правила форума


ВНИМАНИЕ!

Вопросы по SAP Query и Quick View - сюда



Начать новую тему Ответить на тему  [ Сообщений: 24 ]  На страницу Пред.  1, 2
Автор Сообщение
 Заголовок сообщения: Re: Область видимости переменных
СообщениеДобавлено: Пн, июл 09 2007, 20:25 
Председатель
Председатель
Аватара пользователя

Зарегистрирован:
Чт, апр 13 2006, 12:32
Сообщения: 1503
Откуда: Питер
sy-uname написал(а):
Code:
  DO 5 TIMES.
    d = d + 1.
    DATA d TYPE i VALUE 0.
    WRITE:/ d.
  ENDDO.


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

rsn81 написал(а):
кстати, еще одна недопустимость использования в ОО контексте - нельзя создавать внутренние таблицы с header line... Никто не знает, почему?


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


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Область видимости переменных
СообщениеДобавлено: Пн, июл 09 2007, 20:31 
Председатель
Председатель
Аватара пользователя

Зарегистрирован:
Чт, апр 13 2006, 12:32
Сообщения: 1503
Откуда: Питер
rsn81 написал(а):
for (int k = 0; k < 5; k++) {
int i = 0;
System.out.println(++i);
}


Кстати, MS Visual С++ только в Visual Studio 2005 поменял область видимости int в
for (int k = 0; k < 5; k++) {

а то тоже было через ж$пу. А вы говорите ABAP старый и несовместимый.


Последний раз редактировалось vga Пн, июл 09 2007, 20:33, всего редактировалось 2 раз(а).

Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Область видимости переменных
СообщениеДобавлено: Пн, июл 09 2007, 20:32 
Гуру-эксперт
Гуру-эксперт

Зарегистрирован:
Вт, сен 07 2004, 17:47
Сообщения: 2988
rsn81 написал(а):
В Java-то как раз есть понятие области видимости переменной... о чем и начинал говорить в первом сообщении.
И в ABAP-е она есть, другое дело что внутри подпрограмм не предусмотрено разделителейоператоров для создания локальных областей видимости. Как и нельзя определять локальные подпрограммы внутри потрограмм (в отличии от Pascal-я)
rsn81 написал(а):
... пример, приведенный в первом сообщении на Java:
Цитата:
for (int k = 0; k < 5; k++) {
int i = 0;
System.out.println(++i);
}
выведет пять единиц в отличие от ABAP-а.
Данный пример не может быть однозначно переведён на ABAP из-за {}

_________________
"После" - не значит "вследствие"


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Область видимости переменных
СообщениеДобавлено: Пн, июл 09 2007, 20:53 
Начинающий
Начинающий
Аватара пользователя

Зарегистрирован:
Вт, июн 05 2007, 05:16
Сообщения: 13
Откуда: Пермь
vga написал(а):
Коллеги, а можете привести хоть один язык, в котором данная конструкция работает? Помоему спор ни о чем.
Согласен.
vga написал(а):
Вы заметили кстати, что взаимодействие с тем же OLE2 реализовано как-раз на классах.
Тоже интересное место... чтобы не мучаться с перехватом OLE-ошибок после каждого OLE-чиха, проверяя содержимое системной переменной (огромная в ABAP-синтаксисе конструкция if-endif или как минимум один вызов подпрограммы) пришлось написать над всеми необходимыми OLE-классами свои классы-обертки (вроде шаблона проектирования - адаптер, который теория чаще всего рекомендует применять при необходимости использовать чужой ненадежный код), которые выполняя типовые действия над OLE-объектами, применяют соответственно минимальное количество аналогичных проверок, а внешнему коду передают ошибку событием - то есть клиенту достаточно один раз подписаться на событие и в обработчике вызвать функцию вывода сообщения об ошибке. Не знаю, возможно ли сделать как-то более проще для клиента OLE-классов... Просто меня удивило такое жуткое неудобство со стороны вроде бы как стандартных реализованных OLE-оберток.
sy-uname написал(а):
И в ABAP-е она есть, другое дело что внутри подпрограмм не предусмотрено разделителейоператоров для создания локальных областей видимости. Как и нельзя определять локальные подпрограммы внутри потрограмм (в отличии от Pascal-я)
Ну так и говорю: область видимости только на уровне подпрограмм: form, class, method и т.п.
sy-uname написал(а):
Данный пример не может быть однозначно переведён на ABAP из-за {}
Как так? Чем код между XXX и endXXX (к примеру, для XXX = do) существенно отличается от кода между { и }?


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Область видимости переменных
СообщениеДобавлено: Пн, июл 09 2007, 21:23 
Председатель
Председатель
Аватара пользователя

Зарегистрирован:
Чт, апр 13 2006, 12:32
Сообщения: 1503
Откуда: Питер
rsn81 написал(а):
Тоже интересное место... чтобы не мучаться с перехватом OLE-ошибок после каждого OLE-чиха, проверяя содержимое системной переменной (огромная в ABAP-синтаксисе конструкция if-endif или как минимум один вызов подпрограммы) пришлось написать над всеми необходимыми OLE-классами свои классы-обертки


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


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Область видимости переменных
СообщениеДобавлено: Пн, июл 09 2007, 21:28 
Гуру-эксперт
Гуру-эксперт

Зарегистрирован:
Вт, сен 07 2004, 17:47
Сообщения: 2988
rsn81 написал(а):
... Ну так и говорю: область видимости только на уровне подпрограмм: form, class, method и т.п.

Есть ещё третий уровень - видимось для TABLES: ... BEGIN OF COMMON PART ... (второй - глобальные переменные отчёта, ГФ).

_________________
"После" - не значит "вследствие"


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Область видимости переменных
СообщениеДобавлено: Вт, июл 10 2007, 06:40 
Начинающий
Начинающий
Аватара пользователя

Зарегистрирован:
Вт, июн 05 2007, 05:16
Сообщения: 13
Откуда: Пермь
vga написал(а):
Интересно, что у вас за разработка, если возникла потребность анализа ошибок таких разноплановых ситуаций?
Ничего такого грандиозного... :-)
С одной стороны, ABAP не особенно подталкивает к повторному использованию кода, конкретно более успешному в этом плане ООП по сравнению с процедурным подходом. С другой стороны, даже имеющийся набор OLE-классов каждый раз порождает overhead. В итоге, как заметил, сотрудники моего отдела в каждой выгрузке/загрузке в/из Excel пишут один и тот же код... отличающийся, пожалуй, только специфическими для каждой программы багами.

Идея состояла в реализации библиотеки классов для упрощения выгрузки/загрузки простых отчетов Excel.

Делегирование

Над каждым необходимым OLE-классом делается обертка, которая, во-первых, дает более высокоуровневый интерфейс взаимодействия, а во-вторых, инкапсулирует все, что повторяется в любом OLE-взаимодействии. Например, повторяющимся действием для OLE является освобождение handler, по аналогии с java.io.Closeable можно оформить интерфейсом:
Цитата:
* Закрытие
interface ICloseable.
methods close.
endinterface.
Данный интерфейс должны реализовывать все классы, работающие с OLE. Пример самих классов-оберток приведу ниже.

Диагностика ошибок

OLE-классы с жутко неудобной диагностикой ошибок. Вместо того, чтобы уведомлять о возникшей ошибке или пробрасывать по стеку вызова возникшее исключение (как происходит в Java), клиент вынужден после каждого чиха спрашивать: ошибка произошла, а сейчас, и теперь тоже все OK? Реализация исключений в ABAP-е не очень чтобы очень, а вот события для этой цели подошли как нельзя кстати.

По сути обычный шаблон проектирования Observer (Издатель/Подписчик):
Code:
* Уведомитель исключения
class ExceptionEventPublisher definition abstract.
  public section.
    events exception exporting value(message) type string.
  protected section.
    methods:
* Проверить наличие ошибки
      check,
* Зажечь событие об ошибке
      raise abstract.
endclass.

class ExceptionEventPublisher implementation.
  method check.
    if sy-subrc <> 0.
      call method raise.
    endif.
  endmethod.
endclass.
Этот абстрактный уведомитель конкретизируется в наследнике, несущем конкретику OLE:
Code:
* Уведомитель Ole-исключения
class OleExceptionEventPublisher definition
  inheriting from ExceptionEventPublisher.
  protected section.
    methods raise redefinition.
endclass.

class OleExceptionEventPublisher implementation.
  method raise.
    data message type string.
    concatenate
      'Error in OLE call'
      sy-msgli
    into message
    separated by ' '.
    raise event exception exporting message = message.
  endmethod.
endclass.
Далее любой класс, работающий с OLE, с одной стороны, наследует класс OleExceptionEventPublisher - оповещает об ошибках делегируемого OLE-класса, а во-вторых, сам подписывается на события создаваемых изнутри него классов (так приложение прослушивает события книг, книга - листов, лист - ячеек и т.п.) и в случае возникновения, пробрасывает выше как собственное.

Самый простой пример (выдрал все неважное из класса):
Code:
* Ячейка
class Cell definition
  inheriting from OleExceptionEventPublisher.
  public section.
    interfaces ICloseable.
    aliases close for ICloseable~close.
    methods:
* Конструктор
      constructor
        importing _cell type ole2_object,
* Получить значение
      getValue
        returning value(result) type string,
* Установить значение
      setValue
        importing value type string.
  private section.
    data:
      cell type ole2_object.
endclass.

class Cell implementation.
  method constructor.
    call method super->constructor.
    cell = _cell.
  endmethod.

  method getValue.
    field-symbols: <_value> type any.
    assign result to <_value>.
    get property of cell 'value' = <_value>.
    call method check.
  endmethod.

  method setValue.
    field-symbols: <_value> type any.
    assign value to <_value>.
    set property of cell 'value' = <_value>.
    call method check.
  endmethod.

* override
  method ICloseable~close.
    if not cell is initial.
      free object cell.
    endif.
  endmethod.
endclass.
С классом Cell в основном работает только класс Sheet: создает его при обработке ячеек, закрывает его (незаметно для клиента) по окончанию обработки вызовом метода close, подписывается на его события об ошибках, пробрасывая выше как собственное при возникновении и т.п.:
Code:
* Лист
class Sheet definition
  inheriting from OleExceptionEventPublisher.
  public section.
    interfaces ICloseable.
    aliases close for ICloseable~close.
    class-data MAX_LINE_WIDTH type i value 256 read-only.
    methods:
* Конструктор
      constructor
        importing
          _sheet type ole2_object,
* Установить название
      setName
        importing name type string,
* Получить ячейку
      getCell
        importing
          rowIndex type i
          columnIndex type i
        returning value(result) type ref to Cell.
  protected section.
* Обработка событий ячейки
    methods catchCellException for event exception of Cell
      importing sender message.
  private section.
    data sheet type ole2_object.
endclass.

class Sheet implementation.
  method constructor.
    call method super->constructor.
    sheet = _sheet.
  endmethod.

  method setName.
    field-symbols: <_name> type any.
    assign name to <_name>.
    set property of sheet 'name' = <_name>.
    call method check.
  endmethod.

  method getCell.
    data range type ole2_object.
    get property of sheet 'cells' = range
      exporting
        #1 = rowIndex
        #2 = columnIndex.
    call method check.
    create object result
      exporting _cell = range.
    set handler catchCellException for result.
  endmethod.

  method catchCellException.
    raise event exception exporting message = message.
  endmethod.

* override
  method ICloseable~close.
    if not sheet is initial.
      free object sheet.
    endif.
  endmethod.
endclass.

Писатели, читатели

По аналогии с Java создал классы, умеющие писать/читать содержимое по соответствующему OLE-каналу.
Code:
* Писатель
interface IWriter.
  interfaces ICloseable.
  aliases close for ICloseable~close.
  data:
    headerLine type table of string.
  methods:
* Записать строку (ListString type table of string)
    writeLine
      importing line type ListString,
* Установить заголовок
    setHeader
      importing header type ListString,
* Получить индекс текущего ряда
    getCurrentRowIndex
      returning value(result) type i.
endinterface.

* Читатель
interface IReader.
  interfaces ICloseable.
  aliases close for ICloseable~close.
  methods:
* Прочитать строку (ListString type table of string)
    readLine exporting line type ListString,
* Получить индекс текущего ряда
    getCurrentRowIndex
      returning value(result) type i.
endinterface.
Соответственно, классы, наследующие данные интерфейсы: SheetWriter/SheetReader (умеет писать/читать с листа), SheetWriter/SheetReader - с книги (писатель учитывает ограничения листа по 64K строк, при необходимости создает новый лист в рамках книги, освобождает ресурсы обработанных листов и т.п.) и другие.

Использование

В итоге простой экспорт выглядит так (не показан только перехват исключений):
Code:
include zbc_excel_io.

data path type string.
path = 'c:\temp\book.xls'.

* Пример генерации XLS-файла

* 1. Создаем XLS-контейнер
data excel type ref to Excel.
create object excel.

* 2. Создаем писатель XLS-документа
data writer type ref to ExcelWriter.
create object writer
  exporting _excel = excel.

* 3. Устанавливаем шапку таблицы
data header type table of string.
append 'Заголовок 1' to header.
append 'Заголовок 2' to header.
append 'Заголовок 3' to header.
append 'Заголовок 4' to header.
call method writer->setHeader
  exporting header = header.

* 4. Формируем строку таблицы
data line type table of string.
append 'Значение 1' to line.
append 'Значение 2' to line.
append 'Значение 3' to line.
append 'Значение 4' to line.

* 5. Записываем строку 20 раз
do 20 times.
  call method writer->writeLine
    exporting line = line.
enddo.

* 6. Сохраняем и закрываем XLS-документ
call method writer->close
  exporting path = path.
Что мы получили:
  • мы избавлены от необходимости работы с OLE-классами напрямую;
  • мы избавлены от необходимости перехвата ошибок после каждого действия, достаточно один раз подписаться на событие exception писателя writer;
  • мы избавлены от низкоуровневой работы с таблицами, к примеру, вся работа с ячейками спрятана внутри используемых нами классов, мы же просто командуем на запись, передавая строку таблицы Excel;
  • мы избавлены от необходимости явно закрывать handler каждого OLE-канала, все это делается автоматически;
  • мы получаем библиотеку со специфическими ошибками, но не множественными, если писать данный функционал каждый раз снова и снова.
vga написал(а):
Наверно как минимум полгода ABAP-а.
Наверно я как-то излишне сильно раздул щеки... :-)
Нет, просто некоторая оптимизация работы отдела, что-то около 3 дней... столько же - научить своих пользоваться данными классами.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Область видимости переменных
СообщениеДобавлено: Вт, июл 10 2007, 09:14 
Председатель
Председатель
Аватара пользователя

Зарегистрирован:
Чт, апр 13 2006, 12:32
Сообщения: 1503
Откуда: Питер
rsn81 написал(а):
call method writer->setHeader
exporting header = header.

* 4. Формируем строку таблицы
data line type table of string.
append 'Значение 1' to line.
append 'Значение 2' to line.
append 'Значение 3' to line.
append 'Значение 4' to line.

* 5. Записываем строку 20 раз
do 20 times.
call method writer->writeLine
exporting line = line.
enddo.


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


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Область видимости переменных
СообщениеДобавлено: Вт, июл 10 2007, 11:04 
Начинающий
Начинающий
Аватара пользователя

Зарегистрирован:
Вт, июн 05 2007, 05:16
Сообщения: 13
Откуда: Пермь
vga написал(а):
Глубоко с вашим кодом не разбирался. Какова логика программы, если скажем запись в header сгенерирует исключение?
Программа продолжит писать строки?
В том примере перехват исключений вообще не показан, конкретно в нем ничего не произойдет. Логику обработки исключений определяет, разумеется, клиент. К примеру, так:
Code:
* Обработчик событий писателя Excel
class ExcelWriterEventHandler definition.
  public section.
    methods catchException for event exception of ExcelWriter
      importing message.
endclass.

class ExcelWriterEventHandler implementation.
  method catchException.
    perform showMessage using 'Ошибка' message.
  endmethod.
endclass.

* Вывести сообщение
form showMessage
  using
    title type string
    message type string.
  if title is initial.
    title = 'Сообщение'.
  endif.
  call function 'POPUP_TO_DISPLAY_TEXT'
  exporting
    titel = title
    textline1 = message.
endform.
Для того, чтобы эта логика заработала достаточно только подписаться на событие исключения у соответствующего объекта (опять же, подписаться достаточно на головной объект, все исключения дочерних объектов будут "снизу вверх" доставлены до него):
Code:
data eventHandler type ref to ExcelWriterEventHandler.
create object eventHandler.
set handler eventHandler->catchException for writer.
Все. Далее, какие бы мы действия не производили с писателем, все исключения мы перехватим и покажем пользователю в виде окна с описанием ошибки без дополнительных телодвижений.


Принять этот ответ
Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 24 ]  На страницу Пред.  1, 2

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


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

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB