I am working on a simple API in C++ where the end user of my code will pass an instance of a UserProfile class around to various other classes for modification. The user profile has a very basic public interface, with the data stored in a private pimpl object. I then add implementation classes as friends so they can access the internal data structure, which is defined in a separate implementation file. The basic outline of this class looks as follows . . .
// For pimpl here
class UserProfileData;
class UserProfile
{
public:
/// ctor to allocate impl
UserProfile();
/// dtor
~UserProfile();
/// Do some very simple stuff with a few methods
std::string getProfileName() const;
private:
/// Use pimpl and hide impl so API user can just use simplified interface
std::unique_ptr<UserProfileData> userProfileData;
/// Allow implementation classes access to userProfileData
friend class ClassOne;
friend class ClassTwo;
};
Building a big list of friend classes doesn't feel like the most elegant solution for hiding the data from the API user. It seems a little smelly. Are there any patterns or idioms that will allow me to achieve the same goal differently?
Think about what you're trying to achieve by hiding the implementation details of your UserProfile class. From the sounds of it, you're probably working to decouple consumers from the internal structure of the data. Doing this with the data container may be more trouble than it's worth, though.
Purely from the consumer's perspective, there's no need to hide the details of a class like this. Consider the following data types:
struct ProfileData
{
std::string profileName;
}
struct ProfileDataWithHiddenDetails
{
std::string getProfileName();
}
The purpose of each of these types is straightforward: they're used to transmit profile information between interested parties. Each type suits this purpose well, but one is much simpler to reason about than the other.
Does getProfileName communicate with a database? Does it retrieve the profile name from a deep hierarchy of values? Is the profile name just stored in a member variable? Any of these (among others) is possible; the information has been purposefully hidden from the consumer.
The first question is: Does this information need to be hidden from the consumer? If the consumer is using the object as a data container, then abstractions would only get in the way.
If your intent is to indeed hide details of the data structure, the next question is: What information do you need to hide from the consumer? If the object is not a simple data aggregator, consumers will need to adopt a different mindset when using it.
Abstractions can make it easier to reason about a system, but they can also make it harder. Try to abstract the behavior in your API rather than the data.
Example
Imagine ProfileDataWithHiddenDetails::getProfileName actually retrieves the profile name from a rich object model that you wanted to keep hidden from consumers. Something like:
std::string getProfileName
{
return objectModel.getRoot().getUserProfile().profileName;
}
These details don't need to be hidden in the implementation of getProfileName. Perhaps there was an API function call that returned the profile data:
ProfileDataWithHiddenDetails getProfileData()
{
return ProfileDataWithHiddenDetails(objectModel);
}
Instead of returning an abstraction, this API function could handle the abstraction itself:
ProfileData getProfileData()
{
auto profileName = objectModel.getRoot().getUserProfile().profileName;
return ProfileData { profileName };
}
Related
I am refactoring a biometric recognition SDK, which public API provide feature extraction and some CRUD feature management interface like:
class PublicComponent{
public:
FeaturePublic extract_feature();
int add_feature(const FeaturePublic&);
void update_feature(int id, const FeaturePublic&);
void delete_feature(int id);
}
The actual feature that all other private implementation component must to deal with is complicated, it contains many fields that we don't want to expose to the API user, like:
struct FeatureDetail{
int detail1;
int detail2;
// ...
float detailN;
};
And basically the PublicComponent just forward its job to these internal components.
So the gap occurred, basically all the public API accept or give back FeaturePublic as argument/result. However all other existed internal implementation heavily depends on FeatureDetail, they must touch the internal data member of feature. It just seems that we need to retrieve concrete type from the type erased public handle, but unable to publish the retrieve method. I've came up with two solutions, but either of them seems quirky.
Solution 1
Just use type erased raw buffer like std::vector<std::byte> or std::pair<std::byte*, size_t> as FeaturePublic.
It is simple, however, the cons is pretty straightforward: We just throw away the type safety that we already have, and i have to insert all the input data integrity check and serialize/deserialize code at all the public API border even though the caller might just add a feature that generated right before.
Solution 2
Use pimpl like idiom to hide FeatureDetail inside FeaturePublic.
// public api header
class FeatureDetail; // forward declartion
class FeaturePublic{
private:
std::unique_ptr<FeatureDetail> detail_;
};
Under which we can maintain the type safety, however, to let the internal component to touch the concrete type FeatureDetail, we must have some way to let them retrieve a FeatureDetail from PublicComponent passed FeaturePublic. But since the detail_ field is a private member, The two ways that i can think of is to provide a get_raw method on FeaturePublic or make the field public, any of them seems pretty ugly.
Suppose we have a complex (i.e. non-primitive) class ComplexObject defined below:
class A{...};
class B{...};
class C{...};
class ComplexObject
{
private:
A _fieldA;
B _fieldB;
C _fieldC;
};
I would like to implement a serializer that serializes instances of ComplexObject into binary form. From my experience in C#, I have seen essentially 3 distinct ways to implement a serializer.
Define a serialize(binarystream&) method in ComplexObject's definition and those of the "child" classes, A, B, and C. The serialize method defined in ComplexObject will recursively call those of the child members.
Create a separate class that contains methods to serialize each of ComplexObject, A, B, and C. The method used to serialize ComplexObject will recursively call those of the child members. Of course, getters will have to be defined in the classes to retrieve private fields for the serializer.
Use reflection to generate a template of the object and to write all serializable fields into a table according to the generated template.
Unfortunately I believe reflection will be extremely hard to utilize in C++, so I shall stay away from the third option. I have seen options 1 and 2 both been used very often (in C#).
An advantage that option 1 possess over option 2 is that it allows for classes that derive from ComplexObject, by marking the serilalize(binarystream&) method virtual. However, it would add to the list of member functions of an object and confuse programmers. You don't see a serialize method being defined in std::string, do you?
On the other hand, option 2 takes out and groups all serialization methods together to make things a bit neater. However, I suppose it isn't as easy to accommodate for derived classes of ComplexObject.
Under which circumstances should each of the options (1 and 2) be used?
I choose "both". Serialization has components in the object and (templated) free standing functions.
For example:
class Serialization_Interface
{
public:
virtual void load_from_buffer(uint8_t*& buffer_ptr) = 0;
};
void Load_From_Buffer(unsigned int& number, uint8_t*& buffer_pointer)
{
number = *((unsigned int *) buffer_ptr);
buffer_pointer += sizeof(unsigned int);
}
template <class Object>
void Load_From_Buffer(Object& obj, uint8_t*& buffer_pointer)
{
obj.load_from_buffer(buffer_pointer);
}
Don't limit yourself to two choices. There's always a third alternative. :-)
Also, don't reinvent the wheel, check out Boost::serialization.
C++ doesn't have reflection, but that doesn't mean serialization code needs to be written by hand.
You can use a code generator (for example, protocol buffers) to create the serialization code from a simple description. Of course, that description format doesn't support the rich C++ features for creating your public API, but you can take the data structure type created by the code generator and embed that inside your "real" class, either directly embedded or via pimpl. That way you write all non-serialization behavior in your class, but it doesn't have any data of its own, it relies on the serialization object to store the data.
It's basically like your method #2, but applying inversion of control. The serializer logic doesn't reach into your class to get access to the data, instead it becomes responsible for storing the data where your class also can use it.
I wold not bother with self-made serializer.
(Notice that designing deserialization is harder than serialization...)
I would rather use something line:
https://code.google.com/p/protobuf/
http://android-developers.blogspot.com/2014/06/flatbuffers-memory-efficient.html
or boost (you can also check how they solved similar problem)
http://www.boost.org/doc/libs/1_56_0/libs/serialization/doc/index.html
Getting back to your dilemma.
Grouping all serialization code in a single class is a bad idea, because this class would grown with each new serializable object. You could use friend "serializer" class for each "serializable" class,
or use friend method / operator<<.
But there is no perfect solution and it is not easy task. If you can, use lib.
I wanted to get some few pointers to below design problem.
Suppose I wanted to write some classes to enumerate USB devices and select particular device and transmit data through it for different platforms.(Just a very rudimentary scenario.More of a design question than anything related to USB).
Now I want to have a device base class for USB devices which can have functions like enumerate_devices, get_particular_device based on a string etc. Now this would be implemented differently on different platforms. So I'll probably have some child classes which will implement this using the platform specific apis.
Now the other class I want to have will be some buffer class that will transfer data to USB endpoint. This again will need to be implemented by different platforms based on the apis they provide.
Now suppose I create a Windows based USB device class and a buffer class and implement those using Windows provided apis. My question is what do I do if my Windows buffer class needs some data from my Windows device class. What kind of pattern can I use so that the base classes remain anonymous to the internal intermediate platform based structures used in child classes and yet buffer class can use particular device class data members? Want to get a good design for this. Dont know if I am clear enough in writing. Hope to get some insight.
Edit: I know factory and abstract factory. This is not related to them. I cant access child class member function through factory patterns through an object of UsbDevice*
Brief outline.
SomeWindowsUsbDevice : public UsbDevice {
public:
void findDevices() { // just a child class function. Not in base class
//Code to find devices using platform apis.
//fills below two private structures.
}
private:
DevEnum* pdevenum; //some platform specific structure.
Buffsize* pbufsize; // some platform specific structure.
}
SomeWindowsUsbDataTrf : public UsbDataTrf {
public:
DevEnum* getdevicelist() {
//Need to get access to SomeWindowsUsbDevice::pdevenum
}
Buffsize* getbuffsize() {
//Need to get access to SomeWindowsUsbDevice::pdevenum
}
}
Try Endpoint Redirection, more details are available at Endpoint Redirection
I also suggest you to read factory pattern, on reading you will get the point why it is suggested, just google factory pattern and you will have a huge description available
Abstract Factory pattern applies to your case.
"Provide an interface for creating families of related or dependent objects without specifying their concrete classes."
Before anything, thanks for reading!
I'm developing an application in C++ and I want an advice about a design issue. Let me explain:
The main class of my application has some collections, but other classes eventually need to get a value from one of those collections. Something like this:
class MainClass {
private:
// Collections are internally implemented as QHash
Collection<Type1> col1;
Collection<Type2> col2;
};
class RosterUnit {
public:
RosterUnit() {
/* This method needs to get a specific value from col1 and
initialize this class with that data */
}
};
class ObjectAction {
public:
virtual void doAction() = 0;
};
class Action1 : public ObjectAction {
public:
void doAction() {
// This needs a specific value from col2
}
};
class Action2 : public ObjectAction {
public:
void doAction() {
// This needs a specific value from col1
}
};
My first approach was passing the whole collection as parameter when needed, but it is not so good for ObjectAction subclasses, because I would have to pass the two collections and if I later create another subclass of ObjectAction and it needs to get an element from other collection (suppose col3), I would have to modify the doAction() signature of every ObjectAction subclass, and I think that is not too flexible. Also, suppose I have a Dialog and want to create a RosterUnit from there. I would have to pass the collection to the dialog just to create the RosterUnit.
Next I decided to use static variables in RosterUnit and ObjectAction that pointed to the collections, but I'm not very happy with that solution. I think it is not flexible enough.
I have been reading about design patterns and I first thought a Singleton with get functions could be a good choice, but after some more investigation I think it isn't a proper design for my case. It would be easier and more or less the same if I use global variables, which don't seem to be the right way.
So, could you give some advices, please?
Thank you very much!
As mentioned previously, Iterators are good for abstracting away the details of the Collection. But going this route implies that the objects that use the Iterators will need to know about what's inside the Collection. Meaning they will need to know how to decide which object in the Collection they need, thus increasing the coupling. (more details below in the Factory paragraph) This is something you need to consider.
Another approach would be to create accessor methods on the MainClass that take some sort of key and return an object from the Collection (findObject(key)). Internally the MainClass methods would search through the container(s) and return the appropriate object. To use this approach, you will however need access to the MainClass, either by dependancy injection as mentioned before, or possibly making it a Singleton (not recomended in this scenario, though).
With the info provided so far, it may even be better for your ObjectAction Factory to have a reference to the MainClass, and as a part of the ObjectAction creation logic, call the appropriate MainClass accessor and pass the result into the ObjectAction, thus decoupling the ObjectAction Objects from the MainClass.
You probably want to use iterators, they exist exactly for the purpose of abstracting away sequences from specific containers.
If your issue is how to pass the iterators to the code that needs them in the first place, do not give in to the temptation to use globals. It may look more convoluted if you have to pass parameters in, but your code is that much more decoupled for it. "Dependency Injection" is a good keyword if you want to read more about this topic.
I would also advise you to check out std::function or boost::function instead of inheriting from ObjectAction. Functional style is getting more common in modern C++, as opposed to how it's usually done in languages like Java.
There's not enough information here of what you are trying to do. You make it sound like 'at some point in the future, this statically created action needs this data that was left behind.' How does that make any sense? I would say either construct the actions with the data, as you would for instance with a Future or Callable), or have the command ask for the next piece of data, in which case you are just implementing a Work queue.
Sounds like you are trying to do something like a thread pool. If these actions are in any way related, then you should have then in some composing object, implementing something like the Template Method pattern, e.g. execute() is abstract and calls a few other methods in a fixed sequence and that cannot be overridden, the other methods must be (protocol enforcement).
I have a couple of base/interface classes each of which has several derived classes. I have a need to store metadata on each derived class that has a lot of overlap, but different values.
I also have a Factory class for creating instances of the derived classes that's implemented as a singleton and has a few macros. For example, you'd:
REGISTER_COMPONENT("MyComponent", MyComponentClass);
// create an instance of each component
BaseComponent *base;
foreach(QString component, ComponentRegister::componentList())
{
base = ComponentRegister::create(component);
// do stuff with base
}
The question is: how and where to store the metadata from a solid design viewpoint.
I could store the data in the ComponentRegister as a QMap structure. When someone registers a component, they could also register its metadata with something like
REGISTER_COMPONENT_METADATA("MyComponent", MyMap);
If the QVariant::isValid() for a particular key, you know the metadata is set and available.
Another way would be static class variables or maybe a static class QMap.
I see advantages and draw backs to both. Most of the metadata are things like "path to QResources for this class" which is not tightly coupled to the business logic of the class itself.
Another issue with the static class variable method comes into play with inheritance. You can't enforce overriding of static class variables like you can with pure virtual functions. So if someone forgets...it could be unclear where in the inheritance tree the values are coming from. If you require access to the metadata through a series of pure virtual "getters" then setting of the MetaData is spread across all implementations of the Base class.
With data held, set, and looked up in the Register if you needed to make changes (like changing the root path for resources), you could do so at a single point...in the class registration calls, probably a header or wrapped in a application Utility function. With static data, you'd have to edit each class declaration.
Open to suggestions and thanks!
If data related to an object isn't specific to a single instance, as the path in your example, my designs usually include a class which manages my collection of objects. That's where I put the meta data.
example:
class zoo { std::vector<animals> zoo_animals; size_t count; }
count is metadata about the animals.