Введ ение
Мне часто приходится участвовать в собеседованиях (отборе) кандидата-программиста. Постепенно пришел к выводу, что написание по техническому заданию новой обработки (отчета) – не лучший вариант:
- Требуется существенное время + среда разработки (компьютер)
- Может вызвать негативную реакцию, раздражение кандидата.
- Для проверки требуется сотрудник высокой квалификации.
- Увеличение длительности отбора увеличивают вероятность отказа кандидата от участия.
Поэтому было решено давать кандидату уже написанный код 1С с ошибками, которые он должен найти.
- Поиск ошибок в чужом коде происходит быстро, читать - с листа.
- Повышает самооценку кандидата.
- Результат можно проверить по шаблону ответов
Благодарю всех коллег, кто морально и материально поддержал мою прошлую статью Отбор кандидата-программиста. Им всем респект и скидка 50% на новые файлы, СМ будут начислены после покупки в чатике как вознаграждение.
Пример одного вопроса
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
|Сумма(1) / 1000000
|ИЗ
|РегистрСведений.ЦеныНоменклатуры КАК Цены";
Сценарий интервью
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
|Сумма(1) / 1000000
|ИЗ
|РегистрСведений.ЦеныНоменклатуры КАК Цены";
Вопрос: Для чего может быть использован такой запрос?
(Проверяем, насколько кандидат понимает чужой код. Программисты занимаются этим большую часть времени. Обращаем внимание на навыки общения кандидата.)
Ответ: Запрос считает количество записей регистра. Похожим запросом можно считать количество элементов справочника или строк в документе.
Вопрос: Для чего делить на миллион?
(Этот вопрос неочевидный, отвечать необязательно. Для любителей, знатоков и коллекционеров)
Ответ: Деление - чтобы не было ошибки sql переполнения.
Вопрос: Какая ошибка может возникнуть при работе с данными запроса?
(Умение предусмотреть null - очень важное. Если кандидат смог ответить - в его коде будет значительно меньше ошибок)
Ответ: Сумма(1) может быть null.
Вопрос: Как правильно написать запрос?
Ответ: Слово РАЗЛИЧНЫЕ не нужно. Использовать функцию КОЛИЧЕСТВО.
(Рекомендации ИТС: https://its.1c.ru/db/v8std#content:787:hdoc Если кандидат читает ИТС - это хороший знак. С другой стороны, если кандидат ответил ВСЕ вопросы - возможно, он готовился к интервью. Выбирайте сами)
Как видите, даже короткий фрагмент кода может показать уровень квалификации кандидата. В приложенных файлах только вопросы-ответы, комментарии отсутствуют.
Еще пример
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВводОстатковТоваров.Ссылка КАК Ссылка
|ИЗ
| Документ.ВводОстатковТоваров КАК ВводОстатковТоваров
|
|УПОРЯДОЧИТЬ ПО
| ВводОстатковТоваров.Дата";
//10
ТЗ = Запрос.Выполнить().Выгрузить();
НачалоГода = НачалоГода( ТекущаяДата() );
//13
Для Каждого ТЗЦикл ИЗ ТЗ Цикл
//15
Если ТЗЦикл.Ссылка.Дата < НачалоГода Тогда Продолжить; КонецЕсли;
Документ = ТЗЦикл.Ссылка.ПолучитьОбъект();
Документ.ПометкаУдаления = Истина;
Документ.ОбменДанными.Загрузка = Истина;
Документ.Записать(РежимЗаписиДокумента.Запись);
//21
КонецЦикла;
Сценарий интервью
Вопрос: Для чего может быть использован такой код?
Ответ: Для пометки на удаление документов "Ввод остатков товаров" за текущий год.
Вопрос: Что произойдет с регистрами накоплений, движениями товара? Почему?
Ответ: Ничего, код пометит документы, регистры накоплений и движений товара останутся без изменения. Помеченные на удаление документы будут изменять остатки, это очень неприятно. Такая особенность записи в режиме ОбменДанными.Загрузка = Истина.
Вопрос: Как исправить?
Ответ: Вместо строк 18-19-20, использовать УстановитьПометкуУдаления(Истина).
Вопрос: За какой период документы быстрее помечать на удаление: текущий месяц, прошлый месяц, позапрошлый месяц? Почему?
Ответ: При пометке удаления документов происходит очистка регистров и очистка итогов регистров. Регистры остатков имеют рассчитанные итоги на каждый месяц. Например, (если итоги регистров активны) изменение остатков за позапрошлый месяц вызовет изменения таблиц итогов за три месяца. Смотрите Зачем в 1С нужно периодически пересчитывать итоги по регистрам?
Вопрос: В чем проблема в строке 16?
Ответ: Отбор по дате необходимо производить в запросе выборки документов, не допуская объектного чтения.
Вопрос: Если все документы должны быть помечены на удаление, то нужно ли помечать все документы на удаление? Какие отборы должны быть в запросе?
Ответ: На удаление не нужно помечать документы, которые уже помечены на удаление. В запросе должны быть отборы "Где ВводОстатковТоваров.Дата > &НачалоГода И НЕ ВводОстатковТоваров.ПометкаУдаления".
Вопрос: В чем проблема в строке 11 ?
Ответ: Не нужно использовать выгрузку в таблицу, используйте выборку.
// 01 //////////////////////////////////////////////////////////////////////////////////////
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| РеализацияТоваровУслуг.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| НАЧАЛОПЕРИОДА(РеализацияТоваровУслуг.Дата, МЕСЯЦ) = &Январь2025";
// 02 //////////////////////////////////////////////////////////////////////////////////////
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура,
| ХарактеристикиНоменклатуры.Ссылка КАК Характеристика
|ИЗ
| Справочник.Номенклатура КАК Номенклатура,
| Справочник.ХарактеристикиНоменклатуры КАК ХарактеристикиНоменклатуры
|ГДЕ
| ЛОЖЬ";
Таблица = Запрос.Выполнить().Выгрузить();
// 03 //////////////////////////////////////////////////////////////////////////////////////
Запрос.Текст =
"ВЫБРАТЬ
| СрезЦен.Регистратор.Ссылка,
| СрезЦен.Номенклатура,
| СрезЦен.Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Завтра, ) КАК СрезЦен
|ГДЕ
| СрезЦен.Регистратор ССЫЛКА Документ.УстановкаЦенНоменклатуры";
// 04 //////////////////////////////////////////////////////////////////////////////////////
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Сумма(1) / 1000000
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК Цены";
// 05 //////////////////////////////////////////////////////////////////////////////////////
Запрос.Текст =
"ВЫБРАТЬ
| Выразить(РеализацияТоваровУслуг.Ссылка КАК Документ.РеализацияТоваровУслуг).Ссылка,
| НАЧАЛОПЕРИОДА(РеализацияТоваровУслуг.Дата, МЕСЯЦ) КАК НачалоМесяца
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|
|УПОРЯДОЧИТЬ ПО
| НачалоМесяца";
// 06 //////////////////////////////////////////////////////////////////////////////////////
Запрос.Текст =
"ВЫБРАТЬ
| ОстаткиТоваров.Номенклатура,
| СрезЦен.Цена
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(, Склад = &Склад) КАК ОстаткиТоваров
| Левое СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, Типцен = &Типцен) КАК СрезЦен
| ПО ОстаткиТоваров.ХарактеристикаНоменклатуры = СрезЦен.ХарактеристикаНоменклатуры
|ГДЕ
| НЕ СрезЦен.Номенклатура.ПометкаУдаления";
// 07 //////////////////////////////////////////////////////////////////////////////////////
НоменклатураВыбрать = Справочники.Номенклатура.Выбрать();
Пока НоменклатураВыбрать.Следующий() = Истина Цикл
Сообщить( НоменклатураВыбрать.Ссылка + НоменклатураВыбрать.Артикул );
КонецЦикла;
// 08 //////////////////////////////////////////////////////////////////////////////////////
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 9
| Номенклатура.Ссылка КАК Номенклатура,
| ХарактеристикиНоменклатуры.Ссылка КАК Характеристика
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ХарактеристикиНоменклатуры КАК ХарактеристикиНоменклатуры
| ПО (ХарактеристикиНоменклатуры.Владелец = Номенклатура.Ссылка)
|ГДЕ
| ХарактеристикиНоменклатуры.ПометкаУдаления";
// 09 //////////////////////////////////////////////////////////////////////////////////////
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ТоварыНаСкладахОстатки.Номенклатура,
| ТоварыНаСкладахОстатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
|ГДЕ
| ТоварыНаСкладахОстатки.Номенклатура В ИЕРАРХИИ(&ГруппаНоменклатуры)";
// 10 //////////////////////////////////////////////////////////////////////////////////////
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| РеализацияТоваровУслугТовары.ЕдиницаИзмерения,
| МАКСИМУМ(РеализацияТоваровУслугТовары.Ссылка) КАК Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
|ГДЕ
| (ВЫРАЗИТЬ(РеализацияТоваровУслугТовары.Коэффициент КАК ЧИСЛО(5, 0))) < РеализацияТоваровУслугТовары.Коэффициент
|
|СГРУППИРОВАТЬ ПО
| РеализацияТоваровУслугТовары.ЕдиницаИзмерения";
// 11 //////////////////////////////////////////////////////////////////////////////////////
//модуль справочника ХарактеристикиНоменклатуры
Процедура ПриЗаписи(Отказ)
ОбработкаПрерыванияПользователя();
Попытка
НачатьТранзакцию();
МойОбъект = Владелец.ПолучитьОбъект();
МойОбъект.Наименование = СокрЛП(МойОбъект.Наименование);
МойОбъект.Записать();
ЗафиксироватьТранзакцию();
Исключение
Предупреждение("Ошибка проведения",5);
ОтменитьТранзакцию();
КонецПопытки;
КонецПроцедуры
// 12 //////////////////////////////////////////////////////////////////////////////////////
&НаКлиенте
Функция ЗначениеВДанныеФормы()
//строка 03
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
//строка 06
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| 1 / Номенклатура.ЕдиницаДляОтчетов.Коэффициент КАК ОбратныйКоэффициент,
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
//строка 13
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальная = РезультатЗапроса.Выбрать();
//строка 16
Пока ВыборкаДетальная.Следующий() Цикл
Сообщить( ВыборкаДетальная.Ссылка.Наименование + " " + ВыборкаДетальная.ОбратныйКоэффициент );
КонецЦикла;
//строка 20
УстановитьПривилегированныйРежим(Ложь);
//строка 22
КонецФункции
// 13 //////////////////////////////////////////////////////////////////////////////////////
&НаСервере
Функция ЗначенияРеквизитов(Номенклатура)
ЗначенияРеквизитов = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Номенклатура, "Наименование, ВариантОформленияПродажи");
Если ЗначенияРеквизитов.ВариантОформленияПродажи = Перечисления.ВариантыОформленияПродажи.РеализацияТоваровУслуг Тогда
Возврат ЗначенияРеквизитов;
КонецЕсли;
КонецФункции
&НаКлиенте
Процедура ПоказатьТовары(Команда)
Для Каждого Товар Из Объект.Товары Цикл
ЗначенияРеквизитов = ЗначенияРеквизитов(Товар.Номенклатура);
Если ЗначенияРеквизитов <> Неопределено Тогда
ОбщегоНазначенияКлиент.СообщитьПользователю(ЗначенияРеквизитов.Наименование);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// 14 //////////////////////////////////////////////////////////////////////////////////////
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВводОстатковТоваров.Ссылка КАК Ссылка
|ИЗ
| Документ.ВводОстатковТоваров КАК ВводОстатковТоваров
|
|УПОРЯДОЧИТЬ ПО
| ВводОстатковТоваров.Дата";
// строка 10
ТЗ = Запрос.Выполнить().Выгрузить();
НачалоГода = НачалоГода( ТекущаяДата() );
Для Каждого ТЗЦикл ИЗ ТЗ Цикл
// строка 15
Если ТЗЦикл.Ссылка.Дата < НачалоГода Тогда Продолжить; КонецЕсли;
Документ = ТЗЦикл.Ссылка.ПолучитьОбъект();
Документ.ПометкаУдаления = Истина;
Документ.ОбменДанными.Загрузка = Истина;
Документ.Записать(РежимЗаписиДокумента.Запись);
// строка 21
КонецЦикла;
Вопрос: Вы советуете НЕ выгружать результат запроса в таблицы значений, а ERP это активно использует.
Ответ: Мы должны верить, что напишем больше и лучше, чем ERP !
Вопрос: Зачем такие тесты, ведь кандидатов можно отбирать, спрашивая про красно-черные деревья и вялые огурцы ?
Ответ: Спасибо, Кузяра! Вы сделали мой день!
Вопрос: Тут уж совсем детский уровень.
Ответ: Здесь спрятано 20 ошибок, не каждый ребенок найдет.
Вопрос: Это код одна сплошная ошибка!
Ответ: Вы нам не подходите. Слишком умных лучше не брать. Подсидят через пару лет. ))
Вопрос: Выжду годик и сам запилю такую публикацию.
Ответ: Через годик у меня уже будет четыре плюсика и одно скачивание !
Вопрос: Зачем мне код с ошибками ?
Ответ: Все хотят быть сеньором-тимлидом, но никто не хочет исправлять чужой плохой код ))
Вопрос: Мне нужно просеять кандидатов через воронку отбора (остаться должен 1%)
Ответ: Вы затеяли "Голодные игры"? Интер есная воронка - но напрашивается аналогия с большим динозавром - пока сигнал от хвоста дойдет до мозга, хвост уже отгрызут :-)
Вопрос: Где Вы берете такой плохой код ?
Ответ: Проекты прошлых лет (шутка).
Найти ошибки в коде - популярная тема на собеседованиях. Например, используется на собеседованиях Вайлдберриз-Тех для программистов Java.
Содержит избранные комментарии из предыдущей статьи Отбор кандидата-программиста.
Благодарю модератора Ирину Пятакову, которая помогает сделать статьи более читабельными. Без нее у меня получилась бы просто куча неструктурированной информации.