Слабое связывание в процедурном языке
От: zelenprog  
Дата: 25.07.24 11:11
Оценка:
Добрый день!

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

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

Как это делается в процедурных языках?
Re: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 25.07.24 11:28
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Как в этом случае можно хоть в каком-то виде реализовать слабое связывание?

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

Z>Модуль, реализующий интерфейс (форму, с которой работает пользователь), должен в ответ на это оповещение понять какие данные изменились и отобразить эти изменения.


Z>Как это делается в процедурных языках?

https://www.youtube.com/watch?v=M7uo5jmFDUw
Re[2]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 25.07.24 11:51
Оценка:
_>https://www.youtube.com/watch?v=M7uo5jmFDUw

В "моем" ЯП нету таких возможностей как в Erlang-е.
Я использую простой-примитивный язык.
Отредактировано 25.07.2024 11:51 zelenprog . Предыдущая версия .
Re[3]: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 25.07.24 12:05
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>В "моем" ЯП нету таких возможностей как в Erlang-е.

Z>Я использую простой-примитивный язык.

ST ?
Re: Слабое связывание в процедурном языке
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.07.24 12:19
Оценка:
Здравствуйте, zelenprog, Вы писали:
Z>Как это делается в процедурных языках?
Обычно в процедурных языках есть тип данных "указатель на процедуру". Всё строится поверх него.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 25.07.24 13:11
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Я использую простой-примитивный язык.


Используйте язык DSL который будет компилироваться в ваш неведомый простой-примитивный язык.
Re: Слабое связывание в процедурном языке
От: cppguard  
Дата: 26.07.24 00:16
Оценка: 1 (1)
Здравствуйте, zelenprog, Вы писали:

Z>Как это делается в процедурных языках?


Да куча вариантов. Например, можно определить формат обмена данных и передавать данные через unix socket, fifo, или обычный файл. Оповещения можно реализовать через сигналы или подписку на события файловой системы. Если язык совсем уж примитивный, и нет доступа ни к функциям операционной системы, ни к сырой памяти (чтобы реализовать указать на функцию), то нужно задуматься о целесообразности использования этого языка. Названия языка можно узнать? Или это секретные секреты местных НИИ?
Re[2]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 27.07.24 13:38
Оценка:
Z>>Как это делается в процедурных языках?
S>Обычно в процедурных языках есть тип данных "указатель на процедуру". Всё строится поверх него.

В том-то и дело, что в "моем" языке нету указателей на процедуру.
Как выкрутиться в этой ситуации?
Re[2]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 27.07.24 13:42
Оценка:
C> Названия языка можно узнать? Или это секретные секреты местных НИИ?

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

C> Если язык совсем уж примитивный, и нет доступа ни к функциям операционной системы, ни к сырой памяти (чтобы реализовать указать на функцию), то ...


Доступа к функциям ОС и к сырой памяти нету, указателей на функцию нету.
Re[4]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 27.07.24 13:46
Оценка:
_>Используйте язык DSL который будет компилироваться в ваш неведомый простой-примитивный язык.

DSL, мне кажется, тут не поможет.
DSL ведь можут работать с классами\объектами. Значит в нем "естественным" образом реализуется и слабое связывание и внедрение зависимостей.
Переложить это на процедурный язык, мне кажется, просто невозможно.
Re[5]: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 27.07.24 15:00
Оценка:
Здравствуйте, zelenprog, Вы писали:


_>>Используйте язык DSL который будет компилироваться в ваш неведомый простой-примитивный язык.


Z>DSL, мне кажется, тут не поможет.

Z>DSL ведь можут работать с классами\объектами. Значит в нем "естественным" образом реализуется и слабое связывание и внедрение зависимостей.
Z>Переложить это на процедурный язык, мне кажется, просто невозможно.

Приведите пример кода на вашем "безымянном" языке
Создание переменных (локальных, глобальных)
Ветвление
Циклы
Вызов функций
Определение функций
Опрелеление массивов
Определение структур
Есть ли какие ограничения?
Re[3]: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 27.07.24 15:05
Оценка: +1
Здравствуйте, zelenprog, Вы писали:


C>> Названия языка можно узнать? Или это секретные секреты местных НИИ?


Z>Нет, это не секреты. Но называть этот язык не хочу — засмеёте.

Вы из-за такой ерунды переживаете? Вам шашечки или ехать?

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


C>> Если язык совсем уж примитивный, и нет доступа ни к функциям операционной системы, ни к сырой памяти (чтобы реализовать указать на функцию), то ...


Z>Доступа к функциям ОС и к сырой памяти нету, указателей на функцию нету.

Целые числа есть? Массивы есть? Если да то можно всё что угодно сделать.
Re: Слабое связывание в процедурном языке
От: vsb Казахстан  
Дата: 27.07.24 17:53
Оценка:
Сделать отдельную структуру-очередь. К примеру на основе кольцевого списка. Далее один модуль в него добавляет оповещение. У других модулей есть функция вроде process_events(), которая вызывается где-то в основном цикле. Эта функция проверяет наличие оповещений и обрабатывает их, если они есть.

Т.е. развернуть модель работы с push на poll.

Второй вариант — реализовать концепцию указателей на функции поверх существующих средств, в прошлой подобной теме я уже про это писал, повторяться не буду.
Отредактировано 27.07.2024 17:53 vsb . Предыдущая версия .
Re[3]: Слабое связывание в процедурном языке
От: cppguard  
Дата: 27.07.24 21:43
Оценка:
Здравствуйте, zelenprog, Вы писали:

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

VBScript? 1C?

Z>Доступа к функциям ОС и к сырой памяти нету, указателей на функцию нету.

Аналог eval() точно должен быть. Если и этого нет, то это сизифов труд, писать на таком языке.
Re[3]: Слабое связывание в процедурном языке
От: Stanislav V. Zudin Россия  
Дата: 27.07.24 21:51
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>>>Как это делается в процедурных языках?

S>>Обычно в процедурных языках есть тип данных "указатель на процедуру". Всё строится поверх него.

Z>В том-то и дело, что в "моем" языке нету указателей на процедуру.

Z>Как выкрутиться в этой ситуации?

У меня дежавю
Автор: zelenprog
Дата: 14.07.23
?
Прошёл всего год.
_____________________
С уважением,
Stanislav V. Zudin
Re[3]: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 27.07.24 22:35
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Нет, это не секреты. Но называть этот язык не хочу


VisualBasic ?
Re[6]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 28.07.24 08:41
Оценка:
_>Приведите пример кода на вашем "безымянном" языке
_>Создание переменных (локальных, глобальных)
_>Ветвление
_>Циклы
_>Вызов функций
_>Определение функций
_>Опрелеление массивов
_>Определение структур

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

_>Есть ли какие ограничения?


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

Без указателей на функции код получается жестко связанным.
Отредактировано 28.07.2024 8:43 zelenprog . Предыдущая версия .
Re[7]: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 28.07.24 08:49
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>По сути мне нужно "вручную" придумать механизм, заменяющий указатели на функции.

Зачем?

Z>Без указателей на функции код получается жестко связанным.

Какую задачу вы хотите решить? Причем тут жесткая связанность. Все проблемы связанности важны при масштабированиии, в маленьких программах это не принципиально.
В C это решалось написанием мелких утилит которые компоновались друг с другом через ввод/вывод.
cat input | prog1 --prm 1 | prog2 | prog3 > result
Re[4]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 28.07.24 10:00
Оценка:
SVZ>У меня дежавю
Автор: zelenprog
Дата: 14.07.23
?

SVZ>Прошёл всего год.

Да, настоящая тема — очень похожа на ту старую тему.

Только в той старой теме я использовал более "продвинутую" (более позднюю) версию "моего" языка, которая умела работать с несколькими модулями.
То есть программа могла состоять из нескольких модулей. Можно было использовать отдельный файл-модуль как отдельный класс.
Это позволяло "эмулировать" работу с объектами.
И нужно было придумать, как реализовать механизм наследования, используя отдельные модули как классы.

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

Но это не исключает того, что этот модуль надо организовать так, чтобы методы были разделены по обязанностям. Чтобы между методами, относящимися к разным обязанностям, было как можно меньшее связывание.
Так как по объему кода, по количеству функций, этот модуль получится достаточно большой.
Без "логичного" разделения в нем будет трудно ориентироваться.

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

Смысл в том, что потом потребуется создать еще один (третий) вид интерфейса.
И хорошо было бы, чтобы создав новую процедуру для нового интерфейса, например "GUI_Update3()", реализующую новый способ "реакции", я поменял бы только код вызывающей процедуры, добавив новое условие:

func UserStartProcess()
{
    if (...)
        lGUIUpdater = GUI_Update1
    elseif (...)
        lGUIUpdater = GUI_Update2
    elseif (...)
        lGUIUpdater = GUI_Update3

    DoBusinessProcess(lGUIUpdater);
}


И чтобы мне не пришлось менять ни бизнес-процедуру, ни других частей программы.
Отредактировано 28.07.2024 10:03 zelenprog . Предыдущая версия .
Re[8]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 28.07.24 10:05
Оценка:
_>Какую задачу вы хотите решить? Причем тут жесткая связанность. Все проблемы связанности важны при масштабированиии, в маленьких программах это не принципиально.

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

Вот здесь подробнее описал:
https://rsdn.org/forum/design/8788388.1
Автор: zelenprog
Дата: 28.07 13:00
Re[2]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 28.07.24 10:13
Оценка:
vsb>Сделать отдельную структуру-очередь. К примеру на основе кольцевого списка. Далее один модуль в него добавляет оповещение. У других модулей есть функция вроде process_events(), которая вызывается где-то в основном цикле. Эта функция проверяет наличие оповещений и обрабатывает их, если они есть.
vsb>Т.е. развернуть модель работы с push на poll.

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

vsb>Второй вариант — реализовать концепцию указателей на функции поверх существующих средств, в прошлой подобной теме я уже про это писал, повторяться не буду.


Как раз интересен этот вариант.
А в какой теме вы это писали?
Если имеется ввиду моя старая тема, то там вы не написали как это можно сделать.
Вот ваш ответ: "Изобрести указатель на функцию можно, но не нужно."
Re[5]: Слабое связывание в процедурном языке
От: Stanislav V. Zudin Россия  
Дата: 28.07.24 10:57
Оценка:
Здравствуйте, zelenprog, Вы писали:


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

Z>То есть программа — это один монолитный большой программный файл-модуль.

Z>Но это не исключает того, что этот модуль надо организовать так, чтобы методы были разделены по обязанностям. Чтобы между методами, относящимися к разным обязанностям, было как можно меньшее связывание.

Z>Так как по объему кода, по количеству функций, этот модуль получится достаточно большой.
Z>Без "логичного" разделения в нем будет трудно ориентироваться.

Ну раз нет возможности использовать полиформизм на уровне кода, значит придётся использовать полиморфизм на уровне данных.
В качестве примера можно подсмотреть стек TCP, виндовый WinAPI — структуры переменного размера, в начале размер и тип данных. Внутри обработчика анализ заголовка и передача по цепочке. Т.е. в какой-то точке программы будут собраны все обработчики. Это не хорошо, но и не плохо. Чудес не бывает, какие-то накладные расходы всегда будут.
Наконец, вспомнить, как работал Int 21h

Если есть доступ к ОСи (надеюсь, язык не совершенно оторван от реалий), то можно использовать системозависимые механизмы для обмена данными, выше камрады об этом упомянули.
_____________________
С уважением,
Stanislav V. Zudin
Re[5]: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 28.07.24 11:11
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Только в той старой теме я использовал более "продвинутую" (более позднюю) версию "моего" языка, которая умела работать с несколькими модулями.

Перепишите уже "свой" язык и добавьте то чего вам нехватает

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

o_O архиология под дос?
Всё таки я склоняюь к мысли что был Visual Basic 6.0

А стал Visual Basic 1.0:


Z>То есть программа — это один монолитный большой программный файл-модуль.

И что плохого?

Z>Без "логичного" разделения в нем будет трудно ориентироваться.

Так разделите логично

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

??? Зачем. Пересылайте сообщения как в objective-c

Z>Например, есть процедура, которая выполняет "бизнес"-операцию.

Z>Эта процедура "оповещает" о выполненных действиях. На эти оповещения должен отреагировать другой код.
Так и посылайте оповещения

Z>Для простоты рассмотрим интерфейс: на оповещения интерфейс должен перерисоваться соответствующим образом.

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

Z>Смысл в том, что потом потребуется создать еще один (третий) вид интерфейса.


Z>И хорошо было бы, чтобы создав новую процедуру для нового интерфейса, например "GUI_Update3()", реализующую новый способ "реакции", я поменял бы только код вызывающей процедуры, добавив новое условие:

В процессе не должно быть вызовов GUI_Update1, только notifyUpdate
Более того если у вас длительные процессы вам надо переделать ваши процессы на итерационные.

Z>И чтобы мне не пришлось менять ни бизнес-процедуру, ни других частей программы.

Так и в чем проблема? Вы не придумали как имеющимся средствами сделать по феншую?

ps: вы хотя бы примеры кода на своём загадочном языке привели бы, или названия, что бы было понятно какие ограничения есть и как их обойти.
Re[6]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 28.07.24 13:01
Оценка:
Z>>То есть программа — это один монолитный большой программный файл-модуль.
_>И что плохого?

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

Z>>Без "логичного" разделения в нем будет трудно ориентироваться.

_>Так разделите логично

Логично я разделил.
Но кроме этого, еще нужно реализовать слабое связывание.

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

_>??? Зачем.

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

_>Пересылайте сообщения как в objective-c

_>Так и посылайте оповещения

Я не знаю objective-c
Но судя по описанию в википедии, это объектно-ориентированный язык.
Мой язык — процедурный. В нем нету ни сообщений, ни оповещений.
Как в процедурном языке посылать сообщения и оповещения?

Z>>Для простоты рассмотрим интерфейс: на оповещения интерфейс должен перерисоваться соответствующим образом.

Z>>то есть имеется процедура, которая отображает что-то на форме в зависимости от оповещения о выполненном дейтсвии.
_>... Есть модель которую кто-то меняет, а есть слушатели изменений и по изменения они изменяют то что отображается.

Ну да. Это я и имел ввиду.
Может быть не точно выразился.

Z>>Смысл в том, что потом потребуется создать еще один (третий) вид интерфейса.

...
_>Так и в чем проблема? Вы не придумали как имеющимся средствами сделать по феншую?

Да, не придумал. Ну как-то наколбасить, конечно, можно.
Но меня интересует как это сделать "правильно".

_>ps: вы хотя бы примеры кода на своём загадочном языке привели бы, или названия, что бы было понятно какие ограничения есть и как их обойти.


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

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


  Код
// эта процедура срабатывает по инициативе пользователя,
// который запускает какую-то обработку,
// например, нажимает красную кнопку на приборе
void GUI_Event_StartProcess()
{
    // сначала определяется какая конкретная процедура должна вызываться
    // при возникновении события в бизнес-процедуре
    // в зависимости от условий и параметров
    
    if (...)
        // при этих уловиях должна срабатывать GUI_Update_1:
        // оповещения в консоль
    elseif (...)
        // при этих уловиях должна срабатывать GUI_Update_2:
        // оповещения в виде сигнальных лампочек

    // вызываем бизнес-процедуру
    BL_DoProcess();
}

void GUI_Update_1()
{
    // первый способ отображения изменений модели,
    // например вывод в консоль
    Text = ....
}

void GUI_Update_2()
{
    // второй способ отображения изменений модели,
    // например включаем соответсвующие сигнальные лампочки
    switch_on(lamp1);
}

void BL_DoProcess()
{
    while(...)
    {
        ...
        // обработка данных
        ...
        BL_notifyUpdater();
    }
}

void BL_notifyUpdater()
{
    // что здесь должно быть, чтобы вызывалась
    // конкретная процедура GUI_Updater_xxx?
}
Re[6]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 28.07.24 13:49
Оценка:
SVZ>Ну раз нет возможности использовать полиформизм на уровне кода, значит придётся использовать полиморфизм на уровне данных.
SVZ>В качестве примера можно подсмотреть стек TCP, виндовый WinAPI — структуры переменного размера, в начале размер и тип данных. Внутри обработчика анализ заголовка и передача по цепочке. Т.е. в какой-то точке программы будут собраны все обработчики.

А можно простой пример?
Чтобы было понятнее?

SVZ>Если есть доступ к ОСи (надеюсь, язык не совершенно оторван от реалий), то можно использовать системозависимые механизмы для обмена данными, выше камрады об этом упомянули.


Через файлы обмен будет очень медленным — это самый крайний вариант.
Re[3]: Слабое связывание в процедурном языке
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.07.24 13:49
Оценка: 2 (1)
Здравствуйте, zelenprog, Вы писали:
Z>В том-то и дело, что в "моем" языке нету указателей на процедуру.
Z>Как выкрутиться в этой ситуации?
Тогда ваш единственный выход — switch.
То есть примерно так:

int BinaryOp(int a, int b, int functionNo) // весь полиморфизм - здесь
{
  switch(functionNo)
  {
    case 0: return Add(a, b);
    case 1: return Mul(a, b);
    case 2: return Sub(a, b);
    default: throw new Exception("Unknown function no: " + functionNo.ToString());
  }
}

int Foo(int[] data, int initValue, int functionNo)
{
  var acc = initValue;
  for(var item in data)
    acc = BinaryOp(acc, item);
  return acc;
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[7]: Слабое связывание в процедурном языке
От: Stanislav V. Zudin Россия  
Дата: 28.07.24 14:43
Оценка:
Здравствуйте, zelenprog, Вы писали:


SVZ>>Ну раз нет возможности использовать полиформизм на уровне кода, значит придётся использовать полиморфизм на уровне данных.

SVZ>>В качестве примера можно подсмотреть стек TCP, виндовый WinAPI — структуры переменного размера, в начале размер и тип данных. Внутри обработчика анализ заголовка и передача по цепочке. Т.е. в какой-то точке программы будут собраны все обработчики.

Z>А можно простой пример?

Z>Чтобы было понятнее?

WinAPI: https://learn.microsoft.com/en-us/windows/win32/controls/lvn-getdispinfo

Для множества уведомлений set/get используется единая схема.
Шлётся сообщение WM_NOTIFY, в качестве параметра — указатель на структуру с данными.
Все структуры имеют одинаковую структуру:

typedef struct tagNMLVFINDITEMA {
  NMHDR       hdr;
  int         iStart;
  LVFINDINFOA lvfi;
} NMLVFINDITEMA, *LPNMLVFINDITEMA;

typedef struct tagLVDISPINFOW {
  NMHDR   hdr;
  LVITEMW item;
} NMLVDISPINFOW;

и т.д.


Первым идёт заголовок NMHDR, в нём лежит код уведомления.
В зависимости от кода уведомления указатель на void кастится к нужной структуре.

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

в Си все эти преобразования происходят без копирования памяти. А в твоём случае —

SVZ>>Если есть доступ к ОСи (надеюсь, язык не совершенно оторван от реалий), то можно использовать системозависимые механизмы для обмена данными, выше камрады об этом упомянули.


Z>Через файлы обмен будет очень медленным — это самый крайний вариант.


А через сокет? Работа с localhost (наверное в 99% операционок) реализована через память (внутри драйвера), без обращения к железу.
_____________________
С уважением,
Stanislav V. Zudin
Re[7]: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 28.07.24 14:53
Оценка:
Здравствуйте, zelenprog, Вы писали:

Как на вашем языке будет выглядеть очередь сообщений?
MQ_PostMessage(queue,message);
message=MQ_GetMessage(queue);

Как выглядит объявление стуктур и объявления переменных?

Как будет выглядеть подобный код на вашем языке?
struct State { int a,b; };
int fn1(State* state) { 
  return state->a + state->b; 
}
int global=123;
int fn2() {
  State s[2];
  s[0].a=10;
  s[0].b=20;
  s[1].a=30;
  s[1].b=40;
  return fn1(&s[0]) + fn1(&s[1]) + global;
}
int fn3(int s) {
  switch(s) {
    case 0: { return 10; } break;
    case 1: { return 20; } break;
    case 7: { return 15; } break;
    default: return 0;
  }
}
int fn4(int n) {
  int r=0;
  for(int i=0;i<n;i++) {
    if (i%3>1) r++; else r--;
  }
  return r;
}
int fn4( int (*fn)(int) ) {
  return fn(7);
}
int fn5() {
  return fn4(fn3);
}
Re[3]: Слабое связывание в процедурном языке
От: vsb Казахстан  
Дата: 28.07.24 17:49
Оценка: 2 (1) +1
Здравствуйте, zelenprog, Вы писали:

vsb>>Второй вариант — реализовать концепцию указателей на функции поверх существующих средств, в прошлой подобной теме я уже про это писал, повторяться не буду.


Z>Как раз интересен этот вариант.

Z>А в какой теме вы это писали?
Z>Если имеется ввиду моя старая тема, то там вы не написали как это можно сделать.
Z>Вот ваш ответ: "Изобрести указатель на функцию можно, но не нужно."

Тут лучше бы больше знать про то, что доступно в языке.

Самый простой вариант это что-то вроде

function call_by_pointer(pointer: integer, argument: integer): integer {
  if (pointer == 1) return function_1(argument);
  if (pointer == 2) return function_2(argument);
  if (pointer == 3) return function_3(argument);
  throw error;
}


Т.е. у нас указатель это некое число и при передаче его в функцию call_by_pointer мы вызываем целевую функцию. Далее в тех местах, где нужен указатель на функцию — мы храним это число, а при необходимости вызвать функцию мы вызываем call_by_pointer.

Если в языке есть строки, может быть лучше заменить число на строку, к примеру банально — названию функции:

function call_by_name(name: string, argument: integer): integer {
  if (name == "function_1") return function_1(argument);
  if (name == "function_2") return function_2(argument);
  if (name == "function_3") return function_3(argument);
  throw error;
}
}


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

Этот подход можено улучшать в зависимости от того, что ещё в языке есть.
Re[8]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 29.07.24 05:41
Оценка:
SVZ>... чтобы отправить уведомление надо ... структуру с данными , массив отправить в диспетчер.
SVZ> Диспетчер десериализует заголовок, подсмотрит тип сообщения и вызовет нужную функцию, которая уже десериализует структуру целиком и обработает уведомление.
SVZ>Т.е. тут у тебя диспетчер знает о всех обработчиках, но зато остальные части приложения знают только о диспетчере.

Понятно, спасибо.

То есть суть решения — в диспетчере.
Диспетчер — это будет отдельная процедура, которая будет знать типы сообщений и вызывать соответствующий обработчик.
Re[8]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 29.07.24 06:05
Оценка:
_>Как на вашем языке будет выглядеть очередь сообщений?
_>
_>MQ_PostMessage(queue,message);
_>message=MQ_GetMessage(queue);
_>


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

_>Как выглядит объявление стуктур и объявления переменных?

_>Как будет выглядеть подобный код на вашем языке?

  Код
_>
_>struct State { int a,b; };
_>int fn1(State* state) { 
_>  return state->a + state->b; 
_>}
_>int global=123;
_>int fn2() {
_>  State s[2];
_>  s[0].a=10;
_>  s[0].b=20;
_>  s[1].a=30;
_>  s[1].b=40;
_>  return fn1(&s[0]) + fn1(&s[1]) + global;
_>}
_>int fn3(int s) {
_>  switch(s) {
_>    case 0: { return 10; } break;
_>    case 1: { return 20; } break;
_>    case 7: { return 15; } break;
_>    default: return 0;
_>  }
_>}
_>int fn4(int n) {
_>  int r=0;
_>  for(int i=0;i<n;i++) {
_>    if (i%3>1) r++; else r--;
_>  }
_>  return r;
_>}
_>int fn4( int (*fn)(int) ) {
_>  return fn(7);
_>}
_>int fn5() {
_>  return fn4(fn3);
_>}
_>


Все это можно реализовать на моем языке. Массивы, структуры (в урезанном виде) есть.
За исключением следующих моментов:

1) Нету указателей на функции. То есть вот этот код нельзя реализовать:

int fn4( int (*fn)(int) ) {
  return fn(7);
}
int fn5() {
  return fn4(fn3);
}


2) Нету строгой типизации. Переменные, параметры и возвращаемые значения функций могут быть любого типа.

3) Все параметры методов по умолчанию передаются по ссылке.
Нет необходимости специально писать вот так:
"int fn1(State* state)" — вместо этого можно написать просто "func fn1 (pState)"
"return fn1(&s[0]) + fn1(&s[1]) + global" — можно написать "return fn1(s[0]) + fn1(s[1]) + global"

Можно параметры передавать по значению.
Но для передачи по значению писанины больше, и так редко делается, редко возникает такая необходимость.
Re[9]: Слабое связывание в процедурном языке
От: Stanislav V. Zudin Россия  
Дата: 29.07.24 06:08
Оценка:
Здравствуйте, zelenprog, Вы писали:

SVZ>>... чтобы отправить уведомление надо ... структуру с данными , массив отправить в диспетчер.

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

Z>То есть суть решения — в диспетчере.

Z>Диспетчер — это будет отдельная процедура, которая будет знать типы сообщений и вызывать соответствующий обработчик.

Как минимум функция, возможно, несколько функций.
Если потребуется асинхронность, то нужна будет очередь (структура данных) и функция, которая будет эту очередь проворачивать в правильный момент (В WinAPI это связка функций GetMessage/PeekMessage + DispatchMessage).
_____________________
С уважением,
Stanislav V. Zudin
Re[4]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 29.07.24 06:35
Оценка: +1
vsb>Самый простой вариант это что-то вроде

  call_by_pointer
vsb>
vsb>function call_by_pointer(pointer: integer, argument: integer): integer {
vsb>  if (pointer == 1) return function_1(argument);
vsb>  if (pointer == 2) return function_2(argument);
vsb>  if (pointer == 3) return function_3(argument);
vsb>  throw error;
vsb>}
vsb>

vsb>Т.е. у нас указатель это некое число и при передаче его в функцию call_by_pointer мы вызываем целевую функцию. Далее в тех местах, где нужен указатель на функцию — мы храним это число, а при необходимости вызвать функцию мы вызываем call_by_pointer.

vsb>Если в языке есть строки, может быть лучше заменить число на строку, к примеру банально — названию функции:


  call_by_name
vsb>
vsb>function call_by_name(name: string, argument: integer): integer {
vsb>  if (name == "function_1") return function_1(argument);
vsb>  if (name == "function_2") return function_2(argument);
vsb>  if (name == "function_3") return function_3(argument);
vsb>  throw error;
vsb>}
vsb>}
vsb>


vsb>Для каждого сочетания аргументов и возвращаемого значения нужно будет делать новую такую функцию.


vsb>Этот подход можено улучшать в зависимости от того, что ещё в языке есть.


Идею понял. Спасибо.
Выше писали что-то похожее про диспетчер.

Если провести аналогию с ООП (внедрение зависимости), то получается следующая картина.
Допустим есть рабочий код (процедура), которая в ходе выполнения должна вызывать какой-то конкретный "внедренный" метод-обработчик (процедуру).
Для этого рабочий код вызывает что-то типа процедуры "call_by_name".
В данном случае "call_by_name" — по сути является "интерфейсной" процедурой.
А реальная процедура, которая будет вызываться в зависимости от параметра — это внедренная процедура.
Клиентский код для "внедрения" конкретной процедуры в рабочий код, передает в рабочий код параметр, обозначающий конкретную процедуру.
Верно?

Процедуру "call_by_name" можно назвать "интерфейсной" процедурой или "базовой" процедурой (процедурой базового класса).
Получается эта "базовая" процедура должна знать названия всех процедур-"наследников".
Re[4]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 29.07.24 06:47
Оценка:
S>Тогда ваш единственный выход — switch.
S>То есть примерно так:

S>
S>int BinaryOp(int a, int b, int functionNo) // весь полиморфизм - здесь
S>{
S>  switch(functionNo)
S>  {
S>    case 0: return Add(a, b);
S>    case 1: return Mul(a, b);
S>    case 2: return Sub(a, b);
S>    default: throw new Exception("Unknown function no: " + functionNo.ToString());
S>  }
S>}

S>int Foo(int[] data, int initValue, int functionNo)
S>{
S>  var acc = initValue;
S>  for(var item in data)
S>    acc = BinaryOp(acc, item);
S>  return acc;
S>}
S>


Понял, спасибо.
Очень похожие решения также написали выше (про диспетчер, хотя суть немного отличается) и ниже (call_by_name).
https://rsdn.org/forum/design/8788561.1
Автор: Stanislav V. Zudin
Дата: 28.07 17:43

https://rsdn.org/forum/design/8788641.1
Автор: vsb
Дата: 28.07 20:49


Получается, это действительно единственный выход.
Отредактировано 29.07.2024 6:53 zelenprog . Предыдущая версия .
Re[10]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 29.07.24 06:50
Оценка:
SVZ>Если потребуется асинхронность, то нужна будет очередь (структура данных) и функция, которая будет эту очередь проворачивать в правильный момент (В WinAPI это связка функций GetMessage/PeekMessage + DispatchMessage).

Асинхронность конечно хорошо бы добавить. Но боюсь, что это невозможно.
Так как в этой программе есть только один поток.
Пользователь инициирует запуск программы, программа ждет ввода пользователя, пользователь например нажимает кнопку, и вызывается процедура, которая вызывает другие процедуры... И все это в одном потоке до возвращения управления пользователю.
Re[11]: Слабое связывание в процедурном языке
От: Stanislav V. Zudin Россия  
Дата: 29.07.24 06:56
Оценка:
Здравствуйте, zelenprog, Вы писали:


SVZ>>Если потребуется асинхронность, то нужна будет очередь (структура данных) и функция, которая будет эту очередь проворачивать в правильный момент (В WinAPI это связка функций GetMessage/PeekMessage + DispatchMessage).


Z>Асинхронность конечно хорошо бы добавить. Но боюсь, что это невозможно.

Z>Так как в этой программе есть только один поток.

Как раз это не проблема.

Z>Пользователь инициирует запуск программы, программа ждет ввода пользователя, пользователь например нажимает кнопку, и вызывается процедура, которая вызывает другие процедуры... И все это в одном потоке до возвращения управления пользователю.


Раз есть окошко, значит есть какой-то цикл обработки сообщений (обработчики нажатий кнопок откуда-то же вызываются).
Значит можно в этом цикле вызвать твою функцию, которая будет дергать обработчики сообщений из твоей собственной очереди.
_____________________
С уважением,
Stanislav V. Zudin
Re[12]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 29.07.24 07:21
Оценка:
SVZ>Раз есть окошко, значит есть какой-то цикл обработки сообщений (обработчики нажатий кнопок откуда-то же вызываются).
SVZ>Значит можно в этом цикле вызвать твою функцию, которая будет дергать обработчики сообщений из твоей собственной очереди.

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

Я читал, что есть "примочки", которые позволяют сделать вызов какой-то процедуры по таймеру.
Но это все делается через подсовывание хакнутых dll-модулей в runtime-среду этого языка.
Пока что не хочется с этим связываться.
Re[13]: Слабое связывание в процедурном языке
От: Stanislav V. Zudin Россия  
Дата: 29.07.24 08:17
Оценка:
Здравствуйте, zelenprog, Вы писали:


SVZ>>Раз есть окошко, значит есть какой-то цикл обработки сообщений (обработчики нажатий кнопок откуда-то же вызываются).

SVZ>>Значит можно в этом цикле вызвать твою функцию, которая будет дергать обработчики сообщений из твоей собственной очереди.

Z>Цикл обработки сообщений есть, но он не доступен для разработчика программы.

Z>Вмешаться в него штатными средствами невозможно.

А точно нет никаких callback'ов? Типа обработчика OnIdle? Или хотя бы таймера7
_____________________
С уважением,
Stanislav V. Zudin
Re[14]: Слабое связывание в процедурном языке
От: zelenprog  
Дата: 29.07.24 09:54
Оценка:
SVZ>А точно нет никаких callback'ов? Типа обработчика OnIdle?

Нету

SVZ>Или хотя бы таймера7


Таймер можно сделать с помощью подмены в среде выполнения хакнутой dll-ки.
Но так мне не хочется делать.
Хочется по максимуму использовать штатные средства.
Re: Слабое связывание в процедурном языке
От: BVA Интернет  
Дата: 29.07.24 12:23
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Как это делается в процедурных языках?


Да назовите вы язык то. Хватит стесняться. Тут и люди, которые к мейнфреймам 70-х готов web api прикручивали есть, так что легаси это не страшно. Это просто больно.
--
http://www.slideshare.net/vyacheslavbenedichuk
https://www.linkedin.com/in/vbenedichuk
Re[2]: Слабое связывание в процедурном языке
От: Умака Кумакаки Ниоткуда  
Дата: 09.08.24 06:21
Оценка:
Здравствуйте, BVA, Вы писали:

BVA>Да назовите вы язык то. Хватит стесняться. Тут и люди, которые к мейнфреймам 70-х готов web api прикручивали есть, так что легаси это не страшно. Это просто больно.


с вероятностью 99% это какой-нибудь MQL4 или подобная шляпа
нормально делай — нормально будет
Re[3]: Слабое связывание в процедурном языке
От: kov_serg Россия  
Дата: 09.08.24 09:30
Оценка:
Здравствуйте, Умака Кумакаки, Вы писали:

УК>с вероятностью 99% это какой-нибудь MQL4 или подобная шляпа


Не, в MQL4 функции не так объявляются, оно больше на GDScript похоже, но там классы есть.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.