На чем написать модульную софтину?
4611
31
В перспективе требуется софтина для обработки большого количества данных определенного формата.
Проблема в том, что алгогритмы обработки должны меняться пользователем. В идеале хотелось бы оформить софтину модульно - каждый алгоритм в отдельном модуле. Какая из технологий позволит это реализовать без особых накладных раходов? Dll и Com пока не устраивают.
AnotherBoris
А можно поподробней про структуру данных, что такое "обработать" и язык реализации?
Mad_Dollar
Подробнее. Есть драйвер - он собирает данные определенного формата из железа. По идее либа,
зацепленная к драйверу предоставляет доступ к этим данным в произвольном порядке, а также
сейвит сырые данные на винт. После одним алгоритмом данные обрабатываются в другие данные в соотношении 1 к 1. Получаем второй массив данных, его сейвим уже по желанию. Далее еще один алгоритм кучкует данные второго массива. Эти кучки обрабатываем (используя как первый, так и второй массивы) и получаем третий массив. Соответственно, третий массив опять кучкуем, обрабатываем и получаем четвертый. На этом пока все:улыб:В общем, где-то на работе есть схемка со структурой обработки данных, но до работы я пока не добрался :). И вот во всем этом
хочется, чтобы алгоритмы обработки и кучкования данных были оформлены в отдельные модули и
могли заменяться во время работы программы (или хотя бы при ее переинициализации). Да, еще -
хотелось бы, чтобы программа работала под WinXP, хотя это и не критично:улыб:Язык реализации
- C++. Вроде бы все. Хотя, учитывая, что мне все равно придется изучать новую технологию...
может быть язык не столь уж и критичен.
AnotherBoris
И опять таки ДотНет. Очень простой способ собирания модулей, включая динамическую загрузку, пространства имен, можно контролировать версии и еще много всего хорошего
AnotherBoris
В вашем варианте как я понял вы начали "снизу вверх" проектировать.
1. Попробуйте "сверху вниз".
2. На мой взгляд ваша задача сводится к:
2.1 абстрагированию типов данных, которые вы получаете (неким образом, либо как результат первичной работы вашего драйвера, либо как результат операции "кучкования" с другими данными. Типов данных насколько я понимаю ограниченное число (в противном случае алгоритмического решения не будет, так ведь?)
2.2. написанию примитивных методов работы с этими абстрактными данными - в категории получить, сохранить, произвести некие другие специфические операции, нужен лишь минимальный набор операций, который путем комбинации можно будет превратить в любую необходимую вам нужную более сложную операцию. Для этого определите перечень операций и попробуйте их разбить на более простые.
2.3. придумайте (возьмите готовым) синтаксис описания операций. Напишите в этом синтаксисе более сложные опреации и напишите процедуру разбора синтаксиса.
3. Все. Вы имеете универсальное средство, прозрачное для пользователя, гибкость которого ограничена набором "примитивов". Ваш пользователь может например сам написать несколько строк вида:
- "получить_данные" А
- "загрузить_данные" В
- "кучковать_1" А и В в С
- "кучковать_2" А и С в Е
- "сохранить" Е
Причем если вы опишите применение примитивов, ваши пользователи при использовании неких синтаксических лексемм сами получать операции "кучковать_n". По существу получаете узкозаточенный интерпретируемый язык обработки узкозаточенных данных, имеющий максимальную гибкость в пределах примитивных операций. Если описание типов данных и примитивов работы с ними вы разобьете по dll-кам или другим типам библиотек, и вынесете конфиг процедуры интерпретации в отдельный файл, процедура добавления абстрактных типов данных и примитивов их обработки будет заключаться в "дописывании" конфига путем добавления строки,описывающей в какой библиотеке какой тип данных и примитивы работы с ним лежит.
Вопрос можно - а что это за данные и конечная цель какова? Ответить можно в личку.
Mad_Dollar
Программа, а точнее система Акустико-Эмиссионная диагностическая:улыб:Железо собирает высокочастотные акустические сигналы. В идеале до 100-150 сигналов в секунду на 32 канала... Итого 8192*32*150 = 38 метров в секунду максимум пишет на винт драйвер. Алгоритм номер один обрабатывает сигналы получая время прихода, амплитуду, коэффициент нарастания и т.п. - второй набор данных. Кучкователь номер один кучкует сигналы в события - группы сигналов, теоретичесик происходящих от одного события. Алгоритм номер два из кучки сигналов формирует событие - расчет его параметров (место на объекте, характеристики и т.п.) - третий набор данных. Кучкователь номер два и Алгоритм номер три из событий собирает кластеры - группы сигналов, теоретически отнолсящиеся к одному источнику. Ну это в двух словах...:улыб:Про гуй для этого я вообще молчу:улыб:В общем где-то так...
Касаемо типов данных - их конечное число, но, возможно все же большое - при отказе юзера от расчета одного из парамеров в первом алгоритме, автоматически меняются все последующие наборы данных - Это как раз было больным местом в COM-е, где под каждый тип пришлось бы заводить собственный GUID.
Что касаемо примитивов обработки данных, мысль добрая, благодарю. Хотя, мне кажется, в моем случае набор операций определен жестко - кучкователь кучкует, Алгоритм (точнее, если вспоминать терминологию - Конвертер), Конвертер - конвертирует... Но мысль я подумаю, спасибо:улыб:
AnotherBoris
Я же говорил что "снизу вверх" =) Попробуйте "сверху вниз" (есть входные данные, есть выход/результат - детализируйте до полного построения алгоритма), учитывая что сигналы у вас "однотипные" первично, а операция "кучкования" - выборка из таблицы БД. Дальше же просто не хватает технического понимания что и зачем вы там с данными делаете, уж извините. В любом случае сначала определите необходимые и необходимые объекты данных, а потом уже из этого предоставляйте пользователю свободу операций. Представьте сначала что у вас все данные определены (необходимы для начала расчета), разработайте алгоритм обработки, а потом рассматривайте что можно удалить из списка "необходимых" объектов данных и какую свободу пользователю это даст - достаточную ли. Пример - если у вас есть понятие первообразной n-го порядка, то для ее достижения необходимо знать первообразную n-1 порядка. Если вы определите операцию нахождения первообразной для аксиоматических функций типа степенной, логарифмической, и операции "работы" с этими функциями вы можете построить множество сложных функций. Так и у вас - определитесь с тем, что аксиоматично (необходимо), и дайте примитивы пользователю - тогда вы сможете решать задачу "уровнем выше", из примитивов строя более сложные конструкции и применяя их дальше. Ну в общем как-то так.
Mad_Dollar
Да нет с этой точки зрения все более или менее понятно, хотя еще раз спасибо за мысли. Меня больше интересует НА ЧЕМ это сделать. В силу того, что последние лет пять основным языком для меня был асм, а основным дебаггером осциллограф... Я несколько отстал от жизни:улыб:Структура данных, последовательность обработки, жизненный цикл и пертурбация данных продумана более или менее - на бумаге структура программы есть. Ее бы реализовать теперь:улыб:И еще, хоть это и не в тему - моим пользователям не понравится то что вы предлагаете:улыб:Им нужна кнопка "Делаю все". Так что cfg-шники тоже программер, то бишь я писать буду. А так не хочется изобретать велосипед...
AnotherBoris
Если им без вариантов - то логику описать то можно всем, даже асмом =) а в гуе действительно оставить только кнопку "сделать" все =)
Вопрос на чем писать - пишите на чем вам проще, если структура на бумаге есть то это просто банальный кодинг. Вам с++ подойдет за глаза, ибо обладает основными необходимыми инструментами - объектами (классами) и наследованием этих объектов (классов). А если с гуем надо - то любой с++ билдер из подручных подойдет насколько я понимаю.
Mad_Dollar
Да, но как быть с взаимозаменяемостью модулей? Их же нужно аттачить к уже готовому проекту. Типа выпускать аддоны и все такое... Я-то как раз об этом. Нужны подключаемые модули отдельные от исполняемого кода. В dll-ках слишком уж никакой контроль версий, проверка совпадения типов и т.п. В COM-е наоборот все слишком наворочено - я сам в гуидах заблужусь... Вои т интересуюсь, что есть еще?
AnotherBoris
В dll-ках слишком уж никакой контроль версий, проверка совпадения типов и т.п.
А вы напишите некое подобие скрипт-языка, а все типы и примитивы вводите через длл с определенным интрефейсом через некий конфиг для той части кода которая будет "парсить" и выполнять ваши "скрипты" по расчету, тогда вам контроль версий ни к чему по существу. Встречая скрипт-покамду "кучковать_А" или "конвертировать_Б" будет загружаться длл с необходимой функцией, однако со строго-регламентированным способом передачи данных предположим в виде указателя на область памяти. А внутри длл и фкункций работы с данными сами определяйте в каком порядке и как у вас в памяти данные лежат.
То есть сделать можно так:
1. есть модуль так называемого ядра:
1.1 кусок который имеет универсальное апи и служит для определения типов данных и их верификации, сравнения, сохранения и преобразования (пользуясь теми функциями которые прописываются в длл) и который могут вызывать из "плагинов-команд"
1.2. кусок который умеет "понимать" команды - связывать их с внешними функциями в других плагинах/длл
а каждая длл должна иметь определнные стандартные функции сравнения, преобразования, инициализации данных и некий набор примитивов работы с ними.
то есть в каждой длл, которая аттачится к ядру парсера должны быть некие стандартный функции определения данных, которые будут работать с кусками памяти и всегда возвращать результат указатель. Тогда вам контроль версий нужен внутри одной библиотеки для работы с одним "типом данных". А все более сложные вещи писать на этом скрипт-языке - гибкость будет гибче некуда =) В общем нутром понимаю, а объяснить не могу =)
AnotherBoris
Выпускайте dll с версией - и с методом getVersion().
Mad_Dollar
Что-же, где-то так оно и планировалось, тем более это единственный инструментарий, которым я пока владею:улыб:Просто как представлю, что каждом модуле надо расковыривать pointer-ы на данные, смотреть где чего есть, чего нет, писать API под это дело, в конце концов вызывать LoadLibrary, грузить список функций... Ужас... Вот и думается мне, что сей велосипед уже кто-то изобрел... Самописаный код, конечно рулез, рулезнее некуда, но времени на него уходит...
AndyK
GetVersion(), говоришь... А ты представь: есть у меня конечное множество парамеров. Есть, соответственно Descrption для каждого где-то отдельно в конфиге. Мои модули эти параметры туда-сюда гоняют и радуются... И тут теоретик Вася Пупкин изобретает параметр X, в корне изменяющий подход к решению проблемы (что кстати, вполне реально и уже встречалось на моей памяти). Мне мало того, что этот Х надо ввести в таблицу Descrptior-ов, мне нужно переписать половину модулей, чтобы они могли его юзать, мне нужно в гуе зеранее учесть, что оный Х может нарисоваться как... да как "Х" и нарисуется:улыб:Мне заранее нужно учесть в остальных модулях, что этот Х может появиться, и что его, хоть и не надо считать, но нужно пропускать через себя... В общем, просто GetVersion, мне кажется, мне как собаке пятое колесо - не поможет:улыб:
AnotherBoris
Для таких теоретиков как Вася - хороший инсттрумент визуального программирования LabView. Все что вам нужно - запихать исходные данные - дальше пускай вася мастерит. Только сходя из своего опыта скажу - данных шибко много - чем больше абстрации тем сложнее все засинхронизировать и обеспечить нужное время исполнения.
bravot
LabView иделаен для именно Васи:улыб:Видел я, как они на нем мастерят и что у них выходит. Здорово, кончено, но нехай именно они этим далее и занимаются. А мне надо бы пару-тройку гигов данных в раелатйме обрабатывать. Точнее обрабатывать-то меньше, но обеспечиать доступ именно по 32-битному адресу. LabView повесится на таком объеме:улыб:
AnotherBoris
Привязывать логику к GUI - думаю дело в неверном подходе к разработке архитектуры приложения.
AndyK
Нет, гуй как раз вторичен. Первый вариант планируется вообще консольным - во избежание.
AnotherBoris
.NET + .NET Reflection

Позволит на ходу менять алгоритмы и / или собирать прям внутри софтины исполняемый код из текста программы, если это необходимо.
AnotherBoris
мне нужно в гуе зеранее учесть, что оный Х может нарисоваться как... да как "Х" и нарисуется
Ошибка здесь
AndyK
Ох, наверное, мне пора уже выплевывать щуп осциллографа из зубов время от времени...
Я вижу это так: Есть ядро, обеспечивающее доступ к наборам данных. Как оно мне видится теперь - оно автономно и имеет лишь средства для мониторинга происходящих с данными изменений. И есть гуй. Он подписывается на мониторинг, читает данные, отображает их... Местами чем-то в ядре рулит. Но тем не менее, при проектировании гуя нужно учесть ту особенность, что для некоторых параметров, которые появятся позже он не найдет соответственной формы отображения.. Поэтому, будет банально писать цифирки и ждать адд-она к себе. Никакого отношения к ядру это не имеет.

Где здесь несоответствие? С удовольствием ткнусь в него носом - мне это полезно:улыб:
AnotherBoris
проще сказать что вся структура состоит из трех частей:
коллектор, интерпретатор/интегратор и визуализатор, которые взаимодействуют по общим принципам и протокола?
xprogrammer
.NET + .NET Reflection
Вот это лучше в топку. Глючней и бестолковей у МС только сам маздай.
:ха-ха!:
AnotherBoris
Может универсальнее строить динамически GUI по текстовому описанию?
Появились параметры - вместо аддона - дописываете в текстовое описание форму и место отображения.
AndyK
вопрос не в том как сделать гуй, а как добится гибкой модульности на этапе коллектора / конвертора =)
Mad_Dollar
Спасибо Mad Dollar:улыб:Вы меня понимаете:улыб:
xprogrammer
Железо собирает высокочастотные акустические сигналы. В идеале до 100-150 сигналов в секунду на 32 канала... Итого 8192*32*150 = 38 метров в секунду максимум пишет на винт драйвер.
.NET .NET Reflection
что-то мне кажется для таких обработок, написанных на NET железо должно быть маманегорюй )))
Mad_Dollar
А железо-то тебе каким боком мешает?:улыб:Насчет дотнета, да, не улыбается мне пока такой вариант. А вот набор Dll, с учетом предложенных тобой мыслей самое оно... Но железо-то тут причем? Воткнем что-нибудь в PCI - нехай себе шлет все подряд. В силу специфики моей работы железо меня не колышет в принципе - плавали, знаем:улыб:
AnotherBoris
38 мегабайт - это поток инфы в примерно в 250-300 мегабит... Ну причем ее нужно обрабатывать в режиме реального времени насколько я понимаю. Масштаб железяки порядка приличного центрального маршрутизатора (хотя бы некоего крупного узла) сессий (к примеру пппое) довольно крупного (не мелкого во всяком случае) провайдера. Представил себе софтину на .NET, которая бы этим занималась и железо, которое бы она потребовала.
А в тему pci - сама шина такой поток то выдержит? Просто не помню, но скорость поступления данных в место обработки тоже существенный фактор насколько я представляю...
Mad_Dollar
:улыб:Дак сейчас-то держит:улыб:Под более примитивной софтиной:улыб:К тому же, в одну шину вставляется лично в нашей конфигурации только четыре канала... Так что нагрузка на один слот значительно меньше. Хотя... 8 PCI девайсов... тоже не слабо:улыб:Но это все равно наши проблемы - вытянем:улыб:
AnotherBoris
Вообще надо исходить из правильно поставленной задачи.
А то под первое описание действительно подходит лучше всего с# или java - модульность на высоте.
Для быстрого доступа к данным во первых ограничение это ОС - QNX, OS9, DOS, LinuxRT, Win emb.
Потом компилятор - явно с/с++.
Ну исходя из этого вариантов маловато.
Наиболее правильным велосипедом наверное будет модуль записи/доступа к shared memory куда будут складываться принятые данные. Остальные модули согласно API доступа достают данные для своих нужд. как то так.
Ну и как то с трудом верится что такой поток данных без тормозов удастся - получить, обработать умными алгоритмами и вывести в GUI.
AndyK
Хех, мне местами в это тоже не верится, а что делать? Все равно придется сначала писать тестовый вариант, с заглушками вместо кода, смотреть на скорость работы, а потом уж думать дальше. Опять же, не забывайте, что указанный поток данных ПИКОВЫЙ. В нормальном режиме он несколько меньше.

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