Let's suppose I'm developing a small movie database. In dynamic language like python I'd write:
db = ConnectionFactory.get_connection(db_name) # (1) Create database connection
model = MovieModel(db) # (2) object-to-relational mapper
star_wars = Movie("Star Wars", ...)
model.store(star_wars) # (3) Save object
et = model.fetch("E.T.") # (4) Retrieve one object
movies = model.fetch_all() # (5) Retrieve all objects
When translating this to C++, problem arises how to pass objects around: by value, by reference, by plain-old-pointers, or by one of a few smart pointers.
Line 1 incorporates an Abstract Factory, which returns subclass of some base class, so returning a pointer is necessary here. Question is, what kind of pointer should be returned? std::unique_ptr
seems a good fit.
In line 2 MovieModel
is constructed, which takes a database connection as argument and stores it for future use. As one connection could be shared between one or more Models, database connection should be passed and stored as std::shared_ptr
, I presume. But then, should I convert std::unique_ptr
created by ConnectionFactory
to shared_ptr
or modify ConnectionFactory
to return shared_ptr
?
In line 3, an object being stored in database. As Movie
is simple "data" class, it should be passed by value, or better, by const reference. That's simple, but in line 4 another object is retrieved. Since Movie
has "value" semantics, returning by value seems natural. But what happens when particular movie is not found? Is it better to throw an exception, or change return type to smart pointer and return a nullptr
in that case?
Last, a collection of objects is returned. Is it better to return a container (e.g, std::vector
) of objects, or container of (smart)pointers. In latter case, which pointers?