Задача на ошибки и неоптимальности при проведении приходной накладной

06.12.23

Разработка - Рефакторинг и качество кода

Задачу эту дают на собеседованиях, видимо, те франчи, которые не в состоянии оценить человека по резюме и в ходе беседы. По идее задачи, подобные этой, должны давать начинающим студентам. Но дают всем подряд. Итак: мои 5 копеек. Критика приветствуется.

Задача:

Документ ПоступлениеТоваров при проведении делает движения по 2 регистрам:

  • приход по регистру накопления ТоварыНаСкладах
  • расход по регистру накопления ЗаказыПоставщикам

Запись в регистр накопления ТоварыНаСкладах делается в рублях (Сумма) и в долларах (СуммаВал). Курс берется на дату партии.

Документ может содержать в табличной части Товары тысячи строк с различными партиями.

Ниже представлена обработка проведения документа ПоступлениеТоваров.

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

ВНИМАНИЕ, ТУТ ЗАЛОЖЕНО БОЛЕЕ 20 ОШИБОК И НЕОПТИМАЛЬНЫХ РЕШЕНИЙ, необходимо найти минимум 15.

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
	| Товары.Номенклатура КАК Номенклатура,
	| Товары.Партия КАК Партия,
	| Товары.Количество КАК Количество,
	| Товары.Сумма КАК Сумма,
	| Заказы.КоличествоОстаток КАК КоличествоОстаток
	|ИЗ
	| Документ.ПоступлениеТоваров.Товары КАК Товары
	|ЛЕВОЕ СОЕДИНЕНИЕ
	|РегистрНакопления.ЗаказыПоставщикам.Остатки(&Период, Контрагент = &Контрагент) КАК Заказы
	| ПО Товары.Номенклатура = Заказы.Номенклатура
	| И Товары.Партия = Заказы.Партия
	|ГДЕ
	| Товары.Ссылка = &Ссылка
	| И (Заказы.Номенклатура, Заказы.Партия) В
	| (ВЫБРАТЬ
	| Товары.Номенклатура,
	| Товары.Партия
	| ИЗ
	| Документ. ПоступлениеТоваров.Товары КАК Товары
	| ГДЕ
	| Товары.Ссылка = &Ссылка)
	|ИТОГИ
	| СУММА(Количество),
	| СУММА(Сумма),
	| СУММА(КоличествоОстаток)
	|ПО
	| Номенклатура,
	| Партия";
	
	ВыборкаНоменклатура = Запрос.Выполнить().Выбрать();
	Пока ВыборкаНоменклатура.Следующий() Цикл
		Если ВыборкаНоменклатура.Количество > ВыборкаНоменклатура.КоличествоОстаток Тогда
			Сообщить("Количество в поступлении " + ВыборкаНоменклатура.Количество + " " + ВыборкаНоменклатура.Номенклатура.ЕдиницаИзмерения + " превышает остаток по заказам " 
			+ ВыборкаНоменклатура.КоличествоОстаток + " " + ВыборкаНоменклатура.Номенклатура.ЕдиницаИзмерения);
		Иначе
			ВыборкаПартия = ВыборкаНоменклатура.Выбрать();
			Пока ВыборкаПартия.Следующий() Цикл
				СуммаВал = СуммаВал	+ РегистрыСведений.КурсыВалют.ПолучитьПоследнее(ВыборкаПартия.Партия.Дата, Новый Структура("Валюта", Справочники.Валюты.НайтиПоНаименованию(«USD»)));
				Движение = РегистрыНакопления.ЗаказыПоставщикам.Добавить();
				Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
				Движение.Период = Дата;
				Движение.Номенклатура = ВыборкаПартия.Номенклатура;
				Движение.Количество = ВыборкаПартия.Количество;
			КонецЦикла;
			Движение = Движения.ТоварыНаСкладах.Добавить();
			Движение.Период = Дата;
			Движение.Номенклатура = ВыборкаНоменклатура.Номенклатура;
			Движение.Количество = ВыборкаНоменклатура.Количество;
			Движение.Сумма = ВыборкаНоменклатура.Сумма;
			Движение.СуммаВал = СуммаВал;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

 

 

Ответы:

  1. Нет удаления старых движений документа.

  2. Старые движения удаляем, если дата дока сдвинута вперед.

  3. Нет установки флага для записи движений в конце транзакции.

  4. Нет наложения управляемой блокировки.

  5. Для минимизации времени блокировки запрос при помощи МенеджерВременныхТаблиц необходимо разбить на 2: а) получение ланных документа б) Получение остатков.

  6. Нет установки параметров запроса.

  7. В параметре на &период вирт. Таблицы «Остатки» следует использовать МоментВремени.

  8. В случае оперативного поведения параметр «МоментВремени» следует установить в Неопределено.

  9. Условие при выборке остатков на (Номенклатуру, Партию) следует делать в параметрах виртуальной таблицы.

  10.  «РегистрыСведений.КурсыВалют.ПолучитьПоследнее(» - запрос в цикле. Курс нужно получать в запросе по таблице документа через макс период партии.

  11.  Первый запрос следует сгруппировать по номенклатуре, партии.

  12.  Итоги не нужны.

  13.  Т.к. остатка в регистре может не быть, поле «Заказы.КоличествоОстаток» следует обернуть в ЕстьNUll

  14.  При выборке запроса не указан параметр «ОбходРезультатаЗапроса.ПоГруппировкам».(хотя идет именно по группировкам).

  15.  Обход по группировкам не нужен.

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

  17.  «ВыборкаПартия.Партия.Дата» - чтение всего объекта «через точку». При необходимости работы с полем дата его нужно добавить в запрос.

  18.  «ВыборкаНоменклатура.Номенклатура.ЕдиницаИзмерения» - аналогично.

  19.  «СуммаВал = СуммаВал + РегистрыСведений.КурсыВалют.ПолучитьПоследнее(» - странный алгоритм. Для вычисления валютной суммы вероятно стоит умножать Сумму в рублях на курс.

  20.  +19 переменная СуммаВал не задана.

  21.  «ЗаказыПоставщикам.Добавить();» - лучше использовать «ДобавитьРасход()»

  22.  Не указан ВидДвижения при добавлении дв-ний ТоварыНаСкладах.

  23.  При списании «ЗаказыПоставщикам» не задается партия.

Ответы от компании Софтвектор (извиняюсь за несоответствие номеров строк кода):

1.   Ошибка. Нет установки параметров для запроса. 3 шт.
2.   Строка 12-15. СОЕДИНЕНИЕ РегистрНакопления.ЗаказыПоставщикам.
    a. Нельзя соединяться с виртуальными таблицами в запросе. Следовало бы использовать сначала чтение во временную таблицу.
3.   Строка 9. Заказы.КоличествоОстаток КАК КоличествоОстаток при левом соединении здесь надо использовать ЕСТЬNULL(, 0). Иначе потом при «ВыборкаНоменклатура.Количество > ВыборкаНоменклатура.КоличествоОстаток» будет исключение о приведении типов
4.   Строка 34. ВыборкаНоменклатура = Запрос.Выполнить().Выбрать(); Здесь не совсем не точность, скорее просто небольшая оптимизация.  Когда каждая мс выполнения дорога, лучше сначала проверять что РезультатЗапроса не пустой, а потом уже тащить с сервера выборку. Иначе получается, что тащится выборка с сервера, а там пусто.
5.   Строка 18. И (Заказы.Номенклатура, Заказы.Партия) . Это параметры вирт таблицы, так что нужно их и вынести в параметры, чем писать их в области ГДЕ. + Там еще и лишние записи будут до соедеинения, т.к.
6.   Строка 23. Документ. ПоступлениеТоваров.Товары – Тут еще раз делается запрос к таблице. Лучше ТЧ товары сначала сохранить в ВТ и потом к ней обращаться.
7.   Строка 37. Сообщить – это скорее устаревший метод, он не работает на УФ, лучше использовать ОбщегоНазначения.СообщитьПользователю. Результат и на ОФ и На УФ будет одинаковым.
8.   Строка 39, 43. ВыборкаНоменклатура.Номенклатура.ЕдиницаИзмерения обращение через точку вызовет запрос к СУБД. Там конечно есть, какое то кэширование серверных значений. Но раз уж тут получаются данные через запрос и там будет номенклатура, то лучше сразу перенести в запрос.
9.   В качестве не оптимальных решений можно так же указать отсутствие установленных БлокировокДанных. Но тут вопрос скорее конфигурации. Может в ней стоит автоматический режим. Может этот документ создается один раз в год и ночью когда никто не работает(хотя это поступление, так что врятли, так что из разряда фантастики)
10.  Строка 49-50.
    a. СуммаВал = СуммаВал         +РегистрыСведений.КурсыВалют.ПолучитьПоследнее()
    b. Это тот же запрос, да еще к вирт. таблице, да еще и вызывается в цикле.  Надо переносить в основной запрос. Хотя бы как пакет, а еще лучше рассчитывать суммуВал для каждой строки в запросе.
11.  Строка 52. Справочники.Валюты.НайтиПоНаименованию(«USD»)  - это в цикле вызывается, и всегда возвращает одно и тоже значение. Лучше перенести поиск до цикла и потом просто его передавать
12.  Строка 52. Справочники.Валюты.НайтиПоНаименованию(«USD»)  - так же тут идет поиск по наименованию, что не верно. Лучше искать по коду. Или по гуиду. Или вообще завести как предопределенное значение, если его нет в конфе.
13.  Строка 52 - Новый Структура("Валюта", …)  тут еще момент, если не учитывать п.9 и п.10. То такую структуру лучше объявить до цикла и потом передавать её в функцию и если надо менять параметр. Тут параметр всегда один, так что лучше и все структуру один раз объявить и заполнить
14.  Строка 54, 61. Движение = РегистрыНакопления.ЗаказыПоставщикам  - перед записью движений надо очищать движения. Т.к. в случае перепроведения коллекция не очистится. Так же, сама коллекция движений явно не записывается, и не установлен флаг Записывать.
15.  Строка 49 – СуммаВал  = Сумма Вал  - Во первых, не инициализируется переменная. Во вторых – изза того что она не инициализацируется в выборке по номенклатуре её значение не «сбрасывается». К тому же, если цикл  ВыборкаПартия.Следующий() будет пустой, то наверное будет ошибка(вот точно не помню, по идее там неопределено будет, а приведется ли он к 0, не пробовал).
16.  Строка 52 - ВыборкаПартия.Партия.Дата – это тоже не явный запрос. Как в п.7
17.  Строка 61 Движения.ТоварыНаСкладах. – не установлен вид движения. Это явно рег. Остатков, так что там надо явно его установить. При проведении должно ругнуться
18.  Строка 39 ВыборкаНоменклатура.Количество – по одной номенклатуре может быть несколько партий, и ВыборкаНоменклаутра будет иметь итог больше чем запрошенное в документе количество. То же самое и с Суммой при формировании движений. И таже проблема с проверкой остатков ВыборкаНоменклатура.Количество > ВыборкаНоменклатура.КоличествоОстаток
19.  Ну еще момент в запросе, что нет группировки по номенклатуре и партии. Если в документе будет указаны одинаковые номенклатуры и партии в 2х строках, то будет не корректное списание партий, т.к. там же левое соединение по этим полям.

 

Задача для программиста на ошибки и не оптимальности

См. также

Рефакторинг и качество кода Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассмотрим основные принципы шаблона проектирования "Стратегия" на простом примере.

25.06.2024    2392    MadRave    30    

22

Рефакторинг и качество кода Программист Платформа 1С v8.3 Абонемент ($m)

В статье расскажу и покажу процесс проведения Code-review на примере обработки с GitHub.

1 стартмани

04.06.2024    4981    mrXoxot    55    

40

Рефакторинг и качество кода Платформа 1С v8.3 Бесплатно (free)

Поделюсь своим опытом аудита кода авторских продуктов с Infostart.ru как одним из элементов применения DevOps-практик внутри Инфостарт. Будет настоящий код, боевые скриншоты, внутренние мемы от команды ИТ-лаборатории Инфостарт и прочее мясо – все, что любят разработчики.

10.04.2024    10728    artbear    84    

104

Рефакторинг и качество кода Программист Платформа 1С v8.3 Россия Бесплатно (free)

Предлагаю вашему вниманию советы мастеров древности. Программисты прошлого использовали их, чтобы заострить разум тех, кто после них будет поддерживать код. Гуру разработки при найме старательно ищут их применение в тестовых заданиях. Новички иногда используют их ещё лучше, чем матёрые ниндзя. Прочитайте их и решите, кто вы: ниндзя, новичок или, может быть, гуру? (Адаптация статьи "Ниндзя-код" из учебника JavaScript)

01.04.2024    3081    DrAku1a    15    

35

Рефакторинг и качество кода Программист Бесплатно (free)

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

01.04.2024    906    Prepod2003    6    

2

Рефакторинг и качество кода Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Когда понадобился новый оператор, но его нет в синтакс-помощнике, что делать?

18.03.2024    1667    ZhokhovM    5    

4

Рефакторинг и качество кода Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Когда разработчик платформы решил пойти на кухню за кофе, а проверку препроцессоров не добавил, и вот тут-то и началось: "Что, опять все сломалось? Ну и кофе же я забыл сделать!".😅

18.03.2024    3422    ZhokhovM    4    

10
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. dhurricane 11.07.23 15:38 Сейчас в теме
0. Код в статье оформлен так, что его читать больно.
dabu-dabu; Дмитрий74Чел; корум; ivanov660; user1334089; d_bat; awk; user1880116; svezr; siamagic; detro; kako1toxren; sapervodichka; Lemmonbri; maksa2005; +15 Ответить
4. sapervodichka 6860 11.07.23 16:21 Сейчас в теме
(1) 0. Нет выравнивания кода отступами )))
Дмитрий74Чел; EvgeniyOlxovskiy; +2 Ответить
11. dhurricane 12.07.23 11:20 Сейчас в теме
(4) Они видимо компенсируются отступами между строк. :)
Дмитрий74Чел; JohnyDeath; sapervodichka; +3 Ответить
14. magic1s 12 12.07.23 18:49 Сейчас в теме
(1) Лучше бы подсказали как текст переносить правильно. В вордовском исходнике межстрочные интервалы нормальные.
А в редакторе Инфотарта я вообще не нашел: где их регулировать?
27. user1880116 18.07.23 21:45 Сейчас в теме
(14)
В вордовском исходнике межстрочные интервалы нормальные.
А в редакторе Инфотарта я вообще не нашел
Господи, как же тяжело программировать-то, оказывается...

Вот, держи c ответами:
https://softvektor.ru/index.php/novosti-1s-its/52-resheniya-zadach-na-sobesedovanie-na-vakansiyu-1s-programmist
2. Lemmonbri 127 11.07.23 16:01 Сейчас в теме
А что, основная деятельность на этой работе - искать ошибки в бреднях стажера? Я думал, что основная деятельность - разрабатывать, и искать ошибки в своем коде. Я бы не пошел в такую компанию...
3. sapervodichka 6860 11.07.23 16:09 Сейчас в теме
(2) это не про стажера, а про собеседование, например, на должность ведущего программиста - понять и оценить понимание и уровень спеца
15. siamagic 13.07.23 07:54 Сейчас в теме
(3)
ведущего программиста
Последний раз я делал движения лет пять назад ... и да тут больше на внимательность - глупый способ оценить кандитата.
16. sapervodichka 6860 13.07.23 08:01 Сейчас в теме
(15) т.е. тот кто сделает этот тест глупый, а кто не сделает умный, или и умный и глупый в равной степени сделают данный тест, или комментарий ради комментария?
25. siamagic 14.07.23 09:49 Сейчас в теме
(16)т.е. тебе его сделает любой студент - отличный способ. Но любой студент в отличие от меня не накидает на колонке подобие КЭДО .
28. user1880116 18.07.23 21:45 Сейчас в теме
(2)
основная деятельность на этой работе - искать ошибки
Переносить код из word
5. Lemmonbri 127 11.07.23 16:23 Сейчас в теме
(3) Я понял что задача про собеседование. Но ведь дальнейшая работа ведущего программиста не проверять код за стажерами. А в этом коде ошибки стажерские, кто только только начал работать и ни разу отладку не запускал. Ведь этот код выдаст результат отличный от задачи.
6. sapervodichka 6860 11.07.23 16:52 Сейчас в теме
(5) по идее если он увидит ошибку в чужом коде, то в своем её не допустит - по-моему мнению этот момент проверяется задачей. (И я думаю только одной такой задачей собеседование не ограничивается)
10. dhurricane 12.07.23 11:19 Сейчас в теме
(5)
Но ведь дальнейшая работа ведущего программиста не проверять код за стажерами.
У кого как. Я на текущей своей работе проверяю весь код, в т.ч. и такой вот стажерский. Другой вопрос конечно же, как скоро автор сего кода перестанет быть стажером.
12. Lemmonbri 127 12.07.23 11:22 Сейчас в теме
(10) Обычно это делают наставники уровня middle, т.к. без разницы кто за стажерами проверяет: мидл или ведущий разраб, компетенций и у того и у того хватает.
"Другой вопрос конечно же, как скоро автор сего кода перестанет быть стажером." - а ещё больший вопрос, как скоро такой проверяющий сойдет с ума от авторов сего кода)))
13. dhurricane 12.07.23 11:26 Сейчас в теме
(12)
а ещё больший вопрос, как скоро такой проверяющий сойдет с ума от авторов сего кода
Есть такая проблема, порой чувствую сильнейшую интоксикацию. :-) Но у всех по-разному, кто-то не принимает так близко к сердцу код, что проверяет.

По поводу проверки мидлом, согласен. Но тут уже вопрос распределения ресурсов на проекте.
Lemmonbri; +1 Ответить
7. Silenser 610 11.07.23 19:39 Сейчас в теме
Проходил недавно такую задачу при трудоустройстве, в одной конторе, связанной с ТВ. В принципе, это не задача на разработку, это задача на внимательность.
siamagic; +1 Ответить
8. gzharkoj 512 11.07.23 22:53 Сейчас в теме
Такой штукой пытать можно, если еще больше отступов между строк добавить =)
Идея классная, вот оформить бы, даже картинкой будет лучше!
18. magic1s 12 13.07.23 19:22 Сейчас в теме
(8) Это не отступы между строк, а увеличенные межстрочные интервалы.
В моем вордовском исходнике межстрочные интервалы нормальные.
При копировании перенеслись так, как видите.
А в редакторе Инфотарта я вообще не нашел: где их регулировать?
Напишите! Я исправлю!
20. gzharkoj 512 13.07.23 19:53 Сейчас в теме
(18) Вы запрос в 1с отформатируйте, а потому оттуда сюда вставьте. Должно 1 к 1 вставится.
22. magic1s 12 13.07.23 20:57 Сейчас в теме
(20) Нет сейчас 1с на компе, с которого пишу)
9. _alex1974 12.07.23 09:47 Сейчас в теме
Один мой сокурсник писал код на С так: в каждой строке было строго 80 символов. Табуляции или двойные пробелы при этом он не использовал. На распечатке получался красивый прямоугольник текста (матричники тогда печатали моноширинным шрифтом), только
совершенно нечитаемый обычными людьми :)
17. Hitcher 176 13.07.23 10:52 Сейчас в теме
Нет удаления старых движений документа.
А почему это ошибка? А если у документа в удалении движений стоит "Удалять автоматически" ?
Oldsad; JohnyDeath; +2 Ответить
19. magic1s 12 13.07.23 19:31 Сейчас в теме
(17) "Удалять автоматически" накладывает блокировку с начала обработки проведения.
Т.е. длительность блокировки.
21. gzharkoj 512 13.07.23 20:45 Сейчас в теме
(19) Остатки можно получать на момент не включая границы, если не оперативно, тогда не надо удалять движения. А вообще остатки надо получать с блокировкой измерений, по которым остатки, именно поэтому сначала пишут (более вероятно, что есть остатки) движения с блокировкой, а потом проверяют остатки.
23. magic1s 12 13.07.23 20:59 Сейчас в теме
(21)
сначала пишут (более вероятно, что есть остатки) движения с блокировкой

В задаче то явно не так!))
24. gzharkoj 512 13.07.23 21:28 Сейчас в теме
(23) Я вот не понял, почему явно не так, обычно документы приходы не самые многочисленные в единицу времени документы, но даже если я не прав, то это только подтверждает, что нужна явная управляемая блокировка. При этом документы явно проводят с целью записи и отражения в системе, а не для проверки остатков, учитывая, что документы будут большие, то для избежания взаимоблокировок конкурирующих транзакций необходимо ставить блокировку с максимальным уровнем изоляции в начале, до чтения и исключительную. А если при этом документы будут с тысячами строк и в единицу времени таких будет не мало, то параллельность спадет на нет. Вот казалось бы все просто, но не просто ;)
JohnyDeath; +1 Ответить
26. alexpvs 64 18.07.23 16:12 Сейчас в теме
Если даже оставить получение курса валюты как есть, то хотя бы избавится по поиска валюты по наименованию в цикле:
...
Новый Структура("Валюта", Справочники.Валюты.НайтиПоНаименованию(«USD»))
- валюту один раз надо бы получить
29. spacecraft 18.07.23 22:59 Сейчас в теме
(0)
«ЗаказыПоставщикам.Добавить();» - лучше использовать «ДобавитьРасход()»

Там более глобальная ошибка.
Движение = РегистрыНакопления.ЗаказыПоставщикам.Добавить();

Добавление не в движения, а напрямую в регистр. Да еще и без указания регистратора...
30. spacecraft 18.07.23 23:18 Сейчас в теме
(0)
Нет удаления старых движений документа.

Тут есть нюансы.
Если это чисто управляемое приложение и на форме не получаются движения, то очищать по сути нечего.
31. ivanov660 4541 23.07.23 09:54 Сейчас в теме
На мой взгляд, проще и правильнее переписать. Честно я попробовал поискать, но после минуты просмотра у меня появилась боль и резь в глазах от такого оформления.
32. magic1s 12 06.12.23 21:19 Сейчас в теме
Оставьте свое сообщение