Паттерн "Стратегия". Пример реализации

25.06.24

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

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

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование SM По подписке [?]
Паттерн «Стратегия». Пример реализации
.cf 85,76Kb
5
5
0 SM
Скачать

Немного про паттерны.

В объектно-ориентированных языках программирования есть такая замечательная вещь, как шаблоны (паттерны) проектирования. В общих чертах паттерны проектирования можно представить как шаблоны эффективного решения однотипных задач, с которыми сталкиваются большинство программистов. Тем самым задачу определенного вида можно решить, подобрав подходящий паттерн, а не создавать свой велосипед. При этом нужно понимать, какой шаблон проектирования использовать для конкретного вида задач. Неправильно подобранный паттерн может значительно усложнить и снизить эффективность решения. У паттернов проектирования есть имена ("Стратегия", "Наблюдатель", "Посредник" и т. д ), благодаря которым, общаясь с коллегами, можно не описывать всю суть решения поставленной задачи, а обойтись фразой "а здесь я применил паттерн %ИмяПаттерна%".

Если проводить аналогию с реальным миром, то в качестве шаблона проектирования можно представить последовательность строительства большинства частных домов:

  • Копка котлована
  • Строительство фундамента
  • Возведение коробки
  • Подключение коммуникаций
  • Внутренняя отделка
  • Отделка фасада

Представленную последовательность можно назвать паттерном «Строительство частного дома». Теперь, если необходимо решить задачу строительства частного дома, можно воспользоваться паттерном «Строительство частного дома».

 

 

За более подробным раскрытием темы «Что такое паттерны проектирования?» рекомендую обратиться к источникам в Интернете.

 

Паттерн "Стратегия".

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

Такое определение приведено в книге "Head First. Паттерны проектирования" (авторы Э. Фримен, Э. Робсон, К.Сьерра, Б.Бейтс). 

Выделим ключевые моменты из приведенного определения:

1. Семейство алгоритмов. Паттерн "Стратегия" позволяет выделить процедуры и функции, которые выполняют схожий функционал, принимают одни и те же параметры и возвращают значение одного типа (если это функция) но имеют разную реализацию.
Например, у нас есть потребность преобразовать элемент справочника "Товары" в формат, понятный другим системам. В зависимости от запроса вызывающей стороны, элемент справочника необходимо преобразовать в строку формата XML или JSON. Было создано две функции: одна создает строковое описание товара в формате XML, другая - в формате JSON. Обе функции в качестве параметра принимают ссылку на справочник "Товары" а в результате возвращают строковое значение (описание товара в формате JSON или XML). Выбор между XML и JSON в данном случае - это выбор стратегии, по которой дальше будет выполняться алгоритм. Условно можно представить в виде следующей схемы:


 

2. Инкапсуляция алгоритмов. Для алгоритмов реализации конкретных стратегий предполагается выполнение следующих условий:

  • Процедуры (функции) реализующие конкретные стратегии изолированы друг от друга;
  • Изменение в одной процедуре (функции) никак не должно отражаться на поведении других процедур (функций) реализующих другие стратегии выполнения;
  • Вызывающей стороне запрещено напрямую обращаться к алгоритму конкретной реализации. Обращение должно выполняться через отдельный интерфейс.

Вернемся к нашему примеру с преобразованием товара в XML и JSON. Следуя условиям инкапсуляции, нам понадобится:

  • Реализовать методы преобразования товара в XML и JSON таким образом, чтобы изменение в алгоритме XML никак не отражалось на изменении в алгоритме JSON и наоборот;
  • Создать общий модуль, содержащий программный интерфейс, через который вызывающая сторона может обращаться к функциям преобразования товара в XML и JSON.

Общий модуль, содержащий методы по преобразованию и программный интерфейс, можно представить следующим образом:

 
 Программный интерфейс СериализацияДанных
#Область ПрограммныйИнтерфейс

// Возвращает строковое описание
// переданного товара в запрашиваемом
// формате
//
// Параметры:
//  Товар	- СправочникСсылка.Товар - товар, который нужно
//			  описать в запрашиваемом формат 
//
//  ФорматСериализации - Строка - возможно одно из значений:
//							"XML", "JSON"
// 
// Возвращаемое значение:
//   - Строка - описание товара в запрашиваемом формате сериализации 
//	
// Пример:
//	ОписаниеТовараXML = СериализацияДанных.СериализованныйТовар(СсылкаНаТовар, "XML");
//
Функция СериализованныйТовар(Товар, ФорматСериализации) Экспорт
	
	// Выбор стратегии
	Если ФорматСериализации = "XML" Тогда
		
		Возврат ТоварXML(Товар);
		
	ИначеЕсли ФорматСериализации = "JSON" Тогда
		
		Возврат ТоварJSON(Товар);
		
	Иначе
		ВызватьИсключение СтрШаблон(НСтр("ru = 'Формат %1 не поддерживается'"), 
			ФорматСериализации);
	КонецЕсли;
	
КонецФункции

#КонецОбласти

 

Созданный общий модуль назовем «СериализацияДанных». Тогда для получения результата вызывающая сторона должна обратиться к нашему общему модулю:

ТоварВXML  = СериализацияДанных.СериализованныйТовар(СсылкаНаТовар, "XML");

3. Взаимозаменяемость. Выбор стратегии, по которой продолжится выполнение алгоритма, можно делать прямо во время выполнения программы. В нашем примере мы можем выбирать стратегию выполнения путем передачи значения параметра «ФорматСериализации» методу программного интерфейса сериализации товара:

// Здесь мы выбрали стратегию ТоварXML
ТоварВXML  = СериализацияДанных.СериализованныйТовар(СсылкаНаТовар, "XML");

// а здесь стратегию ТоварJSON
ТоварВJSON = СериализацияДанных.СериализованныйТовар(СсылкаНаТовар, "JSON");


Рецепт «Стратегии»

 
 Небольшое уточнение

 Предполагается что у читателя есть базовые представления ООП.


Для использования шаблона «Стратегия» нам потребуется:
* Класс контекста. Поскольку конкретные реализации алгоритмов требуемого действия / результата (по сути стратегии) недоступны вызывающей стороне (клиенту) напрямую, необходима точка взаимодействия, с помощью которой клиент может устанавливать стратегию выполнения, инициировать запуск стратегии. В процессе взаимодействия класс-контекст делегирует выполнение алгоритма конкретному классу-стратегии (вызывает выбранную клиентом реализацию).

* Общий интерфейс. Соглашение, содержащее описание методов (без реализации) которые должны быть реализованы в классах конкретных стратегий. Требуется для того, чтобы класс-контекст «не задумывался» о том, какая стратегия будет вызвана, т.к. все стратегии содержат методы, описанные в интерфейсе.

* Классы-реализации конкретных стратегий. Это объекты, в которых содержатся реализованные методы-стратегии, описанные в общем интерфейсе (п.2.). Данные методы вызываются, когда класс-контекст делегирует продолжение выполнение алгоритма классу реализации конкретной стратегии.

Способ применения:

1. Вызывающая сторона (клиент) выбирает стратегию выполнения алгоритма путем создания экземпляра класса-реализации конкретной стратегии. 

2. Клиент обращается к классу контексту:

2.1 Сообщает классу-контексту, какую стратегию нужно выполнить. Для этого у класса-контекста должен присутствовать метод, сохраняющий ссылку на экземпляр выбранной стратегии из п.1 в реквизит класса-контекста.

2.2 Вызывает метод класса-контекста, инициирующий запуск выполнения стратегии. В этот момент класс-контекст «пробрасывает» вызов от клиента в метод класса реализации выбранной стратегии.

3. Для смены стратегии клиент создает экземпляр другого класса-реализации и обращается к классу-контексту как в п.2
Схема взаимодействия выглядит следующим образом:

Для понимания приведу пример из жизни. Мне понадобилось подстричься. Рассматриваю отзывы на стилистов из ближайшей парикмахерской и выбираю определенного мастера по стрижке. Придя в парикмахерскую, сообщаю администратору, что хочу подстричься у выбранного мной мастера. Администратор проводит меня в зал к определенному мастеру. Я усаживаюсь в кресле, и стилист принимается за работу. Закончив, я понимаю, что не мешало бы и подравнять бороду. Но у текущего мастера закончилась рабочая смена, и мне приходится выбрать другого стилиста.  Определившись с парикмахером, подхожу к администратору, сообщаю, что хочу подровнять бороду у другого выбранного стилиста. Меня снова отводят в зал к выбранному парикмахеру, усаживают в кресло, и мастер выполняет стрижку бороды.

С точки зрения паттерна стратегии в описанной ситуации присутствуют следующие составляющие:

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

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

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

* Выбор стратегии. Выбирая определенного стилиста, я выбирал стратегию.

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

Получается следующая схема взаимодействия:

 

Думаю, становится очевидным, что все описание шаблона проектирования «Стратегия» было приведено с использованием понятий объектно-ориентированного программирования. Классы, интерфейсы, экземпляры класса – все эти понятия далеки от мира 1с. Но ничто не мешает нам выделить суть составляющих паттерна «Стратегия» и правильно их применить. Тогда с точки зрения механизма паттерна «Стратегия» нам понадобится:
1. Точка взаимодействия – объект, с которым будет взаимодействовать вызывающая сторона. Через точку взаимодействия клиент будет передавать информацию о выбранной стратегии выполнения и инициировать запуск алгоритма стратегии. Точкой взаимодействия может быть, например, общий модуль.

2. Соглашение по реализации методов стратегий. В соглашении должны быть перечислены и описаны методы, обязательные к реализации в конкретных стратегиях. Такое соглашение можно оформить в документации и в описании модуля точки взаимодействия.

3. Объекты, реализующие конкретные стратегии. Это объекты, содержащие методы из соглашения п.2, к которым будет переходить управление в момент делегирования вызова от точки взаимодействия. Объекты реализации конкретных стратегий должны содержать все методы из соглашения. Такими объектами-стратегиями могут быть, например, общие модули, модули-менеджеры объектов.
 
Тогда применение паттерна «Стратегия» можно описать так:

  • Клиент обращается к точке взаимодействия, передав информацию о выбранной стратегии и входные параметры алгоритма выполнения стратегии.
     
  • В точке взаимодействия на основании полученной информации о стратегии управление передается объекту-реализации – вызывается метод объекта-реализации, описанный в соглашении по реализации алгоритмов стратегий. Параметры от клиента «пробрасываются» в этот метод.

В качестве клиента может быть любое место конфигурации (модуль объекта, модуль менеджера, общий модуль и т.д.), из которого можно «дотянуться» до точки взаимодействия.

 


 

Пример

 
 Для информации

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

В качестве примера использования шаблона проектирования «Стратегия» рассмотрим следующую задачу: необходимо создать алгоритм расчета математического выражения суммы, разности, умножения и деления для двух чисел (такой же пример рассматривается в статье на википедии). Задачу будем решать на пустой конфигурации.
Исходя из описанных условий, можно выделить схожие алгоритмы – это расчет суммы, разности, произведения и частного двух чисел. На вход функциям поступают два числа, а в результате расчета возвращается другое число.  Таким образом, есть четыре стратегии:

  • Сумма
  • Разность
  • Умножение
  • Деление

Создадим серверные общие модули, в которые в последующем поместим алгоритмы расчета математического выражения:

 

 

Общие модули «Сумма», «Разность», «Умножение», «Деление» - это объекты, реализующие конкретные стратегии.

Далее нам потребуется соглашение по реализации методов стратегии - во всех ранее созданных общих модулях обязательно должна присутствовать функция «РезультатВыражения» с двумя числовыми параметрами, возвращающая числовое значение. Вставим заготовку в созданные ранее общие модули:

#Область СлужебныйПрограммныйИнтерфейс

// Параметры:
//  ПервоеЧисло	 - Число
//  ВтороеЧисло	 - Число
// 
// Возвращаемое значение:
//   - Число
//
Функция РезультатВыражения(ПервоеЧисло, ВтороеЧисло) Экспорт
	
	
КонецФункции

#КонецОбласти

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

 
 ОбщийМодуль.Сумма

 

#Область СлужебныйПрограммныйИнтерфейс

// Параметры:
//  ПервоеЧисло	 - Число
//  ВтороеЧисло	 - Число
// 
// Возвращаемое значение:
//   - Число - результат сложения первого и второго числа
//
Функция РезультатВыражения(ПервоеЧисло, ВтороеЧисло) Экспорт
	
	Сообщение = Новый СообщениеПользователю;
	Сообщение.Текст = НСтр("ru = 'Вызов стратегии Сумма'");
	Сообщение.Сообщить();
	
	РезультатВыражения = ПервоеЧисло + ВтороеЧисло;
	
	Возврат РезультатВыражения;
	
КонецФункции

#КонецОбласти

 

 
 ОбщийМодуль.Разность

 

#Область СлужебныйПрограммныйИнтерфейс

// Параметры:
//  ПервоеЧисло	 - Число - уменьшаемое
//  ВтороеЧисло	 - Число - вычитаемое
// 
// Возвращаемое значение:
//   - Число - разность первого и второго числа
//
Функция РезультатВыражения(ПервоеЧисло, ВтороеЧисло) Экспорт
	
	Сообщение = Новый СообщениеПользователю;
	Сообщение.Текст = НСтр("ru = 'Вызов стратегии Разность'");
	Сообщение.Сообщить();
	
	РезультатВыражения = ПервоеЧисло - ВтороеЧисло;
	
	Возврат РезультатВыражения;
	
КонецФункции

#КонецОбласти

 

 
 ОбщийМодуль.Умножение

 

#Область СлужебныйПрограммныйИнтерфейс

// Параметры:
//  ПервоеЧисло	 - Число
//  ВтороеЧисло	 - Число
// 
// Возвращаемое значение:
//   - Число - произведение первого и второго числа
//
Функция РезультатВыражения(ПервоеЧисло, ВтороеЧисло) Экспорт
	
	Сообщение = Новый СообщениеПользователю;
	Сообщение.Текст = НСтр("ru = 'Вызов стратегии Умножение'");
	Сообщение.Сообщить();
	
	РезультатВыражения = ПервоеЧисло * ВтороеЧисло;
	
	Возврат РезультатВыражения;
	
КонецФункции

#КонецОбласти

 

 
 ОбщийМодуль.Деление

 

#Область СлужебныйПрограммныйИнтерфейс

// Параметры:
//  ПервоеЧисло	 - Число - делимое 
//  ВтороеЧисло	 - Число - делитель
// 
// Возвращаемое значение:
//   - Число - частное первого числа от второго 
//
Функция РезультатВыражения(ПервоеЧисло, ВтороеЧисло) Экспорт
	
	Сообщение = Новый СообщениеПользователю;
	Сообщение.Текст = НСтр("ru = 'Вызов стратегии Деление'");
	Сообщение.Сообщить();
	
	РезультатВыражения = ПервоеЧисло / ВтороеЧисло;
	
	Возврат РезультатВыражения;
	
КонецФункции

#КонецОбласти

 

На текущем этапе мы завершили создание объектов-реализаций конкретных стратегий. Теперь нам нужен объект точка взаимодействия. В качестве точки взаимодействия создадим серверный общий модуль «МатематическиеВыражения»:

 

 

На вход точке взаимодействия нужно передать информацию о выбранной стратегии и параметры алгоритма. В нашем случае информация о стратегии – это выбранная математическая операция (сумма, разность, умножение, деление), параметры алгоритма – это первое и второе число. Тогда программный интерфейс модуля «МатематическиеВыражения» можно реализовать так:

 
 ОбщийМодуль.МатематическиеВыражения

 


#Область ПрограммныйИнтерфейс

// Возвращает результат выбранной математической
// операции двух чисел
//
// Параметры:
//  Операция	 - Строка - математическое выражение. 
//				   Допустимые значения: "Сумма", "Разность",
//				   "Умножение", "Деление".
//
//  ПервоеЧисло	 - Число
//  ВтороеЧисло	 - Число
// 
// Возвращаемое значение:
//   - Число - результат математической операции первого и второго числа
//
Функция РезультатМатематическойОперации(Операция, ПервоеЧисло, ВтороеЧисло) Экспорт
	
	// 1. Получим объект-реализации стратегии математической операции (общий модуль)
	МодульРеализацииРасчета = Вычислить(Операция);
	
	// 2. Делегируем выполнение расчета объекту-реализации конкретной стратегии
	РезультатОперации = МодульРеализацииРасчета.РезультатВыражения(ПервоеЧисло, ВтороеЧисло);
	
	Возврат РезультатОперации;
	
КонецФункции

#КонецОбласти

 

 

Теперь можно приступать к проверке. Для этого нам понадобится клиент, который будет обращаться к нашей точке взаимодействия. В качестве клиента создадим обработку «ПроверкаМатематическихВыражений»:

Реквизиты обработки:

  • МатематическаяОперация (Строка 99) – здесь мы будем указывать, какую операцию хотим выполнить;
  • ПервоеЧисло (Число 15, 2);
  • ВтороеЧисло (Число 15, 2);
  • Результат (Число 15, 2) – результат расчета выбранного математического выражения

Откроем модуль объекта созданной обработки и опишем обращение к точке взаимодействия:

 
 ПроверкаМатематическихВыражений.МодульОбъекта

 

#Область ПрограммныйИнтерфейс

// Вычисляет результат выбранной математической
// операции двух чисел. Выражение указывается в 
// реквизите "МатематическаяОперация"; 
// параметры - в реквизитах "ПервоеЧисло", "ВтороеЧисло";
// результат вычисления помещается в реквизит "Результат"
//
Процедура РасчитатьРезультатМатематическогоВыражения() Экспорт
	
	Результат = МатематическиеВыражения.РезультатМатематическойОперации(МатематическаяОперация,
					ПервоеЧисло, ВтороеЧисло);
	
КонецПроцедуры

#КонецОбласти

 


Создадим основную форму обработки, разместим реквизиты:

 


Для элемента формы «МатематическаяОперация» определим список выбора и установим свойство «Режим выбора из списка»:

 

 

Разместим на форме команду «Рассчитать выражение»:


 

Для команды создадим клиентский обработчик и напишем в нем следующий код:

 
 ПроверкаМатематическихВыражений.МодульФормы

 


#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура РассчитатьВыражение(Команда)
	
	Если НЕ ЗначениеЗаполнено(Объект.МатематическаяОперация) Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'Необходимо выбрать математическую операцию'"), 20);
		Возврат;
	КонецЕсли;
	
	Если Объект.МатематическаяОперация = "Деление" И Объект.ВтороеЧисло = 0 Тогда
		ПоказатьПредупреждение(, НСтр("ru = 'Деление на 0 недопустимо'"), 20);
		Возврат;
	КонецЕсли;
	
	РассчитатьВыражениеНаСервере();
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

&НаСервере
Процедура РассчитатьВыражениеНаСервере()
	
	ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
	ОбработкаОбъект.РасчитатьРезультатМатематическогоВыражения();
	
	ЗначениеВРеквизитФормы(ОбработкаОбъект, "Объект");
	
КонецПроцедуры

#КонецОбласти


 

Здесь мы проверяем заполнение обязательных параметров и вызываем метод расчета математического выражения, расположенный в модуле объекта.

Запустим наше приложение и проверим обработку:

 

 

В ходе проверки можно заметить, что алгоритм расчета мы можем менять прямо в ходе выполнения программы путем установки значения реквизита «Математическая операция».
Таким образом, в ходе построения примера мы реализовали следующие ключевые моменты шаблона проектирования «Стратегия»:

  • Схожие алгоритмы. Выделили алгоритмы расчета суммы, разности, умножения и деления в отдельные функции, которые на входе принимают два числа, а возвращают другое число – результат математической операции.
     
  • Инкапсуляция. Каждый алгоритм расчета выражения поместили в отдельный объект-реализацию – это общие модули «Сумма», «Разность», «Умножение», «Деление». Для внешней стороны (клиента) создали программный интерфейс (точку взаимодействия) по вызову функций расчета – это общий модуль «МатематическиеОперации».
     
  • Взаимозаменяемость. Как было показано в ходе проверки, алгоритмы расчета мы можем менять прямо во время исполнения программы путем выбора значения реквизита «Математическая операция» обработки-клиента.

В виде схемы полученное решение можно представить так:


 

Реальные примеры использования

Применение паттерна «Стратегия» можно увидеть в подсистемах «Отправка SMS» (см. общий модуль «ОтправкаSMS») и «Базовая функциональность» (см. общий модуль «АдминистрированиеКластера») библиотеки стандартных подсистем.


Заключение

В данной статье мы познакомились с шаблоном проектирования «Стратегия» а также рассмотрели простой пример использования данного паттерна. «Стратегию» следует применять, когда:

  1. У нас есть схожие алгоритмы для решения поставленной задачи;
     
  2. Алгоритмы необходимо изолировать друг от друга, чтобы реализация одной «стратегии» не зависела от реализации другой. Это позволит изменять конкретные реализации алгоритмов без ущерба для других. Также подобный подход позволит легко расширить имеющийся функционал – для добавления новой «стратегии» нам понадобится просто добавить ещё один объект-реализацию;
     
  3. Реализация алгоритмов («стратегий») не должна зависеть от внутренней структуры клиента (вызывающей стороны). Взаимодействие должно выполняться с разными клиентами с различной структурой;
     
  4. Есть потребность менять алгоритмы прямо во время исполнения программы;
     

При выборе паттерна «Стратегия» следует учитывать:

  • Для того чтобы в зависимости от условий выбрать правильную стратегию, вызывающая сторона должна знать о существовании всех возможных стратегий и чем они отличаются;
     
  • Каждая новая стратегия – это новый объект-реализация (т.е. ещё один общий модуль, внешняя обработка и. т.д.), что приводит к разрастанию структуры конфигурации. 


Рассмотренный пример может быть модифицирован и улучшен по желанию читателя. Конфигурация с примером прикреплена к данной статье.

 

Спасибо за внимание! 

Шаблоны проектирования паттерн Стратегия

См. также

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

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

1 стартмани

04.06.2024    4513    mrXoxot    51    

37

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

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

10.04.2024    10343    artbear    84    

104

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

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

01.04.2024    2993    DrAku1a    15    

35

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

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

01.04.2024    872    Prepod2003    6    

2

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

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

18.03.2024    1616    ZhokhovM    5    

4

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

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

18.03.2024    3354    ZhokhovM    4    

10
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. user1950534 26.06.24 09:59 Сейчас в теме
Я вот не знаю, где-то в этих ваших ООП ориентированных платформах, наверное, стоит заморачиваться вот такой эдакой пирамидальной структурой проектирования. А в 1С - чем проще, тем надежнее. Не, я не спорю, DRY должен быть, названия корректные должны быть, объединение в общие модули по смыслу, наверное тоже. Но вот инкапсуляция с изолированием конечных функций... не уверен. Потом когда отлаживаешься на чужом коде, стопицот раз F12 или через стек вызовов.. с ума сойти можно.
rpgshnik; MadRave; +2 1 Ответить
5. alex_sayan 27.06.24 07:29 Сейчас в теме
(1)
А в 1С - чем проще, тем надежнее


В 1с как раз принято делать сложно и порочно: здоровенные методы, которые делают всё и сразу; зависимости в коде всего от всего; махровое дублирование кода... Ничего общего с простотой это не имеет. Наоборот, порождение бессмысленной сложности
dhurricane; rpgshnik; KirillZ44; Viktor_Ermakov; Артано; Gesperid; +6 Ответить
8. Артано 764 27.06.24 08:37 Сейчас в теме
(1) Разработка через отладчик это не разработка. Тут и просто умеющего читать/писать человека можно посадить.

Статья хорошая, подход понятный и прозрачный. По реализацию через модули можно спорить, я бы использовал отдельные обработки, но тут опять же просто пример реализации идеи.
13. Gesperid 2 27.06.24 09:57 Сейчас в теме
(1)
чем проще, тем надежнее

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

Инкапсуляция - это считай единственный способ борьбы со сложностью, остальные - интструменты разработки, конвенции именования и идиомы - вторичны и вносят меньший вклад.
2. MadRave 18 26.06.24 13:35 Сейчас в теме
инкапсуляция с изолированием конечных функций...


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

Создать подключаемый модуль, подходящий сразу для всех конфигураций мы не можем из-за различного состава метаданных.
3. sh_oleg 26.06.24 16:19 Сейчас в теме
Отличная статья. Спасибо!
4. kalyaka 1085 26.06.24 21:49 Сейчас в теме
Какой выигришь от того, что для одной функции требуется целый общий модуль выделять?

Может так проще подменять эти функции-модули через механизм расширений? Так то в точку взаимодействия можно передавать любую функцию из либого модуля в виде строки вызова с параметрами + контекст.

Если вместо функции передать обработку как объект с реализацией нужной функции, то можно открыть еще и принцип инверсии зависимостей.

Еще эта тема перекликается с абстрактными алгоритмами.

В общем тема использования абстракций как то мало представлена в мире 1С. Побольше бы таких исследовательских статей!
6. alex_sayan 27.06.24 07:35 Сейчас в теме
Паттерны проектирования это хорошо... Но, как рассказывают бывалые товарищи ( https://www.ozon.ru/product/adaptivnyy-kod-gibkoe-kodirovanie-s-pomoshchyu-patternov-proektirovaniya-i-printsipov-solid-2-e-1419101067/ ), даже в мире ООП паттерны чаще применяют где не надо, и не применяют где надо. В среде 1сников они ещё очень нескоро приживутся
7. rambomax 27.06.24 08:35 Сейчас в теме
К глубокому сожалению, для описания метода подобран очень слабый пример, который, строго говоря, больше вредит, чем поясняет.
"Модуль" в 1С действительно можно представить как "объект" в полном смысле слова - там есть данные и есть внутренний и внешний интерфейс. Можно даже сделать искусственное "наследование", как в БСП.
Однако суть ООП - в сокрытии ДАННЫХ и доступ к ним только через МЕТОДЫ. В указанном примере данных нет, есть только функции, поэтому пример показывает обычную процедурную декомпозицию, а ООП притягивают за уши из-за модных и красивых слов.
Разница между ООП и процедурными методами аналогична разнице между "католичеством" и "протестантизмом" - ключевое это ВЕРА. Автор статьи ВЕРИТ в модные красивые слова "ООП", поэтому в глазах верующего пример адекватен.
Есть мнение, что по вопросам веры, всё-таки лучше ходить в церковь, а не писать псевдонаучные статьи.
morin; Артано; +2 Ответить
9. Артано 764 27.06.24 08:40 Сейчас в теме
(7) Согласен, кроме грубости. В целом подход реализован здравый. В 1с не так много инструментов для реализации конкретной функциональности. В другом комментарии я указывал, что использовал бы обработки - они здесь реально были бы к месту. Но это тоже своего рода костыль в практике применения абстрактной парадигмы на инструментах 1с
14. Viktor_Ermakov 365 27.06.24 10:07 Сейчас в теме
(7)
что по вопросам веры, всё-таки лучше ходить в церковь, а не писать псевдонаучные статьи.

С нетерпением ждем от Вас статью, как Вы видите этот шаблон в 1С.
Это не шутка, реально интересно.
16. rambomax 27.06.24 10:32 Сейчас в теме
(14) Я бы сначала без шуток хотел бы увидеть доказательства того, что такой "шаблон" чем-то лучше более других.
Дано: в конце прошлого века люди летали на Луну. У этих людей не было "шаблонов", "ООП" и прочего, но алгоритмы, заложенные в примитивные тогда вычислители, выполнили операцию на отлично.
В 21м веке есть "шаблоны" и т.п., но современные продвинутые вычислители не смогли попасть красным автомобилем в Марс настолько, что даже сидящий в этом автомобиле манекен удивился.
Таким образом мы видим, что вместо "развития" нам предлагаются модные "шаблоны", которые стерилизуют мысль разработчика, в результате не рождается ничего жизнеспособного.
Берём разработку отсталым "водопадным методом" и с отсталым "процедурным подходом". Основное там: требуются люди, которые возьмут на себя ОТВЕТСТВЕННОСТЬ за свои решения и построят АРХИТЕКТУРУ решения.
Это фу-фу-фу, не модно - берём барбершоп, вейп и рождаем новое слово - современные "паттерны".
Мы не знаем заранее какая будет архитектура - не беда, у нас будет "гибкая стратегия", которая описана в статье, чтобы "когда не подойдёт объект "А", он будет на лету заменяться на объект "Б", что такое архитектура приложения думать не надо". Т.е. описывается модный метод "тяп ляп и в продакшн", метод опирается на авторитет лучших барбершоперов, кто не согласен - в сад.
Имеем то, что имеем.
Вместо дискурса на тему "зачем нам в 1С все эти барбершопные свистелки" мы получаем дискурс "как нам приделать эту модную свистелку к платформе". И с таким подходом Луны нам не видать как своих ушей.
17. Gesperid 2 27.06.24 10:58 Сейчас в теме
(16)
Дано: в конце прошлого века люди летали на Луну. У этих людей не было "шаблонов", "ООП" и прочего, но алгоритмы, заложенные в примитивные тогда вычислители, выполнили операцию на отлично

Вполне возможно когнитивное искажение "ошибка выжившего" типа - я не помню, что раньше не падали ракеты из-за багов, а сейчас падают - значит раньше не было ошибок в ПО ракет.
Без статистики и данных о различиях методов разработки утверждать сложно.
Но, как были косяки и успехи связанные с багами софта так и остались https://www.csoonline.com/article/567417/8-famous-software-bugs-in-space.html
У вас есть статистика и данные, и когда произошло отсечение на "свистопердельные методологии"?

Берём разработку отсталым "водопадным методом" и с отсталым "процедурным подходом". Основное там: требуются люди, которые возьмут на себя ОТВЕТСТВЕННОСТЬ за свои решения и построят АРХИТЕКТУРУ решения.

Водопад показал свою несостоятельность в крупных системах. Ну не может человек запроектировать с первого раза хорошо что-то крупное.
KirillZ44; kalyaka; +2 Ответить
18. rambomax 27.06.24 11:12 Сейчас в теме
(17)
Это слишком серьёзное утверждение: какой "проект" был настолько "крупный", что не нашлось умного человека, который смог бы его "запроектировать"?
Проект "Буран" потребовал создания своего собственного ЯП "Дракон" и полёт таки случился.
Слом парадигмы случился когда началась "рейганомика", когда образовалось большое количество "лишних людей", которых надо было чем-то занять и отлично подошли "графические интерфейсы" и "управление мышью". Т.е. раньше фантасты писали: "командир сказал "рассчитать траекторию" и мелодичный звон колокольчика известил что расчёт закончен". Ни в одном старом фильме нет космонавта с мышью - даже в "Чужих" вполне себе голосовой интерфейс.
Засада произошла в тот момент, когда понадобилось убрать персональную ответственность за результат и появилось "событийно управляемое программирование". Поскольку мы в принципе не можем предугадать все возможные входящие события, то мы по определению не способны написать безошибочный алгоритм - требуется создать что-то, потом начать его "тестировать" входящими воздействиями и бесконечно исправлять. В результате у нас "лишние люди" оказываются заняты в "тестировании", в "исправлении ошибок" и написании книг "как никогда ни за что не отвечать". Все довольны. Просто вопрос: "если у вас законодательно определённая регламентированная отчётность, почему она в заданный момент времени не делается автоматически, автоматически не отправляется и автоматически не обрабатывается" задавать нельзя: придётся сокращать людей, которые мужественно ежемесячно эту отчётность делают/отправляют/проверяют.
Обсуждаемая "проблема" имеет не теоретическую, а социально-политическую причину - дедушка Кнут не описывал "паттерны" не потому что был глуп и отстал, а потому что он описывал реальность без учёта прогрессивной повестки.
20. Gesperid 2 27.06.24 11:34 Сейчас в теме
(18)
Это слишком серьёзное утверждение: какой "проект" был настолько "крупный", что не нашлось умного человека, который смог бы его "запроектировать"?

Отвечу вопросом на вопрос: вы никогда не переписываете функции, не меняете стуктуру регистров из-за ошибки проектирования или вы PM, а "ОТВЕСТВЕННОСТЬ" на безответственных разработчиках? Или вы просто переоцениваете способности человеческого мозга и недооцениваете сложность систем, и не хотите принимать подходы преодоления сложности.
...

Сложно спорить с большим набором слабо связанных утверждений собранных в одном абзаце.
22. rambomax 27.06.24 11:42 Сейчас в теме
(20)
А вы никогда не задумывались, что то, что вы называете "ошибки" являются результатом работы над совершенно другим заданием? - что та структура регистров решала ТУ задачу? Откуда уверенность, что ТА структура для ТЕХ условий была не правильная, потому что СЕЙЧАС что-то изменилось?
Диалектика это когда росток отрицает зёрнышко - тут нет противоречий.
Если вам попались безответственные рэмэ, то как это нивелируется "паттернами проектирования"? - нет ли тут логического противоречия?
Если теория требуется ответственного рэмэ, а у вас его нет - это проблема теории?
25. Gesperid 2 27.06.24 12:05 Сейчас в теме
(22)
Откуда уверенность, что ТА структура для ТЕХ условий была не правильная, потому что СЕЙЧАС что-то изменилось?

Пара предварительных замечаний:
1. Разумеется речь идёт про фиксированную требования/спецификацию с функциями f1, ..fn оцененные как одинаковые по трудозатратам.
2. Проектные решения (design) - решения более высокоуровневые относительно реализации. Например, для конфигурации на 1С - это не текст в worde/confluence/и т.п. с детализацией до кода, а нечто более высокоуровневое (абстрактное, модель) например, сценарии, схемы, структуры.

Так вот, реализуя эти функции по предварительному проекту, исполнитель на какой-то функции f i может столкнутся с такой когнитивной сложностью взаимосвязей деталей, что скорость реализации упадет в разы c f i-1.
Но при водопаде мы не можем менять проект, чтобы уменьшить сложность и просто реализуем f i с превышением сроков и в надежде, что fn вообще реализуется в разумные сроки.
27. rambomax 27.06.24 12:53 Сейчас в теме
(25)
вы так говорите, как буд-то это что-то плохое (с) )))
10. rambomax 27.06.24 08:57 Сейчас в теме
(9) В чём грубость не понял, но ладно.
Вопрос ключевой вот в чём: зачем за модными словами скрывать простое, реальное, данное нам в ощущениях действие - декомпозицию? Что дало статье упоминание модных слов? - стала она от этого проще? понятнее?
Начинается здраво: "делай как сержант, когда научишься, будешь делать лучше сержанта".
Но потом начинается невыносимое натягивание совы на глобус - подгонка реального, данного в ощущениях, кода под надуманные вычурные "парадигмы".
Это пример "каргокульта", но в данном случае белые господа совсем не оценят стараний.
Если выкинуть всю муть про барбершопы, то останется: принцип проектирования, постановка задачи, выделение ПРОЦЕДУР, реализация ПРОЦЕДУР.
Вот об этом и надо было писать, без казуистики.
12. Артано 764 27.06.24 09:57 Сейчас в теме
(10) Речь идёт об абстрактных методологиях, реализация которых в 1с "искаропки" отсутствует. Так что лично я считаю, что автор имеет право поразмышлять на тему и попробовать реализовать. Если не согласны - пишите списком:
- Вот здесь и здесь, мол не согласен
- Здесь вы слишком вольно обращаетесь с терминологией, а здесь неверно понимаете назначение паттерна итд
15. rambomax 27.06.24 10:22 Сейчас в теме
(12)
В том-то и дело: в 1С пытаются "тянуть" методологии, реализация которых отсутствует. Это предполагает логическое продолжение: отсутствуют, потому что разработчики 1С не адекватные люди.
Т.е. мы натягиваем сову на глобус не потому, что мы любители натягивания, а потому что "сова отдельно глобус отдельно" не модно.
В этом и есть суть моего несогласия: притягивание "абстрактных методологий" туда, где они отсутствуют без доказательства, что такое притягивание:
а) чем-то полезно
б) что-то улучшает
в) имеет какие-то преимущества
т.е. статья априори подразумевает, что есть некие безусловно ПРАВИЛЬНЫЕ ТЕХНОЛОГИИ БЕЛЫХ ЛЮДЕЙ, которые обязательно нужно применить к серой недоразвитой платформе. И основной смысл: "чтобы было как у белых людей".
Итого: в платформу 1С заложены "паттерны", про которые нет хороших книжек. Автор прочитал модную книжку и написал статью как сделать из того, что есть, то, что написано в модной книжке. Получилось кривовато, но это вклад в продвижение модной темы.
Есть мнение, что вместо гонки за модой, лучше бы сосредоточиться на объективной реальности, данной нам в ощущениях.
Alxby; grumagargler; +2 Ответить
19. kalyaka 1085 27.06.24 11:22 Сейчас в теме
(15) Методология нужна для ментальных моделей. Язык программирования может поддерживать выбранную методологию, а может и нет. Однако даже в ассемблере можно писать в ООП стиле :)

Ментальные модели нужны для построения сложных решений без потери контроля над сложностью. При этом если среда поддерживает методологию, то это помогает не потерять этот контроль. А если нет, то это требует поиска выражения методологии в языке и поддержки дисциплины программирования без поддержки и контроля со стороны инструмента. Частично проблему поддержки можно решать через разработку фреймворков (например БСП).

В любом случае методология - это естественный результат процесса обобщения известных способов описания действительности, которые были найдены на практике. Глупо не изучать известные методологии и пытаться найти свой путь там, где уже прошли до тебя :)
Артано; Gesperid; +2 Ответить
29. grumagargler 726 27.06.24 17:23 Сейчас в теме
(10) Ну а что вы хотели, люди почти ровесники языка, на котором им приходится писать программы, пытаются полученные в институтах из современных учебников по информатике знания, применить к модели, ничего о них не знающей. Что из этого получается? Ну как...служебные интерфейсы, типизирующие комментарии, префиксы, суффиксы, соглашения, обряды, культы, заповеди ИТС и ритуалы. И ничего в этом такого уж плохого нет, работу надо работать в конце-концов, а плохое начинается когда по чуть люди начинают думать что это нормально, что оказывается все приёмы современной разработки уже есть и у нас в 1С, забывая на каких рефлексиях и соглашениях это построено. И вот именно здесь и происходит недопустимое допущение: паттерны неразрывно связаны с возможностями языка для их применения, а не в самоцель. И тот факт, что без этих всех костылей, текущую парадигму (например) библиотечной разработки в 1С не реализовать, трубит который год о проблеме в языке, а не о том, как прекрасно можно любой паттерн заэмулировать на 1С.
rambomax; Alxby; +2 Ответить
11. realchel 27.06.24 09:07 Сейчас в теме
Комментаторы что то накинулись на автора.
Большинство их с огромным опытом.
Беда сообщества 1С, которое культивируется самой фирмой, это вырастить внедренца.
Я в 1С с 99 года.
Внедрен пришел к клиенту заплатку сделал и ушел.
Он не думает о дальнейшем сопровождении кода.
А это надо начать менять в головах и сознании 1С, иначе на 1С так и будут смотреть как на недопрогеров
(сейчас на них смотрят как на необходимость из за санкций и требований уходить на российское ПО)
При этом 1С экосистему считаю оптимальной для реализации бизнес задач в ИТ.

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

Те кто не знаком с методологиями Чистого кода, Чистой архитектуры рекомендую ознакомиться с одноименными книгами, и другие книги автора будут полезны.
Можно еще почитать 5 строк кода.
(подозреваю что есть еще подобные до которых я не дотянулся)

А в книге(относительно свежей) Ум программиста, можно сказать научно объясняется в чем проблема сопровождать монструозный не "качественный" код.

PS: Кто соскучился по ООП , марш в 1С:Элемент, там есть задатки)))
PS2: Закидывание тапками приветсвуется.
rambomax; +1 Ответить
21. rambomax 27.06.24 11:37 Сейчас в теме
(19)
Хороший вопрос тогда: а вы уверены, что "ментальные модели" для ёжиков, хорошо подходят и для зайчиков? Наука - это всегда начинать с "области применимости" теории. У учёных не является признаком большого ума применять "принцип относительности" при "прочностных расчётах".
В статье описываются "методологии", которые были разработаны для совершенно конкретных условий и описывают совершенно конкретный процесс для абсолютно другого процесса с совершенно другими условиями.
Глупо зайчику тренироваться становится ёжиком вместо занятий бегом и прыжками.
23. kalyaka 1085 27.06.24 11:51 Сейчас в теме
(21) Разработка, как и инженерное дело, всегда опирается на теорию и на практику. Если текущий уровень теории достаточен для практического решения задач, то можно дальше и не развиваться :) Другое дело, что если хочется большего, лучшего, а пределы не позволяют - то требуется исследования и развитие вначале теории, а затем и практики. Дальше цикл повторяется до бесконечности :)

Эта статья - своего рода исследование возможностей приложения методологии в условиях среды 1С. Исхожу из того, что аудитория этой статьи все таки разработчики - профессионалы своего дела. И вне зависимости от уровня профессионализма статья полезна: для низкого уровня в качестве развития, для среднего - проверка идей, для высокого - площадка для обмена мнениями.
24. rambomax 27.06.24 12:00 Сейчас в теме
(23)
Пожалуйста, приведите конкретный пример из статьи: чем описанное "больше", "лучше", какие "пределы не позволяют" лучше и больше?
Мне кажется, что тут как раз пример того, что "если бы у бабушки были бы колёса, то это была бы не бабушка, а Дилижанс".
26. kalyaka 1085 27.06.24 12:42 Сейчас в теме
(24) Ну в статье приведен слишком простой пример, который, к сожалению, не позволяет оценить силу паттерна. Выбор удачного примера - это тоже не тривиальная задача. С одной стороны пример должен быть достаточно не замороченный, а с другой в нем должна быть очевидная для большинства польза. В общем это должен быть простой пример, иллюстрирующий мощь подхода :)

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

Я рассматриваю эту статью как начальную. Возможно изложенные идеи можно будет использовать на практике в 1С, а может быть и нет.
28. booksfill 27.06.24 17:23 Сейчас в теме
Размышлизмы:
1. Класс-стратегия, также как и класс-контекст, должен реализовывать интерфейс.
Без этого класс-контекст вынужден доверять клиенту, что он в него передаст имя модуля/обработки, имеющего нужный метод.

Без контроля таких вещей со стороны IDE и компилятора уже явно ненадежный подход.

2. Класс - контекст должен иметь возможность хранения переданного экз. стратегии.
Даже в вашем простейшем примере с одним методом - плохая идея пихать в каждый вызов метода строку с именем стратегии.
Поэтому, как вариант, вместо общего модуля следовало бы использовать обработку.

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

4. В Вашем пример класс - контекст, как вы сами отметили, это скорее недоинтерфейс с методами, идея подозрительно похожа на костыль от JavaScript, где тоже нет интерфейсов, но хотя бы есть "почти классы".

5. Пример, по-моему, неудачен - продемонстрирован случай, когда криво реализованный паттерн только усложняет код,
делает его более уязвимым и при этом мало чего не дает взамен.
По-моему, лучше уйти от пуританства и добавить какое-то доп. поведение в класс-контекст, тогда хотя бы появится смысл в его использовании.
Например, можно в классе - контексте организовать совместную работу нескольких, не знающих друг про друга, стратегий и получать какой-то дополнительный функционал.
30. leobrn 622 28.06.24 13:45 Сейчас в теме
Еще небольшие примеры использования стратегии в 1с https://leobrn.github.io/ones-patterns/patterns/strategy
Оставьте свое сообщение