While outlining the post, I was uncertain what to call the particular group of classes (or concern) now called the Controllers. If you look through the GitHub project, you'll find that at one point they were called Routers. I agree with you that this design is not a MVC by the traditional definition (i.e. Smalltalk's), however there are many variants out there, see for example Apple's https://developer.apple.com/library/archive/documentation/Ge..., that I didn't think it would hurt 'to add' another. As long as it's clearly defined what it is. But perhaps it is not clear.
In this design, the 'traditional controller' is already part of the front-end. One of the goals of this design is to keep the front-end only concerned with styling and the layout of the application, and not the logic or the flow. So from the front-end, the user-interactions will be forwarded down to the 'back-end' Controllers. Those controllers are responsible for the flow of the application. The back-end includes logic and models in the traditional sense, see for example the DocumentsModel (https://github.com/Fagrell/clean-editor/blob/master/lib/publ...), however there are also models that correspond to specific Components. Those "Model Components" contain logic and a state, e.g. the MenuModel referred to in the post.
Perhaps an even better separation would be to add another layer?
- UI front-end - View/Component layer -> includes the 'view and controller by the traditional definition'.
- Router/Controller layer -> includes Models for specific components and Routers (as Controllers are defined in the post). Defines the flow.
- Back-end layer -> includes models by the traditional definition.
The apple diagram doesn’t look too far off what quietbritishjim described though, assuming that the “updates” arrow from controller to model is the model asking for an update, but the model actually implementing the logic.
Personally, I hate the name controller because its really unclear to me what they actually do. What do they control? The actual update logic is part of the domain knowledge, so that should live in the model itself, as quietbritishjim said. Router is a better name imho (even if itself not a perfect name).
Hey buddy!
I've meant to add RSS and email to the blog but haven't got around to do it yet. Sorry...
Thanks for the reminder though, I'll see what I can do over the weekend!
Cheers, Alex
Reading that post and the comments makes me want to try out Qbs! I was vaguely aware of its being announced a few years ago, but I hadn't realised it had even become mature, let alone deprecated. Sounds like a good match for some of my gnarlier qmake-based projects. (Can't abide CMake)
This is very sad indeed, because Qbs was both well architected and well executed. Very fast and the only build system where I never had to clean the build because the build system broke itself due to bad design/assumptions (e.g. mtime checking).
Hi guys,
This is the 7th post in the series "Crash course in Qt for C++ developers." Do you structure and architect your application in a similar way? Let me know what you think and I would appreciate if you have any feedback.
Can you say a little bit about what makes it great? Is it just a well designed wrapper? Super easy to use? Good documentation? More mature than Rusts Qt bindings?
Personally, I like Qt a lot more than GTK (both as a programmer and a user), but to each their own. QtQuick/QML is really great way of quickly whipping together complex UI’s. I’ve never used Qt on Rust though.
Hopefully my experience could be useful, having tried rust-qt just a while ago on a project. Bottom line: it is usable.
It is pretty trivial if you want to build an almost purely QML app. As soon as you want to do some C++ stuff (e.g. registering new C++ classes, using QtWidgets), however, things go south very quickly. The main problem is that Qt has its own ideas about ownership (QObject-parent-stuff), and Rust really does not like that. You end of working a lot with raw pointers and boxes. It feels like you’re writing C++ but in Rust (if that makes sense).
Rust-qt is really nice IMO, and I would extremely encourage anyone interested to take a look, and provide more feedbacks and contributions to the maintainers (I am not one of them). Some non-trivial examples would help a lot. But expect sharp edges.
I have virtually no experience with Qt (as a developer). That said, I find the gtk-rs bindings good and easy to use in rust. They are automatically generated from C code, and as the generator matures the bindings come more and more complete. Tho' some of the bindings are manually written. AFAIK Gtk has QML counter part, but I haven't used that either.
The documentation isn't perfect but its _really_ easy to map the documentation of the bindings to the original C documentation. From quick glance the situation seems to be more or less (maybe a bit less) the same with python bindings for Gtk.
I'm developing a few hobby projects with Qt and Rust. The Rust Qt Binding Generator I developed for that works so well for me that I've barely needed to improve it in months.
The JSON glue could be changed to Rust macros, but I've not found the time to do that. It's a bit ugly but free and works for me on Linux and I've had reports of success on Raspberry Pi and Windows.
If it fails to build on Mac OS, I'd like to see why and help. The latest version uses Cargo for building, so e.g.
`cargo qrep && qrep` should give you a working Rust + Qt example application.
Hey there! Thanks, great comment. I'm considering rearranging the topics when it's finished.
My thinking was that the event loop is one of the first thing that you'll encounter, i.e. app.exec() in main, when using Qt. The fact that the flow of the app is event-driven is important to understand when working with a GUI toolkit and thought it would be good to introduce early on (even though you rarely use the actual event system itself). Perhaps not as a first topic though.
Yeah, I realised that it shouldn't be Shown HN, but can't find a way to edit it, thanks.
Yeah, geezerjay has it right. For a new programmer trying to get a "crash course" in Qt, app.exec() is a black box you don't really need to mess with.
You can explain that it drives all the mouse, keyboard, and QTimer signals when you begin to implement the event slots on your widgets, but as far as getting an app to run it's a matter of calling app.exec() and leaving it alone.
Thanks, very true. Several people have pointed this out so I'm convinced I'll have to rearrange the order. Perhaps just start with a simple example and move the event loop/handling after Widgets/QML. I believe I'll also have to split Widgets and QML into two separate posts as those are big subjects.
Just to complement my comment on Qt's event system, one place where it does play a central role in Qt's mental model is in Qt's concurrency framework. When covering that subject, the event loop and the different connection types are fundamental to understand how QObjects automagically communicate between themselves with Qt's signal-slots framework even when residing in different threads, or how Qt supports concurrency without requiring stuff to run on a separate thread.
While outlining the post, I was uncertain what to call the particular group of classes (or concern) now called the Controllers. If you look through the GitHub project, you'll find that at one point they were called Routers. I agree with you that this design is not a MVC by the traditional definition (i.e. Smalltalk's), however there are many variants out there, see for example Apple's https://developer.apple.com/library/archive/documentation/Ge..., that I didn't think it would hurt 'to add' another. As long as it's clearly defined what it is. But perhaps it is not clear.
In this design, the 'traditional controller' is already part of the front-end. One of the goals of this design is to keep the front-end only concerned with styling and the layout of the application, and not the logic or the flow. So from the front-end, the user-interactions will be forwarded down to the 'back-end' Controllers. Those controllers are responsible for the flow of the application. The back-end includes logic and models in the traditional sense, see for example the DocumentsModel (https://github.com/Fagrell/clean-editor/blob/master/lib/publ...), however there are also models that correspond to specific Components. Those "Model Components" contain logic and a state, e.g. the MenuModel referred to in the post.
Perhaps an even better separation would be to add another layer?
- UI front-end - View/Component layer -> includes the 'view and controller by the traditional definition'.
- Router/Controller layer -> includes Models for specific components and Routers (as Controllers are defined in the post). Defines the flow.
- Back-end layer -> includes models by the traditional definition.
Thoughts?