LINUX.ORG.RU

Отделение кода от гуя, best practices


0

5

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

Суть проблемы:
есть модуль_А получающий данные от различных бекэндов, каждый из которых должен иметь виджеты для настройки и мониторинга состояния. У каждого бекэнда настройки совершенно различны (например RS-485 и TCP/IP бекэнды).
Сейчас каждый бекэнд отдает свой виджет, вставляемый в нужное место, через который и настраивается. Некрасиво.

Далее, получив данные, модуль_А разбивает их на группы и рассылает прочим модулям, которые, обработав эти данные, должны нарисовать свое состояние. Релизовано так же как и в вышеприведенном случае.

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

Да, все пишется на qt.
А как делаете в своих проектах вы?

★★★★☆

Вот тебе ещё более костыльный вариант. Бэкенд отдаёт что-то вроде формы для заполнения с обязательными и необязательными полями. Фронтенд эту форму читает и по ней строит гуй который призван эту форму заполнить.

KblCb ★★★★★
()

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

- Отдаете «описание» параметров бекенда

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

- Когда универсальная форма редакторов дюжекрива выходит для какогото бекенда рисуете в редакторе точку расширения и внее вставляете кастомынй редактор (не всю форму меняете, а только редактор нужного параметра)

на яве всеь этот код пишется за полдня

belous_k_a
()

Имхо, тут нужна фабрика виджетов, которая для каждого бекэнда будет отдавать нужный виджет\виджеты.

Norgat ★★★★★
()

А как делаете в своих проектах вы?

Выделяю буфер в разделяемой памяти, либо использую mmap'нутую структуру-посредник, либо открываю сокет...

Eddy_Em ☆☆☆☆☆
()

ковыряю сейчас один проект, у него вся логика сделана демоном, уи на Qt, связь через D-Bus.

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

а в чем костыльность?

aol ★★★★★
()
Ответ на: комментарий от aol

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

Tweaker ★★★★☆
() автор топика
Ответ на: комментарий от aol

MVC - это идея, а не конкретное физическое исполнение. К разделению я в конечном итоге и хочу придти, вопрос именно в технической реализации.

Tweaker ★★★★☆
() автор топика
Ответ на: комментарий от den73

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

Tweaker ★★★★☆
() автор топика
Ответ на: комментарий от belous_k_a

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

Tweaker ★★★★☆
() автор топика

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

anonymous
()
Ответ на: комментарий от belous_k_a

на яве

я тоже за java с некоторых пор, в смысле лютобешеноплюсую.

anonymous
()
Ответ на: комментарий от Chaser_Andrey

Чтоб визуализация была свистящей и пердящей.

Tweaker ★★★★☆
() автор топика
Ответ на: комментарий от anonymous

Дешифруй, пожалуйста. Что делать в случае если интерфейс нельзя унифицировать?

Tweaker ★★★★☆
() автор топика
Ответ на: комментарий от Tweaker

Сейчас хочу сделать все по уму.

Если тебе только нужно не тащить некий графический код в некое место, воспользуйся RPC (remote procedure call).

Мой вариант, но я не знаю,пройдёт ли он по трудоёмкости, требованиям быстродействия и контроля доступа. Я бы стал писать его руками с нуля, это не так уж трудоёмко, но, вероятно, есть и готовые фреймворки.

Порядок действий такой:
1. копируешь проект и называешь первую копию «сервер», а вторую - «клиент». Сервер будет заниматься работой, клиент - графикой.
2. просматриваешь весь код. Выстраиваешь линию разреза по классам/функциям, которые занимаются графикой и которые ты по этой причине не хочешь тянуть туда, где будут железки. Называешь их «классы/функции отображения».
3. Смотришь, с какими классами/функциями, оставляемыми в сервере, они взаимодействуют. Называешь их «классы/функции для отображения».
4. Повторяешь пункты 3 и 4, пока не достигнешь следующего результата:
- как можно меньше точек обращений к «классам/функциям для отображения»
- достаточно маленький трафик через границу
- главный цикл обработки событий Qt должен оказаться на стороне клиента
- «классы для отображения» должны быть твоими классами, а не классами Qt.

5. Выбираешь скриптовый язык, поддерживаемый SWIG, для встраивания в сервер. Допустим, tcl, php или mzscheme. Рассмотри такие вопросы, как безопасность, многопоточность, обработку ошибок, вопросы освобождения памяти, поддержку кириллицы, если она нужна.
6. Все «классы для отображения» оборачиваешь в этот язык. Рекомендуется использовать SWIG. Работа со SWIG довольно легка и приятна, ты можешь быстро обернуть десятки классов, поддерживаются и шаблоны, всё прилично документировано.
7. Реализуешь listener, который позволяет клиенту вызывать собственно связь «клиент-сервер», например, с помощью сокетов. Задача - чтобы ты мог в клиенте печатать команду, а команду выполнял бы встроенный в сервер интерпретатор.
8. Все обращения «классов/функций отображения» к «классам/функциям для отображения» подменяешь на вызовы интерпретатора через listener. ВОзможно, ты захочешь для этого написать (или нагенерить) классы-представители для каждого «класса для отображения», тогда работа над клиентом будет состоять в замене «классов для отображения» на представителей.

Немного сумбурно получается, но сам я по этому пути до конца не ходил, поэтому не могу выдать точно работающую стратегию с учётом всех граблей. Немного пробовал, вроде так должно получиться. Конкретно, я пытался сделать обёртки для полной VCL (библиотека видгетов Delhpi), чтобы пользоваться ей из Common Lisp. Остановил меня большой объём работы, а остальные вопросы, перечисленные в плане, были решены. Так что я не рекомендую так, попытайся ограничиться маленьким набором классов.

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

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

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

den73 ★★★★★
()
Ответ на: комментарий от den73

Вот, кстати, влезу с вопросом. Сам натыкался на этот swig, и возник интерес: неужели с ним проще сделать GUI, чем, скажем, используя те же C+GTK?

Eddy_Em ☆☆☆☆☆
()

MVC спасёт отца русского костылестроения

shty ★★★★★
()
Ответ на: комментарий от Tweaker

MVC - это идея, а не конкретное физическое исполнение. К разделению я в конечном итоге и хочу придти, вопрос именно в технической реализации.

так у тебя в ОП всё написано, в чём проблема то?

shty ★★★★★
()
Ответ на: комментарий от Eddy_Em

Не знаю, т.к. некогда не пытался сделать C+GTK. С Qt приходилось работать и с tk немного. Я вообще не линуксоид, я просто иногда сюда захожу для фана. Да и SWIG был на уровне экспериментов. Однако, эти эксперименты показали, что SWIG- это хороший инструмент, в котором продуманы все нюансы практики.

den73 ★★★★★
()
Ответ на: комментарий от den73

Спасибо за пищу для ума.

Насчет SWIG, я так понял у него свой препроцессор, у Qt свой. И SWIG если нужно будет натравливать уже на мокнутые файлы, то, мне кажется, будет тот еще геморрой.

Tweaker ★★★★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.