1. C++ / Говнокод #22027

    −20

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    83. 83
    84. 84
    85. 85
    86. 86
    Допустим, хочу добавить новый функционал. Что нужно для этого сделать:
    1. Объявить сигнал в интерфейсе интерфейсов (хех). Этот, например, скажет презентеру, что пользователь хочет добавить нового ученика в бд.
    void addStudSIG(StudentData newStudent); 
    2. Объявить одноимённый слот в презентере. Пока всё терпимо.
    void addStudSLOT(StudentData newStudent); 
    3. прихуярить их друг к другу в методе презентера, который отвечает за подписку на сигналы интерфейса
    QObject::connect(uI, SIGNAL(addStudSIG(StudentData)), this, SLOT(addStudSLOT(StudentData)));
    4. реализуем этот слот, реализация состоит из вызова одного метода ("o_" это указатель на "модель", "o" значит "owl", но это не важно)
    o_->addStud(newStudent);
    5. объявляем этот метод в "модели"
    qint32 addStud(StudentData newStudent); // возвращаемое значение это id новой записи в таблице
    6. реализуем, опять вызовом одного метода
    sController_.addItem(newStudent); // для каждой сущности в таблице у меня есть controller, который отвечает за её обработку
    7. Теперь, просто реализуем метод контроллера средствами подключённой ормки, если контроллер есть.
    Если нет, то нужно ещё немного покопипастить своего кода.
    Т.е. "бизнес-логика" размазана по этим контроллерам. Такая архитектура порождает кучу проблем. Копирую имена методов, чтобы создавать методы.
    А если хочешь узнать, что же делает сигнал и тебе не достаточно комментария над ним, нужно идти в глубь на 3 или 4 слоя по вызовам одноимённых
    методов, нихуя не понимая.
    Думал, создать для всех этих объектов общий интерфейс и возможностями Qt Creator, чередуя левую и правую кнопку мыши, частично генерировать
    код. Но это какая-то абстрактная говнокод-фабрика получится. И лапша из перевызова методов не распутается, пусть даже готовиться эта лапша будет
    быстро.
    Думал, вместо внедрения контроллеров в модель, пронаследовать моделью все эти контроллеры и спокойно вызывать методы. Но 4 предка у одного
    класса показалось мне диковатым.
    У меня ощущение, что я как ооп-обезъяна забил трюм ненужными классами и потонул. Может не нужно было явно выносить model, view, presenter
    в классы? Может не нужно было делать классы для контроллеров, а сделать процедуры в отдельном файле? Слишком много "может".
    Я доделал это. Оно злобно рычит, но работает. Но я не хочу каждый раз так задрачивать кнтрлц/кнтрлв. Любой фидбек поможет.
    Заранее спасибо. Прикрепляю заголовочники упомянутых классов, сколько влезет.
    // абстрактный класс, родитель для любого интерфейса
    class UserInterface : public QObject
    {
        Q_OBJECT
    public:
        UserInterface();
        // методы для обновления интерфейса
        virtual void update(данные для обновления интерфейса) = 0;
        // далее куча подобных методов
    
    // сигналы сообщают Presenter-у, что произошли изменения в интерфейсе и передают данные от пользователя на дальнейшую обработку
    signals:
        void addStudSIG(StudentData newStudent);
        // далее куча сигналов
    };
    
    // назвал presenter чертом
    class Daemon : public QObject
    {
        Q_OBJECT
    
    public:
        // подписаться на все события (сигналы) интерфейса пользователя, запомнить указатели на представление и модель
        void listen(UserInterface *uI, Owl *o);
    
    // чтобы узнать, что делает слот, смотри одноимённые сигналы UserInterface
    public slots:
        void getStudsByGradeSLOT(qint32 grade);
        // далее куча слотов
    
    private:
        // указатель на интерфейс
        UserInterface *uI_;
        // указатель на модель (бизнес-логику)
        Owl *o_;
    
        // прихуярить все сигналы uI к слотам Daemon
        void connectSiWithSl_(UserInterface *uI);
    };
    
    // это "модель"
    class Owl
    {
    public:
        Owl();
        ~Owl();
    
        void addStud(StudentData s);
        // далее все возможные преобразования над бд, owl получился что-то вроде фасада над конкретными контроллерами
    
        // создание бд, открытие и закрытие соединения
        void initDb_();
        void close_();
    private:
        // контроллер, отвечающий за создание бд и открытие, закрытие соединения...
        BasicDquestDbController bController_;
        StudentController sController_;
        // далее по контроллеру на каждую сущность базы данных
    };

    Ахой, матросня! Сегодня с вами капитан Кьют и мы будем бороздить просторы говноморей в поисках код-ревью. Пишу сейчас проектец на Qt. Нас на палубе 2 говнокодера. И я близок к тому, чтобы килевать самого себя. У кого есть время и желание, жду от них совета, а те, кто не захочет помочь, сможет поугарать над начинающей c++ макакой.
    В двух словах о проекте: несложное приложение, работает с локальной бд на SQLite через ормку какого-то случайного азиата с гитхаба, интефейс на Qt-шных формах. Архитектурно попытался изобразить MVP. Почему его? Интерфейс нужно было отделить от всего остального. Разработка интерфейса выделилась в отдельную, сложную (и, вроде бы, интересную) задачу. Ею занимаюсь не я. Я отвечаю за "presenter" и "model". Наверное, можно это назвать бекендом. И, чтобы каждый раз не тратить несколько минут на сборку проекта, (все эти ебучие виджеты) я имею заглушку интерфейса. Так вот, братва, я где-то проебался. Нахуярил классов и проебался. Заметил за собой, что при добавлении каждой новой фичи (при готовом скелете архитектуры) снова и снова копирую и вставляю одноимённые функции в одноимённые функции...

    Запостил: PascalOverlord, 24 Января 2017

    Комментарии (66) RSS

    • Во-первых, зачем ты используешь устаревший синтаксис сигналов и слотов? Новый и на лямбды, и на не-слоты/не-методы-QObject-derived-класса замкнется.
      Во-вторых, для реализации моделей в Qt есть несколько классов-моделей QAbstract*Model. Наследуйся, переопределяй методы, получай модель, выхлоп которой тривиально подается в различные виджеты и QML - компоненты.
      В-третьих, ты уверен, что со всеми этими интерфейсами ты сэкономил время?
      Ответить
      • Спасибо за ответ, дядя Antervis.
        * Это мой второй проект на Qt. Сейчас я им пользуюсь неуверенно и, как видишь, быдлокожу немного (много).
        Я пользуюсь Qt 5.6. Либо там ещё не поддерживается новый синтаксис сигналов и слотов, либо я не в ту сторону читал документацию. Поищу инфу про новый синтаксис.
        * Про модели в Qt не знал. Потому и понаделал своих моделей. Пойду смотреть про упомянутые классы.
        * Вот именно, что не сэкономил. Я потратил кучу времени на то, чтобы их сделать. И пусть, они и удовлетворяют каким-нибудь требованиям инкапсуляции и отделения, расширять их очень заёбно.
        Пойду, короче, дальше курить документацию. Теперь хотя бы знаю, что искать, спасибо.
        Ответить
        • > PascalOverlord
          > Qt
          но зачем? собрался на пердоликсе запускать?
          Ответить
          • Ну не крестобилдер и мфц же юзать...
            Ответить
            • ну если ты собрался пилица только под винду то трольтехника это немного оверхед, нет?
              Ответить
              • Что значит "трольтехника"? Извините, я просто с Уфы.
                Ответить
                • TrollTech
                  Ответить
                • trolltech сделали кутэ. потом их купила нокия, потом кутэ выкупила еще какая-то шарага - пустили по рукам в общем. теперь кутэ потаскана жизнью, как портовая блядь.
                  Ответить
                  • за то на куте были написаны Кеды!

                    ну и вообще там же своя атмосфера
                    свои API для всего
                    свой QML или как там его
                    Ответить
                  • Ей хотя бы атласный бант на шею выдали за выслугу лет?
                    Ответить
                  • > теперь кутэ потаскана жизнью, как портовая блядь.
                    а ты не завидуй
                    Ответить
            • какой крестобилдер, какой мфц
              на календаре сейчас 2017 год, проверь
              Ответить
              • Крестобилдер 10.1 ‘Berlin’ и MFC 14.0, очевидно же.
                Ответить
                • да, но нет

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

                  Всякую годную рожь на MVC с нормальными абстракциями, ОРМ, DI, нормальным UI под шиндошс нужно писать на WPF (особо упоротые могут теребонькать UWP), а сишарп даже JS-питушок учит за месяц в достаточном объеме - принципы фронта то одинаковые, если ты не пыхоимбецил
                  Ответить
                  • >>Всякую годную рожь на MVC
                    MVVM же;) В WPF все про него говорят.
                    Ответить
                  • Как же, блядь, тяжело понимать, что вы все тут пишете, но я справился.
                    Если пишешь под винду, то всё, кроме сишарпа есть извращение, ты считаешь? А кьют не стоит трогать, если прога не кросплатформенная? Наверное, учту.
                    И спасибо за ответы.
                    Ну и что, что паскаль-оверлорд. Я мог хоть SuperAssassin1999 назваться, прогать от
                    этого я лучше бы не стал.
                    Ответить
                    • Всё просто:

                      1) Под винду если можно писать на сишарпе, то лучше писать на сишарпе
                      2) Если можно делать гуи на WPF, то лучше делать их на WPF
                      Ответить
                      • Лучше все же на "PHP" и "DevelStudio".
                        Ответить
                        • А почему не на дельфи?

                          Вообще можно написать веб-приложение под виндуос на дельфи чтобы там была SQL инъекция как на пхп?

                          ps: блядь, они реально написали CGI на делфьи
                          http://www.codenet.ru/progr/delphi/stat/webd.php
                          Ответить
                        • Почему лучше? Зачем мне трогать пхп, когда есть сишарп?
                          Ответить
                          • пхп не стоило бы трогать даже в том случае, если бы C# не существовало
                            Ответить
                      • Резонно...
                        Спасибо.
                        Ответить
                        • Вообще всегда выбирай самый выскоуровневый инструмент (язык) из всех возможных для решения задачи.
                          Ответить
                          • Почему? Чтобы не писать велосипедов?
                            Просто, когда в жизни написал 1.5 программы, выбор инструментов больше наудачу происходит.
                            Ответить
                            • да, чтобы не писать велосипедов и чтобы получать бенефиты от более лаконичной записи и более безопасных языков

                              с другой стороны изучать С++ тоже полезно
                              Ответить
                              • > изучать С++ тоже полезно
                                Если с qt, то не факт.
                                Ответить
                              • Qt != C++
                                Я же не пользуюсь stl. Я даже вместо int пишу qint32; это, вроде, дефайн int, но гипотетический qt погроммист и строчки на чистых плюсах не напишет.
                                О, господин Хуесто то же самое говорит.
                                О, господин Хуесто исчез.
                                Ответить
                                • там есть свои приколы. Например, QVector не может работать с move-only объектами, а copy-on-write может инвалидировать итераторы/указатели.

                                  п.с. зачем писать qint32 когда можно писать через стандартный int32_t? Во-первых, сразу наглядно видно, где важен фиксированный размер поля, во-вторых, переводить с Qt на чистые плюсы может быть проще (да, бывают такие задачи)
                                  Ответить
                              • Я с такой целью (изучения плюсов или другого "системного" языка), кстати, хотел сделать рогалик с текстовой графикой. Почти с нуля. Чтобы обосраться. Поковырять классику этих игор, почитать про генерацию уровней и сделать что-нибудь своё. Можно будет потом загнать как диплом, в моей шараге.
                                Я слышал ещё про Руст. По мощности близок с крестам, но не стреляет по ногам. Этот проект пока на стадии размышлений...
                                Ответить
                              • Спасибо за консультацию.
                                Ответить
                      • Стандартный компилятор сишарпа генерирует ненативный код. Это потеря пирфоманса.
                        Ответить
                        • Тем не менее он на порядок будет быстрее UI твоего веб-приложения (сайта) в браузере.
                          И если уж тормозит 2д гуй, то что говорить о качестве бизнес-функций этого софта на данной машине.

                          Ну а случаи разные бывают.
                          Так-то у нас есть заказчик, который не может соскочить с "документооборота" на Лексикон.
                          Ответить
                        • >> пирфо

                          Евангелисты от MS говорят: ".net джитица под конкретный CPU и работает более быстро, чем натиывный код под дженерик 686"

                          зы: кстати, если тормозит то надо посцать на GDI и юзать Direct2D.
                          Он умеет рисовать прямо в GPU
                          Ответить
                          • В теории джит может и оптимизировать лучше на основе реального профиля работы, чем компилятор. А еще сборщик мусора в теории может быть дешевле традиционной кучи (не по памяти, конечно).
                            Ответить
                            • я тоже слышал историю о том, что выделение памяти в managed средах очень дешевое (ни о чем не надо думать -- просто нарезал кусок и всё), а GC может и вовсе никогда не настать
                              Ответить
                              • Да и сборка мусора может оказаться дешевле, чем возвращение всего этого мусора в обычную кучу (особенно если мусора при сборке больше, чем живых объектов).
                                Ответить
                                • >>(особенно если мусора при сборке больше, чем живых объектов).
                                  ради этого и задумали поколения, тащемто
                                  Ответить
                            • А на практике я выключил службу NGEN, потому что при запущенной службе всё тормозило.

                              Включи NGEN
                              @
                              Почувствуй себя гентушником, вечно собирая «нативные образы».
                              Ответить
                              • а есть утилита типа ngen.exe которая генерит нативный код сразу же из clr потребованию
                                Ответить
                • Опечатался. Конечно же MFC 15.0 (Release Candidat). Сейчас же 2017.
                  Ответить
                  • А что это вообще за звери такие?
                    Ответить
                    • C++ обертки вокруг Win32API.
                      Ответить
                      • Кстати, у MFC есть кроссплатформенный клон — wxWidgets.
                        Ответить
                        • И у нас даже был неудачный опыт по использованию этого куска говна.
                          Хотя задачи то решались так се, простецкие. Кнопочки с надписями и рисунками, текстовое поле.
                          Последней каплей стали анальные проблемы с обработкой 150%, 200% и прочего масштабирования в винде.
                          В итоге переписав целиком тот модуль на кутэ вышло экономнее, чем продолжать ебаться с wxwidgets.
                          Ответить
                          • @inkarus#a0a0a0, @d++ и вообще @everyone
                            когда и если обожжетесь о qtquick - расскажете, хорошо?
                            Ответить
                            • > qtquick
                              Ну оно же совсем не для энтерпрайзной опердени...

                              А няшная хуйня с кастомным дизайном на нём неплохо лепится. Мне понравилось.
                              Ответить
                            • > @#defec8
                              Оконный С++ это в принципе та ещё клоака. В кутэ нырять - только в погоне за кросс-платформенностью помноженной на обязательность нативного толстого приложения. Таких задач, откровенно говоря, маловато попадается (и слава богу). У нас всего 1 (один) проект, где такое интересно, да и то он внутренний. (Могу по секрету сказать, что это вообще Браузер (oh shi), и там кутэ нужно только так, организовать нескучную примитивную оболочку над CEF под основные оси - менюбар, онскрин кейборд, табы).

                              В остальном достаточная ынтерпрайзная кросс-платформенность достигается SPA веб-приложениями, которые тупо и неприхотливо работают в любом современном браузере под любой ОС, плюс заодно мобильные девайсы. Мы там даже 3d на webgl успешно применяли. При этом, такие приложения не надо даже деплоить и сопровождать/обновлять на клиентских устройствах - клиент всегда получает последнюю версию для использования, что очень заебись и экономит дохуя денег и нервов.

                              Толстое приложение само по себе редко требуется - у нас есть и такие проекты. Спасает то, что понятно, что приложение будет работать вот конкретно в шиндошс, и даже можно некие требования наложить на современность этого шиндошс. Тогда, конечно, WPF, нехер думать. Но тут, конечно, и все недостатки толстого приложения, не только достоинства.

                              Ну и касательно qtquick - годно, это вообще правильная тема разделять представление от данных. В том же WPF или Xamarin приличная доля проекта - разметка вьюх на XAML. Если ты всё ещё в раздумьях учить/юзать или нет - тут других мнений быть не может, конечно брать.
                              Ответить
                              • Ого, не ожидал такой большой и подробный ответ. Однако, спасибо. Видимо, мало кто делал что-то серьёзное с QtQuick.

                                > в погоне за кросс-платформенностью
                                Именно за кроссплатформенность и взяли Qt. В военку понемногу внедряют линукс в виде эльбруса, astra, МСВС (упаси Аллах), QNX Neutrino и у начальства появляются охуи восхитительные идеи: "А давайте скомпилируем наше нечто на очередной порезанный военный линукс".
                                Больше всего приложения похожи на встроенные, запускающиеся в киоск-режиме; некритичные элементы систем могут снабжаться акустическими сенсорными дисплеями, поэтому пилить интерфейсы на QtQuick выглядит более логичным, чем на виджетах.
                                Однако, сколько я ни пытался нырнуть в эту прорубь, все попытки заканчиваются тем, что я погружаю пальчики задней лапы и валю обратно в виджеты.

                                > правильная тема разделять представление от данных
                                QML и QtQuick с той же мыслью рекламируются - отделение представления от данных и программиста от дизайнера. И сделано прокидывание нативного кода в QML весьма удобно, но стоит отойти от примеров - появляются проблемы. Нужно прокинуть список объектов из C++ в QML? Пиши прокси-модель. Редактировать элементы списка в удобной формочке? Дописывай обвязку на JavaScript в сотни строк, ищи узкие места, чтобы интерфейс не тормозил и не прыгал. Таблицы? У QtQuick их не было до недавних пор, всё сырое. Наследовать стандартный контрол тоже нельзя по причине приватности их C++ классов. Документация разрозненная, версионирование упоротое. Это всё мелочи, но из них складывается впечатление эскизного проекта кучки недавних студентов, который почему-то продают уже шесть лет.

                                > Если ты всё ещё в раздумьях <...> конечно брать
                                Я, конечно, ещё погуляю по граблям и шишек понабиваю, быть может, я просто лошара и не понял сути QtQuick, но сомнения пока что придержу у себя.
                                Ответить
                                • >> отделение представления от данных и программиста от дизайнера

                                  Мне кажется это уже везде так. Гуи надо писать декларативно, причем лучше даже так, чтобы был отдельный инструмент (blend, например).

                                  Даже для свинга есть формбилдеры у интеллиджа.
                                  Ответить
                                • Как же хорошо, что я не пишу все эти гуи.
                                  Ответить
                                  • тоже ненавижу гуи, да) но всё таки верстать их в чем-то XMLе подобном (как в впф, вебе или андроиде) или хотя-бы в человечком редакторе (Как interface builder в xcode) в разы приятнее чем собирать императивно.
                                    Ответить
                                    • кстати, вот когда появился QObject::connect сигналов на лямбды, мне стало проще и быстрее писать на QWidget'ах императивно, чем натыкивать в формочках.
                                      Ответить
                                • > Нужно прокинуть список объектов из C++ в QML? Пиши прокси-модель.
                                  Необязательно. Можно прокинуть QVariantList вручную, можно сделать Q_PROPERTY типа QVariantList (очень прикольная тема кстати - вьюхи могут вместо модели принимать QList объектов и работать так же), еще забыл как, но можно сделать проперти типа "список объектов с пропертями".

                                  > Редактировать элементы списка в удобной формочке?
                                  А ты в QAbstractItemModel::setData не заглядывал?

                                  У меня сейчас один из проектов достаточно крупный, с огромной долей интерфейса на QML. Пока что мой вердикт - QML ОЧЕНЬ хорош, если знать, как им правильно пользоваться. Лично я "стукнулся" только об одну фигню: QML Map не умеет вращаться, причем судя по исходникам, эту фичу убрали, потому что не знали как поддерживать её с тайлами
                                  Ответить
                                  • > можно сделать проперти типа "список объектов с пропертями"
                                    Модели добавляется свойство типа QQmlListProperty, которое подключается моделью к списку. Это выглядит как хорошее решение для неизменяемых списков, если же начать добавлять, удалять или перемещать элементы списка, то нужно сообщать об этом вьюхе сигналом NOTIFY listChanged, при этом у списка теряется выделение элементов, скролл и он полностью перерисовывается. Это вообще не вариант.

                                    > А ты в QAbstractItemModel::setData не заглядывал?
                                    Заглядывал. Чтобы получить от ListView вменяемое поведение при каких-либо изменениях крестовой модели, к нему нужно подключать QAbstractItemModel. Сам ListView в реализации не подключает к себе модели напрямую, а использует недокументированный класс посредника (QQuickItemModel, вроде), который отображает сигналы QAbstractItemModel::rowsMoved и другие в понятные вьюхе события. Это выглядит как лучший способ прокидывания модели в QML, для которого нужно писать портянку switch(role) { case case case case case } в пяти местах, что совсем не привлекает.

                                    > мой вердикт - QML ОЧЕНЬ хорош
                                    Мне он тоже нравится, собственно потому и продолжаю жрать кактус и пытаться обходить подводные камни.
                                    Ответить
                                    • > для которого нужно писать портянку switch(role) { case case case case case } в пяти местах, что совсем не привлекает.

                                      Значит, ты не настолько тривиальную вещь хочешь сделать, чтобы можно было обойтись без с++-модели
                                      Ответить
                        • Уж лучше Qt, чем это говнище.
                          Ответить
    • кутэ - говно
      /тхреад
      Ответить
    • m_studs.append(stud);
      qStableSort(m_studs);
      owl.who();
      Ответить
    • Но при всем этом в Qt есть implicitly-shared containers with copy-on-write. А в высокоуровневом C# контейнеры по умолчанию передаются по ссылке, которая еще зачем-то может быть null.
      Ответить
      • > implicitly-shared containers with copy-on-write
        Как будто это что-то хорошее
        Ответить
      • Потому что обьекты иам сегда по ссылке, не?
        Ответить
    • Заворачиваешь все в лямбды - создание гуя, конект слотов и все-все-все в 1 месте внутри метода, сами слоты - лямбды (не забываеш время жизни, поинтеры идут через QPointer копированием + проверкой внутри тела, например). Получается громадный метод строк на 120, который делает и настраивает все в 1 месте. На выходе из него какой-нить интерфейсный указатель с нужными методами - добавить/поделить. Удалил указатель - весь гуй с ним туда же ушел. Если наберется много одинаковых кусков - их в предков/макросы (локальные в этом же СРР)/шаблоны (тоже можно локальненько). Результат - все в 1 месте и сильно запрятано, минус - длинный код листать.
      Ответить
    • C# + WPF (UWP) это круть крутая для винды но с появлением Electron (software framework) + Node.js WPF уйдет в небытие так же как и пришел от тудава :)
      Ответить

    Добавить комментарий