<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>dev.101101101.ru</title><subtitle>Техническое приложение к блогу 101101101.ru</subtitle><author><name>dev.101101101.ru</name></author><id>https://teletype.in/atom/dev.101101101</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/dev.101101101?offset=0"></link><link rel="alternate" type="text/html" href="https://dev.101101101.ru/?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/dev.101101101?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-05-13T10:45:02.985Z</updated><entry><id>dev.101101101:funny</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/funny?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>Забавное</title><published>2026-03-14T11:52:51.850Z</published><updated>2026-03-14T11:57:05.337Z</updated><summary type="html">Позвонил аналитик-питонист...</summary><content type="html">
  &lt;p id=&quot;sRiM&quot;&gt;Позвонил аналитик-питонист...&lt;/p&gt;
  &lt;p id=&quot;pQ0z&quot;&gt;- Как мне из 1С достать начисления и оплаты покупателей в разрезе договоров? - поинтересовался он.&lt;br /&gt;- Оборотно-сальдовая ведомость по счету 62 - ответил я.&lt;/p&gt;
  &lt;p id=&quot;4quE&quot;&gt;И тут же пришло понимание, что для него эта фраза прозвучала, как какое-то заклинание. Понятно, что человек, увлеченный прогрессивными технологиями, в этом не виноват. Появится больше времени - поделюсь, покажу, научу...&lt;/p&gt;
  &lt;p id=&quot;yXcP&quot;&gt;Огорчает другое. Как далеки все эти надутые как пузырь современные парадигмы со всеми своими, по сути второстепенными, шашечками от реального мира. А в реальном мире технарям, и не только им, очень полезно разбираться в экономике и бухгалтерии...&lt;/p&gt;
  &lt;p id=&quot;Rm8w&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;80eI&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/AutorecordingOfAccountingTransactions&quot; target=&quot;_blank&quot;&gt;←41&lt;/a&gt; | заметка 42&lt;/p&gt;

</content></entry><entry><id>dev.101101101:AutorecordingOfAccountingTransactions</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/AutorecordingOfAccountingTransactions?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>Автоматическая запись бухгалтерских проводок</title><published>2026-03-01T15:39:06.083Z</published><updated>2026-03-31T09:42:24.032Z</updated><summary type="html">Примерно раз лет в 10 возникает эта простая задача. Помнить это естественно невозможно, поэтому решил записать (в том числе для себя), чтобы больше не разгребать странные советы из поисковиков...</summary><content type="html">
  &lt;p id=&quot;KAaG&quot;&gt;Примерно раз лет в 10 возникает эта простая задача. Помнить это естественно невозможно, поэтому решил записать (в том числе для себя), чтобы больше не разгребать странные советы из поисковиков...&lt;/p&gt;
  &lt;p id=&quot;gY9g&quot;&gt;Итак, нужно у автоматически создаваемых документов подправить стандартные проводки и добавить еще несколько новых. Больше всего для решения подходит вполне себе типовой механизм ручной корректировки. Тут 1С-ники использовали неудачный термин. Вручную делать это вовсе необязательно...&lt;/p&gt;
  &lt;pre id=&quot;lpmG&quot;&gt;//Сначала заполненный программно документ проводим как обычно,
//чтобы кроме проводок записались все необходимые регистры
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);

//Затем меняем реквизит ручной корректировки и записываем уже без проведения
НовыйДокумен.РучнаяКорректировка = Истина;
НовыйДокумен.Записать(РежимЗаписиДокумента.Запись);

//Перебираем существующие проводки, заменяем счет и субконто
Для Каждого Движение из НовыйДокумен.Движения.Хозрасчетный Цикл
	Если Движение.СчетКт = НеправильныйСчет Тогда
		Движение.СчетКт = ПравильныйСчет;
		
		//Перед установкой субконто обязательно очищаем имеющуюся коллекцию:
		//и виды, и значения
		Движение.СубконтоКт.Очистить();
		
		//Устанавливаем нужные субконто (допустим счет у нас взаиморасчетный)
		Движение.СубконтоКт.Контрагенты = НужныйКонтрагент;
		Движение.СубконтоКт.Договоры = НужныйДоговорКонтрагента;
		Движение.СубконтоКт.ДокументыРасчетовСКонтрагентами = НужныйДокумент;
	КонецЕсли;
КонецЦикла;

//Фрмируем новые проводки (например нужно частично сторнировать поступление)
Для Каждого СтрокаНачислений из МассивСтрокНачислений Цикл
	НовоеДвижение = НовыйДокумен.Движения.Хозрасчетный.Добавить();
	НовоеДвижение.Период = НовыйДокумен.Дата;
	НовоеДвижение.Регистратор = НовыйДокумен.Ссылка;
	НовоеДвижение.Активность = Истина;
	НовоеДвижение.СчетДт = Счет20_01;
	НовоеДвижение.ПодразделениеДт = НужноеПодразделениеЗатрат;
	НовоеДвижение.СубконтоДт.НоменклатурныеГруппы = СтрокаНачислений.НоменклатурнаяГруппа;
	НовоеДвижение.СубконтоДт.СтатьиЗатрат = СтрокаНачислений.СтатьяЗатрат;
	НовоеДвижение.СчетКт = Счет60_01;
	НовоеДвижение.СубконтоКт.Контрагенты = НужныйКонтрагент;
	НовоеДвижение.СубконтоКт.Договоры = НужныйДоговорКонтрагента;
	НовоеДвижение.СубконтоКт.ДокументыРасчетовСКонтрагентами = НужныйДокумент;
	НовоеДвижение.Организация = НужнаяОрганизация;
	СуммаБезНДС = СтрокаНачислений.СуммаБезНДС;
	НовоеДвижение.Сумма = -СуммаБезНДС;
	НовоеДвижение.СуммаНУДт = -СуммаБезНДС;
	НовоеДвижение.СуммаНУКт = -СуммаБезНДС;
	НовоеДвижение.Содержание = &amp;quot;Реализация услуг&amp;quot;;
КонецЦикла;

//Записываем проводки
НовыйДокумен.Движения.Хозрасчетный.Записать();&lt;/pre&gt;
  &lt;p id=&quot;Y3FM&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;oug8&quot;&gt;Вот и все. В результате получается проведенный документ с нужными нетиповыми проводками. Иногда, сейчас уже очень редко, это нужно. А ломать стандартный механизм проведения или создавать новый вид документов не пришлось.&lt;/p&gt;
  &lt;p id=&quot;SchV&quot;&gt;P.S. Только важно помнить, что у помеченных на удаление документов с ручной корректировкой проводки остаются. У них просто переключается свойство Активность в положение Ложь. И понятно для чего так сделано. Чтобы при снятии пометки удаления все восстановилось как было. Поэтому в запросах не к виртуальным таблицам, а напрямую к записям регистра бухгалтерии (и других регистров) надо не забывать это учитывать (обязательно добавлять условие &amp;quot;Активность = Истина&amp;quot;). В примере ниже данные не выведутся:&lt;/p&gt;
  &lt;pre id=&quot;uGNd&quot;&gt;Выбрать * Из РегистрБухгалтерии.Хозрасчетный
Где Регистратор Ссылка Документ.РеализацияТоваровУслуг
и Регистратор.ПометкаУдаления = Истина и Активность = Истина&lt;/pre&gt;
  &lt;p id=&quot;llGT&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;ezmj&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/DeletingRows&quot; target=&quot;_blank&quot;&gt;←40&lt;/a&gt; | заметка 41 | &lt;a href=&quot;https://dev.101101101.ru/funny&quot; target=&quot;_blank&quot;&gt;42→&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>dev.101101101:DeletingRows</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/DeletingRows?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>Правильное удаление строк</title><published>2026-01-10T12:20:13.364Z</published><updated>2026-03-01T15:43:58.776Z</updated><summary type="html">Как обычно очень простая задача. Зачем такое вообще пишу, ведь легко и быстро гуглится, да и языковые модели все это знают и умеют. Но ключевое слово здесь &quot;Правильное&quot;...</summary><content type="html">
  &lt;p id=&quot;je2y&quot;&gt;Как обычно очень простая задача. Зачем такое вообще пишу, ведь легко и быстро гуглится, да и языковые модели все это знают и умеют. Но ключевое слово здесь &amp;quot;Правильное&amp;quot;...&lt;/p&gt;
  &lt;p id=&quot;YipF&quot;&gt;Итак имеем таблицу, например табличную часть документа, где главная колонка - номенклатура. Например:&lt;/p&gt;
  &lt;pre id=&quot;tKYE&quot;&gt;1. Помидор
2. Огурец
3. Редиска
4. Лук
5. Укроп&lt;/pre&gt;
  &lt;p id=&quot;kDRV&quot;&gt;Допустим хотим удалить Помидор и Редиску. И для этого у нас заполнился МассивИндексовДляУдаления с соответствующими индексами 0 и 2...&lt;/p&gt;
  &lt;p id=&quot;eBLj&quot;&gt;Возьмем цикл с прямым обходом:&lt;/p&gt;
  &lt;pre id=&quot;fGUu&quot;&gt;Для Каждого Индекс из МассивИндексовДляУдаления Цикл
	Таблица.Удалить(Индекс);
КонецЦикла;&lt;/pre&gt;
  &lt;p id=&quot;rjcx&quot;&gt;При этом удалятся Помидор и Лук. Потому что после удаления строки помидора, строка лука станет третьей (с индексом 2). Эта ошибка известна всем.&lt;/p&gt;
  &lt;p id=&quot;vZN0&quot;&gt;Хорошо, тогда давайте сделаем цикл с обратным обходом, ну или проще, отсортируем наш массив индексов по убыванию:&lt;/p&gt;
  &lt;pre id=&quot;4Wxi&quot;&gt;Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(МассивИндексовДляУдаления);
Список.СортироватьПоЗначению(НаправлениеСортировки.Убыв);
МассивИндексовДляУдаления = Список.ВыгрузитьЗначения();
Для Каждого Индекс из МассивИндексовДляУдаления Цикл
	Таблица.Удалить(Индекс);
КонецЦикла;&lt;/pre&gt;
  &lt;p id=&quot;fDw4&quot;&gt;Удалились Помидор и Редиска. Все работает, все отлично. Но давайте порассуждаем дальше. Зачем нам удалять строки? Вероятно срабатывает какая-то проверка, которая по какому-то условию находит лишнее и заполняет массив для удаления. А если мы потом добавили еще одну проверку. И какая-то строка была настолько отвратительной, что не прошла обе проверки и в итоге в массив для удаления ее индекс добавится дважды. Ведь мы же обязательно забудем проконтролировать дубли :-) Как сработает наш код, если попробовать дважды удалить Редиску? А удалятся Редиска и Лук. Без какой-либо сигнализации об ошибке. И всплывет это счастье вовсе не на тестах, а уже в эксплуатации когда успеет много чего испортить.&lt;/p&gt;
  &lt;p id=&quot;KQy5&quot;&gt;Поэтому всегда следует удалять строки не по индексу, а по значению. То есть в массив для удаления нужно добавлять сами строки таблицы:&lt;/p&gt;
  &lt;pre id=&quot;ebdl&quot;&gt;Для Каждого СтрокаТаблицы из МассивСтрокДляУдаления Цикл
	Таблица.Удалить(СтрокаТаблицы);
КонецЦикла;&lt;/pre&gt;
  &lt;p id=&quot;uhSr&quot;&gt;Это же даже проще. Синтаксис такой-же, а направление обхода теперь не важно. Ну а если в массиве появится задвоение, удалить уже удаленную строку не удастся, поэтому будет вызвано исключение, пользователю выведется информация об ошибке, при этом ничего не испортится. Программист добавит проверку массива на дубли и все будет хорошо.&lt;/p&gt;
  &lt;p id=&quot;N7fT&quot;&gt;Ну то есть, этот конкретный пример подталкивает нас к использованию двух фундаментальных принципов:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;JH9L&quot;&gt;Не нужно делать сложно, если можно сделать просто&lt;/p&gt;
    &lt;p id=&quot;Nugq&quot;&gt;Не нужно использовать потенциально опасные приемы, даже если это разрешено&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;0pY4&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;JYWI&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/stoppers&quot; target=&quot;_blank&quot;&gt;←39&lt;/a&gt; | заметка 40 | &lt;a href=&quot;https://dev.101101101.ru/AutorecordingOfAccountingTransactions&quot; target=&quot;_blank&quot;&gt;41→&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>dev.101101101:stoppers</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/stoppers?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>Заглушки в отдельном расширении</title><published>2025-11-07T16:19:03.970Z</published><updated>2026-01-10T12:26:04.273Z</updated><summary type="html">Предположим прямо в конфигурации 1С есть старые самописные бредовые обработки и вместо них в расширении с интенсивным развитием уже созданы и используются аналогичные нормальные. Удалить физически маразм пока нельзя, чтобы сохранить историю (было - стало). Небольшой простой совет, как с этим жить поаккуратнее...</summary><content type="html">
  &lt;p id=&quot;g3b5&quot;&gt;Предположим прямо в конфигурации 1С есть старые самописные бредовые обработки и вместо них в расширении с интенсивным развитием уже созданы и используются аналогичные нормальные. Удалить физически маразм пока нельзя, чтобы сохранить историю (было - стало). Небольшой простой совет, как с этим жить поаккуратнее...&lt;/p&gt;
  &lt;p id=&quot;RlBx&quot;&gt;К сожалению в расширении нельзя убрать объекты из интерфейса. Но можно и, на первое время, нужно поставить &amp;quot;заглушки&amp;quot;. Заимствовать в расширение форму, а в модуле написать:&lt;/p&gt;
  &lt;pre id=&quot;R7G0&quot;&gt;&amp;amp;НаСервере
Процедура ПрефиксИмен_ПриСозданииНаСервереВместо(Отказ, СтандартнаяОбработка)
	Сообщить(&amp;quot;Этот бред устарел и отключен! Вместо него используйте другой...&amp;quot;);
КонецПроцедуры

&amp;amp;НаКлиенте
Процедура ПрефиксИмен_ПриОткрытииВместо(Отказ)
	ЭтаФорма.Закрыть();
КонецПроцедуры&lt;/pre&gt;
  &lt;p id=&quot;dIpH&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;Uo4u&quot;&gt;Все отлично и наглядно, но ведь обязательно придет время физического удаления ненужных обработок. И тогда важно не забыть удалить заглушки из расширения, а то оно не применится. А если оно большое и в нем все активно используется, если кучу пропавших механизмов и элементов интерфейса заметят пользователи, а что будет если наоборот не обратят внимания и получат кривые записи в базе данных...&lt;/p&gt;
  &lt;p id=&quot;SNJh&quot;&gt;Ну и тут на ум приходит простое очевидное правило из заголовка статьи. Заглушки и любые другие изменения в объектах, которые скоро или когда-нибудь потом будут удалены, нужно делать в отдельном специальном расширении. Не применится, ну и ладно. Во всяком случае ничего сильно страшного не произойдет. Конечно лучше вообще таких ситуаций не допускать, например с помощью чек-листа с проверками. Но в реальной жизни возможны любые накладки. И если сбой потенциально возможен, пусть он будет безобидным.&lt;/p&gt;
  &lt;p id=&quot;qDqL&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;FHGN&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/UglyButWorkingSolution&quot; target=&quot;_blank&quot;&gt;←38&lt;/a&gt; | заметка 39 | &lt;a href=&quot;https://dev.101101101.ru/DeletingRows&quot; target=&quot;_blank&quot;&gt;40→&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>dev.101101101:UglyButWorkingSolution</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/UglyButWorkingSolution?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>Отвратительное, но рабочее решение</title><published>2025-04-29T15:30:06.625Z</published><updated>2025-11-07T16:42:32.511Z</updated><summary type="html">В отчете необходимо было добавить колонку с информацией, имеются ли настройки в табличной части основания регистратора некоего регистра или нет...</summary><content type="html">
  &lt;p id=&quot;EpSb&quot;&gt;В отчете необходимо было добавить колонку с информацией, имеются ли настройки в табличной части основания регистратора некоего регистра или нет...&lt;/p&gt;
  &lt;p id=&quot;50lz&quot;&gt;База данных маленькая, служебная. Вид деятельности (сдача в аренду нежилых помещений) ну никак не предполагает стремительного роста объема данных. В итоге позволил себе написать в запросе такой кусок:&lt;/p&gt;
  &lt;pre id=&quot;zftq&quot;&gt;Где Регистратор.Основание.ПоказателиОборота.НомерСтроки в (1)&lt;/pre&gt;
  &lt;p id=&quot;BEHq&quot;&gt;Несколько разыменований, лайфках определения пуста ли таблица с помощью проверки есть ли в ней строка с номером один. В общем выглядит это ужасно. Но оно работает и обратите внимание, синтаксис почти повторяет текст задания. Да и писать это - несколько секунд. Лучше потратить время на получение основных данных, а не этого вспомогательного поля.&lt;/p&gt;
  &lt;p id=&quot;rahx&quot;&gt;Через какое-то время оно к сожалению упало, когда у основания одного из регистраторов тип стал составным. Наругалось так:&lt;/p&gt;
  &lt;pre id=&quot;IoyI&quot;&gt;Нельзя обращаться к вложенной таблице через поле составного типа&lt;/pre&gt;
  &lt;p id=&quot;VujB&quot;&gt;Но эта ошибка (в простом и понятном коде) очень легко обнаружилась и исправилась. Буквально за пару минут. Надо было просто привести составной тип к нужному:&lt;/p&gt;
  &lt;pre id=&quot;lXTg&quot;&gt;Где Выразить(Регистратор.Основание Как Документ.РегистрацияДоговоровАренды).ПоказателиОборота.НомерСтроки в (1)&lt;/pre&gt;
  &lt;p id=&quot;cHAY&quot;&gt;Теперь не сломается никогда.&lt;/p&gt;
  &lt;p id=&quot;trzj&quot;&gt;Даже не знаю, зачем это пишу, что и кому хочу доказать. Понятно, что надо учитывать масштабирование, рост объема данных и возможные будущие тормоза. Но на практике на нагруженных системах чаще встречаются инциденты из-за неправильной архитектуры и применения медленных алгоритмов. И это бывает у тех же авторов, которые идеально и многоэтажно (без разыменований, с кучей явных соединений) пишут запросы. Примеры:&lt;/p&gt;
  &lt;ul id=&quot;KaC7&quot;&gt;
    &lt;li id=&quot;d02a&quot;&gt;Дополнительный интеграционный код, хранящийся в дополнительных реквизитах (в другой таблице без индекса).&lt;/li&gt;
    &lt;li id=&quot;COHg&quot;&gt;Сервис часто отдающий объемные одинаковые данные (изменение номенклатуры и цен) сотням клиентов, вместо горизонтального масштабирования и кеширования в виде публикации готового файла.&lt;/li&gt;
    &lt;li id=&quot;SCoQ&quot;&gt;Падение файловых магазинных розничных баз из-за блокировок типовых планов обмена.&lt;/li&gt;
    &lt;li id=&quot;gbeH&quot;&gt;Программный перебор ячеек экселевской таблицы, вместо загрузки целой области или вообще работы с CSV.&lt;/li&gt;
    &lt;li id=&quot;7eZN&quot;&gt;Массовая запись в регистр сведений (сегменты номенклатуры) без использования транзакций.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;JhJy&quot;&gt;Понимаете, пройдет время, выйдут новые версии 1С и СУБД, выполнение запросов с разыменованиями будет оптимизировано и ускорено, а архитектурные просчеты и медленные циклические операции так и будут приводить к деградации производительности учетных систем. Как-то так...&lt;/p&gt;
  &lt;p id=&quot;Rrn7&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;Hp8d&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/NegativeStep&quot; target=&quot;_blank&quot;&gt;←37&lt;/a&gt; | заметка 38 | &lt;a href=&quot;https://dev.101101101.ru/stoppers&quot; target=&quot;_blank&quot;&gt;39→&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>dev.101101101:NegativeStep</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/NegativeStep?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>Отрицательный шаг цикла</title><published>2025-04-14T20:47:23.144Z</published><updated>2025-04-29T22:01:18.194Z</updated><summary type="html">Если вы программируете на чем-нибудь высокодуховном, то вероятно будете смеяться. Ведь нам в 1С до сих под этого не подвезли...</summary><content type="html">
  &lt;p id=&quot;xXq3&quot;&gt;Если вы программируете на чем-нибудь высокодуховном, то вероятно будете смеяться. Ведь нам в 1С до сих под этого не подвезли...&lt;/p&gt;
  &lt;p id=&quot;ESHt&quot;&gt;Как же обойти значения от большего к меньшему? Раньше применял что-то подобное:&lt;/p&gt;
  &lt;pre id=&quot;qPqI&quot;&gt;Для СчетчикЦикла = 1 По Всего Цикл
	НужноеЗначение = Всего - СчетчикЦикла + 1;
	...
КонецЦикла; &lt;/pre&gt;
  &lt;p id=&quot;PYTb&quot;&gt;Особенно бесила эта дурацкая плюс единица, из-за которой надо было внимательно проверять как оно будет работать, особенно если речь идет о коллекции с индексами.&lt;/p&gt;
  &lt;p id=&quot;Jg04&quot;&gt;А тут внезапно, в поисковике проскочила оригинальная идея:&lt;/p&gt;
  &lt;pre id=&quot;BTmb&quot;&gt;Для СчетчикЦикла = -Всего По -1 Цикл
	НужноеЗначение = -СчетчикЦикла;
	...
КонецЦикла;&lt;/pre&gt;
  &lt;p id=&quot;FGUB&quot;&gt;Ну согласитесь, что это красота! И главное, в таком подходе невозможно ошибиться.&lt;/p&gt;
  &lt;p id=&quot;01FF&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;ZGLS&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/CorrectStringSearch&quot; target=&quot;_blank&quot;&gt;←36&lt;/a&gt; | заметка 37 | &lt;a href=&quot;https://dev.101101101.ru/UglyButWorkingSolution&quot; target=&quot;_blank&quot;&gt;38→&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>dev.101101101:CorrectStringSearch</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/CorrectStringSearch?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>Правильный поиск в строке с разделителями</title><published>2024-11-23T07:45:14.208Z</published><updated>2025-04-14T20:51:36.558Z</updated><summary type="html">Чтобы понять проблему, как всегда рассмотрим несколько утрированный пример...</summary><content type="html">
  &lt;p id=&quot;j5QA&quot;&gt;Чтобы понять проблему, как всегда рассмотрим несколько утрированный пример...&lt;/p&gt;
  &lt;p id=&quot;5lfV&quot;&gt;При интеграции из другой системы прилетает массив расчетных показателей. Их много. Записывать их отдельно в какой-нибудь таблице в своей базе данных необязательно. Для работы нужны 2-3 из 100, не более. Поэтому такой массив временно хранится в строке с разделителями, примерно так:&lt;/p&gt;
  &lt;pre id=&quot;eafm&quot;&gt;СуммаОборота; СуммаОборотаСНДС; ээНачальныеПоказания; ээКонечныеПоказания&lt;/pre&gt;
  &lt;p id=&quot;FaBm&quot;&gt;Так вот, на каком-то этапе некий парсинг ищет в этой строке. Как искать правильно? Допустим простое решение в лоб:&lt;/p&gt;
  &lt;pre id=&quot;J5Oc&quot;&gt;Если Найти(СтрокаПоказателей, СтрокаПоиска) Тогда&lt;/pre&gt;
  &lt;p id=&quot;Wklk&quot;&gt;Но ведь косяк же. Видите его? Честно признаюсь, я несколько раз больно натыкался. Например:&lt;/p&gt;
  &lt;pre id=&quot;YBkh&quot;&gt;Если Найти(СтрокаПоказателей, &amp;quot;СуммаОборота&amp;quot;) Тогда&lt;/pre&gt;
  &lt;p id=&quot;pSCn&quot;&gt;Поиск будет неожиданно успешным если суммы оборота в показателях нет, зато есть сумма оборота с НДС. Обидно. Что делать в таких случаях?&lt;/p&gt;
  &lt;p id=&quot;NMbH&quot;&gt;Понятно, что если перед поиском строку переделать в массив и искать в нем, все будет в порядке. Но тратить на это время, особенно если таких строк много и наш парсинг работает в цикле, такое себе решение.&lt;/p&gt;
  &lt;p id=&quot;P9DF&quot;&gt;Добавить в строку поиска разделитель? Но у последнего элемента разделителя же нет. Ну так в чем проблема, давайте его добавим и в строку показателей (один раз прямо перед поиском):&lt;/p&gt;
  &lt;pre id=&quot;ecsP&quot;&gt;СтрокаПоказателей = ХранящаясяСтрокаПоказателей + &amp;quot;;&amp;quot;;

Если Найти(СтрокаПоказателей, СтрокаПоиска + &amp;quot;;&amp;quot;) Тогда&lt;/pre&gt;
  &lt;p id=&quot;5gQA&quot;&gt;Вот теперь все хорошо.&lt;/p&gt;
  &lt;p id=&quot;jkk5&quot;&gt;Еще один важный момент. Понятно, что к поиску надо всегда относится аккуратно. Ну а наименование любых сущностей надо продумывать с удвоенной внимательностью. Что такое эта наша СуммаОборота? Какая она, с НДС или без НДС, ведь это же неочевидно, это почему-то надо помнить, и программистам, и пользователям. А вот если бы было явно: СуммаОборотаБезНДС, СуммаОборотаСНДС, то ошибки поиска бы не возникло. В итоге вырисовывается полезное правило:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;LV3N&quot;&gt;Если в наименование какой-либо сущности добавляется уточнение, то тогда не должно быть случаев без этого уточнения.&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;NVFS&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;Zu4r&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/DidNotWork&quot; target=&quot;_blank&quot;&gt;←35&lt;/a&gt; | заметка 36 | &lt;a href=&quot;https://dev.101101101.ru/NegativeStep&quot; target=&quot;_blank&quot;&gt;37→&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>dev.101101101:DidNotWork</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/DidNotWork?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>Не сложилось</title><published>2024-11-17T07:58:29.282Z</published><updated>2024-11-25T12:10:38.220Z</updated><summary type="html">Функциональная парадигма. Полностью функциональные языки программирования, круто, таинственно, доступно только для избранных...</summary><content type="html">
  &lt;p id=&quot;7cbs&quot;&gt;Функциональная парадигма. Полностью функциональные языки программирования, круто, таинственно, доступно только для избранных...&lt;/p&gt;
  &lt;p id=&quot;qIWB&quot;&gt;Смотрю подкаст со счастливым адептом, умиляюсь, завидую. А ведущий возьми, да и поинтересуйся: &amp;quot;Вот у вас нет переменных, в смысле переменные не могут менять значения. Как же так. К примеру, как вы в таком случае реализуете алгоритм сортировки?&amp;quot;. А гуру и говорит: &amp;quot;Так это же в готовой библиотеке сделано, естественно нормально. Там переменные значения меняют&amp;quot;. О как! Получается, стандартные вещи у них решены удобно, а для собственных разработок зачем-то нужно мучиться.&lt;/p&gt;
  &lt;p id=&quot;nrVk&quot;&gt;Да ну его, подумал я, взял, да и выключил этот бред. В общем не сложилось у меня с функциональщиной.&lt;/p&gt;
  &lt;p id=&quot;aNfn&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;vlAc&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/ForAallTheGoodAgainstAllTheBad&quot; target=&quot;_blank&quot;&gt;←34&lt;/a&gt; | заметка 35 | &lt;a href=&quot;https://dev.101101101.ru/CorrectStringSearch&quot; target=&quot;_blank&quot;&gt;36→&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>dev.101101101:ForAallTheGoodAgainstAllTheBad</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/ForAallTheGoodAgainstAllTheBad?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>За все хорошее против всего плохого, хотя так не бывает</title><published>2024-11-16T01:32:41.754Z</published><updated>2024-11-24T18:42:56.881Z</updated><summary type="html">Полистал старую книгу по программированию. Когда-то именно в ней нашел размышления про эффект первого разбитого окна, про необходимость немедленного ремонта (исправления ошибки) для предотвращения дальнейшего разрушения (потери контроля над проектом). После такого откровения и остальным тезисам автора веришь. Но сейчас, при повторном прочтении, обнаружилось странное...</summary><content type="html">
  &lt;p id=&quot;7U8V&quot;&gt;Полистал старую книгу по программированию. Когда-то именно в ней нашел размышления про эффект первого разбитого окна, про необходимость немедленного ремонта (исправления ошибки) для предотвращения дальнейшего разрушения (потери контроля над проектом). После такого откровения и остальным тезисам автора веришь. Но сейчас, при повторном прочтении, обнаружилось странное...&lt;/p&gt;
  &lt;p id=&quot;lCLi&quot;&gt;Причем это очень популярное заблуждение теоретиков от программирования. Почему-то считается, что надо одновременно бороться с дублирующим и зависимым (связанным) кодом. Типа с помощью декомпозиции (повторного использования кода путем вынесения его в отдельную процедуру или функцию) можно добиться изоляции (когда доработки ничего не ломают). Но как же так. Ведь даже в обычной жизни очевидно, что нельзя быть за все хорошее против всего плохого. Нельзя выступать за низкие налоги и одновременно за высокие социальные льготы, потому что такое просто невозможно.&lt;/p&gt;
  &lt;p id=&quot;dOTF&quot;&gt;В проекте с идеальной декомпозицией без дублей кода, с огромным количеством маленьких процедур, функций, методов, которые стремительно вызывают друг друга, изоляция невозможна, потому что все зависит от всего. Одно небольшое исправление может как эффект бабочки привести к самым неожиданным последствиям. А уж зависимость от сторонних разработок (библиотек) у большинства из нас вызывает яркие воспоминания об отказах после обновлений, описать которые можно только на эмоциональном русском языке. Наоборот, изолированный (несвязанный) код процедуры, функции, метода должен содержать в себе важные фрагменты, которые могут встретиться где-нибудь еще. Лишь бы изменение, добавление, обновление в одном месте системы не повлияло на другие отлаженные механизмы. Изоляция также может быть на уровне модулей с заимствованием (дублированием) служебных процедур и функций из других модулей и стандартных (сторонних) библиотек. Например, чтобы легко перенести модуль в другой (новый или наоборот устаревший) проект.&lt;/p&gt;
  &lt;p id=&quot;W4mW&quot;&gt;То есть, получается, что декомпозиция и изоляция - антагонисты и взаимодействие между ними - это шкала:&lt;/p&gt;
  &lt;pre id=&quot;fCSq&quot;&gt;Декомпозиция &amp;lt;-------------------------&amp;gt; Изоляция&lt;/pre&gt;
  &lt;p id=&quot;mQIc&quot;&gt;Ну или если вам не нравится такое представление, можно наоборот:&lt;/p&gt;
  &lt;pre id=&quot;xYDb&quot;&gt;Изоляция &amp;lt;-------------------------&amp;gt; Декомпозиция&lt;/pre&gt;
  &lt;p id=&quot;wcSp&quot;&gt;Важно, что направления противоположны и в крайних положениях код получается отвратительным. То есть абсолютная декомпозиция также вредна, как и абсолютная изоляция.&lt;/p&gt;
  &lt;p id=&quot;uva1&quot;&gt;Так что же делать, где на рассматриваемой шкале поставить свою точку? Тут-то и сказывается опыт разработчика, который примет приемлемое решение исходя из задачи. Если нужно написать какую-нибудь утилиту для чего-нибудь очень специфического, в качестве Open Source или может речь идет о внутренней офисной системе с большими технологическими окнами (нерабочее время и целые выходные), то здесь вполне можно блеснуть передовыми технологиями и декомпозицией. А если у вас интеграция розничных продаж с банками, где возможны прямые финансовые потери вкупе с трудоемким неочевидным интеграционным тестированием и неотзывчивой техподдержкой, то ну его на фиг, пусть все методы будут максимально изолированными даже с дублирующим кодом. Чтобы при добавлении нового, не упало то что работало.&lt;/p&gt;
  &lt;p id=&quot;u02P&quot;&gt;Можно конечно пообещать себе и вселенной, что любой рефакторинг для улучшения декомпозиции обязательно пройдет процесс полного подробного тестирования. Но мы же взрослые люди, прекрасно понимаем, что это вранье.&lt;/p&gt;
  &lt;p id=&quot;onX7&quot;&gt;Вы все еще не согласны со мной? А если скажу, что ставшая популярной микросервисная архитектура (в противовес монолиту) - это отчаянная попытка добиться изоляции, с пониманием, что раз сервисы разные, значит и одинаковый код, просочившийся в каждый из них, больше не под запретом! Ну разве это не забавно...&lt;/p&gt;
  &lt;p id=&quot;ujiO&quot;&gt;Может показаться, что не стоит читать книги с сомнительными советами или крайне осторожно выбирать техническую литературу. Это не так. Просто не надо относится к писателям, как небожителям. Они обычные люди, такие же как мы. Они делятся своими знаниями и естественно могут заблуждаться. Просто не надо слепо верить написанному. Читайте, пробуйте, делайте собственные выводы. Придет время и может оказаться, что вы разобрались в теме лучше, чем написано в книге.&lt;/p&gt;
  &lt;p id=&quot;h4DQ&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;mcpG&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/UnexpectedReturn&quot; target=&quot;_blank&quot;&gt;←33&lt;/a&gt; | заметка 34 | &lt;a href=&quot;https://dev.101101101.ru/DidNotWork&quot; target=&quot;_blank&quot;&gt;35→&lt;/a&gt;&lt;/p&gt;

</content></entry><entry><id>dev.101101101:UnexpectedReturn</id><link rel="alternate" type="text/html" href="https://dev.101101101.ru/UnexpectedReturn?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=dev.101101101"></link><title>Неожиданный возврат</title><published>2024-11-06T02:54:09.724Z</published><updated>2025-04-18T10:35:01.807Z</updated><summary type="html">Расширение конфигурации в хранилище. А там проверка, предотвращающая дубли записей некоего справочника. Но уже имеющийся дубль исправлять и склеивать не нужно для сохранения истории этой задвоенности. Хочется просто пометить на удаление, а это невозможно как раз из-за проверки. Как исправить быстро без танцев с хранилищем...</summary><content type="html">
  &lt;p id=&quot;7KtE&quot;&gt;Расширение конфигурации в хранилище. А там проверка, предотвращающая дубли записей некоего справочника. Но уже имеющийся дубль исправлять и склеивать не нужно для сохранения истории этой задвоенности. Хочется просто пометить на удаление, а это невозможно как раз из-за проверки. Как исправить быстро без танцев с хранилищем...&lt;/p&gt;
  &lt;p id=&quot;z0KO&quot;&gt;Все просто. Создаем еще одно временное расширение, в него заимствуем ту же процедуру ПередЗаписью() и собственно разрешаем писать. Казалось бы, чего тут извергать из себя буквы. Но обратите внимание как неожиданно работает возврат. Вот простой пример...&lt;/p&gt;
  &lt;p id=&quot;eXEm&quot;&gt;В конфигурации:&lt;/p&gt;
  &lt;pre id=&quot;OymU&quot;&gt;Процедура ПередЗаписью(Отказ)
	Сумма = 1000; //любой код
КонецПроцедуры&lt;/pre&gt;
  &lt;p id=&quot;Vnc1&quot;&gt;В первом расширении:&lt;/p&gt;
  &lt;pre id=&quot;taED&quot;&gt;&amp;amp;После(&amp;quot;ПередЗаписью&amp;quot;)
Процедура Расш1_ПередЗаписью(Отказ)
	Если Истина Тогда //какое-нибудь условие
		Отказ = Истина;
		Возврат;
	КонецЕсли;
	
	Сумма = 2000; //этот код не выполняется
КонецПроцедуры&lt;/pre&gt;
  &lt;p id=&quot;MQZV&quot;&gt;Во втором расширении:&lt;/p&gt;
  &lt;pre id=&quot;0kMR&quot;&gt;&amp;amp;После(&amp;quot;ПередЗаписью&amp;quot;)
Процедура Расш2_ПередЗаписью(Отказ)
	Отказ = Ложь; //этот код
	Сумма = 3000; //выполняется	
КонецПроцедуры&lt;/pre&gt;
  &lt;p id=&quot;M7h2&quot;&gt;То есть, возврат производится только из процедуры в конкретном расширении, но не из процедуры вообще. И это не баг, а фича, нужная как раз для подобных задач. Иногда такое поведение огорчает. Например, если охота не после, а перед стандартной процедурой проверить условие и вообще ее не выполнять:&lt;/p&gt;
  &lt;pre id=&quot;4Xdr&quot;&gt;&amp;amp;Перед(&amp;quot;ПередЗаписью&amp;quot;)
Процедура Расш1_ПередЗаписью(Отказ)
	Если КакоеНибудьУсловие Тогда
		Возврат;
	КонецЕсли;
КонецПроцедуры&lt;/pre&gt;
  &lt;p id=&quot;o7VN&quot;&gt;Но нет, такой возврат вовсе не предотвращает исполнение стандартного кода, хотя казалось бы. В этом случае необходимо использовать &amp;amp;Вместо:&lt;/p&gt;
  &lt;pre id=&quot;mSNQ&quot;&gt;&amp;amp;Вместо(&amp;quot;ПередЗаписью&amp;quot;)
Процедура Расш1_ПередЗаписью(Отказ)
	Если КакоеНибудьУсловие Тогда
		Возврат;
	Иначе
		ПродолжитьВызов(Отказ);
	КонецЕсли;
КонецПроцедуры&lt;/pre&gt;
  &lt;p id=&quot;2edT&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;GJQS&quot;&gt;Механизм расширения конфигураций очень удобен, нужно только понимать некоторые тонкости...&lt;/p&gt;
  &lt;p id=&quot;9bno&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;Lo0e&quot;&gt;&lt;a href=&quot;https://dev.101101101.ru/UglyCode&quot; target=&quot;_blank&quot;&gt;←32&lt;/a&gt; | заметка 33 | &lt;a href=&quot;https://dev.101101101.ru/ForAallTheGoodAgainstAllTheBad&quot; target=&quot;_blank&quot;&gt;34→&lt;/a&gt;&lt;/p&gt;

</content></entry></feed>