Рефакторинг и реинжиниринг в повседневной практике

20.06.22

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

В этой статье будут затронуты многие темы. Использование WS ссылок, HTTP запросов, асинхронных запросов к внешним сервисам, работа с XML, методики интеграции. Но лишь попутно. Для наглядности. На технических вопросах реализации останавливаться не буду. Все примеры работы с этими объектами есть в коде. Файлы обработки и расширения доступны. Главная цель - рассмотреть рефакторинг и реинжиниринг как инструменты для достижения вполне конкретных практических целей.

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

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

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

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

Однако, к делу. Задача заключалась в интеграции информационной системы с системами поставщиков электронной техники, используя их API. Одна из составных частей задачи - получение и размещение в базе информации о каталогах поставщиков. Загрузка каталогов, в свою очередь, состоит из двух подзадач. Получение информации и укладка ее в наши справочники и регистры. Как правило, в исходном варианте кода, который застаешь, прибыв на место действия, эти подзадачи решаются вместе. Как говорится, в одном флаконе. Хотя, очевидно, что задача укладки решается одинаково для всех поставщиков, а задача получения данных специфична для каждого из них.

Итак, первым делом разделяем их. Получаем данные от разных контрагентов и помещаем их в унифицированное хранилище. Затем укладываем в нашу базу одинаковым образом. 

Еще немного сузим поле битвы. Укладку оставим за бортом. С ней все ясно и для каждой базы данных она имеет свои особенности. Займемся более интересным и полезным. Получением разнородной информации существенно разными способами и приведением ее к единому формату. 

Примерно, вот к такому:

 

Материал, в нашем случае, подобрался хороший и показательный. Два поставщика предоставили WSDL описание с моделью данных. Третий дал описание, но без модели и возвращает в ответе на запрос не объект XDTO, а строку XML. Четвертый вообще предлагает делать HTTP запросы. Двое отдают каталог по одному запросу, остальные двое дают информацию о товарах только в разрезе групп. Один поставщик экономит трафик и отвечает только на асинхронные запросы.

Отсутствие общепринятых стандартов при создании API сильно подвигает к индивидуальной работе с каждым поставщиком. К сожалению, вижу результат этого на практике часто.  Соблазн пойти по этому пути всегда есть. Однако, наступил себе на горло и занялся объединением этого зоопарка и выделением общих черт у жирафа и антилопы.

Цель перед собой ставил вполне конкретную. За счет унификации методики обеспечить существенный выигрыш во времени разработки уже на третьей-четвертой интеграции. Т.е. все достаточно меркантильно. Никакой эстетики. Хотелось добиться того, чтобы новый поставщик интегрировался легко и бездумно. Чтобы из описания просто переносился состав полей ответа, вызов методов и их параметры.

На первые две интеграции ушло три дня. Пришлось много раз перерабатывать код. Первые варианты вызывали только нервный смех, так далеки они были от поставленной цели. Поэтому рассказывать о них не буду. Уже третья интеграция заняла значительно меньше времени. Четвертая, наконец, получилась так как задумано. Быстро, бездумно и без напряжения. Лягушка взбила масло.

Теперь посмотрим, что получилось и стоила ли игра свеч.

Были отработаны две методики: 

Первая - Товары (весь каталог со ссылками на группы) получается отдельно и группы отдельно.

Вторая - товары запрашиваются в разрезе предварительно полученных групп.

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

В итоге, функция выглядит так:

// Это главная вызываемая функция. Возвращает структуру, состоящую из унифицированной таблицы товаров и унифицированной таблицы или дерева групп (в случаях фиксированной или произвольной вложенности).
// В ней реализованы две главные методики получения данных. Первая - Товары (весь каталог со ссылками на группы) отдельно и группы отдельно. Вторая - товары запрашиваются в разрезе групп.
// Сначала делается попытка получить весь каталог (если раздел поставщика есть в функции СписокПолныеДанныеПоставщика). В этом случае группы запрашиваются независимо.
// Для этой методики асинхронная работа не предусмотрена.
// Затем (если товары так получить не удалось) запрашиваются группы и делается попытка получить данные в разрезе каждой группы. 
// Соответствующие функции отрабатывают в случае если в них есть раздел данного поставщика. Затем таблицы с разными видами данных сворачиваются (СвернутаяТаблицаДанныхПоставщика) и уходят на выход. 
// Для этой методики есть нюанс в случае использования асинхронных запросов. 
// Перед циклом получения данных по идентификаторам ответов в разрезе групп при необходимостие делаются асинхронные запросы (ИдентификаторыАсинхронныхЗапросов).
Функция ОбновитьДанныеПоставщика(ИмяПоставщика, Пользователь, Пароль) Экспорт
	
	Ответ = Неопределено; 
	
	Попытка
		
		ПараметрыПоставщика = ПараметрыПоставщика(ИмяПоставщика, Пользователь, Пароль);		
		ТаблицаДанныхПоставщика = НоваяТаблицаДанныхПоставщика();
		
		СписокПолный = СписокПолныеДанныеПоставщика(ИмяПоставщика, ПараметрыПоставщика);
		ПоместитьВТаблицуДанных(ИмяПоставщика, СписокПолный, "Товары", ТаблицаДанныхПоставщика);
		
		Если ТаблицаДанныхПоставщика.Количество() > 0 Тогда
			ТаблицаГрупп = НовоеДеревоГрупп();
			ТаблицаГрупп = ГруппыПоставщика(СписокГруппПоставщика(ИмяПоставщика, ПараметрыПоставщика), СтруктураПолейГруппы(ИмяПоставщика), ТаблицаГрупп.Строки);
		Иначе 
			
			ТаблицаГрупп = ГруппыПоставщика(СписокГруппПоставщика(ИмяПоставщика, ПараметрыПоставщика), СтруктураПолейГруппы(ИмяПоставщика)); 
			// Если есть асинхронная работа
			ТаблицаГрупп = ИдентификаторыАсинхронныхЗапросов(ТаблицаГрупп, ИмяПоставщика, ПараметрыПоставщика);
			
			Для Каждого СтрокаГруппы Из ТаблицаГрупп Цикл  
				// Каббалистическое условие из-за особенностей Мерлиона
				Если СтрДлина(СтрокаГруппы.КодГруппы) >= 8 Тогда  
					СписокТоваров = СписокТоваровКаталогаПоставщика(СтрокаГруппы, ИмяПоставщика, ПараметрыПоставщика, СтрокаГруппы.ИдентификаторТовары);
					СписокОстатков = СписокОстатковПоставщика(СтрокаГруппы, ИмяПоставщика, ПараметрыПоставщика, СтрокаГруппы.ИдентификаторОстатки);
					СписокЦен = СписокЦенПоставщика(СтрокаГруппы, ИмяПоставщика, ПараметрыПоставщика, СтрокаГруппы.ИдентификаторЦены);
					СписокШтрихКодов = СписокШтрихКодовПоставщика(СтрокаГруппы, ИмяПоставщика, ПараметрыПоставщика, СтрокаГруппы.ИдентификаторШтрихкоды);
					ПоместитьВТаблицуДанных(ИмяПоставщика, СписокТоваров, "Товары", ТаблицаДанныхПоставщика, СтрокаГруппы);
					ПоместитьВТаблицуДанных(ИмяПоставщика, СписокОстатков, "Остатки", ТаблицаДанныхПоставщика, СтрокаГруппы);
					ПоместитьВТаблицуДанных(ИмяПоставщика, СписокЦен, "Цены", ТаблицаДанныхПоставщика, СтрокаГруппы); 
					ПоместитьВТаблицуДанных(ИмяПоставщика, СписокШтрихКодов, "Штрихкоды", ТаблицаДанныхПоставщика, СтрокаГруппы); 
				КонецЕсли;
			КонецЦикла;
			
		КонецЕсли;
		
		Ответ = Новый Структура("Группы, Товары", ТаблицаГрупп, СвернутаяТаблицаДанныхПоставщика(ТаблицаДанныхПоставщика)); 
		
	Исключение
		ТекстСообщения = ОписаниеОшибки();
		Сообщить(ТекстСообщения);
	КонецПопытки;      
	
	Возврат Ответ;
	
КонецФункции

 

Функция помещена в раздел универсальных. Специфики не содержит и пока в нее все методики укладываются. Надеюсь, дальнейшая модификация не потребуется. В процессе вызываются специфические функции с параметром "ИмяПоставщика", которые содержат условный оператор, разветвляющий алгоритм. Они выдают результат если в них есть раздел данного поставщика. Если нет, то операция пропускается.

Эти функции также условно разделены на виды запрашиваемой информации. Выделено пять видов (соответственно пять функций):

1. Запрос полной информации.

2. Запрос свойств номенклатуры.

3. Запрос цен.

4. Запрос остатков.

5. Запрос штрихкодов

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

Функции выглядят примерно так:

	// Запрос всех данных по всему каталогу 
Функция СписокПолныеДанныеПоставщика(ИмяПоставщика, ПараметрыПоставщика) Экспорт
	
	ОтветПолный = Неопределено; 
	
	Попытка
		Если ИмяПоставщика = "Марвел" Тогда
		    ПараметрыНТТРЗавпроса = "";
		    ДобавитьПараметрыНТТРЗапроса(ПараметрыНТТРЗавпроса, "user" , ПараметрыПоставщика.Пользователь);
		    ДобавитьПараметрыНТТРЗапроса(ПараметрыНТТРЗавпроса, "password" , ПараметрыПоставщика.Пароль);
		    ДобавитьПараметрыНТТРЗапроса(ПараметрыНТТРЗавпроса, "secretKey" , "");
		    ДобавитьПараметрыНТТРЗапроса(ПараметрыНТТРЗавпроса, "packStatus" , "1");
		    ДобавитьПараметрыНТТРЗапроса(ПараметрыНТТРЗавпроса, "responseFormat" , "1");
		    ДобавитьПараметрыНТТРЗапроса(ПараметрыНТТРЗавпроса, "inStock" , "1");
			ОтветПоставщика = ОтправитьЗапросHTTP(ПараметрыПоставщика.СерверHTTP, ПараметрыПоставщика.ЗаголовкиHTTP, "POST", "Api/GetFullStock", ПараметрыНТТРЗавпроса); 
			Если ЗначениеЗаполнено(ОтветПоставщика.ОписаниеОшибки) Тогда
				Сообщить(СтрШаблон("Ошибка получения групп %1: %2 ", ИмяПоставщика, ОтветПоставщика.ОписаниеОшибки));
			Иначе  
				Сообщение = ОтветПоставщика.ОтветHTTP.Header; 
				Если Сообщение.Code = 0 Тогда
					ОтветПолный = ОтветПоставщика.ОтветHTTP.Body.CategoryItem; 
				Иначе
					Сообщить(СтрШаблон("Ошибка получения товаров %1: %2 ", ИмяПоставщика, Сообщение.Message));
				КонецЕсли;
			КонецЕсли;
		ИначеЕсли ИмяПоставщика = "Треолан" Тогда
			WSПрокси = ПараметрыПоставщика.WSПрокси;
			Если Не WSПрокси = Неопределено Тогда  
				ОтветТовары = WSПрокси.GenCatalogV2(ПараметрыПоставщика.login, 
													ПараметрыПоставщика.password, 
													ПараметрыПоставщика.category, 
													ПараметрыПоставщика.vendorid, 
													ПараметрыПоставщика.keywords, 
													ПараметрыПоставщика.criterion,
													ПараметрыПоставщика.inArticul,
													ПараметрыПоставщика.inName,
													ПараметрыПоставщика.inMark,
													ПараметрыПоставщика.showNc
												);
												
				ОтветПолный = СписокПозицийСРодителямиИзXML(ОтветТовары, "position");
			КонецЕсли;
		КонецЕсли;
	Исключение
		ТекстСообщения = ОписаниеОшибки();
		Сообщить(ТекстСообщения);
	КонецПопытки;      
			
	Возврат ОтветПолный;
		
 КонецФункции

 

Или так:

		// Доступные остатки
Функция СписокОстатковПоставщика(СтрокаГруппы, ИмяПоставщика, ПараметрыПоставщика, Идентификатор = "") Экспорт
	
	ОтветОстатки = Неопределено; 
	
	Попытка
		Если ИмяПоставщика = "Дихауз" Тогда 
			ОтветОстатки = ОтветАсинхронногоЗапросаДихаус(ПараметрыПоставщика.WSПрокси, Идентификатор);
			ОтветОстатки = ОтветОстатки.ProductRemains.ProductRemain;
		ИначеЕсли ИмяПоставщика = "Мерлион" Тогда
			Если СтрДлина(СтрокаГруппы.КодГруппы) = 8 Тогда  
				WSПрокси = ПараметрыПоставщика.WSПрокси;
				Если Не WSПрокси = Неопределено Тогда  
					cat_id = WSПрокси.ФабрикаXDTO.Создать(ПараметрыПоставщика.ТипСтрока, СтрокаГруппы.КодГруппы);
					ОтветОстатки = WSПрокси.getItemsAvail(cat_id, ПараметрыПоставщика.shipment_method, ПараметрыПоставщика.shipment_date, ПараметрыПоставщика.only_avail, ПараметрыПоставщика.item_id); 
					ОтветОстатки = ОтветОстатки.item;
				КонецЕсли;
			КонецЕсли; 
		КонецЕсли;
	Исключение
		ТекстСообщения = ОписаниеОшибки();
		Сообщить(ТекстСообщения);
	КонецПопытки;      
			
	Возврат ОтветОстатки;
		
 КонецФункции

		// Актуальные цены
Функция СписокЦенПоставщика(СтрокаГруппы, ИмяПоставщика, ПараметрыПоставщика, Идентификатор = "") Экспорт
	
	ОтветЦены = Неопределено; 
	
	Попытка
		Если ИмяПоставщика = "Дихауз" Тогда 
			ОтветЦены = ОтветАсинхронногоЗапросаДихаус(ПараметрыПоставщика.WSПрокси, Идентификатор);
			ОтветЦены = ОтветЦены.ProductPricelist.ProductPrice;
		КонецЕсли;
	Исключение
		ТекстСообщения = ОписаниеОшибки();
		Сообщить(ТекстСообщения);
	КонецПопытки;      
			
	Возврат ОтветЦены;
		
 КонецФункции

		// Отдельно хранимые штрихкоды
Функция СписокШтрихКодовПоставщика(СтрокаГруппы, ИмяПоставщика, ПараметрыПоставщика, Идентификатор = "") Экспорт
	
	ОтветШтрихКоды = Неопределено; 
	
	Попытка
		Если ИмяПоставщика = "Мерлион" Тогда
			Если СтрДлина(СтрокаГруппы.КодГруппы) = 8 Тогда  
				WSПрокси = ПараметрыПоставщика.WSПрокси;
				Если Не WSПрокси = Неопределено Тогда  
					cat_id = WSПрокси.ФабрикаXDTO.Создать(ПараметрыПоставщика.ТипСтрока, СтрокаГруппы.КодГруппы);
					ОтветШтрихКоды = WSПрокси.getItemsBarcodes(cat_id, ПараметрыПоставщика.item_id);
					ОтветШтрихКоды = ОтветШтрихКоды.item;
				КонецЕсли;
			КонецЕсли; 
		КонецЕсли;
	Исключение
		ТекстСообщения = ОписаниеОшибки();
		Сообщить(ТекстСообщения);
	КонецПопытки;      
			
	Возврат ОтветШтрихКоды;
		
 КонецФункции

 

Примеры привел для того, чтобы было понятно, как это выглядит и что код для нового поставщика добавляется по аналогии и не в каждую функцию.

Ответ обрабатывается аналогично, с помощью функций, возвращающей структуру состава полей ответа по имени поставщика. Также предусмотрена процедура для учета нюансов при получении информации из полей ответа. Если они есть. Например, вычисление нужного значения из значений нескольких полей. Работает по принципу причесывания. Если нюансы присутствуют, то надо просто их туда аккуратно занести.

Сюда заносим поля из документации. Функции выглядят так:

// Здесь формируется структура соответствий имен полей унифицированной таблицы данных групп и имен полей из ответа поставщика (на запрос групп).
// Здесь для нового поставщика формируется своя структура.
Функция СтруктураПолейГруппы(ИмяПоставщика) Экспорт  
	
	СтруктураПолей = Новый Структура();  
	
	Если ИмяПоставщика = "Дихауз" Тогда
		СтруктураПолей.Вставить("КодГруппы", "code"); 
		СтруктураПолей.Вставить("Наименование", "name"); 
	ИначеЕсли ИмяПоставщика = "Мерлион" Тогда
		СтруктураПолей.Вставить("КодГруппы", "ID"); 
		СтруктураПолей.Вставить("КодРодителя", "ID_PARENT"); 
		СтруктураПолей.Вставить("Наименование", "Description"); 
	ИначеЕсли ИмяПоставщика = "Марвел" Тогда 
		СтруктураПолей.Вставить("КодГруппы", "CategoryId"); 
		СтруктураПолей.Вставить("КодРодителя", "ParentCategoryId"); 
		СтруктураПолей.Вставить("Наименование", "CategoryName"); 
		СтруктураПолей.Вставить("МассивПодгрупп", "SubCategories"); 
	ИначеЕсли ИмяПоставщика = "Треолан" Тогда 
		СтруктураПолей.Вставить("КодГруппы", "id"); 
		СтруктураПолей.Вставить("КодРодителя", "parentid"); 
		СтруктураПолей.Вставить("Наименование", "name"); 
	КонецЕсли; 
		
	Возврат СтруктураПолей; 
	
КонецФункции

// Здесь формируется структура соответствий имен полей унифицированной таблицы данных по товарам и имен полей из ответа поставщика.
// Здесь для нового поставщика формируется своя структура. Возможно разбиение по видам запросов (Товары, Цены, Остатки, Штрихкоды). 
// Для каждого вида запроса формируется свой раздел.
Функция СтруктураПолейОтвета(ИмяПоставщика, ВидДанных) Экспорт  
	
	Ответ = Новый Структура();  
	
	Если ИмяПоставщика = "Дихауз" Тогда
		Ответ.Вставить("Идентификатор", "code");  
		Если ВидДанных = "Цены" Тогда
			Ответ.Вставить("Цена", "Price");  
		ИначеЕсли ВидДанных = "Товары" Тогда
			Ответ.Вставить("Категория", "Category");  
			Ответ.Вставить("Артикул", "VendorCode");  
			Ответ.Вставить("Наименование", "Name");  
			Ответ.Вставить("Штрихкод", "EAN");  
			Ответ.Вставить("Единица", "Unit");  
		КонецЕсли; 
	ИначеЕсли ИмяПоставщика = "Мерлион" Тогда
		Если ВидДанных = "Остатки" Тогда
			Ответ.Вставить("Идентификатор", "No");  
			Ответ.Вставить("Цена", "PriceClientRUB_MSK");  
			Ответ.Вставить("Остаток", "AvailableClient_MSK");  
		ИначеЕсли ВидДанных = "Товары" Тогда
			Ответ.Вставить("Идентификатор", "No");  
			Ответ.Вставить("Бренд", "Brand");  
			Ответ.Вставить("Артикул", "Vendor_part");  
			Ответ.Вставить("Вес", "Weight");  
			Ответ.Вставить("Длина", "Length");  
			Ответ.Вставить("Ширина", "Width");  
			Ответ.Вставить("Высота", "Height");  
			Ответ.Вставить("Наименование", "Name");  
			Ответ.Вставить("Категория", "GroupCode3");
			Ответ.Вставить("КатегорияРодитель", "GroupCode2");
		ИначеЕсли ВидДанных = "Штрихкоды" Тогда
			Ответ.Вставить("Идентификатор", "ItemNo");  
			Ответ.Вставить("ШтрихКод", "Barcode");  
		КонецЕсли; 
	ИначеЕсли ИмяПоставщика = "Марвел" Тогда 
		Если ВидДанных = "Товары" Тогда
			Ответ.Вставить("Идентификатор", "WareArticle");  
			Ответ.Вставить("Категория", "CategoryId");
			Ответ.Вставить("НаименованиеКатегории", "CategoryName");
			Ответ.Вставить("Наименование", "WareFullName");  
			Ответ.Вставить("Вес", "Weight");  
			Ответ.Вставить("Длина", "Depth");  
			Ответ.Вставить("Ширина", "Width");  
			Ответ.Вставить("Высота", "Height");  
			Ответ.Вставить("Бренд", "WareVendor");  
			Ответ.Вставить("Артикул", "WareArticle");  
			Ответ.Вставить("Цена", "WarePriceRUB");  
			Ответ.Вставить("Остаток", "AvailableForB2BOrderQtyInMSK");  
		КонецЕсли; 
	ИначеЕсли ИмяПоставщика = "Треолан" Тогда
		Если ВидДанных = "Товары" Тогда
			Ответ.Вставить("Идентификатор", "id");  
			Ответ.Вставить("Артикул", "articul");  
			Ответ.Вставить("Бренд", "vendor");  
			Ответ.Вставить("Наименование", "name");  
			Ответ.Вставить("ШтрихКод", "GTIN");  
			Ответ.Вставить("Вес", "brutto");  
			Ответ.Вставить("Длина", "length");  
			Ответ.Вставить("Ширина", "width");  
			Ответ.Вставить("Высота", "height");  
			Ответ.Вставить("Валюта", "currency");  
			Ответ.Вставить("Цена", "price");  
			Ответ.Вставить("Остаток", "freenom");  
			Ответ.Вставить("Категория", "id_Родитель");  
			Ответ.Вставить("КатегорияРодитель", "parent");
		КонецЕсли; 
	КонецЕсли; 
		
	Возврат Ответ; 
	
КонецФункции

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

Итоговая методика добавления контрагента:

1. Блок параметров подключения в виде структуры для нового поставщика.

2. Структура полей ответа на запрос товаров и групп.

3. Код вызова методов с заранее определенными параметрами.

Лично я остался доволен. Устраивает ли такой подход других - каждый может решить сам.

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

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

Файлы обработки и расширения доступны для скачивания по ссылке: https://github.com/MikeSheinesson/Files1C 

 

Вот и все. Спасибо тем, кто дочитал до конца. Буду рад, если данная публикация кому-то принесет практическую пользу или к чему-то побудит. Всем удачи.

 

рефакторинг HTTP rest soap интеграция поставщик оптимизация унификация код асинхронный запрос WS-ссылка метод прокси параметры дерево XML

См. также

Когда понадобился новый оператор

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

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

18.03.2024    1163    ZhokhovM    2    

4

Когда разработчик платформы не добавил проверку препроцессоров

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

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

18.03.2024    2701    ZhokhovM    4    

9

Реструктуризация - бесконечная история

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

При разработке программ требуемый функционал ставят на первое место, но есть еще и архитектура программы. На горизонте 5-10 лет она становится важнее функционала, который должен работать при масштабировании и росте данных. Реструктуризация 5 терабайтной базы 1С 8.2 в формат 1С 8.3, складывает весь пазл архитектурных просчетов, которые сделали ради функционала. Как это исправить? - для разработки правильной архитектуры, нужно всего лишь сместить фокус с функционала и подумать о «вечном».

29.09.2023    1910    1CUnlimited    15    

22

Чистый код. Мой взгляд на жизнь в макаронных джунглях. Часть 2

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

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

27.09.2023    6973    Lemmonbri    136    

36

Чистый код. Мой взгляд на жизнь в макаронных джунглях. Часть 1

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

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

19.09.2023    4355    Lemmonbri    16    

31

5 подходов при доработке конфигурации 1С, чтобы в будущем не было мучительно больно её обновлять

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

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

10.08.2023    9593    0    1c-izhtc    37    

21

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

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

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

11.07.2023    2217    magic1s    32    

11
Оставьте свое сообщение