Сразу напишу вопросы, которые в статье не будут рассматриваться:
1. Разбор и отладка правил конвертации
2. Отладка фоновых заданий.
3. Отладка асинхронных вызовов.
Здесь если начать описывать данный процесс, то получится статья о том, как они работают... А смысла писать давно описанное нет. Для меня пп. 2 и 3 это обычный код, который разбирается в других кейсах.
Итак, прежде чем читать чужой код, необходимо понять, зачем мы это делаем, какой результат хотим получить в итоге. Чтение кода - это задача, причём довольно сложная! И без понимания того, какой результат мы хотим видеть, - никак не обойтись.
В моей практике чужой код необходимо читать в следующих ситуациях:
1. Необходимо выполнить небольшую или, наоборот, большую доработку в уже существующем (не типовом) объекте метаданных или во внешней обработке/отчете.
2. Выполняем код ревью. Актуально для опытных специалистов, которым поручают контроль джуниоров. Иногда перекрестный код ревью, чтоб глаз не замыливался.
3. Отдельно выделю доработку типовой конфигурации. Её код усложнён из-за необходимости учитывать большое количество сценариев и стандартов разработки. Универсальный код всегда сложнее анализировать.
4. Вам необходимо провести обновление доработанной кем-то или Вами конфигурации. Зачастую необходимо обновить вообще незнакомую конфигурацию, возможно, Вы с ней не сталкиваетесь по работе. Например, моя конфигурация ЗУП, но мне приходилось обновлять 5 примерно похожих между собой конфигураций УПП 1.3.
5. Отдельно выделю разбор и изменение запросов.
6. Как разобраться в работе программного интерфейса. Как его использовать в своей доработке.
7. Отдельно выделю необходимость помочь коллеге, или необходимость за кого-то переделать работу в невероятно короткие сроки. Не все разработчики могут выполнить поставленную им задачу, и приходится за кем-то переделывать.
Теперь определимся с ожидаемым результатом от наших действий:
1. Доработка выполнена таким образом, чтоб не сломать уже существующие сценарии. Доработка соответствует общепринятым стандартам разработки. Если дорабатывается тиражное решение - стилистика кода соответствует общепринятой.
2. Проверили работу коллег, указали им на явные и не очень ошибки, рассказали, какой код можно оптимизировать либо заменить на программный интерфейс. Проверили синтаксис написанного кода, указали на опечатки и лишние сокращения.
3. Разобрались, как работает типовой код. Определили объекты метаданных, из которых вызывается. Определили сценарии работы кода. Выполнили свои доработки, не нарушив логической целостности кода.
4. Обновили доработанную конфигурацию, перенесли весь дописанный код. Где-то код заменили на типовой. Где-то пришлось заново доработать.
5. Разобрались с запросом. Внесли в него свои доработки. По возможности оптимизировали запрос.
6. Разобрались с программным интерфейсом, включили его в свою доработку.
7. Помогли коллеге, ответили на вопросы, проверили его способ реализации, подсказали правильный путь. Либо всё это сделали без использования коллеги. Исправили все ошибки, либо с нуля выполнили доработку.
Вводная информация, применимая ко всем кейсам:
1. Конечно же, будут попадаться незнакомые процедуры или функции встроенного языка. Их изучают в 2 простых шага:
-- Синтакс помощник расскажет Вам о её предназначении.
-- Поиск по всем текстам в любой типовой конфигурации покажет Вам множество примеров по использованию. Часто эти примеры можно прямо копировать в свой код, когда будете вести разработку.
2. В целом программирование в 1С построено на том, что любая переменная или реквизит имеет определённый тип значения. Набор свойств и методов, доступных для переменной/реквизита, можно найти в синтакс помощнике в разделе, где описан конкретный тип значения. Тип значения конкретной переменной в коде можно посмотреть отладчиком. Узнав тип значения какой-то переменной, Вам может стать понятней код, который написан применительно к переменной.
3. Не нужно никогда изучать код путём прохождения ВСЕГО кода через отладчик. Поверьте, Вы сойдёте с ума и ничего не поймёте! На выходе будет каша в голове. Пользуйтесь поиском по всем текстам, чтоб найти нужное для разбора и отладки место.
4. Возможно, Вам требуется разобраться с каким-то объектом метаданных, с которым Вы никогда не сталкивались. Тут описанные выше методы не подойдут. Вам необходимо поискать статьи, которые описывают теорию об этом объекте и практическое применение объекта. Например, Вы не знаете, как работают Web-сервисы. Найдите статью об этом, скорей всего, статья даже окажется на Инфостарте. Часто авторы статей совмещают теорию с практикой и показывают примеры кода, как это использовать. Если пример можно скачать за 1$m, не жалейте этих денег. Самостоятельно дольше будете писать! И нет, это не скрытая реклама данного ресурса. Это мой опыт, который позволил со многими трудными механизмами разобраться.
5. Не стесняйтесь непонятные вопросы задавать на форумах. Даже если Вас обольют 10 человек грязью, всегда найдётся один, который поможет!
6. Любая конфигурация/обработка/отчет/объект метаданных - это набор сценариев, который заложил в неё разработчик. Прежде, чем пытаться доработать тот или иной кусок кода, необходимо выявить те сценарии, которые уже заложены. Способы выявления сценариев будут раскрыты ниже для каждого кейса.
7. Приучите себя к правилу: Нельзя начинать разработку, пока Вы четко не знаете существующие сценарии и как должен выглядеть сценарий после Ваших изменений. Сценарий - это основа для любой разработки. Писать его нужно ДО кодирования, а не после!
8. Не рекомендую никому вести разработку на "тестовых примерах". Тестовые данные никогда не показывают полную картину. Максимум тестовый пример охватывает 20-30% сценариев, которые необходимо учесть. Задайте себе вопрос: "Кто будет дорабатывать/тестировать остальные 70-80% сценариев"?
Кейс 1. Доработка кем-то придуманного кода. Условимся, что это не код типовой конфигурации.
В данном случае рассмотрим самую страшную ситуацию, когда доработать нужно либо написанное с нуля решение/обработку/отчет, либо так называемые партнёрские решения.
1. Первое, что Вы должны понять, есть ли описание этого решения, либо человек, который может рассказать, как оно работает. Конечно, Вам не требуется знать всю архитектуру, но Вам обязательно нужно понять, как работает кусок, который требуется доработать.
2. Если так случилось, что нет ни описания, ни носителя знаний - надо запускать в пользовательском режиме и пробовать использовать доработку.
а. С отчетом всё просто - попробовать разные настройки, посмотреть, какие данные выводит, разные варианты отчета посмотреть.
б. С обработкой сложней:
-- Первое, что надо посмотреть в коде - какие объекты модифицирует обработка. Делаем просто поиск процедуры Записать(). Всё станет очевидно.
-- Далее надо ответить на вопрос: откуда берется список объектов, который меняется. Скорей всего есть запрос...
-- Грамотные разработчики для многоразовых обработок создают промежуточную табличную часть, в которую помещают список изменяемых объектов. Попробуйте определить, что это за список на данном этапе.
-- Если обработку писал не очень грамотный или ему она показалась одноразовой... Список изменяемых объектов нужно посмотреть в коде отладчиком. Обязательно нужно изучить массив обрабатываемых данных!
ВАЖНО: Прежде чем отладчиком смотреть такие обработки, необходимо закомментировать все Записать(), найденные на первом шаге. Это убережет Ваши данные от ненужных изменений.
-- Нужно разобраться с заполнением тех параметров, которые выведены на форме. Для этого смотрим, где в запросах они используются? Некоторые параметры могут быть не используемыми! Это нужно определить на данном этапе и убрать сразу их с формы обработки!
-- Когда уже понятно, откуда взялись данные, какие данные будут модифицироваться... Вам нужно пройти отладчиком несколько циклов по обработке данных. Так Вам совсем понятно станет, что происходит.
в. С чужими доработками, особенно когда нет описания, самый сложный случай. Рассмотрим именно его. Финальная цель - также разобраться со сценариями работы и потом их модифицировать. Вот что для этого необходимо сделать:
-- Весь код можно разделить на 2 части: интерфейсный код (управление элементами формы) и объектный код (обработка заполнения, проверки, записи объекта, формирования движений документов, печать). Поэтому первое, что надо сделать - определиться, что Вы планируете доработать - интерфейс или объект.
-- С интерфейсным кодом обычно в самописных решениях никто особо не заморачивается. Поэтому найти, где прячется тот или иной реквизит, несложно. Но здесь стоит напомнить, что прятать реквизиты можно благодаря ещё 2-м механизмам: функциональные опции и права пользователя (для управляемых форм).
-- С объектным кодом чуть сложней. Надо определиться, какую часть кода Вы хотите изменить (обработка заполнения, проверки, записи объекта, формирования движений документов, печать).
-- Далее Вам необходимо посмотреть на уже заполненные данные. Неважно, какой это объект метаданных, можно вывести запросом все или часть данных с отбором по периоду или какому-то полю (чтоб не повесить сервер). Изучите, какими значениями заполнены реквизиты, особенно, если их тип - Перечисление. Стоит помнить, что перечисления созданы для описания сценариев. Можно по коду посмотреть, прописаны какие-то сценарии по значениям перечислений или это просто настройка, которую в отчете используют.
-- Чтобы разобраться с заполнением, необходимо изучить, куда потом заполненные данные идут? Если это документ, то изучаем движения. Если это регистр сведений - изучаем, где он используется. Так можно выяснить часть сценариев работы.
-- Необходимо понимать, где какой код искать. Печать, заполнение - модуль менеджера. Часть процедур могут быть вынесены в общие модули. Проверка заполнения, запись, проведение - модуль объекта. У регистров вместо модуля объекта используется модуль набора записей. Обычно в модуле набора записей расположен код формирования записей вспомогательных регистров сведений. Не стоит искать код заполнения объекта в форме объекта, хотя иногда и такое ещё встречаю.
-- Конечно, потребуется в пользовательском режиме ввести какие-то данные, чтоб увидеть, как работают найденные на предыдущих шагах сценарии работы. Как и в остальных случаях, непонятные куски кода можно посмотреть в отладчике.
После того, как мы выяснили сценарии работы, изучили массив данных, протестировали в пользовательском режиме и посмотрели в отладчике... Можно приступать к доработке такого кода.
ВАЖНО: В остальных кейсах необходимо пройти те же самые шаги. Поэтому по остальным кейсам буду описывать только отличия от первого.
Кейс 2. Выполняем code review.
Почему кейс 2 идёт после доработки нетиповых решений? Всё потому, что проверяем-то мы не типовую конфигурацию от 1С... А проверяем мы то, что написали наши коллеги. Иногда приходится проверять то, что написали уволенные коллеги или уволенная вся команда))) Т.е. никто не знает, как оно работает, и нигде не описано.
НО! Цель код ревью - проверка соблюдения стандартов разработки 1С. На эту тему написано очень много статей, поэтому подробностей здесь не будет. Коротко опишу, что проверяю сам:
1. Есть в стандартах раздел "Соглашения при написании кода". Этот раздел по сути показывает, грамотный человек писал код или нет. Многие любят излишние сокращения, не любят писать с заглавной буквы, делать пустые строки между блоками и т.д. Выполнение разработчиком этой группы стандартов так же важно, как и грамотная устная и письменная речь. Несоблюдение этих стандартов затрудняет чтение и понимание кода! Да и просто это неуважение к остальным коллегам! Ну и собственно длительно с таким кодером я работать не стану. Пару раз предупреждаю о соблюдении этой группы стандартов, не понял - на выход!
2. Если в рамках задачи создаются новые объекты метаданных - проверяю группу стандартов "Создание и изменение объектов метаданных". Цели данной проверки те же. Обеспечение единого подхода при создании объектов метаданных. Иногда встречаю реквизиты вместо Сотрудник, Подразделение - Сотр, Подр. Встречалось, что Сотрудник был с типом "Строка", а не справочник. И это была не механическая ошибка. В самописной базе не было такого справочника! Необходимо создавать объекты метаданных по описанным в стандартах принципам. В обработчике ПередЗаписью встречал проверку заполнения реквизитов и т.д.
3. Далее проверяю вопросы клиент-серверного взаимодействия. Собственно в этой группе стандартов перечислены необходимые проверки. Очень много кода пишут на клиенте, много лишних серверных вызовов, не используется серверный вызов без контекста.
4. Следующее проблемное место в коде - обработка данных (запросы, выборки, транзакции, блокировки).
-- По запросам наиболее часто встречается неверное использование индексов, либо вообще не думают об этом. Данная ошибка тормозит работу не только одного клиентского сеанса, но и сервера в целом! Не используются виртуальные таблицы с параметрами, запросы делают к физическим таблицам. До сих пор встречаю вложенные запросы к довольно большим таблицам.
-- При выборке данных часто встречается Запрос.Выполнить().Выгрузить() и дальше обрабатывается таблица. Зачем? Необходимо использовать выборку из результата запроса.
-- Часто встречаются запросы в циклах. Особенно часто они неявные, возникают при вызове программного интерфейса типовых конфигураций в цикле. Иногда пишут свою процедуру/функцию с запросом и используют её потом в цикле. Цикличное обращение к базе данных в несколько раз замедляет работу кода. При количестве итераций более 1000 замедление будет очень заметным!
-- Избыточное использование транзакций (при редактировании формы, к примеру)
-- Неоправданное использование блокировок при выполнении запросов к регистрам накопления. Ведь блокировка нужна только при ОДНОВРЕМЕННОМ обращении нескольких пользователей К ОДНИМ И ТЕМ ЖЕ ДАННЫМ! Но её используют и там, где пользователи жестко разграничены через РЛС. Необходимо на этапе разработки понимать, как будут работать пользователи. Можно по этому вопросу проконсультироваться с архитектором проекта. На всякий случай использовать блокировки НЕЛЬЗЯ!
-- Из неописанного в стандартах разработки... С удивлением для себя обнаружил, что использование следующего кода сильно тормозит работу. В выборке 6000 записей, в таблице, которую обрабатываем 100 000 (сто тысяч). В итоге этот код выполнялся 40 минут!
//Запрос к справочнику сотрудники
ВыборкаПоСотрудникам = Запрос.Выполнить.Выбрать();
//В таблицу помещаем данные табельного учета за месяц.
//Получается более 100 тыс записей
ТаблицаТабеля = Новый ТаблицаЗначений;
//В цикле необходимо подобрать ссылки для подразделений и сотрудников,
//т.к. данные получены через COM есть только строковые значения.
Для Каждого ТекСтрока Из ТаблицаТабеля Цикл
ВыборкаПоСотрудникам.Сбросить();
Если ВыборкаПоСотрудникам.НайтиСледующий(СтруктураПоиска) Тогда
...
КонецЕсли;
КонецЦикла;
После того, как данный код был переписан на запрос, заполнение ссылок занимает секунды.
5. В последнюю очередь проверяется группа стандартов "Разработка пользовательских интерфейсов" и "Проектирование интерфейсов 8.3". Список проверок описан в стандартах. Нет цели его здесь повторить. Самое главное это удобное расположение элементов формы, таблиц, команд, итогов. Необходимо располагать самые важные элементы так, чтоб они заполнялись первыми. В табличных частях фиксировать левые колонки, если без прокрутки невозможно просмотреть всю табличную часть. Интерфейс должен быть понятен пользователю и не содержать лишних элементов, которые в текущем сценарии не используются.
6. Без привязки к стандартам проверяю выбранный способ решения задачи. Многие коллеги настолько боятся менять типовые объекты, что копируют их целиком и меняют скопированный объект! В этот момент коллеги забывают, что скопированный объект работает на программном интерфейсе конфигурации, в которой он создан. Если через сколько-то релизов сильно изменят программный интерфейс, то скопированный объект перестанет работать и его придётся обновлять! Так почему не доработать сразу типовой объект?!
Аналогично поступают с некоторыми процедурами общих модулей. Создают новый общий модуль, в него копируют процедуры и функции, которые планируют поменять и там меняют. Ошибочно это по той же причине: как только изменят используемые процедуры и функции в типовой конфигурации, Ваша доработка перестанет работать!
7. Также по коду часто видно, отработаны все сценарии? или разработчик схалтурил и сделал лишь часть работы. Понять это можно, анализируя условия, которые есть в доработанных процедурах и функциях. Часто встречаю, что из нескольких веток условия доработка есть только в одной ветке. А кто остальные будет делать?
8. Очень рекомендую проводить дополнительный (промежуточный) этап проверки Desing review. Этот этап проводится когда разработчик выполнил примерно треть своей работы. Он уже разобрался в коде, который ему требуется менять, уже знает, какие запросы и как будет менять, "накидал", как будет выглядеть интерфейс. Цель этого этапа на старте разработки понять, что разработчик выбрал правильный путь решения с одной стороны, архитектор/аналитик верно поставил задачу с другой стороны.
Главная причина срыва сроков в разработке - не все сценарии учтены. Так это или нет позволяет понять промежуточная проверка. Если мы находим новые сценарии или видим, что текущие описаны неверно, можем сразу об этом сообщить руководству/заказчику, согласовать новые сроки и учесть бОльшее количество сценариев при разработке.
Пройдя все описанные этапы код ревью, пишем кучу замечаний разработчику и заставляем его исправлять свой код, даже если ему кажется, что "оно же работает!".
Остальные части доступны по ссылкам:
Часть 2. Доработка типовой конфигурации. Обновление доработанной типовой конфигурации.
Часть 3. Разбор и доработка запросов
Часть 4. Программный интерфейс. Исправление чужих доработок.
Добавляйте себе в избранное, ставьте "+". Статья разрабатывалась 1,5 месяца, а опыт копился 18 лет!
Также напомню о своих предыдущих публикациях, в особенности про статью об архитекторе. Текст статьи полностью переработан, сглажены углы. Будет интересно, даже если уже читали. Вот ссылки:
1. Кто такой архитектор. Редакция 2!
2. Пример работы с файлами odt в клиент-серверной модели работы