Имя: Пароль:
1C
 
Что бы тут можно отрефакторить?
0 Галахад
 
гуру
03.02.22
11:55
Функция ПолучитьПутьКФайлу(Токен, file_id) Экспорт
    
    ПутьКФайлу = Неопределено;
    Результат = Истина;
    
    Соединение = СоединениеТелеграмм();
    
    Ресурс = "bot" + Токен
        + "/getFile"
        + "?file_id=" + file_id;
        
    Запрос = Новый HTTPЗапрос(Ресурс);
    
    Попытка
        
        Ответ = Соединение.Получить(Запрос);
        
    Исключение
        
        ТекстСообщения = "Ошибка получения данных файла " + file_id + " "  + ОписаниеОшибки();
        СообщитьОбОшибке(ТекстСообщения);
        Результат = Ложь;
        
    КонецПопытки;
    
    Если Результат Тогда
        
        КодСостоянияУспешно = 200;
        Если НЕ Ответ.КодСостояния = КодСостоянияУспешно Тогда
            
            ТекстСообщения = "Сервер вернул ошибку " + Ответ.КодСостояния;
            СообщитьОбОшибке(ТекстСообщения);
            Результат = Ложь;
            
        КонецЕсли;
        
    КонецЕсли;
    
    Если Результат Тогда
        
        СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
        ДанныеОтвет = ReadFromJSON(СтрокаОтвет);
        
        Если ДанныеОтвет.ok = Ложь Тогда
            ТекстСообщения = "Ошибка в отправленных данных";
            СообщитьОбОшибке(ТекстСообщения);
        Иначе
            ПутьКФайлу = ДанныеОтвет.result.file_path;
        КонецЕсли;
        
    КонецЕсли;
        
    Возврат ПутьКФайлу;
        
КонецФункции
1 ДенисЧ
 
03.02.22
11:56
Заняться нечем? Работает, и ладно.
2 Галахад
 
гуру
03.02.22
11:58
(1) Моя функция, хочу - рефакторю. :-)
3 ДенисЧ
 
03.02.22
12:02
(2) Ну так рефакторь. Кто-то мешает?
4 mistеr
 
03.02.22
12:03
(0) Считается хорошим тоном флаги типа Результат по умолчанию выставлять в Ложь. А в Истину только в случае успеха.
5 Галахад
 
гуру
03.02.22
12:05
(3) Уже минут 15 смотрю. Переделал как в (0), лучше не стало...

(4) Спасибо.
6 Курцвейл
 
03.02.22
12:07
Вместо НЕ использовать Не
7 mistеr
 
03.02.22
12:08
(0) "Если ДанныеОтвет.ok = Ложь" -> "Если Не ДанныеОтвет.ok = Истина"
8 Галахад
 
гуру
03.02.22
12:13
(6) ИМХО первый вариант читабельнее.

(7) Не понял.
9 Курцвейл
 
03.02.22
12:15
(8) Читабельнее вообще использовать <> вместо Не
10 pechkin
 
03.02.22
12:21
Обращение к данным ответа через точку тоже лучше в попытке
11 pechkin
 
03.02.22
12:21
(6) по стандартам нужно НЕ
12 pechkin
 
03.02.22
12:22
ну и конечно же текст  ТекстСообщения = "Ошибка в отправленных данных";
никак не поможет в расследовании ситуаций
13 Ryzeman
 
03.02.22
12:23
(11) В запросе НЕ, вне запроса Не. По стандартам.
14 Ёпрст
 
03.02.22
12:23
(0) меньше букв, разве что

Функция ПолучитьПутьКФайлу(Токен, file_id) Экспорт
    
    
    Соединение = СоединениеТелеграмм();
    
    Ресурс = "bot" + Токен
    + "/getFile"
    + "?file_id=" + file_id;
    
    Запрос = Новый HTTPЗапрос(Ресурс);
    
    Попытка
        
        Ответ = Соединение.Получить(Запрос);
        
    Исключение
        
        ТекстСообщения = "Ошибка получения данных файла " + file_id + " "  + ОписаниеОшибки();
        СообщитьОбОшибке(ТекстСообщения);
        Возврат Неопределено;
        
    КонецПопытки;
    
    Если  Ответ.КодСостояния <> 200 Тогда
        
        ТекстСообщения = "Сервер вернул ошибку " + Ответ.КодСостояния;
        СообщитьОбОшибке(ТекстСообщения);
        Возврат Неопределено;
        
    КонецЕсли;
    
    
    ДанныеОтвет = ReadFromJSON(Ответ.ПолучитьТелоКакСтроку());
    
    Если НЕ ДанныеОтвет.ok Тогда
        ТекстСообщения = "Ошибка в отправленных данных";
        СообщитьОбОшибке(ТекстСообщения);
    Иначе
        Возврат ДанныеОтвет.result.file_path;
    КонецЕсли;
    
    Возврат Неопределено;
    
КонецФункции
15 Галахад
 
гуру
03.02.22
12:25
(9) Ну...

(10) Типа АПИ поменяли?
Не люблю "попытку", ИМХО понятнее свойство проверить.

(12) Тут да.
16 Галахад
 
гуру
03.02.22
12:26
(14) Возврат где-то в середине функции, ну не знаю. Можно потом проглядеть.
17 Ёпрст
 
03.02.22
12:27
(16) И ? смысл выполнять остальной код и бегать по условиям, когда уже всё ?
Это вкусовщина.
18 Злопчинский
 
03.02.22
12:29
Не люблю когда есть Тогжда и хз где будет или есть но невидно на экране Иначе
.
Если Не Результат Тогда
Иначе
КонецЕсли;
.
конечно зависит от построения и что там делается в НеРезультат,
19 mistеr
 
03.02.22
12:31
(8) Если ты не контролируешь входные данные, там может оказаться совсем не Булево.
20 fisher
 
03.02.22
12:32
Я такой стиль люблю:

Функция ПолучитьПутьКФайлу(ИдентификаторФайла, Токен, ОписаниеОшибки = "")
    
    Соединение = СоединениеТелеграмм(); // желательно учесть возможность переиспользования
    Запрос = Новый HTTPЗапрос(СтрШаблон("bot%1/getFile?file_id=%2", Токен, ИдентификаторФайла));

    Попытка
        Ответ = Соединение.Получить(Запрос);
    Исключение
        ОписаниеОшибки = СтрШаблон("Ошибка получения данных файла %1: %2", ИдентификаторФайла, ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
    
    Если Ответ.КодСостояния <> 200 Тогда
        ОписаниеОшибки = "Сервер вернул ошибку " + Ответ.КодСостояния;
        Возврат Неопределено;
    КонецЕсли;
    
    СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
    ДанныеОтвет = ReadFromJSON(СтрокаОтвет);
    
    Если ДанныеОтвет.ok <> Истина Тогда
        ОписаниеОшибки = "Ошибка в отправленных данных";
        Возврат Неопределено;
    КонецЕсли;
    
    Возврат ДанныеОтвет.result.file_path;;
    
КонецФункции
21 Галахад
 
гуру
03.02.22
12:33
(17) Вот. Поэтому-то и прошу совета. Как в (14) я написал до (0). :-)

(18) Хм. А где в (0) Если...Тогда на несколько экранов?
22 Галахад
 
гуру
03.02.22
12:34
(14), (20) Да вы сговорились...
23 Ёпрст
 
03.02.22
12:35
(22) опыт не пропьешь, да и писать много, рукти устанут..:)
24 pechkin
 
03.02.22
12:35
(20) +1
25 fisher
 
03.02.22
12:43
(20) + Еще я люблю сразу ВызыватьИсключение фигачить, если все равно падать нужно будет.
26 pechkin
 
03.02.22
12:44
(25) а это зачем?
27 Ёпрст
 
03.02.22
12:44
(25) ВызыватьИсключение не всегда красиво, оно вводит пользователей в ступор. Те считают, что "ваша 1с кривая, в ней ошибки.."
28 pechkin
 
03.02.22
12:45
(27) в уф без отладки вполне нормально выглядит
29 fisher
 
03.02.22
12:46
(26) Затем:

Функция ПолучитьПутьКФайлу(ИдентификаторФайла, Токен, ОписаниеОшибки = "")
    
    Соединение = СоединениеТелеграмм();// желательно учесть возможность переиспользования

    Запрос = Новый HTTPЗапрос(СтрШаблон("bot%1/getFile?file_id=%2", Токен, ИдентификаторФайла));

    Попытка
        Ответ = Соединение.Получить(Запрос);
    Исключение
        ВызватьИсключение СтрШаблон("Ошибка получения данных файла %1: %2", ИдентификаторФайла, ОписаниеОшибки());
    КонецПопытки;
    
    Если Ответ.КодСостояния <> 200 Тогда
        ВызватьИсключение "Сервер вернул ошибку " + Ответ.КодСостояния;
    КонецЕсли;
    
    СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
    ДанныеОтвет = ReadFromJSON(СтрокаОтвет);
    
    Если ДанныеОтвет.ok <> Истина Тогда
        ВызватьИсключение "Ошибка в отправленных данных";
    КонецЕсли;
    
    Возврат ДанныеОтвет.result.file_path;
    
КонецФункции
30 pechkin
 
03.02.22
12:47
(29) а потом здравствуй отладка с остановкой по ошибкам
31 Галахад
 
гуру
03.02.22
12:49
(20) Спасибо.

(25) В данном случае исключение некому будет показывать.
32 Галахад
 
гуру
03.02.22
12:50
(29) Гуд.
33 fisher
 
03.02.22
12:50
(30) "здравствуй отладка с остановкой по ошибкам" - это когда попытка не в тему используется. А тут все норм. И если в регламенте потом вызывать будешь - то тоже красота.
34 Галахад
 
гуру
03.02.22
12:55
(33) Не понял, а регламенте какая красота.
35 fisher
 
03.02.22
12:57
(34) Сразу в консоли вменяемое описание, почему упало.
36 Галахад
 
гуру
03.02.22
13:05
(35) Ага. Понятно.
37 fisher
 
03.02.22
13:06
(35) + Если достаточно контекста в исключение напихать, то логи вообще вести не нужно (если они только для баг-трекинга нужны).
38 fisher
 
03.02.22
13:08
Не всегда, конечно. В сложных хренях логи все равно нужны...
39 fisher
 
03.02.22
13:14
(36) А если где-то пользователя в интерактиве голым исключением пугать нежелательно, то всегда можно сверху перехватить через Попытку.
40 Галахад
 
гуру
03.02.22
13:16
(37) Ну, логи-то можно в исторической перспективе почитать. А в консоли истории почти нет.

(39) Это как?
41 fisher
 
03.02.22
13:21
(40)

Попытка
     ПутьКФайлу = ПолучитьПутьКФайлу();
Исключение
     КакоеНибудьСообщить("Вы только не пугайтесь, все под контролем, только вот: " + ОписаниеОшибки());
     Возврат;
КонецПопытки

Кстати, с какого-то там релиза можно выстраивать и раскручивать стек исключений.
42 Смотрящий
 
03.02.22
13:22
(0) ДанныеОтвет у тебя может быть пустая структура или структура к которой твой код не готов.
Проверяйся

Если ДанныеОтвет.Свойство("ок") Тогда
   Если ДанныеОтвет.Ок = Ложь Тогда
   ....
   КонецЕсли;
Иначе
   КакоеНибудьСообщить("Вы только не пугайтесь, все под контролем, только вот ниче нипанятна");
КонецЕсли;
43 FIXXXL
 
03.02.22
13:22
(0) зачем два блока "Если Результат Тогда"?
44 Галахад
 
гуру
03.02.22
13:25
(41) Ага, понятно. Я думал тут как-то по хитрому. :-)

(42) Спасибо.

(43) Потому, что "Результат" может измениться.
45 b_ru
 
03.02.22
13:31
Добавить вразумительное сообщение об ошибке. Хоть полностью ответ вернуть, что ли. Можно не в сообщить, а в ЖР.
46 fisher
 
03.02.22
13:35
(41) + С 17 релиза. ПодробноеПредставлениеОшибки(<ИнформацияОбОшибке>) вернет полный стек вызовов. Как в java :) Ну и самому его можно раскрутить через свойство Причина. Я зачем-то раскручивал. Чем-то мне стандартный вывод не нравился.
47 mmmarat
 
03.02.22
13:46
(0) Тексты сообщений в Нстр() и СтрШаблон() убрать.
48 Злопчинский
 
03.02.22
15:50
(21) мало ли какие экраны и как листается.
Если внутри "если" нет ветки "иначе" я часто юзаю
Если Не Чтотто Тогда
Иначе
   //много кода
КонецЕсли
.
мне так легче - увидел "если" и сразу понятно, логику легче уловить
но тут считаю несущественно, дело вкуса/привычки.
а стандарт это или не стандарт - хз...
49 Конструктор1С
 
03.02.22
15:52
(0)

1. Имя функции ужасное, неинформативное
2. Флаг Результат уродлив, он нарушает естественный порядок чтения, заставляет бегать глазами туда-сюда
3. Тексты ошибок также неинформативные
4. Не изобретай лесапеды, в типовых есть готовые функции, умеющие забирать файлик из интернет-сервиса по URL
50 Конструктор1С
 
03.02.22
15:53
(48) нафига??? Не проще написать вот так?

Если Чтотто Тогда
  //много кода

КонецЕсли
51 pechkin
 
03.02.22
16:05
(50) лишняя вложенность затрудняет чтение
52 pechkin
 
03.02.22
16:07
(51) я сторонник
Если Не Чтото ятогда
  Возврат
КонецЕсли
Код...
53 Конструктор1С
 
03.02.22
16:51
(51) не затрудняет, если уровней вложенности мало и код читается сверху вниз за один проход

Процедура МояРеакцияНаЗарплату(Сумма)    
    Если ОтТрехСотТыщ(Сумма) Тогда
        ВесьЦеликомВаш();
    ИначеЕсли ОтДвухсотДоТрехсотТыщ(Сумма) Тогда    
        РаботатьПрилежно();
    ИначеЕсли ОтСтаДоДвухсотТыщ(Сумма) Тогда    
        НаВсякийСлучайРазместитьРезюме();
    Иначе
        СбежатьНафигИзКонторы();
    КонецЕсли;    
КонецПроцедуры

до двух уровней вложенности нормально, дальше уже выделять подметоды
54 Конструктор1С
 
03.02.22
16:52
(52) а вот возврат уже нарушает естественный ход чтения. Им надо пользоваться осторожно
55 pechkin
 
03.02.22
16:53
(54) нет конечно же. Сначала все проверки, а потом уже работа с корректными данными
56 fisher
 
03.02.22
16:57
(48) > а стандарт это или не стандарт - хз...
Это антипаттерн :) Ветвления с Иначе хуже всего читаются.
57 fisher
 
03.02.22
16:59
А уж в паре с двойным отрицанием - антипаттерновое бинго.
58 Конструктор1С
 
03.02.22
17:23
(55) множественный выход из метода это антипаттерн
59 Конструктор1С
 
03.02.22
17:29
Если УсловиеВыполняется() Тогда
    ОсновноеДействие();    
Иначе
    ДействиеПоУмолчанию();    
КонецЕсли;

и не нужно никаких возвратов в начале процедуры, и прочих отголосков GOTO
60 fisher
 
03.02.22
17:35
(59) Напиши свой вариант (29) или (20). Вдруг мне понравится. Возьму на вооружение, начну снимать шляпу при встречах.
61 Конструктор1С
 
03.02.22
17:42
(60) разделяешь на несколько методов и в дамках
62 fisher
 
03.02.22
17:43
(61) Я тупой. Напиши. Мне проще сравнивать имея перед глазами два варианта. Код-то простой - много времени не отнимет.
63 Конструктор1С
 
03.02.22
17:46
(62) чуть позже, как буду рядом с конфигуратором
64 fisher
 
03.02.22
17:47
(63) Спасибо, буду ждать. Кроме шуток.
65 Конструктор1С
 
03.02.22
18:26
(64) как вариант вот так

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

Функция АдресПолученияФайла(Токен, ИдФайла)
    
    ШаблонАдреса = "bot[Токен]/getFile?file_id=[ИдФайла]";
    АдресФайла = СтрЗаменить(АдресФайла, "[Токен]", Токен);
    АдресФайла = СтрЗаменить(ШаблонАдреса, "[ИдФайла]", ИдФайла);
    
    Возврат АдресФайла;
    
КонецФункции

Функция ФайлИзИнтернета(Соединение, АдресРесурса)
    
    Запрос = Новый HTTPЗапрос(АдресРесурса);
    Ответ = Соединение.Получить(Запрос);
    
    Если Ответ.КодСостояния = 200 Тогда        
        ТекстИсключения = СтрШаблон("Сервер вернул код состояния %1 (ожидался 200)", Ответ.КодСостояния);
        ВызватьИсключение ТекстИсключения;        
    КонецЕсли;
    
    Возврат Ответ.ПолучитьТелоКакСтроку();
    
КонецФункции

Функция ПутьКФайлуИзОтветаИнтернетСервиса(СтрокаJSON)
    
    ВнешниеДанные = СтруктураИзJSON(СтрокаJSON);
    
    ПутьКФайлу = Неопределено;
    Если ВнешниеДанные.OK Тогда
        ПутьКФайлу = ВнешниеДанные.result.file_path;
    Иначе
        ТекстИсключения = "Ошибка в отправленных данных";
        ВызватьИсключение ТекстИсключения;
    КонецЕсли;
    
    Возврат ПутьКФайлу;
    
КонецФункции
66 Ёпрст
 
03.02.22
18:28
(65) как по мне, не читаемо.. и потом, лови в коде ЭТО


Если Ответ.КодСостояния = 200 Тогда        
        ТекстИсключения = СтрШаблон("Сервер вернул код состояния %1 (ожидался 200)", Ответ.КодСостояния);
        ВызватьИсключение ТекстИсключения;        
    КонецЕсли;
67 Конструктор1С
 
03.02.22
18:30
(66) а попытка на что? Всё как раз читаемо. Верхняя функция отвечает на вопрос "что делает?", функции ниже отвечают на вопрос "как делает?". Когнитивная и цикломатическая сложность низенькие. Истинный джентельменский подход в программировании
68 Ёпрст
 
03.02.22
18:37
(67) какая попытка ? Условие не верное
69 Конструктор1С
 
03.02.22
18:38
(68) попытка в верхней функции. Она и ловит выбрасываемые исключения. Какое условие неверное?
70 Конструктор1С
 
03.02.22
18:42
(68) условие вижу, должно быть так

    Если Ответ.КодСостояния <> 200 Тогда        
        ТекстИсключения = СтрШаблон("Сервер вернул код состояния %1 (ожидался 200)", Ответ.КодСостояния);
        ВызватьИсключение ТекстИсключения;        
    КонецЕсли;

заметь, как ты ошибку быстро нашел, а ещё говоришь код нечитаемый
71 fisher
 
03.02.22
18:44
(65) Две вещи не нравятся:
1) не люблю разбивать простые функции на еще более простые преждевременно (пока у них и так хорошая читабельность, небольшой размер и отсутствует дублирование кода), потому что де-факто это усложнение без профита
2) ты выкрутился через общую попытку - это больше похоже на подгонку задачки под ответ
72 Ёпрст
 
03.02.22
18:45
(70) мне фиолетово, кто как пишет, просто твой вариант не по мне - это попахивает типовыми конфами. Где поналепят кучу ненужных функций и используют их в коде ОДИН раз. И прыгай потом из метода в метод
73 Злопчинский
 
03.02.22
18:46
(50) Для меня - не проще. я вижу "Тогда", но не вижу что там где Иначе и есть ли оно вообще...
Труднее код анализировать.
74 Злопчинский
 
03.02.22
18:47
(57) я в курсе.
много из здесь сидящих сначал продумывает архитектуру чтобы было красиво?
или все-таки "херачим!"..?
75 fisher
 
03.02.22
18:49
(73) Я просто стараюсь писать без Иначе (очень часто от него можно избавиться) и избегаю портянок.
76 Злопчинский
 
03.02.22
18:49
(53) согласен.
но я так не люблю
.
Если ОтТрехСотТыщ(Сумма) Тогда
        ВесьЦеликомВаш();
ИначеЕсли..
- а вот там.. в самом конец где конецЕсли - там что-то еще есть? ХЗ....
а если возврат влепить сразу - то логика уже заонченная я ВесьЦеликомВаш() и всё.
.
но я никак не определюсь - то ли к умным то ли к красивым..
то так.. то так...
77 Конструктор1С
 
03.02.22
18:51
(71) >>это усложнение без профита

Нет, дорогой друг, это упрощение и инкапсуляция. Что проще, прочитать название метода или 15-20 строк кода? По-моему ответ очевиден

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

Функция ПутькФайлуИзТелеграмм(Токен, ИдФайла)
    
    АдресФайла = АдресПолученияФайла(Токен, ИдФайла);
    
    ПутьКФайлу = Неопределено;
    Попытка
        Соединение = СоединениеТелеграмм();
        СтрокаJSON = ФайлИзИнтернета(Соединение, АдресФайла);
        ПутьКФайлу = ПутьКФайлуИзОтветаИнтернетСервиса(СтрокаJSON);
    Исключение
        ТекстСообщения = СтрШаблон("Ошибка получения данных файла %1 : %2", ИдФайла,  ОписаниеОшибки());
        СообщитьОбОшибке(ТекстСообщения);
    КонецПопытки;
    
    Возврат ПутьКФайлу;
    
КонецФункции
78 Конструктор1С
 
03.02.22
18:54
(72) ну и что, что функция вызывается один раз? Это какая-то проблема? Если у функции лаконичное, говорящее имя, как бы проговаривающее всё что она делает, то это очень хорошо. Тебе придётся прочитать только название функции, а не те двадцать строк кода, которые она в себе скрывает
79 Ёпрст
 
03.02.22
19:00
(78) ну, заворачивай все операторы в функции, делов то..если за строчки кода платят
80 fisher
 
03.02.22
19:01
(77) Э нет, дорогой друг. Я давно лаптями щи хлебаю и все эти варианты я проходил. Удобнее и проще поддерживать простую и понятную функцию на 15 строчек кода. И декомпозировать ее только тогда, когда это действительно понадобится. С предварительными идеальными абстрагированиями до трехстрочных функций - удобнее сопровождать? Сыросли? Я знаю эти тенденции и баба яга против. Да, ты в итоге поправишь минимум кода, потому что у тебя уже все идеально декомпозировано ранее. Но до того, как реальная необходимость в декомпозиции возникнет - ты постоянно будешь тратить время и силы на восстановление контекста.
81 Конструктор1С
 
03.02.22
19:01
(79) ты о чём вообще? Я где-то призывал писать каждую строку кода в отдельной функции?
82 fisher
 
03.02.22
19:03
"Но до того, как реальная необходимость в декомпозиции возникнет" - если она ВООБЩЕ возникнет
83 Конструктор1С
 
03.02.22
19:06
(80) >>ты постоянно будешь тратить время и силы на восстановление контекста

в смысле тратить время и силы? Как раз здоровые методы заставляют тратить время и силы, перечитывая их от начала и до пока не надоест. Прочитаешь портянку в триста строк кода, несколько раз проскроля вверх и вниз (из-за обилия вложенных управляющих конструкций), и в конце осознаёшь, что это вообще не тот код, который тебе нужен. Мелкие методы, при хорошей декомпозиции, это как оглавление в книге: пару минут чтения, и ты в нужном месте
84 Конструктор1С
 
03.02.22
19:07
(82) декомпозицию в коде нужно делать сразу. А не когда рак на горе свистнет, и автор кода три года как уволился
85 fisher
 
03.02.22
19:09
(83) Вот не надо утрировать. Я говорю предельно конкретно. Пока не возникнет реальная необходимость в декомпозиции, лично мне удобнее сопровождать (29), чем (65)
Так ферштейн? И я готов побиться об заклад, что я далеко не один такой.
86 Конструктор1С
 
03.02.22
19:11
(85) чем удобнее? Я же объяснил, (0) и (29) вынуждают "впервые заглянувшего" прочитать больше строк кода, чем (65)
87 Конструктор1С
 
03.02.22
19:20
Вспоминаю свои "счастливые" времена работы с ЗУП 2.5. Это был полный кабздец. Такое ощущение, что разработчики того ЗУПа считали дурным тоном писать методы короче 500 строк. Чтобы найти ту сраную "Если...Иначе", в которую тебе надо воткнуть свои две строки кода, приходилось проутюжить глазами тысячи строк кода...
88 mikecool
 
03.02.22
21:05
(0) имя функции должно отражать ее суть, а у тебя - хз что происходит
89 valerivp
 
03.02.22
21:34
(0) СообщитьОбОшибке(ТекстСообщения);
- кому и что ты собрался сообщать?
90 080808Ник
 
03.02.22
23:47
(87) вот вот) меня тут забросают тряпками, но я даже тексты запросов в отдельные функции выношу, что бы не листать это все постоянно
91 Галахад
 
гуру
04.02.22
05:40
(49) Спасибо.

(65) Хм. Интересно.

(88) Ну, а какое например?
// Функция получает путь к файлу. В дальнейшем используя путь можно получить файл.

(89) Себе, ну и коллегам в канал телеграмм.
92 Галахад
 
гуру
04.02.22
05:43
Отдельное спасибо Конструктор1С
93 DrZombi
 
гуру
04.02.22
06:14
(0)Коль пошла така пьянка... :)

//стрПараметра = Новый Структура() - С кучей параметров, ограниченных фантазией Программиста :)
Функция ПолучитьПутьКФайлу(стрПараметра) Экспорт
    
    Токен =  стрПараметра.Токен;
    file_id =  стрПараметра.file_id ;

    Если стрПараметра.Свойство("Соединение") Тогда
       Соединение =  стрПараметра.Соединение;
    Иначе
        Соединение  = Неопределено;
    КонецЕсли;

    ПутьКФайлу = Неопределено;
    Результат = Истина;
    
    Если Соединение  = Неопределено Тогда
       Соединение = СоединениеТелеграмм();
    КонецЕсли;
    
    Ресурс = "bot" + Токен
        + "/getFile"
        + "?file_id=" + file_id;
        
    Запрос = Новый HTTPЗапрос(Ресурс);
    
    Попытка
        
        Ответ = Соединение.Получить(Запрос);
        
    Исключение
        
        ТекстСообщения = "Ошибка получения данных файла " + file_id + " "  + ОписаниеОшибки();
        СообщитьОбОшибке(ТекстСообщения);
        Результат = Ложь;
        
    КонецПопытки;
    
    Если Результат Тогда
        
        КодСостоянияУспешно = 200;
        Если НЕ Ответ.КодСостояния = КодСостоянияУспешно Тогда
            
            ТекстСообщения = "Сервер вернул ошибку " + Ответ.КодСостояния;
            СообщитьОбОшибке(ТекстСообщения);
            Результат = Ложь;
            
        КонецЕсли;
        
    КонецЕсли;
    
    Если Результат Тогда
        
        СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
        ДанныеОтвет = ReadFromJSON(СтрокаОтвет);
        
        Если ДанныеОтвет.ok = Ложь Тогда
            ТекстСообщения = "Ошибка в отправленных данных";
            СообщитьОбОшибке(ТекстСообщения);
        Иначе
            ПутьКФайлу = ДанныеОтвет.result.file_path;
        КонецЕсли;
        
    КонецЕсли;
        
    Возврат ПутьКФайлу;
        
КонецФункции
94 Галахад
 
гуру
04.02.22
06:33
(93) Спасибо. А чем "Структура" лучше, пары параметров?
95 DrZombi
 
гуру
04.02.22
07:14
(94) Не захламляет Код кучей переменных, которые по сути могут и перестать быть нужными.
А так же можно добавлять новые.

Просто, перестаете заморачиваться соответствием количеству параметров, особенно если код живет еще во внешних обработках, а ваша функция в общем модуле. :)

Пример:

Функция СтаннаяИНепонятная(Параметр1, Параметр2, Параметр3, Параметр4, Параметр5, Отмена, ЧтоТоЕщеЗабылиНоХочется=Неопределено, АВотЕщеЗабыли=Ложь)
96 Галахад
 
гуру
04.02.22
07:22
(95) Не, это не наш подход. Универсальные функции с огроменным функционалом это не то о чем стоит мечтать.
97 pechkin
 
04.02.22
07:49
До 3х параметров лучше отдельно
98 Конструктор1С
 
04.02.22
07:50
(95) если функция начинает просить множество параметров, стоит задуматься о её разбиении на более мелкие. Во "взрослом" программировании есть такой антипаттерн - божественный объект. Это когда некий класс берёт на себя слишком много обязанностей. В экосистеме 1с стоило бы ввести понятие божественного метода
99 DrZombi
 
гуру
04.02.22
08:33
(98) Да не, ТС(0) попросту тогда придется переписать сам принцип работы с кодом.
Теряется смысл и замысел от Функций :)

Получится так, что процедуры уже будут более насыщенными...
100 Бурза
 
04.02.22
08:36
(90) А в области закрыть чем хуже?
101 acht
 
04.02.22
08:39
(98) > божественного метода
Напомнило.

"Интерфейс с единственной кнопкой "сделать все" реализован только в ядерном чемоданчике Президента и предназначен для однократного применения."

(:
102 Hans
 
04.02.22
09:16
НЕ Ответ.КодСостояния = КодСостоянияУспешно

за такое надо бить.
103 mistеr
 
04.02.22
09:18
(98) В 1С это божественный запрос.
104 mistеr
 
04.02.22
09:21
(102) Чего так?
105 Галахад
 
гуру
04.02.22
09:37
(102) Коллега, хоть как-то аргументируйте свои высказывания.
106 Hans
 
04.02.22
09:39
А НЕ быть не должно если можно сделать так Ответ.КодСостояния <> КодСостоянияУспешно
107 Галахад
 
гуру
04.02.22
09:42
(106) Продолжайте. Не должно быть по причине?..
108 Hans
 
04.02.22
09:43
Использование конкатенаций  - это все устарело.
Ресурс = "bot" + Токен
        + "/getFile"
        + "?file_id=" + file_id;

Ресурс = СтрШаблон("bot%1/getFile?file_id=%2", Токен, file_id)
109 Hans
 
04.02.22
09:45
(107) Усложенние кода. Он  использовал да оператора на ровном месте, там где нужен был один и ухудшил читабельность.
110 mistеr
 
04.02.22
09:53
(109) Насчет читабельности спорно. Для меня НЕ = глазами распознается быстрее.
111 Ryzeman
 
04.02.22
10:02
(110) +1
(102) Меня больше раздражает само размножение сущностей. Зачем нужна КодСостоянияУспешно, если она тут же строчкой выше присваивается и больше нигде никогда не используется? Или у нас в обозримом будущем планируется менять коды состояний HTTP?...
112 Галахад
 
гуру
04.02.22
10:02
(109) Спорно же
"<>" => "<" "ИЛИ" ">"
"НЕ = " => "НЕ" "="
:)
113 Галахад
 
гуру
04.02.22
10:06
(111) Это для коллег, которые HTTP запросами не работали.
114 Ник080808
 
04.02.22
10:15
(100) да ничем, собственно. дело привычки. делал так еще до того, как появились области)
115 Asmody
 
04.02.22
10:41
(111) У меня для таких случаев гроздь функций типа

Функция КодСостоянияУспешно() Экспорт Возврат 200; КонецФункции
Функция КодСостоянияПлохойЗапрос() Экспорт Возврат 401; КонецФункции
Функция КодСостоянияНеНайдено() Экспорт Возврат 404; КонецФункции
Функция КодСостоянияОшибкаСервера() Экспорт Возврат 500; КонецФункции

как-то так
116 Ryzeman
 
04.02.22
10:44
(115) я даже готов это принять, но, господи, почему не сделать хотя б фиксированную структуру или что-то типа того? Зачем весь этот изврат? :(
117 Asmody
 
04.02.22
10:55
(116) Затем, что программноопределяемых перечислений в 1С нет. Фиксированную структуру без танцев с бубном глобально видимой не сделать.
Можно, конечно, влепить перечисление. Но тоже такой себе вариант.

Поэтому, из вариантов написать:

Перечиления.КодыСостоянийHTTP.Успешно

ОбщийHTTP.КодыСостояний().Успешно

ОбщийHTTP.КодСостоянияУспешно()

я выбрал последний
118 Конструктор1С
 
04.02.22
13:13
(11) имя переменной поясняет данное числовое значение. Вообще это хороший тон в программировании - выносить константные значения в "самодокументирующиеся" переменные. Вот увидел ты в коде дату 21.12.2012, о чём она тебе говорит? Да ниочём. А если вот так?

КонецСвета = Дата(2012, 12, 21);
119 Конструктор1С
 
04.02.22
13:15
(118) к (111)
120 Ryzeman
 
04.02.22
13:19
(118) Если вынести за скобку, что речь идёт о стандартных кодах возврата HTTP, которые не меняются в принципе (и интерпретация которых у разных API может быть разная, к слову),

я не вижу принципиально разницы между

Если МояДата = Дата(2012, 12, 21) Тогда //дата конца света
    НамВсемПЦ();
КонецЕсли;

И

КонецСвета = Дата(2012, 12, 21);
Если МояДата = КонецСвета  Тогда
    НамВсемПЦ();
КонецЕсли;

Особенно в случае, когда эта дата не используется вообще нигде больше. И такого мусора я вижу просто неимоверное количество что в типовых что в доработках что в самописках. Порой складывается впечатление что людям за количество строк кода и сомволов доплачивают
121 pechkin
 
04.02.22
13:22
(115) код состояния 200 и так все знают, а остальные и смысла нет перебирать
122 Ryzeman
 
04.02.22
13:24
(121) ну, я иногда редиректы и отсутствие оплаты обрабатываю. Но по разным API разные цифры для этого используют.
123 Конструктор1С
 
04.02.22
14:00
(120) ты не видишь разницы, потому что контекст уже обнажён, он у тебя в голове и тебе понятен. Когда ты не автор кода и смысл константы нельзя вывести из контекста, остаётся только развести руками

Если Документ.Дата >= Дата(2019, 6, 30) Тогда
    Документ.Организация = Справочники.Организации.НайтиПоНаименованию("ООО Ветерок");
Иначе
    Документ.Организация = Справочники.Организации.НайтиПоНаименованию("ИП Пупкин");
КонецЕсли;

В данном случае что означает 30 июня 2019 года? И почему эта дата влияет на выбор организации?
124 pechkin
 
04.02.22
14:02
(123) можно же коммент написать. в чем разница с именованной переменной?
125 mistеr
 
04.02.22
14:04
(124) Как минимум в том, что не нужно искать этот коммент, встретив переменную.
126 pechkin
 
04.02.22
14:05
(125) искать???
127 acht
 
04.02.22
14:07
(120) У тебя слишком вымороченный пример, ты вытащил весь контекст в одно место.
Вот, сравни:

ОбработатьОсобуюДату(ТекущийДокумент, Дата(2019, 6, 30));
ОбработатьОсобуюДату(ТекущийДокумент, Дата(2012, 12, 21));

И

ДеньРожденияБосса = Дата(2019, 6, 30);
ОбработатьДатуСкидки(ТекущийДокумент, ДеньРожденияБосса);

ДеньКонцаСвета = Дата(2012, 12, 21);
ОбработатьДатуСкидки(ТекущийДокумент, ДеньКонцаСвета);
128 acht
 
04.02.22
14:08
(123) > контекст уже обнажён, он у тебя в голове и тебе понятен
Вот точно.
129 Ryzeman
 
04.02.22
14:36
(123) (127) Вы в (120) не увидели, что я для этой цели использую аккуратный комментарий. Когда делаешь какую-то дичь в коде (а хрень типа прописать в коде дату ДР босса = дичь), то самое оптимальное как раз прописать комментом:

ОбработатьОсобуюДату(ТекущийДокумент, Дата(2019, 6, 30));   //ДР босса
ОбработатьОсобуюДату(ТекущийДокумент, Дата(2012, 12, 21));   //Конец Света

Плюс изначальная моя претензия - эти вновь объявленные переменные нигде дальше не используются и никогда не будут. Если условная ДеньРожденияБосса используется в 20 местах по коду, я это готов принять и понять (и то ВСЕГДА лучше константой забубенить), а вот так объявить и тут же использовать - не понятно зачем.
130 acht
 
04.02.22
15:31
(129) Ты не в ту сторону воюешь. Ты выступаешь за облегчение жизни железного болванчика вместо работы с кодом как с сущностью, предназначенной для человека.

Представь, что дата конца света изменилась и ты смотришь на дифф старого и нового кода. В примере с переменной ты с одного взгляда понимаешь суть изменений, просто читаешь их слева направо - дата конца света была 2021 годом, стала 2036.
В примере с комментарием, ты сначала видишь изменение, запоминаешь его, докатываешься до комментария и только тут осознаешь что оно значит. Год вместо 2021, стал 2036, ах, да это же конец света.
А прикинь кто-нибудь еще наченет писать комментарии в отдельной строке и они в дифф не попадут?
131 fisher
 
04.02.22
15:35
(86) Мой поинт вот в чем: чаще всего код приходится анализировать в процессе траблшутинга. А ошибка сплошь и рядом таится не прямо в месте где она выстреливает. Ты попадаешь в окрестности кода и пытаешься впитать максимум контекста. В итоге чаще всего придется заходить и анализировать все связанные функции, потому что ты в этот момент не можешь быть уверен в их беспроблемности. Если же мне нужно доработать код в условиях декомпозиции до трехстрочных функций - мне придется сильно поднапрячься, если текущая декомпозиция неидеальна под новые требования (а это еще необходимо осознать). И тут кроме доп-когнитивной нагрузки мне нужно проанализировать также все использования доп-функций (а не дай бог какие-то еще и экспортные "про запас").
С опытом я стал делать иначе. Если функция все еще хорошо читается и укладывается в пол-экрана или даже экран (но не больше) - то я не тороплюсь ее декомпозировать, если не предполагаю пользу от этого в ближайшем будущем. Зачем? Необходимость в переиспользовании кода еще не возникла. Я уверен в том, что смогу сразу и без оглядок по сторонам ее рефакторить, когда такая необходимость возникнет (и я стараюсь писать именно с прицелом на легкость рефакторинга в будущем). Все и так отлично.
В подобных "подстеланиях будущей соломки" безусловно ведущую роль играет опыт. Если понимаешь что с высокой степенью вероятности какой-то код может быть переиспользован в ближайшем будущем или читабельность функции начинает хромать или она начинает превращаться в портянку - тогда декомпозируешь сразу. Опять таки - в пределах разумного.
Но декомпозировать исключительно чтобы избавиться от банальных проверок на допустимость входящих параметров и промежуточных результатов с досрочным выходом из функции? Увольте. Это не мой путь. Это уже какое-то "горе оверинжениринга от ума".
Мой девиз - "максимальная читабельность и легкость доработок". Реальная легкость доработок, а не гипотетическая. Потому что декомпозиция до трехстрочных функций "из принципа" - дает лишь гипотетическую легкость доработок и нередко наоборот - затрудняет их.
132 Ник080808
 
04.02.22
15:58
(131) "А ошибка сплошь и рядом таится не прямо в месте где она выстреливает. Ты попадаешь в окрестности кода и пытаешься впитать максимум контекста. В итоге чаще всего придется заходить и анализировать все связанные функции, потому что ты в этот момент не можешь быть уверен в их беспроблемности. " зачем заходить и анализировать все связанные функции? Достаточно посмотреть где неправильный параметр и зайти в ту процедуру. Вот у меня недавно было с перепиленной конфой. Документ не проводится а ошибок никаких не выдает. а потому что кто то втулил проверку в конце обработки проведения
Если КакоетоУсловие() Тогда
Отказ = Истина;
КонецЕсли;
И тут два варианта первый:
Процедура ОбработкаПроведения(Отказ)
ПроверкаШапки(Отказ);
ПроверкаТЧ(Отказ);
ПроверкаВторойТЧ(ОТказ);
ЕщеКакоеТонепонятнаяПроверка(Отказ);
КонецПроцедуры
и я просто отладчиком прохожу нахожу процедуру в после которой отказ стал истина и захожу в нее,
Второй вариант я листаю процедуру длиной 1430 строчек кода и пытаюсь найти где отказ стал истина
133 pechkin
 
04.02.22
16:01
(132) эх, а вот если бы была возможность остановки по изменению переменной ...
134 fisher
 
04.02.22
16:11
(132) Во-первых, отладка возможна не всегда. Во-вторых, у меня нет такого суперскилла - "Достаточно посмотреть где неправильный параметр". Траблы - они разные бывают.
135 Ник080808
 
04.02.22
16:19
(134) "Во-первых, отладка возможна не всегда. " офигеть у тебя суперсила без отладки баги отлаживать.
136 Конструктор1С
 
04.02.22
16:31
(131) и в случае с траблшутингом декомпозиция рулит. Включил отладку, "шагаешь через" функцию и смотришь, что она возвращает. Когда функция простая оснований в неё заглядывать всё меньше. А вот в большую, делающую всё и сразу, придётся заглянуть и проутюжить код глазами. Ничего хорошего в этом нет. Пустая трата времени
137 Конструктор1С
 
04.02.22
16:32
(131) >> ошибка сплошь и рядом таится не прямо в месте где она выстреливает

Это тоже из-за нарушенной декомпозиции
138 acht
 
04.02.22
16:38
(134) > отладка возможна не всегда
Точно, в какой-то из версии платформ проклятые парни с Дмитровского шоссе наглухо выпилили методы Сообщить и ЗаписатьВЖурналРегистрации. Общеизвестный случай!
139 fisher
 
04.02.22
17:13
Я поделился своим мнением, сложившимся в процессе долгой практики и как мог попытался его обосновать, в надежде что оно кому-то покажется интересным. Суть его можно выразить фразой - "не тратьте силы на упрощение того, простота чего уже является достаточной". Только хуже будет. Если код уже хорошо читается, хорошо управляется и его легко будет отрефакторить - остановитесь. ЭТО оптимальное состояние кодовой базы. Именно ЭТО, а не обязательная декомпозиция до трехстрочных функций исходя из "идеального видения" на текущий момент.
Если я не встретил понимания - что ж. Меня уже не переубедить. Засуну свое мнение подальше.
140 Ёпрст
 
04.02.22
17:23
(133) Чем точка остановки с условием не подходит ?
141 Ёпрст
 
04.02.22
17:24
(132) а я просто ставлю точку остановки с условием. И не бегаю как угорелый.
142 dmt
 
04.02.22
17:28
(141) а куда ты ее поставишь, если есть надцать процедур, в каждой из которых переменная может быть изменена?
143 Ник080808
 
04.02.22
17:30
(141) так нужно понять куда ее ставить, ведь в тексте ее могут поменять в десятке мест
144 Ёпрст
 
04.02.22
17:36
(142),(143)

        <bpInfo>
            <line>1</line>
            <condition>Отказ = Истина</condition>
        </bpInfo>
        <bpInfo>
            <line>2</line>
            <condition>Отказ = Истина</condition>
        </bpInfo>
...............................................................
        <bpInfo>
            <line>1374</line>
            <condition>Отказ = Истина</condition>
        </bpInfo>
145 maximkasuper
 
04.02.22
17:51
(65) +1. Декомпозированный код легче в сопровождении, особенно на больших проектах. Тем самым обходятся антипаттерны дублирования кода и лапши кода. Да и легче применять методику пристального взгляда по каждому отдельному методу).
146 pechkin
 
04.02.22
17:52
(145) самое сложное в этом, что новый прог не знает 95% методов и делает свои аналогичные
147 Ник080808
 
04.02.22
18:02
(144) эм. я человек темный необразованный. это что?
148 Ник080808
 
04.02.22
18:04
(146) а это уже другая печальная история( Когда даже методов типовой не знает новый прог и пишет свои абсолютно аналогичные.
149 ssh2006
 
04.02.22
18:04
(139)  +1

если код умещается на экран и нет повторных вызовов его кусков городить что-то - это упражнения за счет работодателя
150 Ник080808
 
04.02.22
18:05
(146) было бы очень легче, если бы в СП можно было редактировать в конфигураторе и добавлять свои разделы по общим модулям
151 maximkasuper
 
04.02.22
18:05
(146) Конечно, такая вероятность есть, но также есть вероятность, что программист не будет придумывать велосипед и возьмет готовый метод. Для того, чтобы такого было меньше проводится кодревью ведущим разработчиком или архитектором, который укажет на ошибку программиста. А в лапше кода, такая вероятность стремится к нулю.
152 dmt
 
04.02.22
18:48
(144) гуд!
(147) файл с точками останова, загружается через Отладка - Список точек останова
153 Ёпрст
 
04.02.22
19:07
(152) ага, его можно слепить для каждой строки программно)
извращение, конечно.. но всё же
154 Конструктор1С
 
05.02.22
08:23
(124) имя переменной надёжнее. К тому же это стандарт. Константные значения в коде как бы презрительно называют "магическими числами", "магическими датами" и так далее. Завтра придёт джун Вася и начнёт копипастить константное значение в другие блоки "Если...", и вот твоя константа разлучена с каментом
155 Конструктор1С
 
05.02.22
08:31
(129) >>самое оптимальное как раз прописать комментом

ничего оптимального

>>эти вновь объявленные переменные нигде дальше не используются и никогда не будут

готов зуб дать, что никогда не будут использоваться? Придёт другой прогер, полезет дорабатывать код, захочет повторно использовать это значение и что он сделает? Правильно, скопипастит константу...
156 Конструктор1С
 
05.02.22
08:38
(139) "не тратьте силы на упрощение того, простота чего уже является достаточной"

Да-да-да, всё по постулатам "потом, когда надо будет". Только вот когда наступает это "потом", никто ничего не будет делать. Ибо найдётся немало причин (сроки, некогда, не обязан за Васей подчищать...), по которым небрежный код так и останется небрежным, и продолжит обрастать небрежностью.

P.S. то что ты называешь "тратить усилия", таковым и не является. Это всего-лишь стиль разработки. Либо сразу осознанно писать код с декомпозицией, либо городить функции-портянки, делающие всё и сразу

P.P.S. свой код всегда кажется простым и понятным, не надо прибывать в иллюзии простоты здоровенной функции. Простой она является только для автора
157 Конструктор1С
 
05.02.22
08:54
(142) >>есть надцать процедур, в каждой из которых переменная может быть изменена?

Тут надо остановиться, набрать в лёгкие побольше воздуха и хорошенько подумать. Как так получилось, что переменная изменяется во множестве процедур? Уж нет проблемный ли код, часом?
158 acht
 
05.02.22
09:23
(154) > имя переменной надёжнее
Кстати да, константа семантически оформляется практически так же, как и переменная - через имя. Поэтому остаются только вопли об однократном использовании =)

(156) >  свой код всегда кажется простым и понятным
Это только первую неделю.
159 ivanovpetr79
 
05.02.22
09:28
А в 1С уже завезли юнит тесты?
160 pechkin
 
05.02.22
09:41
Тесты конечно же есть, моков нет
161 Конструктор1С
 
05.02.22
10:49
(159) ещё только-то пытаются

(160) это скорее вопрос к подходу написания кода
162 dmt
 
05.02.22
16:04
(157) главное, чтобы гипервентиляция не случилась, пока ты дышишь над текстом ЕРП
163 ivanovpetr79
 
06.02.22
10:31
(160) они уже встроенны или нужно Ванессу ставить?
164 acht
 
06.02.22
11:23
(160) Это которые плагин Саши Капралова к EDT?
165 pechkin
 
06.02.22
11:48
(163) только встроенные решения признаешь?
166 ivanovpetr79
 
06.02.22
14:00
(165) признаю только хорошо интегрированные в экосистему языка решения для юнит тестирования.
167 acht
 
06.02.22
14:19
(166) > в экосистему языка
Этачотакое для 1С?
168 ivanovpetr79
 
06.02.22
15:18
(167) То есть за 23 года существования 1С так и не удалось построить для нее экосистему?

Появившийся в 95м году Java смог это сделать. Причем так, что все копируют с нее эту экосистему.
169 acht
 
06.02.22
15:24
(168) Я тебя про определение спрашивал. А тебя куда-то уже в разглагольствования понесло.
Что такое, по твоему, экосистема для 1С?
170 Конструктор1С
 
06.02.22
15:35
(166) это скорее больше вопрос к среде разработки. Может у кого-то рукастого руки дойдут написать грамотные плагины для поддержки юнит-тестирования. Вендор на юнит-тесты болт положил
Компьютер — устройство, разработанное для ускорения и автоматизации человеческих ошибок.