Someone says, "You should always check your arguments to see if they're in range." Someone else says, "Half the statements in this program are checking arguments that are intrinsically in range." Have they made the program better or worse? No, I think they've made it worse. I'm not a fan of checking arguments. On the other hand, there ought to be a fail fast. If you make a mistake, the program ought to stop. So there is an art to knowing where things should be checked and making sure that the program fails fast if you make a mistake. That kind of choosing is part of the art of simplification.
Very true. Argument checks are difficult. Personally for low level utility function I prefer to use ASSERT macros to check arguments. They are there in Debug Version to track bugs faster and no performance penalty in Release version. It has happened many times that testing team reports a bug and I start the application in Debug mode. Out pops a 'assertion failure' message. Nearly Zero efforts to locate the cause of bug. In my experience time to find the location bug is usually large percentage of total bug fixing time. If I can reduce that time, then it greatly helps in reducing the total development time and improving the project code quality.
Also it has another benefit that if you wrote a module with asserts and other developer makes a mistake in using those functions, he will get assertion failure during the development/unit testing phase itself. As you know, a bug is detected and correct early, has low cost.
I have an eclectic (or eccentric) mix of hobbies and interest. Starting from software development, astrology to origami and mindmaping. This blog will be mostly about Software Development but I may talk about other things also.
Announcement
Tuesday, July 06, 2004
Tuesday, June 22, 2004
Implementing a Well behaved Singleton - 2
In the second part of this series, Lets look at a simple singleton implementation and see how these questions affect the implementation.
(a) There is no guarantee that User of the class cannot create another instance of the class. So technically this is not a singleton.
(b) User can derive from this class. Usually not a good idea for singletons.
(c) Single instance is implemented using file static object. The sequence of static objects is decided by the compiler. Hence if other static objects depend on Singleton instance of FooSingleton, you have a problem. It may happen that g_fooSingleton is not initialzed yet.
Not a well behaved implementation.
Lets see how to improve on this. First lets make the constructor of the FooSingleton private. This will take care of (a) and (b). Problem however is then you cannot create file static 'g_fooSingleton'. It has to be implemented differently.
1. GetFooObj is returning a pointer. What happens if user deletes this pointer by mistake ? The FooSinglton object will NOT know that the pointer is already deleted.
2. Exactly this singleton instance of FooSingleton is going to be destroyed ? Since m_pFoo is a pointer, its destructor will not get called automatically. That could be a problem.
The User (developer) has to manange the destruction of Singleton object and he needs to be really careful in using the class (.e.g don't keep copy of the pointer to FooSingleton, don't delete the pointer to FooSingleton etc). Not a well behaved implementation.
How to improve on this is part of next installment of this series :-)
The problems with this codeclass FooSingleton{ public : FooSingleton(void); ~FooSingleton(void); static FooSingleton* GetFooObj(void); private : int m_var; }; static FooSingleton g_fooSingleton; FooSingleton* FooSingleton::GetFooObj(void) { return(&g_fooSingleton); }
(a) There is no guarantee that User of the class cannot create another instance of the class. So technically this is not a singleton.
(b) User can derive from this class. Usually not a good idea for singletons.
(c) Single instance is implemented using file static object. The sequence of static objects is decided by the compiler. Hence if other static objects depend on Singleton instance of FooSingleton, you have a problem. It may happen that g_fooSingleton is not initialzed yet.
Not a well behaved implementation.
Lets see how to improve on this. First lets make the constructor of the FooSingleton private. This will take care of (a) and (b). Problem however is then you cannot create file static 'g_fooSingleton'. It has to be implemented differently.
class FooSingleton
{
public:
~FooSingleton(void);
static FooSingleton* GetFooObj(void);
private :
FooSingleton(void);
private :
int m_var;
static FooSingleton* m_pFoo;
};
FooSingleton* FooSingleton::m_pFoo= NULL;
FooSingleton*
FooSingleton::GetFooObj(void)
{
if( m_pFoo == NULL)
m_pFoo = new FooSingleton();
return(m_pFoo);
}
First call to GetFooObj will create the Singleton instance, subsequence calls will return the same instance. There are still problems with this implementation.
1. GetFooObj is returning a pointer. What happens if user deletes this pointer by mistake ? The FooSinglton object will NOT know that the pointer is already deleted.
2. Exactly this singleton instance of FooSingleton is going to be destroyed ? Since m_pFoo is a pointer, its destructor will not get called automatically. That could be a problem.
The User (developer) has to manange the destruction of Singleton object and he needs to be really careful in using the class (.e.g don't keep copy of the pointer to FooSingleton, don't delete the pointer to FooSingleton etc). Not a well behaved implementation.
How to improve on this is part of next installment of this series :-)
Monday, June 21, 2004
Implementing a Well behaved Singleton - 1
Singleton is one of the simplest design patterns. It also the one most abused. I have seen developers replace a global variable with a signleton object and argue that since its a design pattern, its good without really looking at the intent of the pattern and the effects.
What do i mean by a Well Behaved Singleton ? A well behaved Singleton will have following characteristics.
Assuming that you understand intent of pattern and want to implement a singleton, there are many ways to achieve it, depending on your needs. First Lets look at major considerations for how to implement a Singleton.
In this series I plan to look at some ways of implementing Singleton, look at pros/cons of them and see how well behaved they are.
What do i mean by a Well Behaved Singleton ? A well behaved Singleton will have following characteristics.
1. Construction is trasparent to the user(at start of program or on demand).
2. If construction of the singleton depends on some other object being initialized first, then the implementation should ensure that constructor sequence is correct under any circumstances.
3. Destruction is trasparent to the user.
4. If some other object (esp. destruction of some other object) depends on Singleton, timing and sequence of destuction of Singleton should be correct in any circumstances.
5. Single instance is ensured by the implementation. It should be impossible to create a second instance. If the user tries to create a second instance, the implementation should give an error (e.g compilation error, assertion failure etc)
6. All assumptions are made explicit.
Assuming that you understand intent of pattern and want to implement a singleton, there are many ways to achieve it, depending on your needs. First Lets look at major considerations for how to implement a Singleton.
1. Do you anticipate a need to create a derived class which is also a singleton ?
2. Does the initialization of a Singleton object depend on some other object being already initialized ?
3. Does some other object (e.g. other singleton) depend of Singleton object being initialized first ?
4. Does the destruction of a Singleton object depends on existance of some other object ?
5. How Are you ensuring destruction of Singleton ?
In this series I plan to look at some ways of implementing Singleton, look at pros/cons of them and see how well behaved they are.
Subscribe to:
Posts (Atom)