c++interface-design

Return a vector knowing it will always contain a single record in order to be consistent with the rest of the interface?


I'm writing a little address book application and have a design dilemna regarding the interface for the data source / backend.

I have the following abstract base class for data source classes:

class DataSource
{
    private:

    public:
        virtual std::auto_ptr<Contact> getContact(int id) = 0;
        virtual ContactRecordSet getAllContacts() = 0;
        virtual bool addContact(const Contact& c) = 0;
        virtual bool updateContact(int id, const Contact& c) = 0;
        virtual bool deleteContact(int id)=0;
        virtual ~DataSource() {};

};

Below is my record struct and tmy record set is a typedef to an STL vector of these objects.

class Contact 
{
    public:
        std::string firstName;
        std::string lastName;
        std::string phoneNumber;
        std::string address;
        std::string email;

};

typedef std::vector<Contact> ContactRecordSet;

My question involves the return value type used for the DataSource::getContact() method and the DataSource::getAllContacts() method and the search method to be added soon that will get records based on a query.

DataSource::getContact() will return zero or 1 records since I'm looking up by unique id. DataSource::getAllContacts() will return zero or more contacts. The upcoming search method will return zero or more contacts.

As I have it now the getContact() method is returning an auto_ptr to a Contact because it seemed wasteful to return a ContactRecordSet if I know for sure they'll never be more than one and it allows me to return NULL if there is no record that has that id.

Would it be better to for getContact() to return a ContactRecordSet also, simply for the interface to remain consistent?

Part of me chafes at the idea of returning a data structure like that for a single object, but on the other hand it is more consistent and the semantics for checking if a value was found for that id seem more in line with the overall abstraction of the design (check length of returned recordset vs. check for a NULL auto_ptr).

What do you all think?

(Note - I'm aware I'm probably be over-engineering for a simple address book application but I want it to be easy to swap out different back ends (flat file, SQL, etc...) provided they implement the common interface. The goal is to practice good modular design & seperation of concerns.)

UPDATE

I suppose I could look at from the opposite perspective and make the multiple record methods return auto_ptrs to ContactRecordSet objectcs. That way a)it's consistent in that you're always getting a pointer to an object and b) you don't have the overhead of returning a std::vector if the record set is empty, simply return a NULL pointer.


Solution

  • I always follow the design principle of return the least complex thing that defines your object. Vectors are meant to hold lists of things not single item and while it might make the semantics symmetric it will undoubtedly be nonintuitive to another developer.