Заметки: 1С

Мои мысли о жизни, работе и разных интересных штуках вокруг меня.

Показано: 0 · Страница

Большая таблица на клиенте
19 мая 2019 ·

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

Погонял сейчас простые тесты — да, похоже, что так и есть. Метод выглядит отчасти костыльно и на серьезных нагрузках я его ещё не проверял — но, вероятно, его вполне можно иметь ввиду.

Задержки PageLatch
22 апреля 2019 ·

Задержки вида PageIOLatch (я про них сегодня писал) легко встретить в любых системах, в том числе небольших. С задержками PageLatch дела обстоят наоборот — их трудно заметить, пока пользователей меньше нескольких тысяч.

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

Возможных причин две.

Горячее место в индексе

Такой расклад иногда называют хотспотом. Он возникает, когда мы массово пытаемся писать что-то на последнюю страницу индекса; в первую очередь речь идёт об индексе с монотонно возрастающим ключом — например, любые индексы по полям ссылочного типа (начиная с последних версий 8.2, платформа выдает последовательные GUID — это снижает фрагментацию диска и делает ключ индекса монотонно возрастающим).

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

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

Системные страницы tempdb

Когда мы создаём или удаляем таблицу в базе данных, в ней обновляется ряд служебных страниц — IAM (Index Allocation Map), PFS (Page Free Space), GAM (Global Allocation Map), SGAM (Shared Global Allocation Map) и другие.

Почему это важно для tempdb? Для платформы 1С это база, в которой регулярно создается огромное количество таблиц. Служебные страницы при этом обновляются настолько часто, что при этом возникают задержки семейства PageLatch.

Вообще-то MS SQL Server умеет оптимизировать обновления системных страниц для tempdb, благодаря чему это делается реже, но иногда даже этого не достаточно. Особенно если в tempdb создаются таблицы с индексами — а это очень частый кейс для приложений на 1С.

У проблемы есть несколько возможных решений. Первый — если СУБД старше 2016-й, можно отключить смешанные экстенты через флаг трассировки 1118. При этом исчезнет необходимость сразу в двух служебных страницах — GAM и SGAM. Соответственно, ожиданий на их обновлении не будет. Экстент — это восемь страниц данных, т.е. 64 килобайта; если он содержит страницы одной таблицы — это нормированный экстент, если нескольких — смешанный.

Второй подход — разбивать tempdb (с 2016-й версии СУБД она, кстати, по умолчанию разбивается на восемь файлов). Дело в том, что служебные страницы ведутся в разрезе файлов; если их будет несколько — ожидания на обновлениях служебных страниц будут ниже.

Третий вариант — уменьшать количество временных таблиц с целью снизить нагрузку на tempdb. То есть переписывать наиболее частотные запросы так, чтобы они работали приемлемо быстро без временных таблиц.

Объектные блокировки
22 апреля 2019 ·

Во-первых, сразу, чтобы не путаться: объектные блокировки платформы никак не связаны с управляемыми блокировками и, тем более, блокировками СУБД. Во-вторых, различают два вида: пессимистические объектные блокировки и оптимистические.

Оба вида неплохо описаны на ИТС; ниже — просто краткая выжимка.

Пессимистические блокировки

Накладываются расширением формы, когда пользователь начинает редактировать объект — например, меняет значение поля. Если тот же объект попробует отредактировать в форме другой пользователь — форма, которую он открыл, тоже попробует наложить пессимистическую блокировку, не сможет этого сделать и пользователь получит ошибку «Не удалось заблокировать запись».

То есть платформа в данном случае делает своего рода пессимистичную оценку ситуации: мол, раз первый пользователь начал редактировать объект — скорее всего, он его запишет. Раз так, второму пользователю разрешать редактировать нельзя.

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

Оптимистические блокировки

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

Так вот, в момент записи объекта платформа сверяет ту версию, что была получена при чтении объекта из базы данных и ту, что указана в базе данных в момент записи. Если версии различаются — возникает ошибка «Операция не может быть выполнена из-за несоответствия версии или отсутствия записи базы данных».

Это и есть так называемая «оптимистическая блокировка». Называют её так потому, что платформа тянет с проверкой до последнего — пока не произойдет реальной попытки записи.

Наложить оптимистическую блокировку объекта через код нельзя: версия объекта хранится в поле _Version таблицы данных объекта, заполнением которого занимается СУБД. Напрямую изменить это значение средствами платформы нельзя (можно, впрочем, записать объект — тогда его версия изменится).

Растолстевшие роли
18 апреля 2019 ·

Очень любопытная заметка про неприятности, которые можно нажить командой роли «Снять все права». Нет, никакого криминала, права-то она честно снимает — только вот её вызов может привести к тому, что объект роли на пустом месте сожрёт в несколько раз больше памяти, чем ему реально нужно.

Прочитал, задумался и пошел проверять, как обстоят дела с этим у нас в конфигурации. И что бы вы думали? Накопал десятка два ролей, доверху набитых «снятыми галочками». Выгрузка прав весила около трёхста мегабайт, а после оптимизации — усохла почти втрое.

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

Простая галочка
30 марта 2019 ·

Пару недель назад мы добавили в справочник номенклатуры FirstBIT ERP параметр «Inactive». Задача была простой: если товар больше не нужен пользователю — он ставит галочку и тот исчезает отовсюду (из форм выбора, форм подбора остатков на складах и так далее).

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

Параметры выбора

Но пользователи начали жаловаться, что настройка не работает. Мы полезли разбираться и поняли, что забыли про историю ввода — этот механизм, как оказалось, параметры выбора просто игнорирует. То есть пользователи выбирали в инвойсе какой-то товар, потом делали его неактивным, возвращались и инвойс и… Снова видели в истории товар, который вроде только что отключили.

Мы принялись искать выход. Проблема в том, что история ввода хранится в системном хранилище и повлиять на неё программно нельзя. Можно разве что полностью удалить — но фактическая очистка истории происходит только при перезапуске клиента (и то через раз). Отключить историю вообще? Напоминает лечение простуды отсечением головы.

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

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

Минуточку!

А ведь как все невинно начиналось, а?

Однако механизм неплохо работает, хотя его недостатки налицо: во-первых, системное хранилище будет постепенно пухнуть по мере появления всё новых и новых сочетаний реальных параметров выбора и нашего, фиктивного. Во-вторых, запись номенклатуры теперь потенциально узкое место: два пользователя не смогут одновременно записать номенклатуры, у которых изменены флаги Inactive (будет блокировка при записи нового значения нашего скрытого параметра выбора в общее хранилище).

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

Повторяющийся ключ
1 марта 2019 ·

На Инфостарте вышла любопытная статья про ошибку СУБД «cannot insert duplicate key». Одна из возможных причин сбоя — использование уникального идентификатора объекта для сопоставления при обмене с другими информационными базами (то есть, без служебного регистра, сопоставляющего объекты базы данных с идентификаторами объектов внешней базы).

Такой жести, чтобы уникальные идентификаторы совпали в разных базах для одной и той же таблицы, у меня в практике пока не было. Однако от подхода «единого идентификатора» я отрекся окончательно после того, как делал обмен между FirstBIT ERP и GROTEM / Agent.

Архитектура пилотного решения была такая: данные из FirstBIT ERP выгружались сперва в служебную ИБ 1С, написанную разработчиками GROTEM'а, а уже оттуда — в основную базу данных сервера мобильных приложений.

Сопоставление было сделано очень просто — через идентификаторы объектов. Например, один и тот же документ в обеих базах имел один и тот же идентфикатор. Но были и более сложные схемы: например, контрагент FirstBIT ERP на стороне GROTEM'а превращался в три объекта: собственно контрагента, торговую точку и документ взаиморасчетов.

WAIT WHAT

Да, в документ взаиморасчетов. И все три объекта имели один и тот же идентфикатор — идентификатор контрагента FirstBIT ERP. В общем, не то чтобы это было очень изящным решением, но для платформы такой расклад вполне адекватен и мы решили, что проблем быть не должно.

Однако обмен работать отказался.

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

В итоге выяснилось, что:

  1. В этой самой базе есть таблица, где хранятся все интересующие нас объекты. Документы, элементы справочников, вот это всё.
  2. Эта таблица имеет уникальный индекс по GUID объекта.

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

I will not use GUIDs to map objects!

Неудачная охота
21 февраля 2019 ·

При обновлении платформы до 8.13.12.1790 наткнулись на плавающий баг при переключении текущей страницы элемента на сервере. Конкретно на сервере оно срабатывает, но как только управление возвращается на клиент — текущей страницей становится та, что была до изменения. При этом ещё и происходит событие изменения текущей страницы (как будто пользователь сменил её вручную).

Неприятно, но, в общем, ничего страшного — запатчили баг, описали и зарепортили в 1С. Там пока думают. Но я, внезапно, даже как-то расстроен — когда расследуешь такие штуки, они всегда выглядят немного загадочно и кажется, что ты вот-вот найдешь что-то интересное! Например, новый аспект работы платформы или что-то вроде этого.

И вот, наконец, ты смотришь на проблему под правильным углом, а она — обычный жук. Возможно, полосатый или в крапинку, но жук как жук — сидит себе, шевелит усами. И ты такой: блин, это что — и есть моя добыча? :-)

Большие таблицы значений
17 февраля 2019 ·

Пока писал про поиск строк на клиенте, вспомнил ещё один нюанс, связанный с данными на управляемых формах — тоже про передачу между клиентом и сервером.

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

Но когда платформа решит передать такую таблицу на сервер, начнутся проблемы. Дело в том, что передавать она будет не простой и компактный объект ТаблицаЗначений, а весьма насыщенный ДанныеФормыКоллекция. Разница колоссальна — на одном из наших проектов траты на такой обмен данными составляли порядка 40% от всего времени работы ключевой операции.

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

Найти строки на клиенте
12 февраля 2019 ·

Про то, что метод НайтиСтроки() для коллекций данных формы горазд под шумок наделать серверных вызовов, я узнал довольно давно, столкнувшись с неадекватно долгой прогрузкой формы (там он вызывался прямо в обработчике открытия, да ещё и в цикле). Так делать, конечно, не нужно, на что мягко намекает справка: calling the method executes a server call.

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

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

Внезапный барабанщик
9 февраля 2019 ·

Я пишу на платформе 1С довольно давно и повидал некоторое дерьмо, но такое, честно говоря, вижу первый раз.

Оттакота!

Поначалу я даже не понял, с какого конца это жевать. Поискал перевод иероглифа — Википедия лишь сухо сообщила, что это такой тип чашки, а Google Translate вообще развёл руками.

Коллега заметил, что символ отдаленно похож на складского сортировщика — мол, перекладывает что-то там себе между коробками. Не знаю, не знаю. По-моему, больше напоминает барабанщика за работой. Но что, черт побери, это значит? Может быть, 1С пытается что-то мне сказать? Что-то про музыку?

Может, мне нужно было стать басистом, а не вот это всё.

Удаление временных таблиц
7 февраля 2019 ·

Любопытная деталь: при закрытии менеджера временных таблиц не происходит удаления этих таблиц из tempdb. Актуально и для прямого вызова метода Закрыть() объекта менеджера, и для неявного варианта (когда объект менеджера уничтожается при завершении метода, в котором он был создан). На деле в обеих случаях выполняется только TRUNCATE, который удаляет данные таблицы; сама же таблица остаётся на случай, если пользователь снова выполнит запрос с таким же составом полей (это выгоднее, чем заново её создавать).

То же самое (удаление данных, но не самой таблицы) происходит при прямом вызове УНИЧТОЖИТЬ из текста запроса. К слову, эта команда вообще редко бывает осмыслена — разве что если объект менеджера живет сравнительно долго, а во временную таблицу помещён большой объем данных, от которого хочется побыстрее избавиться.

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

Конкатенация строк
27 января 2019 ·

Как и многие другие компании, мы даем соискателям тестовое задание. Оно намеренно несложное и нужно больше для того, чтобы посмотреть — насколько кандидат понимает платформу? Как аккуратно работает с объектами конфигурации и её кодом?

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

Однако тут есть другой аспект. В первой половине прошлого года «Рарус» опубликовал отчет о работах, проделанных для «Билайна». Там много любопытного, но среди прочего есть совершенно оглушительный пункт: за счет отказа от соединения строк разработчики добились 40% снижения нагрузки на процессоры! От двух дополнительных серверов после этих изменений вообще отказались, так как они стали не нужны.

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

Не скомпилированный код
27 января 2019 ·

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

Другой подход с тем же эффектом — это хранение кода внутри базы (в реквизитах служебных справочников, например). Каждый раз, когда такой код нужно запустить, он извлекается из БД и компилируется. Например, у нас в конфигурации можно создавать регламентные задания без изменения метаданных — просто добавляем элемент специального справочника, загружаем в него код и настраиваем расписание работы.

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

А ещё можно вообще отказаться от хранения кода и сделать весь механизм в виде расширения. Возможно, решение будет менее гибким, но все же это лучше, чем потом медитировать над низким APDEX'ом.

Знак амперсанда в 1С
27 декабря 2018 ·

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

Пример ниже выведется как «Project Costing». Символ «P» в ней будет подчеркнут и станет горячей клавишей; если это, например, заголовок команды, то её можно будет вызвать, нажав Alt + P.

ТекстНадписи = "&Project Costing";

Единственное неудобство — если нужно вывести амперсанд прямо в надпись. В этом случае символ следует удвоить: так, пример ниже будет выглядеть как «Project P&L». Никаких горячих клавиш в таком случае создано не будет.

ТекстНадписи = "Project P&&L";
Ссылка нового объекта
29 ноября 2018 ·

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

ИнвойсЗагружен = Документы.Инвойс.ПолучитьСсылку(UUID).Пустая();

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

Я это к чему. Метод УстановитьСсылкуНового() в коде нужно использовать с осторожностью! Проверяйте, что ссылка ещё не установлена до выполнения вашего кода:

СсылкаЗадана = ПолучитьСсылкуНового().Пустая();

Если ссылка задана, то это надо как-то обработать — либо не заменять её вашей (если логика задачи позволяет), либо создать исключение. Иначе может возникнуть нарушение связности данных, которое будет непросто расследовать — да и вообще заметить.

Ну и, конечно, эта штука работает в обе стороны — я имею в виду, что установленную вами ссылку тоже может потереть какой-нибудь посторонний код (например, обработчик события объекта или подписка на него). Это надежно решается только тестированием.

СКД и право просмотра
28 августа 2018 ·

Универсальный подход системы компоновки данных «если у пользователя нет права на просмотр чего-то, то этого как бы нет» иногда заставляет платформу выкидывать знатные фортели. Нет, сферический отчет в вакууме и правда работает хорошо — например, если нет права на просмотр какого-то справочника, то в отчете он фигурировать не будет. Однако реальные примеры бывают посложнее.

Например, пару недель назад я отлаживал отчет, который при попытке генерации выдавал понятную на первый взгляд ошибку:

У вас настройка кривая, товарищ!

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

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

Что касается ошибки, при столкновении с ней стоит вывести проблемный отчет под полными правами. Если тут всё о'кей, нужно набросать список таблиц, откуда отчет читает данные, и проверить — все ли они с правами на чтение и просмотр.

Нудно, но может сэкономить прилично времени.

Сообщение пользователю
30 апреля 2018 ·

В 1С:Предприятии есть удобный метод вывода сообщений — объект СообщениеПользователю. Он выводит их в нижней части формы и это, внезапно, потенциальная проблема: дело в том, что большинство пользователей туда не смотрит. Мол, если никаких явных ошибок на экране нет — беспокоиться не о чем.

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

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

Чего так серьезно?
17 февраля 2018 ·

Иногда при отладке какого-нибудь сложного механизма не хватает времени на адекватные имена переменных и методов. Как итог — в коде появляются загадочные КакогоФига, ПрименитьМагию и прочие ЖивыеНеудачи.

Этого нужно избегать, правда. На первый взгляд, конечно, смотрится забавно, но через месяц-другой написанный код нужно будет доработать — и тут-то проблема встанет в полный рост! Материться сквозь зубы на автора не выйдет лишь потому, что автор — ты сам.

Выгрузка автобусных рейсов
17 ноября 2017 ·

С тех пор, как мы с коллегами заново автоматизировали КПАТ, она работает на «Управлении автовокзалами». Это конфигурация для 1С:Предприятия, то есть её можно сравнительно быстро интегрировать почти с чем угодно.

Первым делом мы решили наладить выгрузку маршрутного расписания автобусов на E-Traffic и Яндекс.Расписания.

Что это за ресурсы?

Первый ресурс, E-Traffic — это крупнейший в России агрегатор данных автовокзалов. Собирает информацию о запланированных рейсах и выступает как агент по продаже электронных билетов. То есть пассажирам не нужно продираться через сайты автовокзалов — на E-Traffic можно купить билет откуда угодно куда угодно.

Что касается Яндекс.Расписаний — это один из дочерних проектов российского поисковика. Как и E-Traffic, предназначен в первую очередь для пассажиров и умеет быстро строить относительно сложные маршруты с пересадками. Билетами они, правда, не торгуют.

Как была сделана выгрузка?

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

Технически всё было сделано в виде веб-сервиса для «Управления автовокзалами». Получив SOAP-запрос от E-Traffic, он собирал внутри информационной базы 1С:Предприятия все необходимые данные о запланированных автобусных рейсах и возвращал их в виде XML-ки.

Нам даже не пришлось писать код получения расписания с каждого вокзала, входящего в сеть КПАТ'а: все они создаются и хранятся в одном месте — главном узле РИБ, а веб-сервис мы развернули именно там. В итоге больше времени ушло на разные согласования, чем на программирование.

А где посмотреть?

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

Авибус
16 февраля 2015 ·

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

По-моему, очень круто! В том числе и тем, что это один из проектов, постепенно разрушающих заплесневелый, но невероятно устойчивый даже среди айтишников миф про 1С — типа, это скучный тормозной софт для бухгалтеров, а настоящие пацаны пишут только на C++ (Java, Javascript, подчеркните, впишите) и тому подобные бредни.