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

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: 1 ... 31 32 [33]
481  Программирование / С/C++ / Re: Базовый класс : Июнь 29, 2013, 15:05
Если 9 из 10 возможных наследников захотят иметь такой метод, а 1 из 10 не нуждается, но и не против, то очевидно, что добавление такого метода в базовый интерфейс - это самое просто и быстрое решение, которое не создает проблем.
Именно так и происходит в моей практике, наверное и в практике других тоже. Однако начав расширять базовый класс - остановиться очень трудно. Напр некоторые форматы имеют background color - прозрачные области показываются не черным а этим цветом, его можно менять. Нет, таких явно не большинство, скорее наоборот, пусть 1/10. Но будете ли Вы с этим возиться? Ведь гораздо проще уговорить себя "это никому не мешает" - и слить в базовый класс. В результате в него все льют и льют. В результате раздутый базовый класс "на все случаи жизни"

Для этого и существует документ "требования к механизму".
Одну и ту же задачу можно решить десятком различных способов. Какой из них выбрать?
Тут даже думать не нужно: самое простое в плане реализации, которое удовлетворяет требованиям к механизму.

У меня был случай на практике: класс Picture. Содержал в себе весь джентельменский набор для тех самых 95% случаев использования: масштабирование, угол поворота, прозрачность по альфе, и тп вещи.

Моя первая реакция: мне угнетало такое большое количество разных методов в одном классе. Какой-то божественный класс.
Я ещё тогда подумал: а как можно сократить количество паблик-методов, не потеряв удобства использования?

Ну так вот: никак. Как бы вы ни выкручивались, по сути вы просто просто перетаскиваете код из одного места в другое:

Код:
//самый простой и очевидный ОО-способ. Удобно для 95% случаев
//Но не позволяет изменять алгоритм по которому выполняется масштабирование
img.Scale(param);

//процедурный стиль. Увеличивает сложность проекта из-за отрыва данных от их обработчиков.
Scale(img, param);

// паттерн "стратегия".
// Позволяет использовать собственный алгоритм обработки,
//без необходимости знать строение Image
img.Process( Scale(param) );

То есть, если функционал Scale стабильно часто требуется пользователям, то его в любом случае придется реализовать.
Вопрос только: где он будет?

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

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

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


Итого:
1. Проблемы нужно решать по мере их наступления. А не пытаться заранее решать ещё не существующие проблемы.
2. Делать нужно так, как можно сделать проще и быстрее.
482  Программирование / С/C++ / Re: Базовый класс : Июнь 28, 2013, 20:59
А можно не так резво? Улыбающийся Не все темы создаются теми кому "непонятно", иногда интересно услышать мнение других о проблеме.

Есть два хороших фактора при разработке:
1. Делать так, как сделать проще и быстрее.
2. Делать так, что бы на сопровождении не отгребсти проблем.

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

Когда создается класс довольно трудно предсказать его эволюцию. Сегодня 9/10 пользуют - не аргумент. Напр загрузчик/обработчик имеджей. Некоторые имеют альфа-канал, др нет. Должны ли альфа-методы быть в базовом классе? Если нет, то какой механизм взамен?

При разработке класса не нужно думать о его возможной эволюции вообще.

Все, о чем стоит думать в момент создания класса:
1. Дизайн использования (как это работает на практике)
2. Требования к механизму (условия эксплуатации)
3. Гарантии рабостопособности и стабильности.

Ваш пример можно перефразировать:

Механизм ImageProcess, должен уметь обрабатывать картинки с альфа-каналом, при этом, картинки могут быть как с альфа-каналом, так и без него. Таким то, и таким то образом.

Лично я:

1. Вообще не стал бы городить тут интрфейсов, ибо по задаче в этом нет необходимости.
2. Дизайн проект. Как пользователи хотя бы приблизительно хотели бы это видеть?

Допустим, действия наиболее частые и характерные для любого множества картинок я бы определил в жесткий "стандартный интерфейс" - в набор паблик методов ImageProcess:

ImageProcess ip("Example.png"); //любое множество картинок умеет загружаться с диска

ip.ScaleXY(100,100); //любое множество картинок можно масштабировать

//некий специфичный обработчик. Умеет делать узко-специализированные действия над буфером цветов картинки
AlphaSpecific as;

ip.Work(as); //AlphaSpecific знает о существовании ImageProcess. Вытряхивает из него нужные данные и работает.

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

И предоставляем пользователям способ, как удобно организовать оставшиеся 5% специфических обработок:
Пользователь порождает от ISpecific класс обработки, и кормит своего потомка ImageProcess::Work(ISpecific*);


483  Программирование / С/C++ / Re: Базовый класс : Июнь 28, 2013, 16:54
Очень даже хорошо представляю.

Тогда что именно не понятно?

Как уже было дважды сказано - легко и просто объявить, "нужен всем", мол, базовое свойство. Ведь это наиболее легкий путь реализации. Но так ли это на самом деле?

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


Да, в принципе возможен такой потомок у которого нет feedback'а с юзером. Хотя пока таких нет и вероятность этого мала. И что?

Если 9 из 10 актуально эксплуатируют метод базы, а 1 из 10 его не использует, то по опыту могу сказать, что в этом 1 из 10 отсутствует здравый смысл использовать такую функцию.

Я в таких случаях говорю так: "а для тебя эта функция означает ничего не деланье".
Я бы добавил метод в интерфейс, который по дефолту ничего не делает. И переопределял бы его везде, где это необходимо.
484  Программирование / С/C++ / Re: Базовый класс : Июнь 27, 2013, 17:40
Ну разумеется все пользующие видят taskScheduler *, а реально создается defautrScheduler. Ладно, но вот выяснилось что нужна ф-циональность checkForAbort - куда ее лепить? Я пошел по пути наименьшего сопротивления - расширил базовый класс. Оправдаться очень легко - является ли проверка на отмену (checkForAbort ) "неотъемлемой" частью taskScheduler? Да, конечно! (ну а почему нет?). Но все же у меня смутное чувство недовольства. Эдак что угодно можно признать "совершенно необходимым" и слить в базовый класс, который очень скоро превратится в хз что. 

Мнения? (понимаю что мой пост может "слишком субъективен")
Спасибо

Сама по себе формулировка "выяснилось что нужна ф-циональность checkForAbort" слишком расплывчатая.
Видимо, вы сами не вполне осознаете, кому и зачем понадобился этот checkForAbort.

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

На плюсах оч хорошо действует правило: "то, чего быть не должно - не должно быть в принципе".
Смысл в том, что бы сделать так, что бы этого метода не было у тех классов, кому этот метод не нужен.


485  Программирование / С/C++ / Re: Как delete[] узнаёт длинну массива? : Апрель 24, 2013, 12:27
Это знает не delete, а конкретный компилятор.

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

Таким образом, первые некоторое количество байт хранят служебную информацию о блоке.
Когда компилятор встречает delete[], он отматывает от адреса эти несколько байт назад, и извлекает служебную информацию. После чего он уже знает как именно нужно удалять блок.

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

Например, для компиляторов от вижал-студии, размер выделенного блока можно узнать вот так:

http://msdn.microsoft.com/en-us/library/z2s077bc.aspx
486  Qt / Установка, сборка, отладка, тестирование / Qt 5.0.1 вместе с mingw47 ошибка в libstdc++-6.dll : Апрель 05, 2013, 19:20
С сайта: https://qt-project.org/downloads
Установил себе: Qt 5.0.1 for Windows 32-bit (MinGW 4.7, 823 MB)

Создаю простейший проект:

Код:
#include <iostream>

using namespace std;

int main()
{
    cout << "Hello World!" << endl;
    return 0;
}

Запускаю: выводит в консольку текст Hello World!
И где-то через мгновение крэшется.

Запускаю из под отладки, выводит:
сигнал: SIGNAL SIGILL
назначение: illegal instruction

Стек вызовов функций показывает на:

0   libstdc++-6!_ZSt4cout   C:\Qt501\mingw47\5.0.1\mingw47_32\bin\libstdc++-6.dll      0x6fcd52a0   
1   libstdc++-6!_ZNSolsEPFRSoS_E   C:\Qt501\mingw47\5.0.1\mingw47_32\bin\libstdc++-6.dll      0x6fc8db7a   
2   ??         0x7ffdf000   
3   __mingw_CRTStartup   crt1.c   244   0x4010b9   
4   mainCRTStartup   crt1.c   264   0x401284   

В чем тут проблема? И как это лечется?

Операционка - 32 битная семерка

Решение найдено:

Помимо мингва идущего в коробке с Qt5.0.1 у меня стоял отдельно идущий и рабочий мингв.

Приложение собралось и заработало без ошибок после того, как я пригрохал этот отдельно идущий мингв, и почистил пути в системном окружении.
Страниц: 1 ... 31 32 [33]

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