views:

662

answers:

5

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 popluate this information. So my questions are twofold:

  1. 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 contrrscutors now. One that poplates the data and one that does not.
  2. 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.

A: 

there are existing tools that reverse db's into java (and probably other languages). consider using one of them and converting that to c++.

A: 

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.

AlexCuse
+1  A: 

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.

bmdhacks
Yeah, I've seen a few (sql2class) being one of them. I hadn't really considered and Active Record or ORM, but that is a possibility, I suppose.
+1  A: 

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.
JohnMcG
I agree 100% about the db trips. The caveat is that there will be muliple execulables using these classes and a lot data would be uncessarily popluated. That's where I start to scratch my head. Most of it will be read only access.
I should clarify that by saying different executables will be using a class for different subsets of fields (columns in the db). Thanks for your reply.
I would still say that unless we're talking about very complex or big data types (like a 2MB CLOB), the cost of multiple database hits is going to eclipse the cost of populating data you won't need pretty quickly.
JohnMcG
A: 

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.

JohnMcG