QWizard: QWizardPage::registerField vs shared object pointer - c++

Looking at the Qt doc, the correct way to handle with objects shared between pages is to use QWizardPage::registerField and QWizardPage::field.
I personally think is more simple, since we are under C++, to pass to the QWizardPage(s), in their constructors, a pointer to my shared object, since there's no risk on cuncurrent access on the shared resource. Every QWizardPage change the value of that object safely and it's shared between pages because the pointer location is the same.
What am I missing? Why the need of such methods?

They are different approaches:
With a shared pointer you need a member for each object you want to share, which means you need to change the interface of your classes.
With the field-API you don't change the interface, but it is then not defined in the interface what fields exist. This means you should document them separately. This seems to me is the better way when having a multitude of fields.
Also note the automatic validation by the wizard:
If an asterisk (*) is appended to the name when the property is registered, the field is a mandatory field. When a page has mandatory fields, the Next and/or Finish buttons are enabled only when all mandatory fields are filled.
To consider a field "filled", QWizard simply checks that the field's current value doesn't equal the original value (the value it had when initializePage() was called). For QLineEdit and QAbstractSpinBox subclasses, QWizard also checks that hasAcceptableInput() returns true, to honor any validator or mask.
As you see: it's mainly a convenience feature. And it might save you from recompiling lots of stuff when working with bigger projects.
As you see: it's mainly a convenience feature. And it might save you from recompiling lots of stuff when working with bigger projects.

Related

How to partly initialize c++ objects when I don't need all values from the database?

I’m trying to cut down on the amount of network queries in my c++ program (to increase speed), and when displaying search results, I don’t want each (of the sometimes thousands) of objects found in the search to initialize themselves completely from the database when I only need to display part of this information.
It is much faster to perform one bigger query where I get all the information I want to display about the objects at once in the query (for example, for each object/row I select the id, the name and the location), passing them to a bigger constructor, and letting all other members be default values. Previously, and in other cases where I need the complete object, I just pass the ID to the object, then call initializeFromDatabase() directly to set all the other values.
//current solution (problem is, I might need many constructors like this for different purposes)
auto *myobject = new MyObject(345, "ObjectName", "Europe");
//no further (costly) initialization since I only need the following 2 values for my search results.
myobject->getName();
myobject->getLocationName();
//prevous solution (resulting in too many queries)
auto *myobject = new MyObject(345);
myobject->initializeFromDatabase();
myobject->getName();
myobject->getLocationName();
//I could also query the other 30 or so members here, everything is set.
This doesn’t feel like good practice though, I would need other custom constructors for say, another search window displaying other kinds of data about the objects.
Are there any general best practices / a suitable design pattern to solve this sort of problem? Should I create a “Search object” that is its own class and that can then be used to create the complete object when needed? Or always initialize with only the database ID (setting a flag that the object is not initialized yet) and use the setters I need?
I found that a solution to this would be to use some sort of Lazy Loading, since I want to quickly load part of the object for the list, then load all of it if a user clicks on one of the objects. For example, a Virtual Proxy or the Ghost Design pattern would be suitable. I simply create a proxy object for displaying the search results (and for other lists in the program) that can create the full object on demand. Every proxy object has one constructor so I avoid the problem of using lots of different constructors for different purposes.
See Chapter 11 of Patterns of Enterprise Application Architecture by Martin Fowler (published by Addison-Wesley Professional, 2002)

C++ Design: Pool and pointers VS client-server

I'm designing a software tool in which there's an in-memory model, and the API user can get objects of the model, query them and set values.
Since all the model's objects belong to a single model, and most operations must be recorded and tested, etc., each created object must be registered to the Model object. The Model stores all objects as std::unique_ptr since it's the only owner of them. When needed, it passes raw pointers to users.
What makes me worry is the possibility that the user calls delete on these pointers. But if I use std::shared_ptr, the user can still use get() and call delete on that. So it's not much safer.
Another option I though of is to refer to objects by a name string, or pass ObjectReference objects instead of the real objects, and then these ObjectReferences can be destroyed without affecting the actual stored object.
These References work somewhat like a client: You tell them what to do, and they forward the request to the actual object. It's a lot of extra work for the developer, but it protectes the pointers.
Should I be worried about the pointers? Until now I was using smart pointers all the time, but now I need to somehow allow the user to access objects managed by a central model, without allowing the user to delete them.
[Hmmm... maybe make the destructor private, and let only the unique_ptr have access to it through a Deleter?]
You shouldn't bother about users calling delete on your objects. It's one of those things that are perfectly fine as a documented constraint, any programmer violating that only deserves whatever problem he runs into.
If you still really want to explicitly forbid this, you could either write a lightweight facade object that your users will pass by value (but it can be lot of work depending on the number of classes you have to wrap) or, as you said, make their destructor private and have unique_ptr use a friend deleter.
I for one am not fond of working through identifiers only, this can quickly lead to performance issues because of the lookup times (even if you're using a map underneath).
Edit: Now that I think of it, there is a way in between identifiers and raw pointers/references: opaque references.
From the point of view of the users, it acts like an identifier, all they can do is copy/move/assign it or pass it to your model.
Internally, it's just a class with a private pointer to your objects. Your model being a friend of this class, it can create new instances of the opaque reference from a raw pointer (which a user can't do), and use the raw pointer to access the object without any performance loss.
Something along the lines of:
class OpaqueRef
{
// default copy/move/assignment/destructor
private:
friend class Model;
Object* m_obj;
OpaqueRef(Object& obj) : m_obj(&obj) {}
};
Still, not sure if it's worth the trouble (I stand by my first paragraph), but at least you got one more option.
Personally, I'd keep the internal pointer in the model without exposing it and provide an interface via model ids, so all operations go through the interface.
So, you could create a separate interface class that allows modification of model attributes via id. External objects would only request and store the id of the object they want to change.

Is passing a NULL Owner argument for dynamically created TComponent derived class instances OK?

I work with C++ RAD Studio and Builder 6 quite a bit and often create forms dynamically or create non-visual components dynamically when writing non-visual code. When designing forms, the Owner property of components dropped onto that form is automatically set so I have never worried about it. However, when creating anything derived from TComponent dynamically I always pass NULL as the Owner argument as I am always taking responsibilty for freeing the memory later.
Borland/Embarcadero documentation doesn't really cover what is required in the case of dynamically creating things (or maybe I have not been looking in the right places) and only seems to ever cover design time form based scenarios.
I would like to know if passing a NULL owner for dynamically created components is the right thing to do, or if it can lead to internal problems that will manifest themselves later.
Code compiles and works ok but I wonder if it is causes or potentially causes any behind the scenes problems.
It's certainly not a wrong thing to do.
Passing an owner, as you already hinted to, alleviates you from having to manage the lifetime of the object yourself. There are no hidden internal side-effects that require you to pass an owner.
FWIW: Creating/using and destroying ownerless components is not uncommon, we do it all the time.
Edit cudo's to Remy
While the components that ship with your installation are fine to use without an owner (beside some corner cases like TXMLDocument that act differently with an owner assigned) , there's always the possibility of a third party or home brew component that rely on the owner being assigned.

The Registry pattern: to use or not to use

I am considering using the Registry pattern in my application to store weak pointers to some of app's windows and panes. The general structure of the application is shown below.
The application has one MainFrame top level window with few child panes within it. There can be many of TabPane type based tabs. I need to reference the ParamsPane panel from all of my TabPane tabs, so I need a pointer to the ParamsPane object to be stored somewhere. There can be a plenty of options, but the most obvious ones are (1) to store the pointer within the Application singleton object or (2) to create a simple registry class. Something like:
class Registry {
public:
static MainApp* application;
static MainWindow* mainWindow;
};
Is this a good practice? What are the benefits and caveats of such an approach?
It depends on why you want to reference ParamsPane. I can think of two reasons and two different solutions.
You want to update data in ParamsPane because data in TabPane changed.
If this data is completely separatable from the view, what you should probably do is separate it. This means following the Model-View-Controller pattern. Both ParamsPane and TabPane instances can access the model separatly. So there is no direct reference between the two.
There is some strong link between the two, irrelevant of data.
If the previous mentioned point isn't relevant, and there is a really strong link between the two panels you could consider writing a specific TabPane class which stores a reference to a ParamsPane class.
I feel both these solutions are better than a Singleton or 'Registry' approach. Beware that I haven't heard of this pattern before, but I believe I understand its intent. More info on why global state objects (more specifically singletons) are a bad practice can be found here.
In terms of testability, it may not be a good idea to use the Registry Pattern. To repost from this article:
Unit testing is predicated on the assumption that you are testing small, discrete units of code that do not have dependencies. This requires that developers do everything they can to either remove dependencies or mock them in such a way that the dependencies are neutralized as contributors to the failure of the unit being tested. In PHP 5, objects are not copied when assigned; instead, their address in a hash table is copied. This means that if you retrieve an object from the registry, and then modify it, every subsequent retrieval from the registry will reflect that modification.
The reason this creates a significant issue is that it prevents you from testing a discrete unit of code. Now, instead of one thing being the variable in a test failure, there are two: the unit of code being tested and the object it retrieved from the registry. Any time there is more than one possibility for failure, the effectiveness of the unit testing is diminished.
Your Registry class and Singleton are OO-ways of global variables. Prefer to make the Params Pane in the MainFrame and to pass it as reference to the tab-panes.

C++ class design from database schema

I am writing a perl script to parse a mysql database schema and create C++ classes when necessary. My question is a pretty easy one, but us something I haven't really done before and don't know common practice. Any object of any of classes created will need to have "get" methods to populate this information. So my questions are twofold:
Does it make sense to call all of the get methods in the constructor so that the object has data right away? Some classes will have a lot of them, so as needed might make sense too. I have two constrcutors now. One that populates the data and one that does not.
Should I also have a another "get" method that retrieves the object's copy of the data rather that the db copy.
I could go both ways on #1 and am leaning towards yes on #2. Any advice, pointers would be much appreciated.
Ususally, the most costly part of an application is round trips to the database, so it would me much more efficient to populate all your data members from a single query than to do them one at a time, either on an as needed basis or from your constructor. Once you've paid for the round trip, you may as well get your money's worth.
Also, in general, your get* methods should be declared as const, meaning they don't change the underlying object, so having them go out to the database to populate the object would break that (which you could allow by making the member variables mutable, but that would basically defeat the purpose of const).
To break things down into concrete steps, I would recommend:
Have your constructor call a separate init() method that queries the database and populates your object's data members.
Declare your get* methods as const, and just have them return the data members.
First realize that you're re-inventing the wheel here. There are a number of decent object-relational mapping libraries for database access in just about every language. For C/C++ you might look at:
http://trac.butterfat.net/public/StactiveRecord
http://debea.net/trac
Ok, with that out of the way, you probably want to create a static method in your class called find or search which is a factory for constructing objects and selecting them from the database:
Artist MJ = Artist::Find("Michael Jackson");
MJ->set("relevant", "no");
MJ->save();
Note the save method which then takes the modified object and stores it back into the database. If you actually want to create a new record, then you'd use the new method which would instantiate an empty object:
Artist StackOverflow = Artist->new();
StackOverflow->set("relevant", "yes");
StackOverflow->save();
Note the set and get methods here just set and get the values from the object, not the database. To actually store elements in the database you'd need to use the static Find method or the object's save method.
there are existing tools that reverse db's into java (and probably other languages). consider using one of them and converting that to c++.
I would not recommend having your get methods go to the database at all, unless absolutely necessary for your particular problem. It makes for a lot more places something could go wrong, and probably a lot of unnecessary reads on your DB, and could inadvertently tie your objects to db-specific features, losing a lot of the benefits of a tiered architecture. As far as your domain model is concerned, the database does not exist.
edit - this is for #2 (obviously). For #1 I would say no, for many of the same reasons.
Another alternative would be to not automate creating the classes, and instead create separate classes that only contain the data members that individual executables are interested in, so that those classes only pull the necessary data.
Don't know how many tables we're talking about, though, so that may explode the scope of your project.