What I'm looking right now is a set of classes derived from a common base class. Most, but not all, of the classes require some input parameters which are obtained through modal dialogs. Those dialogs are set up and executed in the constructor of the classes. As long as the dialog isn't finished, the object isn't constructed completely. What problems could arise by delaying the execution of a constructor?
I was thinking of replacing everything with a callback mechanism that is provided to the dialogs to set up the objects or using a factory to get usable objects right after construction. What other patterns are there to solve this situation?
No "problems" can arise as far as the language is concerned. The constructor is allowed to take as long as it likes.
Where it might be a problem is in the confusion it might cause. Will the programmer using the class be aware that the constructor blocks the thread for a long time?
Without knowing any details of your code, a callback or some other asynchronous mechanism might be better, to avoid blocking the thread.
What do these classes do? If they are not there just to manage the UI, you have a problem with separation of concerns... the user input gathering should be separated from classes that process that input.
I think it's a valid design choice. It does make sense to have a class called "UserInput" that will but be fully constructed after the user has provided input.
It also does induce a tight coupling to the data-entry method - interactive: you won't be able to use these classes with mockup data, for example.
So if you need the flexibility of the choice, do decouple data entry from business logic. If you want ready-to-use objects, go ahead asking the user for input at construction time.
Related
I have a single very large data class (really a struct, honestly), which needs to be manipulated in enough different ways that I don't just want to implement all of the manipulators as member methods of the data class.
Right now, I have the manipulators set up as singletons, or small instantiated classes held by some manager object, and I pass every manipulator a pointer to the data class during initialization. This works, but feels a little sloppy to me.
One complicating issue is that the manipulators have state. One example of manipulator state that could be factored out of the manipulators themselves is thread-safety helpers (mutexes/semaphores), but there are other data members that logically belong to the manipulators so I don't think this problem is going away.
So I'm wondering, is there some design pattern that can provide a cleaner solution for this situation?
A factory pattern could be used with the factory offering a method taking a pointer or reference to the data, and a value (possibly enumeration) indicating the operation to be performed, it then selects the agent that can perfrom that operation and asks it to do so.
As for the states, if the agents' states are synchronised then a single state in the factory would be fine - if they are not then the factory could simply provide a method to be called in the event that anything happens that could change any agent's state and inform all the agents. Or, the agents could themselves be observers of whatever it is that causes the state changes.
As for implementing a state machine - that's also often done using a factory pattern! So you could have a factory of factories where each sub factory is also an observer. This would be almost too awesome for words.
I have a class that represents a data stream, it basically
reads or writes into a file, but first the data are being encrypted/decrypted and there is also an underlying codec object that handles the media being accessed.
I'm trying to write this class in a RAII way and I'd like a clean, nice, usable design.
What bothers me is that right now there is a lot of work being done in the constructor.
Before the object's I/O routines can be safely used, first of all the codec needs to initialized (this isn't very demanding), but then a key is taken into account and crypto and other things are intialized - these require some analysis of the media which takes quite a lot of computation.
Right now I'm doing all this in the constructor, which makes it take a long time. I'm thinking of moving the crypto init stuff (most work) out of the ctor into a separate method (say, Stream::auth(key)), but then again, this would move some responsibility to the user of the class, as they'd be required to run auth() before they call any I/O ops. This also means I'd have to place a check in the I/O calls to verify that auth() had been called.
What do you think is a good design?
P.S. I did read similar question but I wasn't really able to apply the answers on this case. They're mostly like "It depens"... :-/
Thanks
The only truly golden unbreakable rule is that the class must be in a valid, consistent, state after the constructor has executed.
You can choose to design the class so that it is in some kind of "empty"/"inactive" state after the constructor has run, or you can put it directly into the "active" state that it is intended to be in.
Generally, it should be preferred to have the constructor construct your class. Usually, you wouldn't consider a class fully "constructed", until it's actually ready to be used, but exceptions do exist.
However, keep in mind that in RAII, one of the key ideas is that the class shouldn't exist unless it is ready, initalized and usable. That's why its destructor does the cleanup, and that's why its constructor should do the setup.
Again, exceptions do exist (for example, some RAII objects allow you to release the resource and perform cleanup early, and then have the destructor do nothing.)
So at the end of the day, it depends, and you'll have to use your own judgment.
Think of it in terms of invariants. What can I rely on if I'm given an instance of your class? The more I can safely assume about it, the easier it is to use. If it might be ready to use, and might be in some "constructed, but not initialized" state, and might be in a "cleaned up but not destroyed" state, then using it quickly becomes painful.
On the other hand, if it guarantees that "if the object exists, it can be used as-is", then I'll know that I can use it without worrying about what was done to it before.
It sounds like your problem is that you're doing too much in the constructor.
What if you split the work up into multiple smaller classes? Have the codec be initialized separately, then I can simply pass the already-initialized codec to your constructor. And all the authentication and cryptography stuff and whatnot could possibly be moved out into separate objects as well, and then simply passed to "this" constructor once they're ready.
Then the remaining constructor doesn't have to do everything from scratch, but can start from a handful of helper objects which are already initialized and ready to be used, so it just has to connect the dots.
you could just place the check in the IO calls to see if auth has been called, and if it has, then continue, if not, then call it.
this removes the burden from the user, and delays the expense until needed.
Basically, this all boils down to which design to choose from the following three:
Designs
Disclaimer: this post is not encouraging the use of exception specifications or exceptions for that matter. The errors may equivalently be reported using error codes if you wish. Exception specifications as used here are just meant to illustrate when different errors can occur using a concise syntax.
Design 1
This is the most recurring design out there, and totally non-RAII. The constructor just puts the object in some stale state and each instance must be initialized manually after construction takes place.
class SecureStream
{
public:
SecureStream();
void initialize(Stream&,const Key&) throw(InvalidKey,AlreadyInitialized);
std::size_t get( void*,std::size_t) throw(NotInitialized,IOError);
std::size_t put(const void*,std::size_t) throw(NotInitialized,IOError);
};
Pros:
Users have control over when to invoke the "heavy" initialization process
The object can be created before the key exists. This is important for frameworks such as COM, where all objects must have a default constructor (the CoCreateObject() does not allow you to forward extra arguments the object constructor). Sometimes, there are still workarounds, such as a builder object.
Cons:
Objects must be checked for the stale state before using the object. This may be enforced by the object by returning an error code or throwing an exception. Personally, I hate objects that allow me to use them and just appear to ignore my calls (e.g. a failed std::ostream).
Design 2
This is the RAII approch. Make sure the object is 100% usable with no extra artefacts (e.g. manually calling stream.initialize(...); on each instance.
class SecureStream
{
public:
SecureStream(Stream&,const Key&) throw(InvalidKey);
std::size_t get( void*,std::size_t) throw(IOError);
std::size_t put(const void*,std::size_t) throw(IOError);
};
Pros:
The object can always be assumed to be in a valid state. This is so much simpler to use.
Cons:
Constructor might take a long time to execute.
All required arguments must be available at the instance construction. This has once in a while been a problem for me, especially if most other objects in the code base use design #1.
Design 3
Somewhat of a compromise between the two previous cases. Don't initialize yet, but have the other methods lazily invoke the internal .initialize(...) method when necessary.
class SecureStream
{
public:
SecureStream(Stream&,const Key&);
std::size_t get( void*,std::size_t) throw(InvalidKey,IOError);
std::size_t put(const void*,std::size_t) throw(InvalidKey,IOError);
private:
void initialize() throw(InvalidKey);
};
Pros:
Almost as easy to use as design #1. Almost (see below).
Cons:
If the initialization step may fail, it may now fail anywhere there is a first call to any of the public methods. Proper error handling for this scenario is extremely difficult.
Discussion
If you absolutely must pay for the initialization for every instance, then design #1 is out of the question as it just results in more bugs in the software.
The question is just about when to pay for the initialization cost. Do you prefer paying it upfront, or on first use? In most scenarios, I prefer paying upfront because I don't want to assume users can handle errors later in the program. However, there might be specific threading semantics in your program, and you might not be able to stall threads at creation time (or, conversely, at use time).
In any case, you can still get the benefits of design #3 by using dynamic allocation of the class in design #2.
Conclusion
Basically, if the only reason you are hesitating is for some philosophical ideal where constructors execute quickly, I would just go with the pure RAII design.
There's no hard and fast rule on this, but in general it's best to avoid heavy constructors for two reasons that come to mind (maybe others as well):
The order of the objects created intializer list can give rise to subtle bugs
What to do with exceptions in the constructor? Will you need to handle partially-constructed objects in your app?
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How much work should be done in a constructor?
I'm strugging with some advice I have in the back of my mind but for which I can't remember the reasoning.
I seem to remember at some point reading some advice (can't remember the source) that C++ constructors should not do real work. Rather, they should initialize variables only. The advice went on to explain that real work should be done in some sort of init() method, to be called separately after the instance was created.
The situation is I have a class that represents a hardware device. It makes logical sense to me for the constructor to call the routines that query the device in order to build up the instance variables that describe the device. In other words, once new instantiates the object, the developer receives an object which is ready to be used, no separate call to object->init() required.
Is there a good reason why constructors shouldn't do real work? Obviously it could slow allocation time, but that wouldn't be any different if calling a separate method immediately after allocation.
Just trying to figure out what gotchas I not currently considering that might have lead to such advice.
I remember that Scott Meyers in More Effective C++ recommends against having a superfluous default constructor. In that article, he also touched on using methods liked Init() to 'create' the objects. Basically, you have introduced an extra step which places the responsibility on the client of the class. Also, if you want to create an array of said objects, each of them would have to manually call Init(). You can have an Init function which the constructor can call inside for keeping the code tidy, or for the object to call if you implement a Reset(), but from experiences it is better to delete an object and recreate it rather than try to reset its values to default, unless the objects is created and destroyed many times real-time (say, particle effects).
Also, note that constructors can perform initialization lists which normal functions could not.
One reasons why one may caution against using constructors to do heavy allocation of resources is because it can be hard to catch exceptions in constructors. However, there are ways around it. Otherwise, I think constructors are meant to do what they are supposed to do - prepare an object for its initial state of execution (important for object creation is resource allocation).
The one reason not to do "work" in the constructor is that if an exception is thrown from there, the class destructor won't get called. But if you use RAII principles and don't rely on your destructor to do clean up work, then I feel it's better not to introduce a method which isn't required.
Depends on what you mean by real work. The constructor should put the object into a usable state, even if that state is a flag meaning it hasn't yet been initialised :-)
The only rationale I've ever come across for not doing real work would be the fact that the only way a constructor can fail is with an exception (and the destructor won't be called in that case). There is no opportunity to return a nice error code.
The question you have to ask yourself is:
Is the object usable without calling the init method?
If the answer to that is "No", I would be doing all that work in the constructor. Otherwise you'll have to catch the situation when a user has instantiated but not yet initialised and return some sort of error.
Of course, if you can re-initialise the device, you should provide some sort of init method but, in that case, I would still call that method from the constructor if the condition above is met.
In addition to the other suggestions regarding exception handling, one thing to consider when connecting to a hardware device is how your class will handle the situation where a device is not present or communication fails.
In the situation where you can't communicate with the device, you may need to provide some methods on your class to perform later initialization anyway. In that case, it may make more sense to just instantiate the object and then run through an initialization call. If the initialization fails, you can just keep the object around and try to initialize communication again at a later time. Or you may need to handle the situation where communication is lost after initialization. In either case, you will probably want to think about how you will design the class to handle communication problems in general and that may help you decide what you want to do in the constructor versus an initialization method.
When I've implemented classes that communicate with external hardware, I've found it easier to instantiate a "disconnected" object and provide methods for connecting and setting up initial status. This has generally provide more flexibility connecting/disconnecting/reconnecting with the device.
The only real reason is Testability. If your constructors are full of "real work", that usually means the objects can only be instantiated within a fully initialized, running application. It's a sign the object/class needs further decomposition.
When using a constructor and an Init() method you have a source of error. In my experience you will encounter situation where someone forgets to call it, and you might have a subtle bug in your hands. I would say you shouldn't do much work in your constructor but if any init method is needed, then you have a non-trivial construction scenario, and it is about time to look at the creational patterns. A builder function or a factory be wise to have a look at. With a private constructor making sure that no one except your factory or builder function actually build the objects, so you can be sure that it is always constructed correctly.
If your design allow for mistakes in implementation, someone will do those mistakes. My friend Murphy told me that ;)
In my field we work with loads of similar hardware related situations. Factories gives us both testability, security and better ways of failing construction.
It is worth considering lifetime issues and connecting/reconnecting, as Neal S. points out.
If you fail to connect to a device at the other end of a link then it is often the case that the 'device' at your end is usable and will be later if the other end gets its act together. Examples being network connections etc.
On the other hand if you try and access some local hardware device that does not exist and will never exist within the scope of your program (for example a graphics card that is not present) then I think this is a case where you want to know this in the constructor, so that the constructor can throw and the object can not exist. If you don't then you may end up with an object that is invalid and will always be so. Throwing in the constructor means that the object will not exist, and thus functions can't be called on that object. Obviously you need to be aware of cleanup issues if you throw in a constructor, but if you don't in cases like this then you typically end up with validation checks in all functions that may be called.
So I think that you should do enough in the constructor to ensure you have a valid, usable, object created.
I'd like to add my own experience there.
I won't say much about the traditional debate Constructor/Init... for example Google guidelines advise against anything the in the Constructor but that's because they advise against Exceptions and the 2 work together.
I can speak about a Connection class I use though.
When the Connection class is created, it will attempt to actually connect itself (at least, if not default constructed). If the Connection fails... the object is still constructed and you don't know about it.
When you try to use the Connection class you are thus in one of 3 cases:
no parameter has ever been precised > exception or error code
the object is actually connected > fine
the object is not connected, it will attempt to connect > this succeeds, fine, this fails, you get an exception or an error code
I think it's quite useful to have both. However, it means that in every single method actually using the connection, you need to test whether or not it works.
It's worth it though because of disconnection events. When you are connected, you may lose the connection without the object knowing about it. By encapsulating the connection self-check into a reconnect method that is called internally by all methods needing a working connection, you really isolate the developers from dealing with the issues... or at least as much as you can since when everything fails you have no other solution that letting them know :)
Doing "real work" in a constructor is best avoided.
If I setup database connections, open files etc inside a constructor and if in doing so one of them raise an exception then it would lead to a memory leak. This will compromise your application's exception safety.
Another reason to avoid doing work in a constructor is that it would make your application less testable. Suppose you are writing a credit-card payment processor. If say in CreditCardProcessor class's constructor you do all the work of connecting to a payment gateway, authentate and bill the credit card how do I ever write unit tests for CreditCardProcessor class?
Coming to your scenario, if the routines that query the device do not raise any exceptions and you are not going to test the class in isolation then there is its probably preferable to do work in the constructor and avoid calls to that extra init method.
There are a couple reasons I would use separate constructor/init():
Lazy/Delayed initialization. This allows you to create the object quickly, fast user response, and delay a more lengthy initialization for later or background processing. This is also a part of one or more design patterns concerning reusable object pools to avoid expensive allocation.
Not sure if this has a proper name, but perhaps when the object is created, the initialization information is unavailable or not understood by whoever is creating the object (for example, bulk generic object creation). Another section of code has the know-how to initialize it, but not create it.
As a personal reason, the destructor should be able to undo everything the constructor did. If that involves using internal init/deinit(), no problem, so long as they are mirror images of each other.
I need suggestions on how to solve the type of problems described below. I'm fairly new at C++ and OO-design.
I've learnt:
Pointers shall be avoided when ever they can be replaced by references.
Objects shall have no knowledge of objects that they don't need to know about.
But when creating objects having references to other objects we must pass these references as input arguments to the constructor. Thus we need to know about objects we should not not know anything about.
But look at the following example:
Suppose I have a object "Menu" that needs to have it's own timer object "Timer". I'd like to implement this association as a reference.
The object MenuHandler aggregates a lot of Menu objects but shall not have any knowledge about Timer objects. But when the MenuHandler creates a Menu object it must pass a Timer reference argument to the constructor. Thus, ****MenuHandler** must know about **Timer****.
Any suggestions on how to treat these kind of problems?
I'd hesitate to bless your choice of words when it comes to the two numbered points. They're a sign you're on the right way learning C++, but they might be misleading to other novices. When I take a look at your concrete examples, this becomes more obvious.
A MenuHandler should not create menus. The content of menus is determined by by the application, so the application object (or the Controller part, if you've implemented Model-View-Controller) should create menus. The MenuHander merely takes ownership of menus created elsewhere.
Also, it may make sense to give each menu its own timer. That means the relation can be described as "Has a"; the menu has a timer. The relationship usually implmented by references can be described as "Knows a" (the inheritance relationship is usally called "Is a"). If each Menu object has a Timer, it can be a member, and initialized by the Menu constructor(s). The Timer object internally may obtain a reference to the system clock in its constructor, but that's not your concern.
Why not simply make the Timer object a member (by value) of the Menu class?
I find that I produce better (more maintainable, faster, etc) code and that I'm more productive using references in C++ than I would be solving the same problem with pointers... I think the traditional answer to your example would be to have a factory object that creates menus. In this way, the MenuHandler doesn't need to know about the Timer class.
The MenuHandler creates a Timer object, passes it into the Menu constructor, and forgets about it. That seems entirely reasonable.
If the MenuHandler unnecessarily kept a reference to the Timer, that would be against the advice point #2.
In a more general case where you need to provide a class to another class in order to do some kind of callback, you avoid mutual dependency (both know each other) by using an interface.
Class A derives from the interface. Class B accepts the interface as paramater in the constructor and calls the virtual function from that interface when needed.
Also check the observer design pattern.
For #1 Be very careful with the lifetime of your objects. References are no that suitable to handle dynamic graph of objets ( like your menu, menuhandler, timer, etc... ). What if you want to change the timer object later ?
It's not a good idea to have references as members in a class if the lifetime of referenced objects is not really known.
Avoiding pointer does not mean using references everywhere, you should have a look at smart pointers which will be more suitable for what you want to do.
We're trying to build a class that provides the MFC CRecordset (or, really, the CODBCRecordset class) thread safety. Everything actually seem to work out pretty well for the various functions like opening and moving through the recordset (we enclose these calls with critical sections), however, one problem remains, a problem that seems to introduce deadlocks in practice.
The problem seems to lie in our constructor, like this:
CThreadSafeRecordset::CThreadSafeRecordset(void) : CODBCRecordset(g_db)
{ // <-- Deadlock!
}
The other thread might be one having ended up in CThreadSafeRecordset::Close() despite us guarding the enclosed Close call, but that doesn't really matter since the constructor is threading unaware. I assume the original CRecordset class is the culprit, doing bad things at construction time. I've looked around for programming techniques to work around this problem, but I'm unsure what could be the best solution? Since we have no code and can't control other code in our constructor, we can't wrap anything special in a critical section...?
Update: Thanks for the input; I've marked what I ended up with as the answer to my question. That, in combination with returning a shared_ptr as the returned instance for ease of updating the existing thread-unaware code.
You can make the CThreadSafeRecordset constructor private, then provide a public factory method that participates in your locking and returns an instance.
If there's no way to make CODBCRecordset move its thread-unsafe operations out of the constructor (a default constructor followed by an Initialize() call, say), you can always use composition instead of inheritance. Let CThreadSafeRecordset be a wrapper around CODBCRecordset instead of a subclass of it. That way, you can explicitly construct your recordset whenever you like, and can defend it with whatever rigor is appropriate.
The drawback, of course, is that you'll have to wrap every CODBCRecordset method you wish to expose, even the ones that don't relate to your threading guarantees. A C macro in the cpp file (so that it can't escape and afflict your clients) may help.