"Хочу универсально!" [Часть 2]

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

Здесь можно прочитать первую часть статьи: ссыль.

 

Нужно больше универсальности!

 

Начинающий разработчик Василий не так давно начал свой путь универсализации всего и вся.

 

И теперь не собирается останавливаться.

 

На данный момент Вася имеет метод, который открывает значение текущей ячейки. Но что, если расширить функционал? Методы, которые позволят не только открывать текущее значение, но и присваивать его… И независимо от того, находимся ли мы на клиенте или сервере…

 

 

Василий берёт блокнот и записывает:

 

  • программно получить значение текущей ячейки (на клиенте и на сервере)

  • программно установить значение текущей ячейки (на клиенте и на сервере)

  • интерактивно показать значение текущей ячейки (на клиенте)

  • чистить кэш

  • сохранять сессию открытых окон…

 

Почесав затылок, наш начинающий универсальщик скрепя когтями решает отложить часть пунктов «на потом» и сократить список:

 

  • программно получить значение текущей ячейки (на клиенте и на сервере)

  • программно установить значение текущей ячейки (на клиенте и на сервере)

  • интерактивно показать значение текущей ячейки (на клиенте)

 

 

Для всего этого нужна хорошая обёртка. Василий переворачивает страницу блокнота и пишет:

 

  • Возможность передать в метод любую таблицу. Ведь, если на текущем инструменте несколько таблиц, то нужно обеспечить возможность работы со всеми.

  • Работать как «&НаСервере», так и «&НаКлиенте». Естественно, где это возможно.

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

 

Разработчик окидывает взглядом текущий функционал, который он написал в первой статье

 

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

ПутиКДаннымЭлементовФормы = Новый Структура;

Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл

Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы")
ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда

ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным);

КонецЕсли;

КонецЦикла;

КонецПроцедуры


&НаКлиенте
Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента)

ПутьКДаннымЭлемента = Неопределено;
ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;

КонецФункции


&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)

ТаблицаФормы = Элементы.Валюты;

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;

ИмяПоляКолонки     = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ИмяПоляКолонки);

СоставПутиКДанным  = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы  = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];

ЗначениеЯчейки     = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);

ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеЯчейки);

КонецПроцедуры

 

Первое, что попадается на глаза разработчику Васе — метод «ПриСозданииНаСервере». Его используют очень часто для разного рода действий и загромождать своим кодом будет не очень удобно.

 

— Нужно вынести в новый метод!

 

И Василий решает содержимое события «ПриСозданииНаСервере» вынести в отдельный метод. А заодно и протестировать возможность конфигуратора, о которой он вроде бы слышал, но никогда не пробовал — рефакторинг кода.

 

Начинающий разработчик выделяет нужный код, нажимает правую кнопку мыши и выбирает «Рефакторинг» → «Выделить фрагмент»

 

 

 

В появившемся окошке он вводит название своего нового метода: ОбновитьПутиКДаннымЭлементовФормы

 

 

И в результате получает то, что хотел. Конфигуратор сам создал новую процедуру и сделал вызов на неё

 

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

ОбновитьПутиКДаннымЭлементовФормы();

КонецПроцедуры

&НаСервере
Процедура ОбновитьПутиКДаннымЭлементовФормы()

ПутиКДаннымЭлементовФормы = Новый Структура;

Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл

Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы")
ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда

ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным);

КонецЕсли;

КонецЦикла;

КонецПроцедуры

 

— Не зря я учился в Великой Школе Одинэсников Имени Желтого Чайника!

 

В результате, если Вася захочет поделиться наработками, то применить их в другом инструменте будет теперь чуточку проще. Есть ещё один приятный бонус — возможность дополнительно вызывать этот метод по мере необходимости (Василий пока ещё не понял зачем, но об этом позднее…).

 

Для этого сразу же ранее написанный метод «ПутьКДаннымЭлементаФормы» делаем &НаКлиентеНаСервереБезКонтекста. Таким образом один и тот же метод будет доступен и на сервере и на клиенте.

 

&НаКлиентеНаСервереБезКонтекста
Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента)

ПутьКДаннымЭлемента = Неопределено;
ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;

КонецФункции

Василий знает, что при такой директиве метод «теряет» контекст формы, а значит больше не видит её свойств, элементов, реквизитов и так далее. Но как же теперь с этим работать?

Наш разработчик будет просто передавать форму напрямую.

 

&НаКлиентеНаСервереБезКонтекста
Функция ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяЭлемента)

ПутьКДаннымЭлемента = Неопределено;
ЭтаФорма.ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;

КонецФункции

Получается, что, независимо от того, находимся ли мы сейчас на клиенте или же сервере, можно вызвать один и тот же метод и просто передать в него текущую форму:

 

&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)

ТаблицаФормы = Элементы.Валюты;

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;

ИмяПоляКолонки     = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);

СоставПутиКДанным  = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы  = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];

ЗначениеЯчейки     = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);

ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеЯчейки);

КонецПроцедуры

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

 

— Ну-с, приступим!

 

&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)



КонецФункции

Этот метод вернёт значение текущей ячейки. На клиент, на сервер — не важно. А дальше уже мы сможем использовать это по своему усмотрению.

Начинаем с классической проверки:

 

&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;


КонецФункции

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

 

&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;

ИмяПоляКолонки     = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);

СоставПутиКДанным  = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы  = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];

ЗначениеЯчейки     = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);

Возврат ЗначениеЯчейки;

КонецФункции

 

Написанная функция вернёт нам значение текущей ячейки. Что с ним делать? Именно. Открывать.

&НаКлиенте
Процедура ОткрытьЗначениеТекущейЯчейки(ТаблицаФормы)

 ЗначениеТекущейЯчейки = ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы);
Если НЕ ЗначениеТекущейЯчейки = Неопределено Тогда
ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеТекущейЯчейки);
КонецЕсли;

КонецПроцедуры

 

А в нашей команде просто вызываем этот метод:

&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)

ОткрытьЗначениеТекущейЯчейки(Элементы.Валюты);

КонецПроцедуры

Замечательно, теперь наш код стал значительно красивее.

 

//Обработчик команды формы
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)

ОткрытьЗначениеТекущейЯчейки(Элементы.Валюты);

КонецПроцедуры


//Процедура открывает значение текущей ячейки
&НаКлиенте
Процедура ОткрытьЗначениеТекущейЯчейки(ТаблицаФормы)

ЗначениеТекущейЯчейки = ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы);
Если НЕ ЗначениеТекущейЯчейки = Неопределено Тогда
ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеТекущейЯчейки);
КонецЕсли;

КонецПроцедуры

//Функция возвращает значение текущей ячейки
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;

ИмяПоляКолонки     = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);

СоставПутиКДанным  = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы  = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];

ЗначениеЯчейки     = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);

Возврат ЗначениеЯчейки;

КонецФункции

— Рано ликовать!

У Васи готовы методы

 

  • программно получить значение текущей ячейки (на клиенте и на сервере)

  • интерактивно показать значение текущей ячейки (на клиенте)

 

Осталось сделать ещё один

  • программно установить значение текущей ячейки (на клиенте и на сервере)

 

И снова мы начинаем с проверки. Метод, естественно, будет &НаКлиентеНаСервереБезКонтекста

 

&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы, Значение)

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;



КонецПроцедуры

Теперь Василию нужно как-то получить не значение в текущей ячейке, а именно саму эту «ячейку», чтобы установить значение.

 

Но на самом деле , ранее это уже было сделано. В методе ЗначениеТекущейЯчейки() :

//Функция возвращает значение текущей ячейки
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;

 ИмяПоляКолонки     = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);

СоставПутиКДанным  = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы  = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];

ЗначениеЯчейки     = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);

Возврат ЗначениеЯчейки;

КонецФункции

Да, именно этот кусочек кода нужно выполнить в нашем новом методе. Можно было, конечно, скопировать его и вставить в наш новый метод, но…

 

Не этому меня учили в Великой Школе Одинэсников Имени Желтого Чайника!

 

И Василий снова берётся за «рефакторинг». Выделяет наш кусочек кода и выносит в специальный новый метод «ИмяКолонкиТекущейЯчейки»:

 

&НаКлиентеНаСервереБезКонтекста
Функция ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы)

ИмяПоляКолонки     = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);

СоставПутиКДанным  = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы  = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];

Возврат ИмяКолонкиТаблицы;

КонецФункции

 

А в ранее написанной функции теперь просто вызов этого нового метода. Красота. В результате функция стала ещё нагляднее:

&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;

ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы);

ЗначениеЯчейки     = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки, ЗначениеЯчейки);

Возврат ЗначениеЯчейки;

КонецФункции

 

Прекрасно. Теперь у Васи есть метод, который возвращает имя нужно колонки. Осталось только присвоить значение:

&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы, Значение)

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;

ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы);
 Если ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки) Тогда
  ТаблицаФормы.ТекущиеДанные[ИмяКолонкиТекущейЯчейки] = Значение;
 КонецЕсли;

КонецПроцедуры

 

Василий довольный оглядывает весь свой получившийся код.

Спойлер
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

ОбновитьПутиКДаннымЭлементовФормы();

КонецПроцедуры

//Процедура обновляет пути для определения реквизита текущей ячейки
&НаСервере
Процедура ОбновитьПутиКДаннымЭлементовФормы()

ПутиКДаннымЭлементовФормы = Новый Структура;

Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл

Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы")
ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда

ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным);

КонецЕсли;

КонецЦикла;

КонецПроцедуры

//Обработчик команды формы
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)

ОткрытьЗначениеТекущейЯчейки(Элементы.Валюты);

КонецПроцедуры

//Процедура открывает значение текущей ячейки
&НаКлиенте
Процедура ОткрытьЗначениеТекущейЯчейки(ТаблицаФормы)

ЗначениеТекущейЯчейки = ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы);
Если НЕ ЗначениеТекущейЯчейки = Неопределено Тогда
ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеТекущейЯчейки);
КонецЕсли;

КонецПроцедуры

//Процедура устанавливает значение текущей ячейки
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы, Значение)

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;

ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы);
Если ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки) Тогда
ТаблицаФормы.ТекущиеДанные[ИмяКолонкиТекущейЯчейки] = Значение;
КонецЕсли;

КонецПроцедуры

//Функция возвращает значение текущей ячейки
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)

Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;

ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы);

ЗначениеЯчейки     = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки, ЗначениеЯчейки);

Возврат ЗначениеЯчейки;

КонецФункции

//Функция возвращает имя колонки текущей ячейки
&НаКлиентеНаСервереБезКонтекста
Функция ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы)

ИмяПоляКолонки     = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);

СоставПутиКДанным  = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы  = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];

Возврат ИмяКолонкиТаблицы;

КонецФункции


 

 

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

 

Понравилась статья?

Дамы и господа 1Сники. Не будьте равнодушными. Каждая ваша "звёздочка" порадует и автора и программиста Васю. Ведь это показатель того, что кому-то текст зашёл, а значит и время было потрачено не зря. 

Ну а после переходите к другим работам.

"Меньше копипаста!", или как Вася универсальную процедуру писал

Не провоцируйте СКД, или пример "как не надо"

Чем расщепить или "СтрРазделить() VS РазложитьСтрокуВМассивПодстрок()" 

 

 

Кстати. Забыл сказать, что Василий — кот.

4 Comments

  1. SlavaKron

    Могу ошибаться, но мне кажется, если путь к данным колонки таблицы содержит 2 и более точки, то будет ошибка. То есть, например, есть у нас колонка с ссылкой на элемент справочника и мы дополнительно выводим в таблицу колонку с его кодом. В БСП, кажется, есть соответствующие методы. Либо проверять наличие 2-х и больше точек в пути к данным при формировании переменной ПутиКДаннымЭлементовФормы.

    Reply
  2. SeiOkami

    (1) а об этом в следующих сериях 👍

    Reply
  3. acanta

    Так вот для чего эта кнопка! (рефакторинг)

    Reply
  4. AgentNiCho

    А меня учили в других заведениях, и про рефакторинг не рассказали. Зато теперь знаю.

    А в EDT рефакторинг ещё доработали и стало ещё лучше. Схему модуля, например, можно делать проще.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *