Russian Qt Forum
Ноябрь 24, 2024, 02:29 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: QDataStream + exception  (Прочитано 17632 раз)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #15 : Март 26, 2014, 20:31 »

Это плохой подход. Представьте, я получаю в функцию в качестве параметра экземпляр QDataStream. Я не знаю, каким конструктором он был создан, поэтому как мне обрабатывать ошибки: ловить исключениия или проверять инфу об ошибках?
А в вашем случае вы вообще не сможете передать свой стрим в эту функцию, потому что он не является QDataStream.
Плюс можно выкинуть все что могло сериализоваться в QDataStream, оно становится бесполезным.
Я бы это даже решением не назвал.

Как я вижу проблему: есть разработчик, который стоит перед выбором, либо проверять статус на каждый чих, либо использовать исключения. Решает, что с исключениями будет лучше. Тогда он заменяет IO устройство на специальное и оборачивает все в try блок. Все. Никаких других изменений не потребуется.
« Последнее редактирование: Март 26, 2014, 21:20 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Март 27, 2014, 08:53 »

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

Так огласите пожалуйста весь список. Но что то мне подсказывает, что это все очередные выдумки. Улыбающийся
А Вы начните писать и через 5 минут узнаете  Улыбающийся

Эх, была бы лазейка в QDataStream::setStatus - идеально. Но увы  Плачущий
Хоть "feature request" пиши
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #17 : Март 27, 2014, 08:54 »

А Вы начните писать и через 5 минут узнаете  Улыбающийся
Мне не надо.
Ну вы же уже начали, расскажите. Может вы что не так делаете? Улыбающийся
« Последнее редактирование: Март 27, 2014, 08:56 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Март 27, 2014, 08:58 »

Ну вы же уже начали, расскажите. Может вы что не так делаете? Улыбающийся
Проблема очень типовая, упоминалась и на этом форуме (напр Akon'ом). Поэтому мне, право, неудобно такую бытовуху Вам объяснять  Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #19 : Март 27, 2014, 08:59 »

Проблема очень типовая, упоминалась и на этом форуме (напр Akon'ом). Поэтому мне, право, неудобно такую бытовуху Вам объяснять  Улыбающийся
Понятно. Очередное Бла-бла-бла неосилятора. Не интересно.

« Последнее редактирование: Март 27, 2014, 09:02 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #20 : Март 27, 2014, 09:09 »

Понятно. Очередное Бла-бла-бла неосилятора. Не интересно.
А грубить зачем? Я же не виноват что Вы типовых вещей не знаете.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #21 : Март 27, 2014, 09:15 »

А грубить зачем? Я же не виноват что Вы типовых вещей не знаете.
Не придумывайте. Улыбающийся
Было бы что написать - написали бы.
Если вы не можете что-то реализовать, это не значит, что это реализовать нельзя. У вас много чего не получается. Улыбающийся
Поэтому, должны страдать. Так и должно быть, это хорошая мотивация учиться писать нормальный код.
« Последнее редактирование: Март 27, 2014, 09:31 от Old » Записан
Akon
Гость
« Ответ #22 : Март 27, 2014, 18:17 »

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

Собственно, я имел следующее:
Код:
class Wrapper
{
public:
    explicit Wrapper(DataStream& dataStream) : dataStream_(dataStream) {}
   
    Wrapper& operator<<(qint8 i)
    {
        dataStream << i;
        if (OK != dataStream_.status())
            throw std::runtime_error(getStatusDescription());
    }
    ... and so on

private:
  DataStream& dataStream_;
}

template <typename T>
T& operator<<( T& out, const SerializableObject& obj)
{
    out << obj.name();
    ...
}

Usage:

1.
DataStream stream;
SerializableObject obj;
stream << obj;

2.
DataStream stream;
Wrapper wrapper(stream);
wrapper << obj;  // exception aware

Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #23 : Март 27, 2014, 18:22 »

Так чем по вашему это решение лучше предложенного мной? Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Март 27, 2014, 18:39 »

Собственно, я имел следующее:
Код:
template <typename T>
T& operator<<( T& out, const SerializableObject& obj)
{
    out << obj.name();
    ...
}
Это совсем уныло т.к. все-все (QVariant, QList, QVector.. огромную массу) придется переписывать с нуля, воспользоваться QDataStream можно только для простых типов  Плачущий
Записан
Akon
Гость
« Ответ #25 : Март 27, 2014, 19:19 »

Цитировать
Так чем по вашему это решение лучше предложенного мной?
Я уже объяснил. В вашем решении поведение QDataStream будет зависеть от того, с помощью какого конструктора он создан. Выбрасывает функция исключение или нет - это часть интерфейса функции. В данном случае эта часть интерфейса вами будет просто-напросто скрыта. Это недопустимо.

Цитировать
Это совсем уныло т.к. все-все (QVariant, QList, QVector.. огромную массу) придется переписывать с нуля, воспользоваться QDataStream можно только для простых типов
Я вас не понимаю. Вот зачем вам лезь в код сериализации QList, например. Вы разработчик этого класса? Разработчиком определен интерфейс (в случае ошибки возвращается пустой список), только им и пользуйтесь. Допустите ситуацию, когда в коде сериализации чужого класса выделяются ресурсы, - своим исключением вы просто будуте давать утечку. Вы должны использовать исключения для ваших классов и не лезть в реализацию чужих.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #26 : Март 27, 2014, 19:32 »

Я уже объяснил. В вашем решении поведение QDataStream будет зависеть от того, с помощью какого конструктора он создан.
Мда. Я чуть выше написал свое виденье проблемы, но повторюсь:

Как я вижу проблему: есть разработчик, который стоит перед выбором, либо проверять статус на каждый чих, либо использовать исключения. Решает, что с исключениями будет лучше. Тогда он заменяет IO устройство на специальное и оборачивает все в try блок. Все. Никаких других изменений не потребуется.

Поправьте меня пожалуйста, может я ее неправильно представляю. Или мы по разному ее представляем.

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


Выбрасывает функция исключение или нет - это часть интерфейса функции. В данном случае эта часть интерфейса вами будет просто-напросто скрыта. Это недопустимо.
Вы наверное неправильно представляете, что я предлагаю. QDataStream никак модифицироваться не будет и никакой ее интерфейс меняться не будет. Исключения будут приходить от устройства, при невозможности им выполнить запрашиваемую операцию.
« Последнее редактирование: Март 27, 2014, 19:53 от Old » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #27 : Март 27, 2014, 20:19 »

Я вас не понимаю. Вот зачем вам лезь в код сериализации QList, например. Вы разработчик этого класса? Разработчиком определен интерфейс (в случае ошибки возвращается пустой список), только им и пользуйтесь. Допустите ситуацию, когда в коде сериализации чужого класса выделяются ресурсы, - своим исключением вы просто будуте давать утечку. Вы должны использовать исключения для ваших классов и не лезть в реализацию чужих.
Так не выходит, напр
Код
C++ (Qt)
 
   Wrapper& operator<<(QList <MyData> & lst)
   {
       dataStream >> lst;
       if (OK != dataStream_.status())
           throw std::runtime_error(getStatusDescription());
   }
 
Допустим файл калечный, записано только 2 эл-та QList из 5. В этом случае третий эл-т будет прочитан, при этом в теле MyData operator >> никаких исключений не возникнет. Только после этого я получу исключение - но поезд может уже уйти. Ну то еще цветочки. А вот хужее
Код
C++ (Qt)
QDataStream & operator >> ( QDataStream & strm, MyClass & dst )
{
return strm >> dst.data1 >> dst.data2 >>...
}
Только после того как вся цепочка отработает может случиться исключение. И то если она не вложена в другую. А объявлять (в операторах) вместо QDataStream свой враппер - смысла/гибкости нет
« Последнее редактирование: Март 27, 2014, 20:22 от Igors » Записан
Akon
Гость
« Ответ #28 : Март 27, 2014, 21:27 »

Ну а что мешает использовать функции сериализации на уровне MyData (и это более правильный дизайн). При чтении 3-го элемента будет выброшено исключение, дальше зависит от конкретной логики.

Цитировать
А объявлять (в операторах) вместо QDataStream свой враппер - смысла/гибкости нет

Дискуссия несколько расфокусировалась. Акцентирую некоторые моменты:
В одном бите нельзя передать 3 значения. Если  вы хотите сохранить QDataStream в интерфейсе функций сериализации, то ни о какой кастомизации речи быть не может, поскольку QDataStream не спроектирован соответствующим образом (нет полиморфных функций). Косвенным образом, вы можете декорировать нижележащий QIODevice, как было предложено Oldом, с уже оговоренной проблемой.

Враппер в данном случае дает такой "полиморфизм" времени компиляции. Да, это не универсальное решение, но универсального решения в даненом случае и не будет.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #29 : Март 27, 2014, 23:22 »

Косвенным образом, вы можете декорировать нижележащий QIODevice, как было предложено Oldом, с уже оговоренной проблемой.
Пока одни борются с ветреными мельницами, у других все работает. Улыбающийся

Код
C++ (Qt)
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
 
qint8 a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
 
try
{
QFile file( "test.dat" );
ExProxyDev dev( file );
dev.open( QIODevice::ReadOnly );
 
QDataStream in( &dev );
in >> a >> b >> c >> d >> e >> f;
qDebug() << in.status();
}
catch( std::exception &ex )
{
qDebug() << ex.what();
}
 
qDebug() << a << b << c << d << e << f;
 
return 0;
}
 

Ну не вижу я тут никаких "оговоренных проблем".

Резюмируя: это одно из решение конкретной задачи,  поднятой ТС, которое может применяться для чтения/записи в каких-то исключительных случаях, что-бы не засорять логику постоянными проверками.
Костыль ли это - по мне да, и я никогда бы не использовал его в боевом проекте. Я писал бы свои сериализатор и делал  весь обмен на нем. Но если появилась эта тема, то полноценное решение ТС писать не хочет, а хочет как я понял воспользоваться имеющимися наработками. И для таких случаев лучшего решения я пока не вижу. Улыбающийся
« Последнее редактирование: Март 28, 2014, 06:18 от Old » Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.342 секунд. Запросов: 22.