Функциональное программирование на 1С — миф или реальность?




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2026-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

99 Comments

  1. capone

    хм… я тоже люблю python, но субъективно — все это извращение ради извращения

    Reply
  2. kote

    (1) может быть.. но тема препроцессоров и трансляторов в современном Computer Science — одна из самых востребованных.. особенно это в сообществе JS заметно.. количество языков и диалектов транслирующихся в JS — уже перевалило за полсотни, то же и с CSS..

    Думаю, что если программисты не будут требовать улучшения языка — то 1С так и не будет развиваться. А было бы неплохо..

    Один из способов заявить о такой потребности — это использовать такие вот «извращения»…

    Reply
  3. kote

    (2) эта тема программистам интересна. Так что можете не качать.

    Reply
  4. DenisCh

    (4) Это не тема. Это извращение.

    Попытки эмулировать функциональщину на процедурных языках — просто смешны.

    И да, лямбды в 1с не нужны. И ООП тоже.

    Reply
  5. vcv

    Надо же! ООП на восьмёрке! Ну трудитесь, трудитесь. Глядишь, лет через десять до уровня 7.7 с 1С++ разовьётесь 🙂 🙂 🙂

    Reply
  6. vcv

    Подобная попытка расширить язык 1С давно не первая. И все они страдают еще большими, чем штатный язык 1С, проблемами с контролем и валидацией кода. Лучше бы вместе собраться и продавить 1С, что бы сделали опциональную жесткую типизацию, выдачу ошибок при использовании неинициализированной переменной, изменении типа значения переменной и т.п.

    Reply
  7. webester

    >>Один из способов заявить о такой потребности — это использовать такие вот «извращения»…

    Использование извращений ради извращений, это не заявление. Это вообще не о чем. Вы на этих извращениях торговлю напишите или зарплату и когда окажется, что с помощью ваших извращений пишется стройный и красивый код. Когда ваш код начнут цитировать на форумах, вот тогда есть все шансы, что разработчики к вам прислушаются. А в таком ключе… вангую 4 скачивания. Не в том плане, что бы вам обидно, а в том плане, что это мало кому действительно интересно.

    Reply
  8. kote

    (8)

    Насчёт скачиваний — мне совсем не обидно 🙂 на самом деле мне не дали разместить ссылку на бесплатное скачивание этого примера, т.к. на Инфостарте правила, увы, совсем уже стали «жёсткими».. с другой стороны — я подумал о том же, что и Вы — это позволит оценить интерес к теме (т.е. увидеть, кому это действительно интересно).

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

    У меня после каждого переключения из python в 1С — что-то вроде ломки :))) Не знаю, сколько человек испытывают подобные ощущения — но очень хотелось бы, чтоб язык как-то развивался. Со времён 7-ки — ничего не изменилось.. причем, с ней обратной совместимости не было — какой смысл было «замораживать» язык — непонятно..и да 1С++ — до сих пор выглядит куда более продвинутым решением.. ну как же так?

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

    И всё таки Ваше мнение непонятно.(нет, понятно, что все уже и не ждут от 1С ничего в этом направлении..) Но всё же — нужно в 1С все это или нет?

    Reply
  9. vcv
    Со времён 7-ки — ничего не изменилось.. причем, с ней обратной совместимости не было — какой смысл было «замораживать» язык — непонятно..

    А оно как-то принципиально надо? ООП в 1С. Функциональщина. Каковы ваши доводы за то, что оно необходимо языку 1С?

    если у конкурентов строк меньше, а возможностей — больше

    Кого вы считаете конкурентом для 1С? Явно же не Питона. 1С — специализированный, предметноориентированный язык. Конкурентом для него можно считать, например, ABAP. Разве в ABAP есть ООП? Формально, вроде, есть. По крайней мере классы с инкапсуляцией. Остальных китов ООП, если не ошибаюсь, не наблюдается. Так что, по фактур, ООП нет. Функционального программирования в ABAP нет в принципе. Кто еще из конкурентов?

    Reply
  10. webester

    (9)

    У меня после каждого переключения из python в 1С — что-то вроде ломки :)))

    Я написал на питоне вот это. Не сказать, что это, что то невероятное, но в какой то мере погрузиться в него пришлось. Одновременно писал для 1С. Не знаю, где тут может быть ломка. Может я слишком стар для всего этого.

    (9)

    Но всё же — нужно в 1С все это или нет?

    Я говорю, совершенно непонятно в каком это месте могло бы быть нужно. Это у вас как у автора надо спросить. То есть вы бы могли взять и наваять простую конфигурацию которая бы раскрывала, красоту подхода. Не хватает реализации конкретных задач. в семерошном 1С++ я видел красивый код, который просто в 77 так красиво и самое главное, эффективно не сделаешь. То есть он решал реальные задачи. У вас пока это выглядит как «Смотрите я могу кончиком языка до носа дотянуться». Оно то конечно круто, но как-то… зачем?

    Reply
  11. kote

    (10) Axapta/Navision — язык Х++, есть ООП

    системы на СУБД Cache — тоже предметноориентированы, есть ООП,

    про SAP (язык ABAP) Вы сами упомянули,

    разве что в Oracle для разработчиков бизнес-решений вроде как нет ООП.. но по факту — когда нужно что-то, чего нет их BusinesSuite — берётся Java и пилится расширение (ну какое Java без ООП?)

    Из отечественных платформ — посмотрите на Ultimate (там С# со всеми вытекающими — https://www.ultimatebusinessware.ru/).. Конечно, очень дорогое решение, но мы ведь не об этом, не так ли?

    (10)

    Формально, вроде, есть. По крайней мере классы с инкапсуляцией.

    Про наследование/полиморфизм — вопрос достаточно дискуссионный.. многие считают, что их роль в ООП переоценена — это скорее надстройка над ООП.

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

    Хотя, как по мне — вот этот новый механизм «расширений конфигурации» — суть костыль, родившийся из-за отсутствия наследования/полиморфизма в языке. Это же попытка реализации этих преимуществ ООП.. Не согласны?

    И вот еще — очень интересная история про то, что наследование — отдельно, ООП — отдельно. Очень интересные пруфы, на мой взгляд — (1) http://jug.ru/2016/09/bugayenko-west/ (» Есть класс млекопитающих, класс птиц, а потом сталкиваешься с утконосом, и всё ломается..»),

    Ну и про композицию — достаточно наглядно (даже для тех, кто плохо знает английский) — https://www.youtube.com/watch?v=wfMtDGfHWpA&t=1s

    Reply
  12. kote

    (10)

    А оно как-то принципиально надо? ООП в 1С. Функциональщина. Каковы ваши доводы за то, что оно необходимо языку 1С?

    Не хочется писать набившие оскомину банальности про то, что даёт ООП и функциональщина..

    Если одним словом — оно окупается временем на поддержку и на кодирование..

    Ну а если хотите примера — может вот так подойдёт?

    Реализация алгоритма quick_sort на ООП языке с хорошим синтаксическим сахаром (Python):

    def qsort(L):
    if L: return qsort([x for x in L if x<L[0]]) + [x for x in L if x==L[0]] + qsort([x for x in L if x>L[0]])
    return []
    

    .. или с лямбдами:

    def qsort(L):
    if L: return qsort(filter(lambda x: x < L[0], L[1:])) + L[0:1] + qsort(filter(lambda x: x >= L[0], L[1:]))
    return []
    

    Сколько будет занимать и как оно будет выглядеть на 1С? Возьмём отсюда — http://infostart.ru/public/204320/

    //Алгоритм «Быстрая сортировка» {
    Процедура б_Сортировка(Массив,НижнийПредел,ВерхнийПредел)
    
    
    i    = НижнийПредел;
    j    = ВерхнийПредел;
    m    = Массив[Цел((i+j)/2)];
    
    Пока Истина Цикл
    Пока Массив[i] < m Цикл
    i    = i + 1;
    КонецЦикла;
    
    Пока Массив[j] > m Цикл
    j    = j — 1;
    КонецЦикла;
    
    Если i > j Тогда
    Прервать;
    КонецЕсли;
    
    КонецЦикла;
    
    Если НижнийПредел < j Тогда
    б_Сортировка(Массив,НижнийПредел,j);
    КонецЕсли;
    
    Если i < ВерхнийПредел Тогда
    б_Сортировка(Массив,i,ВерхнийПредел);
    КонецЕсли;
    
    КонецПроцедуры
    
    Функция БыстраяСортировка(Массив)
    
    НижняяГраница = 0;
    ВерхняяГраница = Массив.ВГраница();
    б_Сортировка(Массив,НижняяГраница,ВерхняяГраница);
    
    Возврат Массив;
    
    КонецФункции
    //—}
    

    Показать

    Конечно, можно возразить, что в 1С есть встроенный алгоритм сортировки.. но ведь сколько не встроенных — так же?

    И для каждого невстроенного — будет примерно та же история.. я от этого чувствую,что язык просто сжигает много моего времени впустую..

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

    Reply
  13. kote

    (11)

    Я написал на питоне вот это. Не сказать, что это, что то невероятное, но в какой то мере погрузиться в него пришлось.

    У Вас там неработающая ссылка.. пример посмотреть не удалось.

    Reply
  14. DenisCh
    ef qsort(L):

    if L: return qsort([x for x in L if x<L[0]]) + [x for x in L if x==L[0]] + qsort([x for x in L if x>L[0]])

    return []

    Сахар? Сахар, Карл!!!

    Это, что любят мухи, Но не сахар

    Reply
  15. vcv

    (12)

    Хотя, как по мне — вот этот новый механизм «расширений конфигурации» — суть костыль, родившийся из-за отсутствия наследования/полиморфизма в языке. Это же попытка реализации этих преимуществ ООП.. Не согласны?

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

    Местами, конечно… В качестве синтаксического сахара для каких-то мелочей ООП бы пригодился.

    /*Личное субъективное мнение*/ Но, за много лет программирования в 1С, как-то не возникало желания использовать «объекты» шире, чем предусмотрено штатно — базовый объект Документ и унаследованный от него объект КонкретныйДокумент. Хотя, наверное, могло бы возникнуть, опыта в С++, С# и Delphi тоже лет много.

    (13)

    Ну а если хотите примера — может вот так подойдёт?

    Пример ваш, к сожалению плох. Потому что описанная задача не является типичной для области применения 1С. Аналогично можно говорить, что Питон плох, потому что там нет СКД.

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

    Reply
  16. Aphanas

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

    Reply
  17. Aphanas

    (3) Автор, опиши принцип действия. Скачивать и ковыряться в коде нет никакого желания.

    Reply
  18. Aphanas

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

    Вот и всё ООП, больше ничего в нем нет.

    Функции высшего порядка — это тоже способ обеспечения полиморфизма. Всё это лишь средство.

    Нужно ли ООП в 1С? Само по себе ООП нигде не нужно, нужен полиморфизм. Если ООП, этот костыль, может дать полиморфизм, то от безысходности приходится уповать на него.

    Reply
  19. webester

    (14)

    У Вас там неработающая ссылка.. пример посмотреть не удалось.

    Странно. У меня ссылка работает. Напишу текстом https://1c-cod.ru/ это не кусок кода, это ссылка на работающий проект, который написан целиком на питоне gae + flask + местный nosql

    Reply
  20. kote

    (16)


    Пример ваш, к сожалению плох. Потому что описанная задача не является типичной для области применения 1С. Аналогично можно говорить, что Питон плох, потому что там нет СКД.

    Область применения платформы 1С — и возможности языка 1С — это разные вещи. Вы путаете теплое с мягким. Я Вам говорю, что мне не нужен скайп в платформе — дайте мне больше возможностей языка..


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

    Суть примера не в читабельности (он намерено утрирован — записан в одну строку), а в объеме кода..

    Это записывается в несколько строк и читабельность восстанавливается простой расстановкой переносов строк..

    Но количество операторов, которые приходится набивать / читать — в конечном итоге может различаться на порядок.

    Reply
  21. kote

    (19)

    Инкапсуляция — ересь и пустышка, по сути это только защита от дурака.

    Ну Вы очень-очень непреклонны и бескомпромиссны :))

    Исторически — объект, как абстракция (понятие) появился в тот момент, когда вместе со структурой данных стали хранить и методы — функции, для работы с этой структурой.. приём родился раньше, чем его описали — а описал его, вроде бы Вирт..

    Примерно так зародилось понятие ООП — с инкапсуляции и создания объекта (и его можно воспринимать, например, как независимый неймспейс, со своими переменными и функциями, часть которых предназначена для внешнего API)..

    А то, что Вы говорите — так принято считать в Java/С++ — защита и т.п. нагрузка к понятию инкапсуляции были добавлены, но это не основное..

    ===

    (18)

    Автор, опиши принцип действия. Скачивать и ковыряться в коде нет никакого желания.

    Принцип действия таков.

    1) Создан псевдоКласс ФункцияОбъект, который имеет интерфейс для установки кода и его исполнения (+ разные служебные методы и поля).

    2) Код набиваемый в консоли — транслируется в другой код, который на самом деле и исполнятся.. при этом, функции которые описываются пользователем в консоли — превращаются в объекты ФункцияОбъект, а их вызов в коде — подменяется вызовом метода этого объекта..

    И всё это возможно и работает только благодаря Инкапсуляции и возможности порождения РАЗНЫХ объектов от одного класса (на самом деле — экземпляров обработки ФункцияОбъект)..

    По сути — добавлен еще один уровень абстракции и трансляция кода в другой код, который и исполняется..

    Reply
  22. spacecraft

    (21)

    Область применения платформы 1С — и возможности языка 1С — это разные вещи. Вы путаете теплое с мягким.

    А в Python для GUI используете TkInter? Или все же другие библиотеки. Мне больше нравится PyQt. Но мне и в голову не приходит требовать от Python этого из коробки, чтоб было встроено.

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

    Нет одного единственного универсального ЯП, в котором все было бы лучше, чем у других. И сравнивать отдельные места просто не корректно. Это будет вырвано из контекста.

    Reply
  23. vcv

    (21)

    Область применения платформы 1С — и возможности языка 1С — это разные вещи.

    Разные. Но взаимосвязанные. Первое определяет основные требования ко второму.

    Хорошо ли заиметь ООП и элементы функционального программирования в 1С? Однозначно хорошо. Нужно ли? А вот тут вопрос. Например, расширила 1С++ возможности 7.7, введя в неё классы. Что, много народа бросилось создавать свои классы? Нет. Большинство проигнорировало. Большая часть из меньшинства использовало классы как расширение платформы. Скачал несколько файлов, забросил их в конфигурацию — появился новый объект. Получается, по факту, ООП как-то ненужным оказался.

    Но количество операторов, которые приходится набивать / читать — в конечном итоге может различаться на порядок.

    Недостаток, да. Но вряд ли ради только того стоит ломать язык. Существует множество языков, гораздо более многословных, чем Python, C, Java… И ничего живут себе.

    Reply
  24. fixin

    я изучал ФП в универе — язык Лисп.

    То еще говнище, на мой взгляд.

    В современное время я столкнулся с XSLT, та же фигня.

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

    ООП использовал в BC++ еще в 2000.

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

    В 1С не нужно не ФП ни ООП.

    Reply
  25. kote

    (25) на основе Лиспа — предать анафеме всю парадигму функционального подхода — это неправильный подход, на мой взгляд..

    Использование функционального подхода никак не ограничивает Вас в доступе к переменным в «вышележащих» неймспейсах — замыкания на этом и основаны во многих языках поддерживающих функциональщину (js, python, ruby — то, что своими руками пробовал)..

    Потом, Вы тут http://infostart.ru/public/576405/ писали про синхронность/ассинхронность.. ну так — все те же минусы и плюсы у Лиспа. Обратные вызовы требуют сохранения нужных для вызова переменных контекста — но не всех, как Вы утверждаете.. а отказ от глобальных переменных, доступных для изменения из многих точек программы — сильно уменьшает полипотентность Вашей системы..

    (25)

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

    Странное утверждение.. в чём же убогость ООП при программировании форм — Вы случаем, конкретный продукт (фреймворк для построения форм) с подходом не путаете?? Я, например, вижу, что в отношении форм 1С двигается в направлении Adobe Flex — т.е. декларативного описания формы (управляемые формы — как раз про это).. и ООП подход у Flex прекрасно сочетался с декларативными формами — гораздо удобнее и гибче, чем в 1С. А о чем толкуете Вы?

    PS Мне, например, ООП подход только помогает, т.к. приходится чётко разделять ответственность между объектами.. в конечном итоге — в коде меньше «лапши» и он становится проще и лучше поддерживается.. и на самом деле почти всем исследователям ООП в 1С не хватает еще одного уровня абстракции над тем, что Вы предлагаете — некоторого транслятора кода разработчика — в те изыски, что они предлагают (добавляя методы, вызовы и последовательность событий).

    К тому же — даже те, кто что-то предлагал, но не использовал свои наработки в своём коде (в этом замечены даже Вы http://fixin.com.ru/articles/down_oop_1s8/article.htm). Вот где вы использовали Ваши наработки в этом плане?

    И последний вопрос — а почему, собственно, ООП должно именно к формам в 1С иметь отношение?? И почему удобство работы с формами — критерий оценки ООП как подхода?

    Я думаю, что как раз тем, кто хотел бы использовать 1С чуть шире, чем позволяют встроенные объекты — очень помогло бы ООП. А если Вы ограничены рамками бухгалтерии и отчетов.. то, возможно, и правда — как говориться «а нафига козе баян»?

    Reply
  26. starik-2005
    Reply
  27. kote

    (27)

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

    Ну раз камень в мой огород 🙂 Вы считаете надо с теории категорий начинать разговор?

    Reply
  28. starik-2005

    (28)

    Вы считаете надо с теории категорий начинать разговор?

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

    Reply
  29. Aphanas

    (27) Полностью согласен, всё отлично, только позволю себе несколько дополнений.

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

    Когда «в итоге достаточно переопределить» конструктор или методы, это называется ПОЛИМОРФИЗМ. Наследование — это средство обеспечения полиморфизма в классическом ООП. Одно из возможных. Но теоретически (да и практически), полиморфизм можно сделать и без наследования. Для этого нужно просто определить в разных объектах методы с одинаковой сигнатурой. В языках с нечеткой типизацией, необязательно, чтобы они были потомками одного предка.

    Что дает полиморфизм в плане управления потоком выполнения программы?

    Именно он и только он дает возможность определять, какой код будет выполнен в результате вызова метода, вне этого метода. Т. е. он отвязывает сигнатуру от реализации. Это позволяет создавать логику, оперирующую абстракциями высоких порядков. Говоря в терминах классического ООП — представьте себе метод предка (собственный или виртуальный), оперирующий другими виртуальными методами, реализация которых определена, как полагается, в потомках. Так мы можем закодировать достаточно сложную логику, которая будет АБСТРАКЦИЕЙ.

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

    Reply
  30. starik-2005

    (30)

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

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

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

    Reply
  31. fixin

    (26)

    На Лисп и XSLT нет глобальных переменных, отсюда лишний гемор.

    Параллельность может быть и в Си простым fork.

    Попробуй написать простейшее приложение на JAVA с формами, например игру пять в ряд, будешь «приятно» удивлен

    Программисту ERP ООП не очень нужно, на самом деле. Это скорее Real-time приложениям для моделирования предметной области.

    В ERP же есть база данных и формы работы с ней. Не та область. И соответственно, не тот форум для обсуждения ООП.

    Reply
  32. spacecraft

    (29) со многим согласен, но вот с этим:

    Функции в ФП всегда индепотентны, поэтому при одинаковых аргументах всегда возвращают одинаковый результат — это реализовано в 1С через функции модулей повторного использования

    согласиться не могу.

    Механизм повторного использования совсем другой. Это механизм чтения из кэша, по принципу соответствия значений входных параметров. Если в кэше не найдено соответствие [вызываемой функции + значения входных параметров], то выполняется вызов функции и добавляется новое соответствие с новым результатом. Если найдено, то функция не вызывается и данные читаются из кэша напрямую.

    Механизм интересен тем, что данные в кэше временные (если к данным не был доступ в течении 20 минут, то данные исключаются/игнорируются из кэша), но в то же время уникальные для разных значений входных параметров (не перезатираются другими значениями).

    Но это совсем не функциональная парадигма.

    Reply
  33. O-Planet

    (6) 1C++ — шедевр. Нужно большинству теперешних обитателей инфостарта стоя произносить эту аббревиатуру.

    По теме — зачот. Нужное.

    Reply
  34. starik-2005

    (33) парадигма — нет, а вот элемент — да. В ФП именно так все и работает.

    Reply
  35. spacecraft

    (34) хмм. Вот пример функции из модуля с повторным значением:

    Функция НовоеЧисло(СтароеЧисло) Экспорт
    ГСЧ = Новый ГенераторСлучайныхЧисел();
    НовоеЧисло = СтароеЧисло/ГСЧ.СлучайноеЧисло(0, 10000);
    Сообщить(НовоеЧисло);
    Возврат НовоеЧисло;
    КонецФункции
    

    По истечении времени нахождения в кэше, для такого входного параметра будет возвращено совершенно другое значение. Это полное нарушение ФП.

    Reply
  36. kote

    (36) В 1С нет возможности использовать «семя» для ГСЧ (чтоб генерировать строго одинаковые псевдослучайные последовательности, зависящие только от входного параметра).. поэтому функцию ГенераторСлучайныхЧисел() надо воспринимать как доступ к значению глобальной переменной, которая хрен пойми как меняется..

    В общем, строго говоря, нельзя её использовать в ФП — это не валидная функция с точки зрения ФП..

    Reply
  37. kote

    Эээхх.. Никто и не заметил.. придётся самому указать — вот, дополнил описание существенным замечанием для тех, кому ФП не интересно:

    Но даже если Вы не интересуетесь функциональным программированием — Вам наверняка понравится возможность ОПРЕДЕЛЯТЬ ФУНКЦИИ НЕПОСРЕДСТВЕННО В КОНСОЛИ КОДА..

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

    Reply
  38. spacecraft

    (37)

    В 1С нет возможности использовать «семя» для ГСЧ (чтоб генерировать строго одинаковые псевдослучайные последовательности, зависящие только от входного параметра)

    Как это нет?


    Новый ГенераторСлучайныхЧисел(<НачальноеЧисло>)

    Параметры:

    <НачальноеЧисло> (необязательный)

    Тип: Число.

    Начальное число, которым инициализируется генератор случайных чисел.

    Описание:

    Генератор случайных чисел инициализируется начальным числом из параметра.

    Последовательность случайных чисел для одного и того же начального числа будет одинакова.

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

    Само понятие ФП это ориентирование на действия, а не на промежуточные данные.

    Reply
  39. kote

    (39) Ну тогда можно использовать..

    Вот такой код в этой консоли даёт одну и ту же последовательность:

    Функция СлучайноеЧислоФП(ГСЧ) Экспорт
    Возврат ГСЧ.СлучайноеЧисло(0, 100);
    КонецФункции
    
    ////
    
    ГСЧ = Новый ГенераторСлучайныхЧисел(5); // Инициализация генератора «семенем»..
    
    Для НН = 1 По 10 Цикл
    Число = СлучайноеЧислоФП(ГСЧ);
    Сообщить(Число);
    КонецЦикла;
    

    Показать

    Reply
  40. spacecraft

    (40) вопрос не в том, что бы получить одну и туже последовательность, а в том, что функции модуля с повторно используемыми значениями не являются элементами ФП.

    Reply
  41. kote

    (41) Теперь понял Вас.. да, совершенно верно — это лишь периодически обновляемый кеш..

    Reply
  42. kote

    (0) Ура, спасибо модераторам! Теперь можно качать разработку бесплатно..

    Пишите об ошибках. По возможности — будут исправлять.. а если укажете как исправить — то еще лучше 🙂

    Reply
  43. starik-2005

    (36) просто эта функция не является индепотентной (ее результат не связан с аргументом). В этом и различие, но принцип оттуда.

    Reply
  44. dj_serega

    Я так понял больших успехов по управляемых формах не достигли? 😉

    Используете «ЭтаФорма», «ЭтотОбъект».

    В некоторых местах можно реализовать через «НаСервереБезКонтекста» (СериализоватьДанныеСервер()).

    Ну и общий смысл какой? Как тут ООП завязан? 🙂

    Reply
  45. kote

    (45)

    Я так понял больших успехов по управляемых формах не достигли? 😉

    Используете «ЭтаФорма», «ЭтотОбъект».

    Не уверен, что понял суть наезда.. но отвечу, как понял — да, использую и то и другое чтобы явно обращаться к экспортируемым полям объекта (и другим рекомендую).

    В некоторых местах можно реализовать через «НаСервереБезКонтекста» (СериализоватьДанныеСервер()).

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

    Ну и общий смысл какой? Как тут ООП завязан? 🙂

    Нууууу…для начала, хотелось бы уточнить — а что Вы подразумеваете под аббравиатурой «ООП»?

    Reply
  46. dj_serega

    (46)

    Не уверен, что понял суть наезда.. но отвечу, как понял — да, использую и то и другое чтобы явно обращаться к экспортируемым полям объекта (и другим рекомендую).

    Теперь понятно 🙂 И это был не наезд а уточнение 😉

    (46)

    Нууууу…для начала, хотелось бы уточнить — а что Вы подразумеваете под аббравиатурой «ООП»?

    Знаком с тынц и тынц.

    Вопрос больше о том что много кто пытался с 1С сделать ООП и все как-то (имхо) сложно получается.

    Как-то через расширения уже есть но все-равно не то. И, мне кажется, неполучится что-то людское сделать.

    К примеру, можно на 1С писать простенькие игры, но это больше развлечение и реальных задач на это поступать не будет, ибо 1С на это не рассчитана. Аналогично и с ООП, можно что-то свое придумать но оно будет не в том виде как должно быть.

    Reply
  47. kote
    Reply
  48. vadim1011985
    Reply
  49. kote

    (49)

    Конечно это далеко не ФП , но думаю что с этим тоже что-нить придумать Процедура

    Не очень понял, что Вы хотите предложить с этим сделать и как приложить к данной разработке.

    Можно поконкретнее?

    Reply
  50. vcv

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

    Reply
  51. neikist

    (51) Очень жаль на самом деле что тема малоинтересна, привнести в 1с какие то элементы ООП и ФП было бы просто супер. Не раз ловил себя на мысли что платформа со всеми ее механизмами хороша очень во многом… кроме языка. Но, судя по реакции на данную публикацию и мнению коллег — 1с все это и не подумает вводить((

    Reply
  52. kote

    (51) да, я вижу.. похоже, что не интересна.

    Тем не менее эмуляция ООП у меня «прижилась» — оказалось, удобно работать и поддерживать (но немножко сложнее разрабатывать — делить на классы и продумывать API).. Буду дальше использовать — если что достаточно интересное «вылупиться» — покажу..жаль, что у нас конфигурации настолько изуродованы, что даже простые обработки не «заведутся» на стандартных из коробки..

    Что бы показать «своё конг-фу» приходится придумывать что-то, типа вот этой консоли.. она суть и есть демонстрация возможностей ООП подхода к разработке — всё что в ней есть уникального — лишь следствие следования подходу..

    Ладно, поживём — увидим.. может и 1С наконец чем разродится полезным.. а то достали эти «инновации» — додумались уже скайп затолкать в платформу.. хоть бы модульно делали как-то — с опциональной возможностью доустановки.. у пользователей уже проблемы при переходе с платформы на платформу из-за нехватки места на диске..

    Reply
  53. kote

    (52)

    Не раз ловил себя на мысли что платформа со всеми ее механизмами хороша очень во многом… кроме языка.

    Точно.

    ==

    Единственное, я не люблю строго типизированные языки (особенно, с С подобным синтаксисом) — мне в этом плане вполне устраивает python (или ruby) как эталон.. (js тоже здорово сделан, синтаксис как в С)

    Reply
  54. zqzq

    Вообще идее использования обработок без форм как ООП-объектов уже 100500 лет… Включая ТИПОВЫЕ конфигурации: например в УПП 1.3 обработка БухгалтерскиеИтоги (она ещё от бух.1.6 вроде).

    Reply
  55. vadim1011985

    (50) нет, предложить ничего не хочу, я думал что с помощью этой функции как-то реализовать что-то на подобии ФП но приглядевшись понял что не получиться это сделать

    Reply
  56. kote

    (55)

    Вообще идее использования обработок без форм как ООП-объектов уже 100500 лет.

    .. думаю, это совсем не то. Объект — не класс.. попробуйте уловить разницу:

    У меня в коде — именно эмулируется класс (как шаблон объекта).

    И у этого класса есть метод __Новый__(), возвращающий НОВЫЕ экземпляры объекта данного класса..

    Первый раз — в переменную я получаю класс.. а от этой переменной уже — порождаю объекты.

    А там получают эту обработку, как Объект и переиспользуют этот объект много-много раз, так?

    ==

    А совсем «в общем» 1С — это изначально ООП среда, да.. любой Документ или Справочник.. и форма и обработка и отчет — всё это объекты.

    Reply
  57. vcv

    (53)

    додумались уже скайп затолкать в платформу

    На мой взгляд, это хорошо. Если, конечно, получится хороший «скайп».

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

    Поэтому, для корпоративного общения, скайп и иже с ним плох. Получится ли у 1С интересный конкурент — посмотрим.

    (54)

    Единственное, я не люблю строго типизированные языки

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

    Если бы, например, можно было бы включить предупреждение/ошибку при попытке засунуть в реквизит типа «Справочник.Пользователи» значение типа «Справочник.Организации», это бы позволило отлавливать кучу глупых ошибок и опечаток. Это же касается использования неинициализированных переменных. Код типа «Процент = 10; Сумма = Сумма*Процет;» должен выдавать ошибку при выполнении, а не молча выполняться.

    Reply
  58. alexqc

    (13)


    Ну а если хотите примера — может вот так подойдёт?

    Реализация алгоритма quick_sort на ООП языке с хорошим синтаксическим сахаром (Python):

    ….

    .. или с лямбдами:

    ……

    А теперь покажите мне того человека, кто всю эту абракадабру вот так сходу поймет ;0 .

    Это называется «стиль write-only»

    И, эт самое…

    Вы уверены что это оптимальный алгоритм?

    Переводим на человеческий язык:

    Отсортированный_Массив( Исходный_Массив ) это

    : Отсортированный_Массив( Все элементы меньшие Исходный_Массив[0] )

    + элемент Исходный_Массив[0]

    + Отсортированный_Массив( Все элементы Большие Исходный_Массив[0] )

    Я правильно понимаю, что мы тут на каждом шаге по паре подмассивов создаем???

    И вопрос номер 2: что будет если там несколько одинаковых элементов? Мне кажется что они потеряются…


    Сколько будет занимать и как оно будет выглядеть на 1С?

    ….

    Ну, переменным стоило бы дать более осмысленные имена.

    А так — да, это читается много лучше вашей «однострочной» сортировки.

    И еще: это несколько не тот же алгоритм.

    И, опять же, эт самое….

    А вы уверены что этот код вообще что-либо сортирует???

    Как мне кажется, кое-что важное тут забыто 😉 …

    Reply
  59. alexqc

    (59) На счет пропуска одинаковых элементов беру слова назад — просто у вас код в двух вариантах чуть различный, вот у меня в процессе написания «сложились» два ощущения, получился результат со строгими неравенствами.

    Reply
  60. starik-2005

    (59) суть квиксорта в том, что два указателя двигаются навстречу друг другу и внутри них производится рекурсивное доупорядочивание. Т.е. массив не создается никакой новый, а он просо делится на части и скармливается рекурсивным функциям. Функциональная парадигма тут как раз максимально себя проявляет, т.к. позволяет активно параллелить процесс выполнения.

    https://ru.wikipedia.org/wiki/%D0%91%D1%8B%D1%81%D1%82%D1%80%D0%B0%D1%8F_%D1%81%D­0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0 — тут есть картинка, как это делается.

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

    Reply
  61. alexqc

    Не можете сохранить в пониже чем для 8.3.9?

    Reply
  62. alexqc

    (61) А теперь внимание ВОПРОС:

    На какой массив передастся указатель для

    [x for x in L if x<L[0]]

    ?

    Reply
  63. vcv

    (61)

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

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

    Это не касательно именно кода в (13), с ним ситуация немного иная. Это общие размышления о конфликте в функциональных языках. Быстродействие требует передачи структур по ссылке, функциональная парадигма требует работы с копией переменной, что бы не модифицировать оригинал.

    Reply
  64. alexqc

    (61) И заодно скажите, где там 2 движущихся навстречу друг другу указателя (я def…, опять же)?

    После чего скажите, где там в коде 1с происходит собственно сортировка? Ну, хотя бы когда срез массива упростится до двух рядом лежащих элементов…

    Reply
  65. starik-2005

    (63)

    На какой массив передастся указатель для

    Не силен в питоне, но мне лично кажется (могу ошибаться), что массив здесь — это «L». х — это итератор для L (аналог foreach), с условием, когда он меньше чем L[0]. Предположу, что выбираются все элементы, меньшие L[0], элементы, равные L[0] и элементы, больше чем L[0] (как, собственно, и написано в вики). Потом левая и правая часть также квиксортились (рекурсивно). По всей видимости в Питоне в данной конкретной реализации действительно плодятся части массивов (в общей сложности не превышающие по количеству элементов основной массив). Но в реальных условиях данные делятся на две части и центральным элементом выбирается не L[0], но реализация действительно красива (результат = отсортированная правая часть + отсортированная левая часть => qsort: qsort(элементы, меньшие L[0]) + qsort(элементы, большие или равные L[0]) — просто круть!

    Reply
  66. alexqc

    (66) Если вы обратили внимание, я в (59) именно то и написал ( Отсортированный_Массив( Исходный_Массив ) это.. и т.д ).

    Теперь уж по поводу «в общей сложности не превышающие» — казалось бы да, для того чтобы получить результирующий массив, мы должны получить его 2 отсортированные части, а потом их объединить. НО — вы забываете о том, что это рекурсия! Что эти части плодятся на каждом шаге; и в лучшем для нас случае ( когда на каждом шаге массив редуцируется вполовину, иное из соображений симметрии будет менее выгодно — мерять будем по бОльшей части)- мы получим глубину рекурсии log2(N). И на самом глубоком уровне мы будем иметь log2(N) подмассивов с удвояющейся длиной, т.е. фактически еще один массив длиной N.

    В худшем… говорят, что в плохих случаях трудоемкость квиксорта асимптотически приближается к N#k8SjZc9Dxk2. А теперь представьте рекурсию такой глубины, и на каждом уровне — по массиву ;).

    Reply
  67. kote

    (59) Алексей, добрый вечер.

    Алгоритмы на python проверены на тестах TDD на онлайн сервисе обучения языку — они работают.

    Да, там «плодятся» списки (~аналог массива) при помощи list comprehensions (я бы по смыслу перевел, как «списковые генераторы», хотя генератор в Python это еще и «ленивые» вычисления) — но для python это обычная история..

    Можно легко на генераторы переделать (просто поменяв квадратные скобочки на круглые — и всё) — это не поменяет сути, но сделает вычисления «ленивыми» и снизит требования к памяти.. поэтому python_исты стараются писать проще, а к оптимизации прибегают, если данное место становится «бутылочным горлышком».

    Вообще, более правильно то, что предлагает Сергей в (61).. завтра, если со временем получится, добавлю менее «спорный» вариант.. но не обещаю, что в одну строку.. Вот, думаю, может можно подружить алгоритм с ссылками, — если оперировать индексами и возвращать массив индексов элементов, а не отсортированный массив элементов.. Только тогда читать отсортированный список придётся в 2 приёма — сначала индекс из возвращённого списка, а потом элемент с этим индексом из исходного списка? Но тогда будет практически всё равно, какого размера объекты лежат в основном списке — если проблема в этом..

    ===

    Надо сказать, что после небольшой практики на python (буквально один ознакомительный курс на stepic.ru, очень рекомендую) такие алгоритмы, как этот — будет легко читать.. эти «списковые генераторы» укладываются в сознание очень хорошо и ими хочется пользоваться постоянно..

    Читабельность этого почти однострокового алгоритма легко восстанавливается переносами. Одностроковость — подчеркивает лишь лаконичность синтаксиса..

    Синтаксический сахар не означает «легко читать», а означает «легко писать».

    (62) В работоспособности конфы на версии платформы ниже, чем 8.3.9 — не уверен, так как использовал там что-то по работе с текстовыми шаблонами — новые функции платформы..

    Reply
  68. alexqc

    (68)

    Синтаксический сахар не означает «легко читать», а означает «легко писать».

    Вообще-то код в первую очередь для людей пишется. Сопровождать весь этот сахар потом кто будет?


    (62) В работоспособности конфы на версии платформы ниже, чем 8.3.9 — не уверен, так как использовал там что-то по работе с текстовыми шаблонами — новые функции платформы..

    Ну я даже открыть ее не могу :(. Старые версии не читают CFник 839.

    Вы хоть объясните, как делаете — «компилируйте» введенный код в код 1С и потом «выполнить», сделали какой-то свой интерпретатор/ВМ, или сделали обертки для ф-ций?

    Reply
  69. alexqc

    Вообще же, как правильно сказал товарищ Фиксин, функциональщина для прикладных задач на фиг не упала. Ибо наш мир по своей сути — императивный :).

    Для чисто математики, — да, возможно. Для всяких доказательств, теорий и т.п. абстракции.

    Но когда дело доходит до прикладных решений — реально за функциональной формой скрывается императивное исполнение.

    Вот смотрим что на код на питоне, что на ваш код в консоли…. Вот где вы там функ. программирование увидели? Передали функцию в функкцию? да это еще Си без плюсов умел…

    Reply
  70. kote

    (69) Регулярками извлекаю функции, их имена и имена параметров. Порождаю объекты от псевдокласса ОбъектнаяФункция. Внутренний код сохраняю — его будем менять (если потребуется) в момент перед выполнением кода.

    Потом, ищу имена функций в коде и подменяю вызовом метода соотв. объекта ОбъектнаяФункция. Запускаю выполнение кода консоли..

    В момент, когда вызывается метод __Выполнить__(..) этого объекта — анализируются входящие параметры, и если среди них есть объект типа ОбъектнаяФункция — то соотв. переменные (если они вызываются) перед выполнением кода (рекурсивно) подменяются на такой же вызов.

    Так же — «подгружается» контекст и видимость переменных и функций-объектов перед вызовами..

    В общих чертах — где-то так..

    Reply
  71. kote

    (70)

    Вот смотрим что на код на питоне, что на ваш код в консоли…. Вот где вы там функ. программирование увидели? Передали функцию в функкцию? да это еще Си без плюсов умел…

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

    Уж простите бога ради 😉

    Reply
  72. spacecraft

    (71) отдаленно напоминает:

    попытка использовать паттерна Фабрика:

    Регулярками извлекаю функции, их имена и имена параметров. Порождаю объекты от псевдокласса ОбъектнаяФункция. Внутренний код сохраняю — его будем менять (если потребуется) в момент перед выполнением кода.

    Фабричный метод:

    Потом, ищу имена функций в коде и подменяю вызовом метода соотв. объекта ОбъектнаяФункция. Запускаю выполнение кода консоли..
    Reply
  73. spacecraft

    и рекомендую подробно посмотреть БПО. Часть озвученного там уже давно используется.

    Да и в БСП базовая функциональность построена на определение модуля по именам.

    Reply
  74. kote

    (74) Что такое БПО? Какая часть там используется?

    А на счёт БСП — лучше не надо этого.. идея была более-менее, но то, что получилось — превращается в некий ад для разработчика..

    Куча версий, обратной совместимости практически нет, код не самого лучшего качества..

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

    В конечном итоге — это проблема языка 1С, что бы там не говорили..

    Да, можно обойтись без ООП и всего другого — и иметь ERP в 5 миллионов строк.. но, простите — это всё наполнено smell code до самых краёв.. да что там — видели бы Вы какие ошибки и сколько пустых уровней у вызовов в обычной Бюджетной Заплате v3..

    И да.. то, что 1С код НЕ_тестируется (это видно по грубейшим ошибкам после релизов) — это тоже заслуга процедурного подхода и убогости языка, на мой взгляд..

    Reply
  75. spacecraft

    (75)

    Что такое БПО? Какая часть там используется?

    Библиотека Подключаемого Оборудования.

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

    Создано много однотипных общих модулей, которые работают с конкретным типом/производителем оборудования. У них одинаковые названия методов.

    По имени определяется модуль и вызывается функция этого метода.

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

    Идея хорошая, но в рамках 1С это затрудняет отладку. Не приспособлен 1С к ООП.

    Reply
  76. kote

    (76) С отладкой — в любой подобной консоли беда, т.к. внутри кода отданного в метод глобального контекста Выполнить(..) невозможно трассировать выполнение программы. Так что это тут «несущественно» — в силу недостатков отладчика платформы 1С.

    Reply
  77. starik-2005

    (76)

    Идея хорошая, но в рамках 1С это затрудняет отладку.

    И тут мы снова возвращаемся к тому, что язык в 1С — это, по-сути, 5-й паскаль. С тех времен Паскаль ой как далеко ушел (см. Компонентный Паскаль и Оберон). Нежелание 1С развивать язык в принципе говорит о том, что у них в этом плане кризис жанра — они на нормальном языке (С++) не могут сделать нормально платформу, т.к., полагаю, программистов привлекают не самых лучших (или задачи ставят не особо грамотно). «В последнее время участились случаи» (с) вылезания старых ошибок (ошибка POST к ресурсу, ошибка формата потока, ошибка SDBL — это все тянется еще с 8.0, полагаю). Мы нашли интересный глюк, связанный с длиной ключа для функций модулей повторного использования. Уменьшили длину ключа и — о, чудо! — все стало работать, и платформа перестала валиться в дамп при реинициализации через 20 минут (время хранения значения). Ну не бред? Видимо кто-то хеш читает через одно место, а потом оказывается, что он за границами массива, а проверить на это 1С-ники не догадались — и так сойдет!

    Reply
  78. starik-2005

    (77) это решаемо, если выполнять по строке кода (для а = 1 по СтрЧислоСтрок(КодаКусок) Цикл Выполнить(СтрПолучитьстроку(КодаКусок, А)) КонецЦикла). Можно внутрь вставить проверку на точку останова и при наличии у строки данной точки выходить из процедуры выполнения и передавать управление диалогу. В принципе не вижу трудностей (даже с автоподстановкой — но на 1С это уже сложнее запилить — лучше в JS на форме с HTML-полем).

    Reply
  79. alexqc

    (71) Все таки неудобно без исходника говорить. Я вот так и не понял — у вас свой интерпретатор или через Выполнить() 1С? «Запускаю выполнение кода консоли» — вот это что?

    И если через 1С-выполнить() — то как реализуется сохранение/восстановление контекста, локальных переменных и т.п. при _вложенных_ вызовах ф-ций? Контекст-то для Выполнить() — общий….

    Reply
  80. kote

    (79) Думаю, не совсем так просто.. с циклами этот номер не пройдёт. Для деббагера нужно будет строить AST и проигрывать его на state_machine.. т.е. уже эмулировать полноценный интерпретатор.

    Reply
  81. alexqc

    (79) По строчке кода не сможешь Выполнить() для циклов и условий. Да и с определяемыми внутри Выполнить() переменными — бяда и огорчение…

    Reply
  82. kote

    (80) Работает всё через Выполнить().

    Контекст грузиться через структуру Параметры.. и в начало кода перед выполнением дописывается код «ИмяПеременной = Параметры.ИмяПерменной» для всех переменных, которые должны быть доступны..

    Reply
  83. kote

    Вообще, я стремился сделать как можно проще.. и кажется получилось очень неплохо — именно в плане простоты.. (ну сам себя не похвалишь 🙂 )

    Reply
  84. alexqc

    (83) В свое время пытался сделать конвертер кода Выполнить() в код Вычислить() ( Выполнить() не доступна в веб-клиенте) для настраиваемых в пользовательском режиме обработчиков формы. Из-за заморочек с переменными забил на это.

    Reply
  85. kote

    (85) На стороне клиента — пока не думал, как реализовать это всё.. но думаю, если заменить модуль обработки на модуль «левой» формы (и использовать эту форму как Класс) — то применённый тут подход может сработать.

    Reply
  86. starik-2005

    (82) все это решаемо даже на околоязыке программирования от 1С.

    Reply
  87. Brawler

    (16)

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

    Я лично нифига не понял тот пример кода в одну строчку, головоломка для неподготовленного мозга.

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

    Reply
  88. Brawler

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

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

    И такой код не должен проходить проверку

    Код
       Если Истина Тогда
          Б = 7;
       Иначе
          А = 6;
       КонецЕсли;
       Сообщить(А);
    

    Показать полностью

    При исполнении просто тишина, даже ошибка не вываливается.

    Reply
  89. kote

    (88) там все просто… попробую накидать гибридный код с объяснением:

    
    // 1) в python сложение 2х массивов — даёт новый составной массив.. в 1С приходится писать какой нибудь код слияния массивов..
    
    // 2) Фишка python — выражения над списковыми структурами данных (как верно заметил  Sergey Andreev похоже на  .forEach() , но с условием:
    //      семантика выражения [x for x in мМассив if x==мМассив[0]] — выбрать из массива мМассив элементы равные элементу мМассив[0].. по сути
    //      тут цикл по элементам мМассив, в x попадает каждый элемент если он удовлетворяет постусловию ( x==мМассив[0]] )
    
    //3) Вы должны понимать, что такое рекурсия и граничные условия..
    
    Функция БыстраяСортировка(мМассив):
    Если мМассив.Количество() >  0 Тогда
    Возврат БыстраяСортировка([x for x in мМассив if x<мМассив[0]])
    + [x for x in мМассив if x==мМассив[0]]
    + БыстраяСортировка([x for x in мМассив if x>мМассив[0]]);
    Иначе
    Возврат мМассив;
    КонецЕсли;
    КонецФункции;
    

    Показать

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

    Reply
  90. starik-2005

    (89) сообщается «Неопределено», которое не отображается, ибо нечего отображать. Какая тут ошибка? Иногда так заглушки ставят для того, чтобы инициализировать автоподстановку на тип, передаваемый в функцию. Если мне среда разработки на такое ругаться будет — в лес такую среду)))

    А по поводу питона, то там все понятно. С другой стороны, а понятен ли бухгалтеру код 1С? Вряд ли. Так какого лешего 1С-нику должен быть понятен лаконичный код питона? Пусть такой 1С-ник идет и курит бамбук до полного просветления.

    Reply
  91. spacecraft

    (91) ошибка с точки зрения использования не инициализированого значения переменной. Не думая, что ЯП с жесткой типизацией это пропустят.

    Reply
  92. starik-2005

    (92)

    Не думая, что ЯП с жесткой типизацией это пропустят.

    Да, с++ так просто обмануть не получится:

    #include <iostream>
    
    int main()
    {
    if (1) int i=10;
    std::cout << i;
    }
    1.cpp: In function ‘int main()’:

    1.cpp:6:15: error: ‘i’ was not declared in this scope

    std::cout << i;

    #k8SjZc9Dxk
    Reply
  93. Brawler

    (93)

    Да, с++ так просто обмануть не получится:

    Так, если бы вы обратили внимание на ошибку, то там ясно говорится, что переменной i не объявлено вообще в области видимости std::cout, а не переменная не инициализирована.

    В С++ переменная доступна в области видимости, где она объявлена, а вот в 1С это почти полный аналог Паскаля.

    В Паскале, переменные должны объявляться в секции Var методов или модуля. В 1С переменные должны объявляться в начале метода/модуля с применением ключевого слова Перем, однако это не обязательно и в выше приведенном коде фактически транслятор воспринимает код как

    Код
    Перем А;
    Перем Б;
    Если Истина Тогда
        Б = 7;
    Иначе
        А = 6;
    КонецЕсли;
    Сообщить(А);
    

    Показать полностью

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

    Добивает даже такое, что подбешивает

    Код
    Функция Сумма(А, Б)
       Результат = А + Б;
      // Возврат Результат; // случайно забываем написать
    КонецФункции
    
    Сообщить(Сумма(5, 6));
    

    Показать полностью

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

    С такие вещами как по мне имеет смысл побороться с 1С.

    Reply
  94. spacecraft

    (97) Если это именно так, т.е. по-умолчанию идет объявление переменных, тогда это вполне допустимая ситуация. Даже основные ЯП с жесткой типизацией иногда используют инициализацию по-умолчанию. В том же конструкторе класса.

    Reply
  95. starik-2005

    (97)

    Так, если бы вы обратили внимание на ошибку, то там ясно говорится, что переменной i не объявлено вообще в области видимости std::cout, а не переменная не инициализирована.

    Гы… Если бы Вы сами обратили внимание на код, то не говорили бы сейчас такое. А то, что инфостарт грохает пробелы в цитатах — это отдельная песня. std::cout — это не область видимости, а объект потока вывода, std — пространство имен.

    Reply
  96. Brawler

    (99) все я прекрасно там в коде прочитал, ваш код еще вот так записать можно

    Код
    if (1)
    {
       int i=10;
    }
    
    std::cout << i;
    

    Показать полностью

    И вот видим, что переменная i объявлена в ветке Тогда, что располагается между фигурными скобками. И именно там её область видимости не выходящая за эти скобки, а в строке

    std::cout << i;

    её области видимости заканчивается и ее нельзя применять

    Заметьте я не говорю, что std::cout это область видимости, а в момент обращения к std::cout, сама std::cout находится уровнем области видимости выше чем объявлена переменная i, тут та и ошибка возникает, так как нет объявленной переменной.

    Reply
  97. starik-2005

    (102)

    все я прекрасно там в коде прочитал

    Тогда как понять Вашу фразу?

    переменной i не объявлено вообще в области видимости std::cout

    Я ее понял буквально как написано. а написано именно так.

    Reply
  98. Brawler

    (103)

    Я ее понял буквально как написано. а написано именно так.

    Теперь та поняли?

    Reply
  99. nicxxx

    что-то не работает.

    добавил функцию

    Функция УмножитьНа2(чтоУмножаем)
    
    Рез = чтоУмножаем*2;
    Возврат Рез;
    
    КонецФункции
    

    и получаю ошибку «Ошибка компиляции при вычислении выражения или выполнении фрагмента кода: {(51,10)}: Тип не определен (С)»

    и код неправильно отрегэкспился:

    Степень = ЭтотОбъект.Параметры[«Степень»];
    Мап = ЭтотОбъект.Параметры[«Мап»];
    УмножитьНа2 = ЭтотОбъект.Параметры[«УмножитьНа2»];
    
    // Первая функция — берет Число и возводит его в Степень..
    
    // Функция Степень(мЧисло, мСтепень = 3)
    //  Рез = мЧисло;
    //  Для НН=1 По мСтепень Цикл
    //   Рез = Рез * мЧисло;
    //  КонецЦикла;
    //  Возврат Рез;
    // КонецФункции
    
    // Вторая функция — берет Список и к каждому его элементу применяет ОбъектФункцию
    
    // Функция Мап(ОбъектФункция, Список)
    //  МассивРезультат = Новый Массив;
    //  Для Каждого Эл Из Список Цикл
    //   Отображение = ОбъектФункция(Эл); // степень будет 3-я
    //   МассивРезультат.Добавить(Отображение);
    //  КонецЦикла;
    //  Возврат МассивРезультат;
    // КонецФункции
    
    
    // Функция УмножитьНа2(чтоУмножаем)
    //
    //  Рез = чтоУмножаем*2;
    //  Возврат Рез;
    //
    // КонецФункции
    
    // Собственно, сама программа выглядит следующим образом..
    
    мМассив = Новый Массив;
    
    мМассив.Добавить(1);
    мМассив.Добавить(2);
    мМассив.Добавить(3);
    мМассив.Добавить(5);
    мМассив.Добавить(10);
    мМассив.Добавить(100);
    мМассив.Добавить(1000);
    
    // .. а тут нам возвращается новый массив, после возведения каждого его элемента в степень..
    мРезультаты =
    
    // ОбъектнаяФункция / подмена {
    Мап.__Вызвать__(
    Новый С
    
    // ОбъектнаяФункция / подмена {
    УмножитьНа2.__Вызвать__(
    Новый Структура(«чтоУмножаем», Эл),  // список параметров
    ЭтотОбъект.Параметры // передача контекста
    )
    // }
    тФункция, Список», Степень, мМассив),  // список параметров
    ЭтотОб
    
    // ОбъектнаяФункция / подмена {
    УмножитьНа2.__Вызвать__(
    Новый Структура(«чтоУмножаем», Эл),  // список параметров
    ЭтотОбъект.Параметры // передача контекста
    )
    // }
    // передача контекста
    )
    // }
    ;
    
    Для Каждого Эл Из мРезультаты Цикл
    Эл=УмножитьНа2(Эл);
    КонецЦикла;
    
    Для Каждого Эл Из мРезультаты Цикл
    Сообщить(Эл);
    Эл=УмножитьНа2(Эл);
    Сообщить(Эл);
    КонецЦикла;
    
    
    ~___МеткаВозврат____:

    Показать

    Reply

Leave a Comment

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