2017-10-04 9:50 GMT+02:00 Eike Ziller <[email protected]>: > >> On 2. Oct 2017, at 09:29, Elvis Stansvik <[email protected]> wrote: >> >> 2017-09-11 10:00 GMT+02:00 Elvis Stansvik <[email protected]>: >>> 2017-09-11 9:50 GMT+02:00 Eike Ziller <[email protected]>: >>>> >>>>> On Sep 11, 2017, at 09:24, Elvis Stansvik <[email protected]> wrote: >>>>> >>>>> 2017-09-10 11:31 GMT+02:00 Elvis Stansvik <[email protected]>: >>>>>> 2017-09-10 11:03 GMT+02:00 Elvis Stansvik <[email protected]>: >>>>>>> Hi all, >>>>>>> >>>>>>> In a quest to find inspiration for good Qt application architectures, >>>>>>> I've been looking at the plugin based one you're using in Qt Creator. >>>>>>> It strikes me as a really nice design. >>>>>>> >>>>>>> I've been reading the available docs on it, and dug into the code a >>>>>>> bit. This may be a bit much to ask, but I was wondering if any of you >>>>>>> devs could answer a few questions that popped up? It would be much >>>>>>> appreciated! >>>>>>> >>>>>>> It's really just two questions, about two different topics: >>>>>>> >>>>>>> 1. The Invoker / invoke<...> Thingie: >>>>>>> >>>>>>> You have ExtensionSystem::Invoker and the associated invoke<..> >>>>>>> helper, which are syntactic sugar for achieving "soft" extension >>>>>>> points. It seems it's not used that much (?). I grepped for >>>>>>> "Invoker|invoke<" in the code and could only find a few uses of it. I >>>>>>> also grepped for "invokeMethod" to see if the approach was being used >>>>>>> "manually" so to speak (without the sugar), and found a few more hits. >>>>>>> >>>>>>> What was the motivation for adding this? I assume it's for cases where >>>>>>> you want a looser coupling between plugins (no linking, no shared >>>>>>> header), but can you give an example of when you really wanted that >>>>>>> looser coupling and why? >>>>>>> >>>>>>> 2. The Plugin System in General: >>>>>>> >>>>>>> Is there anything about the plugin system in its current form, or how >>>>>>> it is used, that you would do fundamentally different if you could do >>>>>>> it all over again? Any areas that you find messy/awkward, that need a >>>>>>> re-think/makeover? In short: What are the biggest warts in the code in >>>>>>> your opinion? >>>>>> >>>>>> As soon as I hit send, I realized I have a third question: >>>>>> >>>>>> 3. Communication Between Plugins: >>>>>> >>>>>> There seems to be two main mechanisms through which plugins >>>>>> communicate: Either objects that implement shared interfaces are added >>>>>> to the plugin manager object pool and picked up by downstream or >>>>>> upstream plugins (in the top-down or bottom-up phase of plugin >>>>>> initialization, respectively), or a singleton instance is acquired and >>>>>> calls made on it. >>>>>> >>>>>> Is the former approach used when dependants provide functionality to >>>>>> their dependees (which are unknown), and the latter approach used when >>>>>> dependees use their dependants (which are known)? Is that the deciding >>>>>> factor? >>>>> >>>>> And finally, a couple of more down-to-earth questions: >>>>> >>>>> 1. ICore, the class is concrete, so why the I in the name? Was it >>>>> abstract at one point? >>>> >>>> Yes historically. >>>> >>>>> How do you decide whether a class should get >>>>> the interface 'I' in its name? >>>> >>>> It’s a mess ;) >>>> I suppose the trend goes to not prepend the ‘I’. >>> >>> Ok, I figured there was a history :) >>> >>>> >>>>> The same with e.g. IContext, though >>>>> that one at least has a few virtuals and is used as a base class (but >>>>> no pure ones AFAICS, so still concrete). >>>> >>>> Historically these classes where “pure” virtual (except for the QObject >>>> base). >>>> We moved to a more “configurable” approach then to avoid the need to >>>> create subclasses for every little thing, while keeping the option open in >>>> many cases. >>> >>> Alright, this is what I suspected. Thanks for confirming. >>> >>>> >>>>> 2. The relatively liberal use of singleton classes. We all know that >>>>> is a debated subject, and I don't have an opinion either way. I'm just >>>>> interested in if you have some (spoken or unspoken) policy regarding >>>>> singletons in the project. Do you want to minimize the use of them, or >>>>> is it OK for newer code, or is it judged on a case-by-case basis? Have >>>>> you had any moments where you really wish you hadn't used singletons? >>>>> (e.g. I know it can sometimes hurt testability). >>>> >>>> We always had a liberal amount of singletons in Qt Creator, and we even >>>> moved most of them to be classes with mostly static methods a while ago. >>>> There are no plans to move away from that. If you have a central hub for >>>> “managing” something, feel free to use a singleton/static methods. >> >> Getting back to this semi-old thread with another question if that's OK: >> >> Did the liberal use of singletons never get in the way of >> testability/mockability? Was there ever a moment when you though "o >> boy, I wish this thing didn't reach out to so many static things" >> while writing tests? If so, did you find a way to deal with that, or >> is it always just a compromise? > > We use a whole lot of different testing methods which allow a different > amount of integration between parts, and also developers usually only add > tests where they think their usefulness outweigh the effort involved > implementing them. > Also, different people in the project weigh the importance of tests > differently, so you’ll probably get different answers from different > developers. > > - Auto tests: Standalone in tests/auto/... . This is where access to global > state hurts most, and where UI is not great to test either. For auto tests > you have to separate the individual functionality from “connecting > everything” anyhow though. The global state often falls into that latter > part, and with Qt’s signals and slots the separation can be done through > that. E.g. for a new “advanced search” filter, you need to access global > state to create a search result panel, adding search results there and > reacting on user input through it. Testing the actual search, given a set of > parameters is easy by simply separating that and using signals to report > results.
Ah, that is true, provided you are careful to separate the "hooking everything" up part. > It is hard to test e.g. if repeating a search works correctly when the > “search again” button is pressed, with this approach. Note that since > basically all code of Qt Creator is in libraries, these can also be used in > auto tests. > > - Plugin tests: Can be triggered by running qtcreator -test MyPlugin. Plugins > can have test methods which are then run _within_ Qt Creator after Qt Creator > startup. This makes it possible to test functionality that integrates > different parts / where global state is essential for the functionality. Its > e.g. possible to load a project and throw your new advanced search filter on > the project, and repeat a search. Or open a project, wait for parsing to > finish, open a specific file, move the cursor to a location, trigger “follow > symbol” and check the resulting location. > > - Automated UI tests: Using Squish. Starts Qt Creator and simulates e.g. > button presses by finding the buttons through the widget hierarchy, object > names, etc. Used by a small number of QA dedicated people for automated tests > in the style of “create new Qt Widget project, build & run, and check the > state afterwards”. Thanks a lot for sharing your approach to testing. I guess any project using a plugin based architecture needs to think about how to test the plugins in the context of the application. I saw your `qtcreator -test` approach earlier, but I think I'll have a little closer look now. In conclusion, I guess thorough testing is hard, as it always has been :) Elvis > > Br, Eike > >> I'm asking because in my current project, I'm trying to think about >> testability, using mocks where it makes sense, and one thing that >> really hurts testing in isolation is when code simply reaches out for >> something global (like a static instance/helper). >> >> Elvis >> >>> >>> Okay. I also personally think the convenience of singletons outweighs >>> their drawbacks in many cases. Nice to see this liberating attitude. >>> >>> Thanks for sharing Eike. >>> >>> Elvis >>> >>>> >>>> Br, Eike >>>> >>>> -- >>>> Eike Ziller >>>> Principal Software Engineer >>>> >>>> The Qt Company GmbH >>>> Rudower Chaussee 13 >>>> D-12489 Berlin >>>> [email protected] >>>> http://qt.io >>>> Geschäftsführer: Mika Pälsi, >>>> Juha Varelius, Mika Harjuaho >>>> Sitz der Gesellschaft: Berlin, Registergericht: Amtsgericht >>>> Charlottenburg, HRB 144331 B > _______________________________________________ Qt-creator mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/qt-creator
