Основные концепции Конвертации данных (КД) для новичков

В КД очень важно понять основные принципы работы. Вроде и самой КД сто лет в обед, и понаписано уже не счесть, но все как-то не так, как мне бы хотелось. Постепенно крепло желание написать эдакое послание самому себе, начинающему изучать КД, да никак руки не доходили. Последней каплей стала очередная попавшаяся на глаза «неправильная» статья, и я решил — ничего страшного, пусть будет еще одна статья, зато гештальт закрою 🙂 Даже если я излишне самонадеян, авось кому-то она все же поможет. Скриншотов не будет, будет только унылый текст. Но я бы в свое время за него многое отдал.
Чтобы не перегружать статью, в ней не освещаются особенности вроде правил регистрации, особенностей КД 3.0 и т.п.

КОНЦЕПЦИИ ОБМЕНА ДАННЫМИ

Правила конвертации. "Конвертация данных" (далее "КД") — это конфигурация/база 1С, где описываются правила, по которым данные из базы-источника (далее "источник") должны преобразовываться в данные базы-приемника (далее "приемник"). Эти правила выгружаются в xml-файл. И все. Больше КД не делает ничего. Несмотря на название, сама конвертация данных — это уже не ее забота. Это просто "конфигуратор" (или если хотите — IDE для разработки правил). Кто же выполняет саму конвертацию? Изначально за это отвечали внешние обработки выгрузки/загрузки, входящие в комплект поставки КД.

Выгрузка. Обработка выгрузки запускается в источнике, ей указывается файл с правилами из КД, некоторые дополнительные настройки выгрузки (типа отборов данных) и обработка формирует файл обмена. И тут важный момент — в файл обмена пишутся УЖЕ КОНВЕРТИРОВАННЫЕ согласно правилам конвертации данные (фактически это готовые образы объектов для загрузки в приемник) плюс информация из правил обмена о поиске нужных объектов в приемнике, плюс тексты программных обработчиков, которые должны быть выполнены при загрузке данных в приемнике (они будут выполняться в нужных местах с помощью банального "Выполнить"). Теперь повторю важный момент с другого ракурса — в нормальной ситуации ВСЯ КОНВЕРТАЦИЯ ВЫПОЛНЯЕТСЯ В ИСТОЧНИКЕ. То есть и все правила конвертации с их взаимосвязями анализируются в источнике и почти все самые важные с точки зрения конвертации программные обработчики — также выполняются в источнике. Этот момент нужно держать в голове, когда вы пишите код программных обработчиков в КД. Это обычный код 1С, который будет исполнен в источнике с помощью инструкции "Выполнить" в контексте алгоритма выгрузки данных. И, соответственно, в этом контексте вы имеете полный доступ к базе источника и можете писать любой корректный для нее код 1С. А как же упомянутые обработчики "при загрузке", спросите вы? Скажу, что в 99% случаев обработчики на стороне приемника не нужны. Но новички часто ими злоупотребляют по банальной причине — они еще не знают, как настроить правила конвертации правильно, а обработчики в приемнике как-то проще для понимания. Код — он и в Африке код 🙂 Но такой стиль ущербен по многим причинам, так как идет в разрез с неявной идеологией КД. Плюс использование обработчиков при загрузке часто сильно замедляет эту самую загрузку. В нормальной конвертации загрузка сводится просто к поиску/созданию нужного объекта и загрузке в него готовых данных, конвертированных еще в источнике. Но если обработчики "при загрузке" вам все-таки нужны, в них, естественно, вы пишите код уже для приемника. Прямого доступа к источнику там уже нет.

Кстати! Многие не сразу понимают этот ньюанс. Ни в один момент времени не существует одновременного доступа к данным и источника и приемника. Даже для случаев обмена через COM остается четкая модель разделения процесса на выгрузку и загрузку. В обычной ситуации, данных источника и метаданных приемника вполне достаточно для правильной конвертации данных (т.е. для выполнения всей конвертации в источнике). Эта идея и заложена в основу идеологии КД. Но бывают редкие случаи, когда нужных для правильной конвертации данных в источнике нет и также нет ни одного способа их вычислить на основании имеющихся в источнике данных. Вот для таких редких случаев на выручку и приходят обработчики на стороне приемника (при загрузке).

Загрузка. В базе-приемнике запускается обработка загрузки данных, указывается файл обмена и… все. Выполняется загрузка 🙂 Вся необходимая информация уже содержится в файле обмена. И так получилось, что почти все про загрузку я уже сказал, когда говорил про выгрузку 🙂

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

КОНЦЕПЦИИ РАЗРАБОТКИ ПРАВИЛ КОНВЕРТАЦИИ

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

Конфигурации. Очевидно, что КД должна обладать знаниями о метаданных источника и приемника. Они загружается в служебные справочники (главный из них — "Конфигурации") через xml-файлы (которые выгружаются из баз источника/приемника специальными обработками, входящими в состав поставки КД). Соответственно, если конфигурации баз источника/приемника изменяются, то описание их метаданных в КД тоже нужно обновлять. Или не нужно, если изменения не затрагивают конвертацию 🙂

Конвертации. В одной базе КД можно настраивать множество правил обмена между разными конфигурациями. Они идентифицируются элементами справочника "Конвертации", в каждом из которых выбираются конфигурации источника и приемника. Каждая конвертация — это по сути набор…

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

У ПКО перечислены ряд событий при выгрузке/загрузке, для каждого из которых можно написать программный обработчик. И львиная доля гибкости КД зарыта именно в этих обработчиках. Чаще всего используется парочка первых обработчиков ("перед выгрузкой", "перед обработкой" и иже с ними). Вся хитрость в том, что обработчики выполняются в специальном контексте, из которого программно можно влиять на сценарий конвертации. Они имеют доступ к ряду заготовленных "ручек" и "кнопочек", которые позволяют реализовывать различные сценарии обмена. Все, что вам нужно для понимания глубины глубин КД после осознания концепций — это ВСТРОЕННАЯ СПРАВКА по этим обработчикам (доступна обычно по кнопке "Информация по обработчикам"). Там описаны все доступные спец-параметры, момент срабатывания события и даже даны примеры использования. Внимательное и вдумчивое чтение этой справки быстро подскажет и покажет вам все доступное многообразие возможных сценариев конвертации так полно и глубоко, как ни в одной книжке не напишут. Ну, например, с помощью параметров "ИсходящиеДанные" и "ВходящиеДанные" можно передавать данные между обработчиками и между разными ПКО, что в отдельных случаях чрезвычайно полезно и позволяет создавать гибридные ПКО ("объект-объект", но часть данных получающих как "ВходящиеДанные").

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

Правила конвертации свойств (далее ПКС). Суть у ПКС такая же, как у ПКО, только уровнем ниже — "выплюнуть" на выход конвертированное поле объекта приемника для записи в файл обмена. Так как в процессе отработки ПКО у самого ПКО так или иначе поданы на вход какие-то данные, то по умолчанию на вход ПКС также подается одноименное свойство из этих данных. Если у ПКО явно задан источник, то можно параметрически выбрать поле источника, которое будет подано на вход (это самый простой случай). Также данные на вход можно подать программно. Итак, данные на входе есть, нужно теперь их при необходимости конвертировать. Если поле имеет примитивный тип и на вход подан такой же — то красота. Вообще ничего делать не надо. А если не примитивный? Тогда… можно параметрически выбрать готовое ПКО, по которому оно будет конвертировано! Вот ради этого красивого жеста и был весь сыр-бор. Единожды оформленное ПКО можно переиспользовать во всех ПКС всех ПКО, где это необходимо. КД по умолчанию поддерживает конвертацию по ссылкам. Это означает, что при конвертации объекта по ПКО входные данные из его ПКС будут переданы на вход указанным в них ПКО и все это рекурсивно повторяется вниз-вниз-вниз. В результате будут автоматически конвертированы и выгружены ВСЕ связанные объекты (это поведение можно изменить). Правда, красота нечеловеческая? Как-то мне пришлось самому писать похожую систему для тесной интеграции 1С с одним внешним продуктом и конвертацией по ссылкам. С тех пор я нежно люблю КД.

У ПКС, так же как и у ПКО, есть собственный набор обработчиков со своими "ручечками" и "кнопочками". Про важность этих обработчиков уже было написано выше, но для ПКС они еще важнее, чем для ПКО, так как по сути собственно конвертация часто выполняется именно на уровне ПКС. Например, в этих обработчиках можно динамически менять ПКО, по которому будет конвертироваться свойство (в зависимости от каких-то условий). Там есть доступ ко всему объекту, поданному на вход ПКО (параметр "Источник"). Можно прямо в обработчике программно назначить данные, которые будут поданы на вход ПКС (параметр "Значение") — это часто используется для конвертации примитивных типов и не только. И многое, многое другое (читайте справку по обработчикам).

Но как же подать данные на вход ПКО? Они могут быть автоматически поданы в процессе конвертации по ссылкам, это можно сделать в коде с помощью встроенной функции ВыгрузитьПоПравилу, БСП может подать зарегистрированные данные из плана обмена, но каноническим способом остается использование…

Правил выгрузки данных (ПВД). Задача ПВД предельно проста — выбрать данные источника, "скормить" их на вход какого-нить ПКО и умыть руки. Можно сказать, что в отличие от пассивных ПКО, ПВД — активны. Они выбирают данные, передают их ПКО и дают отмашку на конвертацию.

В самом своем примитивном виде, при выгрузке "объект-объект" для вида выборки "стандартная выборка" достаточно параметрически указать вид объекта источника и ПКО для него. И все. В обработке выгрузки можно будет активировать это правило и указать для него стандартные отборы (при необходимости).
Для более сложных случаев предусмотрен вид выборки "произвольный алгоритм" и… правильно! ОБРАБОТЧИКИ! 🙂 Можно, например, запросом сформировать нужную выборку данных и подать ее на вход ПКО без источника. Для произвольных выборок будут недоступны стандартные отборы обработки выгрузки, но внутри можно использовать параметры конвертации.

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

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

26 Comments

  1. leosoft

    Супер!

    Когда же разработчики научатся так качественно доносить

    заложенные ими алгоритмы и идеи?

    Reply
  2. ekaruk

    Отлично описано.

    Кратко и сама суть.

    Reply
  3. babys

    Как то однобоко. Такое впечатление, что автор совсем забыл про ПКО: Перед загрузкой, При загрузке и После загрузки. Оченно нужОннеы и полезные финтифлюшки.

    ИМХО, конфликты загрузки в рамках написанной статьи не решите никогда.

    Reply
  4. progr-2008

    Для новичков — полезно.

    Reply
  5. JaneP

    Плюсанула. Читала внимательно, поэтому простите, есть «ньюанс» 🙂

    Reply
  6. pm74
    что в 99% случаев обработчики на стороне приемника не нужны. Но новички часто ими злоупотребляют по банальной причине — они еще не знают, как настроить правила конвертации правильно, а обработчики в приемнике как-то проще для понимания. Код — он и в Африке код 🙂 Но такой стиль ущербен по многим причинам, так как идет в разрез с неявной идеологией КД

    да ну? ну а например заполнение счетов по регистрам в БП , деление документов 1 в 2 итд итп . Есть целый класс задач , которые просто невозможно выполнить на стороне источника

    Reply
  7. herfis

    (6) Единственный класс задач конвертации, которые невозможно выполнить на стороне источника, я в статье упомянул — если информацию для принятия решения невозможно получить в источнике. Все остальное — РЕШАЕТСЯ.

    Reply
  8. pm74

    (7) ну так это очень частое явление

    Reply
  9. herfis

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

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

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

    Reply
  10. pm74

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

    Reply
  11. herfis

    (10) Эта категоричность появилась не с бухты-барахты. У меня многолетний опыт работы с КД и обмена между принципиально разными конфигурациями и самыми головоломными схемами. И количество раз, когда понадобились обработчики на стороне приемника, можно пересчитать на пальцах.

    Reply
  12. 1Concept

    Спасибо за статью, очень хорошо подано.

    Уважаемый Сан Саныч, выскажите экспертное мнение, относится ли одна задача к тем самым 99%, о которых вы пишите:

    Есть табличная часть, и в ней один реквизит никогда не заполняется в Источнике. После первой загрузки в Приемник этот реквизит заполняется руками, но после следующих обменов Источник-Приемник реквизит очищается, флаг «Отключить» в ПКС для реквизитов ТЧ не работает.

    Я решил эту задачу в обработчике ПослеЗагрузки ПКО данного документа: ищу объект и из него беру постоянно очищаемый реквизит ТЧ:

    Если ОбъектНайден = Истина Тогда
    //подставляем карточку анализа
    Если Объект.Ссылка.Товары.Количество() > 0 И Объект.Товары.Количество() > 0 Тогда
    КарточкаАнализаСсылка = Объект.Ссылка.Товары[0].КарточкаАнализа;
    Если ЗначениеЗаполнено(КарточкаАнализаСсылка) Тогда
    Объект.Товары[0].КарточкаАнализа = КарточкаАнализаСсылка;
    КонецЕсли;
    Попытка
    Объект.Записать(РежимЗаписиДокумента.Запись);
    Исключение
    КонецПопытки;
    КонецЕсли;
    КонецЕсли;

    Показать

    Относится ли моя задача к оставшемуся 1% или её тоже можно как-то решить на стороне приемника?

    p.s. в моем случае в ТЧ всегда будет одна строка, поэтому не критикуйте мой неуниверсальный подход.

    Reply
  13. herfis

    (12) Авторитетно заявляю — фиг его знает! Всегда как-то удавалось избегать частичного обновления объектов в приемнике. Так что увы — навскидку ничего путного не присоветую. Надо бы исследовать вопрос, но руки не стоят. Пару раз на заре КД и возникновении подобных затыков, которые касались явных недоработок КД в части редко используемой функциональности, мне было проще пропатчить КД 🙂

    Reply
  14. pm74

    (12) вобще у пкс есть галка — не замещать значение в приемнике, на обычных реквизитах срабатывает, но в случае ТЧ не факт , надежнее ручками вписать как вы делаете

    Reply
  15. herfis

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

    В идеале — заполнять в источнике. При невозможности — как раз попадаем на вариант, когда в источнике нет необходимых данных 🙁

    Reply
  16. Vladimir_Konyrev

    (13) (14) (15) Коллеги, премного благодраен.

    Reply
  17. OgelO

    Толковый материал, спасибо!

    Reply
  18. Zoomby

    Спасибо, почитаем

    Reply
  19. nvv1970
    Плюс использование обработчиков при загрузке часто сильно замедляет эту самую загрузку

    Дельное замечание.

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

    А вот наиболее болезненным моментом загрузки может быть наличие транзакции и следовательно блокировок. Дольше выполняем — дольше блокируем.

    Reply
  20. herfis

    (19)

    А вот наиболее болезненным моментом загрузки может быть наличие транзакции и следовательно блокировок. Дольше выполняем — дольше блокируем

    Все верно. В обработчиках мало кто заморачивается специальным кэшированием и типичный код сплошь и рядом полон явных и неявных обращений к БД, по факту выполняемых в цикле и никак не оптимизированных. При выгрузке подобное редко становится критичным. Загрузка же гораздо более чувствительна, так как выполняет запись в БД и даже чистая запись в БД может занимать значительное время сама по себе. Про накладные расходы на «Выполнить» я уже не упоминаю. Если же удается всю конвертацию выполнить в источнике — то при загрузке выполняются только оптимизированные алгоритмы КД по записи конвертированных образов.

    Reply
  21. gucci76

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

    Теория, которую можно пощупать на практике усваиваются намного лучше!!!!

    Reply
  22. herfis

    (21) Такие статьи уже есть, цель моей статьи была другая.

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

    Должно отлично зайти в качестве практической части 🙂

    ЗЫ. Добавил ссылку на нее в мою статью, чтобы новичкам было проще переходить от теории к практике 🙂

    Reply
  23. Eriksson
    Теперь повторю важный момент с другого ракурса — в нормальной ситуации ВСЯ КОНВЕРТАЦИЯ ВЫПОЛНЯЕТСЯ В ИСТОЧНИКЕ. То есть и все правила конвертации с их взаимосвязями анализируются в источнике и почти все самые важные с точки зрения конвертации программные обработчики — также выполняются в источнике. Этот момент нужно держать в голове, когда вы пишите код программных обработчиков в КД.

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

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

    Reply
  24. herfis

    (23)

    Следует отметить, что существует два основных варианта применения конвертации

    Лично мне кажется, что достаточно один раз разобраться с принципами, чтобы больше не иметь особых проблем с КД. Поэтому и сподвигся на написание статьи. Я ведь тоже нечасто с ней работаю и на память жалуюсь. Но спорить над цена/качество не готов. Всем приходилось что-то писать на скорую руку. Это дело такое. Но объявлять это прям отдельным направлением программирования я бы не стал 🙂

    Reply
  25. mitia.mackarevich

    «Вот для таких редких случаев на выручку и приходят обработчики на стороне приемника (при загрузке).» М да….они настолько редкие что встречаются почти в каждом нормально обмене (объектов так на 150),а не поделках. Разумнее применять обработчики там где это необходимо (да КЭП где то близко), с точки зрения производительности, логики, архитектуры самого решения. Не стоит забывать что блокировки возникают не только при загрузке, но и при выгрузке.

    Reply
  26. Terve!R

    (11) зачем мне что-то изобретать на стороне источника, если я на стороне приемника могу просто написать ЗаполнитьСчетаУчета(). то есть вызвать уже готовую типовую процедуру, и все? Можно категорично все решать на стороне источника, но бессмысленная и глупая трата времени и сил.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *