Хочу универсально! Часть 2
Продолжение истории про то, как начинающий разработчик Вася проходит путь от простой задачки к созданию своего механизма.
Здесь можно прочитать первую часть статьи
Нужно больше универсальности!
Начинающий разработчик Василий не так давно начал свой путь универсализации всего и вся
И теперь не собирается останавливаться.
На данный момент Вася имеет метод, который открывает значение текущей ячейки. Но что, если расширить функционал? Методы, которые позволят не только открывать текущее значение, но и присваивать его… И независимо от того, находимся ли мы на клиенте или сервере…
Василий берёт блокнот и записывает:
- программно получить значение текущей ячейки (на клиенте и на сервере)
- программно установить значение текущей ячейки (на клиенте и на сервере)
- интерактивно показать значение текущей ячейки (на клиенте)
- чистить кэш
- сохранять сессию открытых окон…
Почесав затылок, наш начинающий универсальщик скрепя когтями решает отложить часть пунктов «на потом» и сократить список:
- программно получить значение текущей ячейки (на клиенте и на сервере)
- программно установить значение текущей ячейки (на клиенте и на сервере)
- интерактивно показать значение текущей ячейки (на клиенте)
Для всего этого нужна хорошая обёртка. Василий переворачивает страницу блокнота и пишет:
- Возможность передать в метод любую таблицу. Ведь, если на текущем инструменте несколько таблиц, то нужно обеспечить возможность работы со всеми.
- Работать как «&НаСервере», так и «&НаКлиенте». Естественно, где это возможно.
- Изолированность — методы должны быть вынесены так, чтобы их было несложно перенести в другой инструмент.
Разработчик окидывает взглядом текущий функционал, который он написал в первой статье
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ПутиКДаннымЭлементовФормы = Новый Структура;
Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл
Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы")
ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда
ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента)
ПутьКДаннымЭлемента = Неопределено;
ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;
КонецФункции
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)
ТаблицаФормы = Элементы.Валюты;
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ИмяПоляКолонки);
СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];
ЗначениеЯчейки = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);
ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеЯчейки);
КонецПроцедуры
Первое, что попадается на глаза разработчику Васе — метод «ПриСозданииНаСервере». Его используют очень часто для разного рода действий и загромождать своим кодом будет не очень удобно.
- Нужно вынести в новый метод!
И Василий решает содержимое события «ПриСозданииНаСервере» вынести в отдельный метод. А заодно и протестировать возможность конфигуратора, о которой он вроде бы слышал, но никогда не пробовал — рефакторинг кода.
Начинающий разработчик выделяет нужный код, нажимает правую кнопку мыши и выбирает «Рефакторинг» → «Выделить фрагмент»
В появившемся окошке он вводит название своего нового метода: ОбновитьПутиКДаннымЭлементовФормы
И в результате получает то, что хотел. Конфигуратор сам создал новую процедуру и сделал вызов на неё
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОбновитьПутиКДаннымЭлементовФормы();
КонецПроцедуры
&НаСервере
Процедура ОбновитьПутиКДаннымЭлементовФормы()
ПутиКДаннымЭлементовФормы = Новый Структура;
Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл
Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы")
ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда
ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
- Не зря я учился в Великой Школе Одинэсников Имени Желтого Чайника!
В результате, если Вася захочет поделиться наработками, то применить их в другом инструменте будет теперь чуточку проще. Есть ещё один приятный бонус — возможность дополнительно вызывать этот метод по мере необходимости (Василий пока ещё не понял зачем, но об этом позднее…).
Для этого сразу же ранее написанный метод «ПутьКДаннымЭлементаФормы» делаем &НаКлиентеНаСервереБезКонтекста. Таким образом один и тот же метод будет доступен и на сервере и на клиенте.
1
2
3
4
5
6
7
8
&НаКлиентеНаСервереБезКонтекста
Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента)
ПутьКДаннымЭлемента = Неопределено;
ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;
КонецФункции
Василий знает, что при такой директиве метод «теряет» контекст формы, а значит больше не видит её свойств, элементов, реквизитов и так далее. Но как же теперь с этим работать?
Наш разработчик будет просто передавать форму напрямую.
1
2
3
4
5
6
7
8
&НаКлиентеНаСервереБезКонтекста
Функция ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяЭлемента)
ПутьКДаннымЭлемента = Неопределено;
ЭтаФорма.ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;
КонецФункции
Получается, что, независимо от того, находимся ли мы сейчас на клиенте или же сервере, можно вызвать один и тот же метод и просто передать в него текущую форму:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)
ТаблицаФормы = Элементы.Валюты;
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);
СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];
ЗначениеЯчейки = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);
ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеЯчейки);
КонецПроцедуры
Почва подготовлена. Теперь Василий может использовать этот код для реализации наших новых методов.
- Ну-с, приступим!
1
2
3
4
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)
КонецФункции
Этот метод вернёт значение текущей ячейки. На клиент, на сервер — не важно. А дальше уже мы сможем использовать это по своему усмотрению.
Начинаем с классической проверки:
1
2
3
4
5
6
7
8
9
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
КонецФункции
И сразу же при помощи волшебного копипаста переносим написанный в прошлой статье код, в наш новый метод:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);
СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];
ЗначениеЯчейки = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);
Возврат ЗначениеЯчейки;
КонецФункции
Написанная функция вернёт нам значение текущей ячейки. Что с ним делать? Именно. Открывать.
1
2
3
4
5
6
7
8
9
&НаКлиенте
Процедура ОткрытьЗначениеТекущейЯчейки(ТаблицаФормы)
ЗначениеТекущейЯчейки = ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы);
Если НЕ ЗначениеТекущейЯчейки = Неопределено Тогда
ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеТекущейЯчейки);
КонецЕсли;
КонецПроцедуры
А в нашей команде просто вызываем этот метод:
1
2
3
4
5
6
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)
ОткрытьЗначениеТекущейЯчейки(Элементы.Валюты);
КонецПроцедуры
Замечательно, теперь наш код стал значительно красивее.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//Обработчик команды формы
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)
ОткрытьЗначениеТекущейЯчейки(Элементы.Валюты);
КонецПроцедуры
//Процедура открывает значение текущей ячейки
&НаКлиенте
Процедура ОткрытьЗначениеТекущейЯчейки(ТаблицаФормы)
ЗначениеТекущейЯчейки = ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы);
Если НЕ ЗначениеТекущейЯчейки = Неопределено Тогда
ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеТекущейЯчейки);
КонецЕсли;
КонецПроцедуры
//Функция возвращает значение текущей ячейки
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);
СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];
ЗначениеЯчейки = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);
Возврат ЗначениеЯчейки;
КонецФункции
- Рано ликовать!
У Васи готовы методы
- программно получить значение текущей ячейки (на клиенте и на сервере)
- интерактивно показать значение текущей ячейки (на клиенте)
Осталось сделать ещё один
- программно установить значение текущей ячейки (на клиенте и на сервере)
И снова мы начинаем с проверки. Метод, естественно, будет &НаКлиентеНаСервереБезКонтекста
1
2
3
4
5
6
7
8
9
10
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы, Значение)
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
КонецПроцедуры
Теперь Василию нужно как-то получить не значение в текущей ячейке, а именно саму эту «ячейку», чтобы установить значение.
Но на самом деле , ранее это уже было сделано. В методе ЗначениеТекущейЯчейки():
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//Функция возвращает значение текущей ячейки
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);
СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];
ЗначениеЯчейки = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);
Возврат ЗначениеЯчейки;
КонецФункции
Да, именно этот кусочек кода нужно выполнить в нашем новом методе. Можно было, конечно, скопировать его и вставить в наш новый метод, но…
Не этому меня учили в Великой Школе Одинэсников Имени Желтого Чайника!
И Василий снова берётся за «рефакторинг». Выделяет наш кусочек кода и выносит в специальный новый метод «ИмяКолонкиТекущейЯчейки»:
1
2
3
4
5
6
7
8
9
10
11
12
&НаКлиентеНаСервереБезКонтекста
Функция ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы)
ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки);
СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];
Возврат ИмяКолонкиТаблицы;
КонецФункции
А в ранее написанной функции теперь просто вызов этого нового метода. Красота. В результате функция стала ещё нагляднее:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
&НаКлиентеНаСервереБезКонтекста
Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы)
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы);
ЗначениеЯчейки = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки, ЗначениеЯчейки);
Возврат ЗначениеЯчейки;
КонецФункции
Прекрасно. Теперь у Васи есть метод, который возвращает имя нужно колонки. Осталось только присвоить значение:
1
2
3
4
5
6
7
8
9
10
11
12
13
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы, Значение)
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы);
Если ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки) Тогда
ТаблицаФормы.ТекущиеДанные[ИмяКолонкиТекущейЯчейки] = Значение;
КонецЕсли;
КонецПроцедуры
Василий довольный оглядывает весь свой получившийся код.
Окончательная Васина процедура
```bsl &НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) ОбновитьПутиКДаннымЭлементовФормы(); КонецПроцедуры //Процедура обновляет пути для определения реквизита текущей ячейки &НаСервере Процедура ОбновитьПутиКДаннымЭлементовФормы() ПутиКДаннымЭлементовФормы = Новый Структура; Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы") ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным); КонецЕсли; КонецЦикла; КонецПроцедуры //Обработчик команды формы &НаКлиенте Процедура ОткрытьЗначениеЯчейки(Команда) ОткрытьЗначениеТекущейЯчейки(Элементы.Валюты); КонецПроцедуры //Процедура открывает значение текущей ячейки &НаКлиенте Процедура ОткрытьЗначениеТекущейЯчейки(ТаблицаФормы) ЗначениеТекущейЯчейки = ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы); Если НЕ ЗначениеТекущейЯчейки = Неопределено Тогда ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеТекущейЯчейки); КонецЕсли; КонецПроцедуры //Процедура устанавливает значение текущей ячейки &НаКлиентеНаСервереБезКонтекста Процедура УстановитьЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы, Значение) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат; КонецЕсли; ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы); Если ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки) Тогда ТаблицаФормы.ТекущиеДанные[ИмяКолонкиТекущейЯчейки] = Значение; КонецЕсли; КонецПроцедуры //Функция возвращает значение текущей ячейки &НаКлиентеНаСервереБезКонтекста Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат Неопределено; КонецЕсли; ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы); ЗначениеЯчейки = Неопределено; ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки, ЗначениеЯчейки); Возврат ЗначениеЯчейки; КонецФункции //Функция возвращает имя колонки текущей ячейки &НаКлиентеНаСервереБезКонтекста Функция ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы) ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя; ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки); СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь); ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()]; Возврат ИмяКолонкиТаблицы; КонецФункции ```Замечтательно! Довольный программист потирает лапки и идёт наслаждаться победой. Но не полной. Осталось придумать, как теперь завернуть это в удобный механизм. Но об этом он подумает завтра.
Кстати. Забыл сказать, что Василий - кот.