• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Singleton

 
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I know this particular design pattern has been discussed many times in this forum. But my doubt is very different. Kindly answer my question



public class Singleton{

private Singleton() {}

private static Singleton instance = null;

public static Singleton getInstance() {
if (instance == null){
instance = new Singleton();
}
return instance;
}
}

public Class CallSingleton {

public static void main(String[] args) {

Singleton single = Singleton.getInstance();
}
}





Here is a singleton class. Everyone are saying there is ONLY ONE instance of singleton class. Here is my doubt.


Singleton single = Singleton.getInstance();

When ever the above line is executed , the following method gets executed




Lets assume the following line is called from 10 classes.

Singleton single = Singleton.getInstance();

Doesn't that mean the getInstance() method will be executed 10 times and every time the method gets executed, new operator runs 10 times and creates 10 new instances of Singleton class?

if (instance == null){
instance = new Singleton();
}
return instance;
 
Ranch Hand
Posts: 47
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
the variable instance is of type static. So once a static object is created it will be the same object that you will be accessing elsewhere from whatever the number of classes you have.
 
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
As you said getInstance() will be called 10 times. But if you see the code it is as follows:

if (instance == null){
instance = new Singleton();
}

Which means you are checking instace == null or not.If it is null then only you are using new operator to instantiate Singleton class otherwise you are returning 'instance' private variable. So you are not creating Singleton class 10 times. You are creating only once (first time) and returning the same reference to other 9 calls to the getInstance() method.



Regards,
Sreek
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


the variable instance is of type static. So once a static object is created it will be the same object that you will be accessing elsewhere from whatever the number of classes you have.



I didn't understand this one.
 
Sreek Gupta
Greenhorn
Posts: 24
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Since you are using static variable for your singleton instance means there will be only one copy to that variable even though you create multiple objects of your singleton class.
A static variable is for Class NOT for each instance. So even though you create 10 objects of your singleton class , there will be only one copy for a static variable.

Regds,
Sreek
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for your reply Sreek Gupta.

I read the Singleton pattern from Head First Book. I understood the concept. I got only one doubt. In page 185, in the last Question and Answer,

Q. I still don't totally understand why global variables ae worse than a Singleton?

In Java global variables are basically static references to objects. There are a couple of disadvanteges to using global variables in this manner. We've already mentioned one: the issue of lazy versus eager instantiation. But we need to keep in mind the intent of the pattern to ensure only one instance of a class exists and to provide a global access. A global variable can provide the latter, but not the former.

I didn't get where exactly the issue between lazy versus eager instantiation has been discussed in the book. Can any point me the page. I also like to know disadvanteges of using global variables.
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am refering to this thread.

Here both Frank Carver and Ilja Preuss are stating Singleton increases coupling through global access point.

My understading of coupling is only when the class name is used within a class and new operator is used explicitly the coupling is increased. In singleton we use global access point to get an instance of singleton class in other classes. Then how coupling is increased. Can you help me understand your point through a sample code.

Example


In the above example how Singleton tightly coupled?
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This is the part that I didn't understand from


By Frank Carver

For me, a class is coupled very tightly to anywhere its name is mentioned in the code. I can't swap that class out for another implementation (one for testing, one for better performance, one for a different customer, whatever) without changing every occurrence of that name. Let's hope you have access to all the source code that uses your class!

That same class might be a lot less coupled if it implements an interface or extends a well-known base class, and the code always just refers to that interface or base class and doesn't care which class implements it. In that case, changing the implementation is very easy and localized, and needs no recompilation of code which uses it.

It's even possible to create a new implementation long after the code which uses it is compiled and deployed, and dynamically load it into a running program. Servers, in particular, use this approach a lot.

The Singleton pattern ties all the code which uses it very closely to a particular name and implementation. Whatever you call them, Singletons and statics are "global", and "globals" are well known for making understanding, maintenance and improvement of software harder and more expensive.



and


By Ilja Preuss

Besides the static reasons Frank mentioned, there is also a dynamic coupling. This coupling gets most obvious when you try to unit test classes using a Singleton (or even the Singleton itself). It's near to impossible to have the testcases being independent from one another without compromising the "only one instance" rule of the singleton.



Can you please explain more about dynamic coupling, because this is the first time I am hearing about this term.
 
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Part of the Singleton pattern is a mechanism to control the number of instances (usually one) and give access to them. The common "static member variable" example is not the only possible mechanism. For example, it could be a factory that could return any compatible class.

SomeInterface single = SingletonFactory.getInstance();

We can configure the factory to return a new class or a test class or whatever we need. Spring uses "dependency injection" with an application assembler, so you just have a method:

public void setSomeObject( SomeInterface theInstance )

and the assembler calls it. Now it's even easier to configure for testing as a JUnit test can setSomeObject to a mock or whatever it needs.

With either the factory or injection, clients never really need to know whether it's a singleton or not. I had a singleton in my current project that was a inherited from a prior project. We found out it used member variables and wouldn't work in a multi-threaded environment, so we just changed the factory to return a new one every time. No more singleton.
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for your reply Stan James.

I appreciate if you can answer my doubts with sample codes.

Thanks in advance.
 
Ranch Hand
Posts: 584
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi ALL,

Everything Stan said regarding multi-thread problems when using Singleton pattern is really true, however, I don't think it's a reason for definitely abandon this pattern.

There are some elegant approaches we can use to solve this problem.

The problem : (Singleton Pattern and Multi-Thread environment)

Supposing that two threads (so named as T1 and T2, respectively) call the getInstance() method of the Singleton class.

After T1 evaluates the line if (instance == null){ it's stopped by CPU which puts T2 to run.

At line if (instance == null){ T2 also will evaluate the expression as TRUE. So, BOOOM, both threads get two distinct instances of Singleton class.


The possible solutions :

Basically the most two elegant ones are :

1. By declaring getInstance() method as synchronized.



2. Change your code to early create the Singleton instance.


Of course that each approach has its pros and cons but they are still an alternative to continue using Singleton pattern in your code.

Hope that helps.
[ June 20, 2006: Message edited by: Edisandro Bessa ]
 
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Even the above two Singleton solutions don't guarantee that there will only ever be one object. All they can even try to guarantee is that there will be only one per classloader context. A typical application server uses a separate classloader context for each application.

In the end it all comes down to why you want a Singleton in the first place. What about this domain object is so unique that just having one of them is not enough, but you need to write extra code and make your program do extra work to enforce this rule.

I do a lot of Java development, and it's years since I last used a Singleton. If I need access to another object I pass it in as a prameter (or at least, pass in a context or facade from which it can be reached).

If there should be only one of an object, I simply call "new" once, and pass in the same object each time. No Singleton, no threading issues.
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello Frank Carver

I had come up with an example and little description of my understanding about your explanation on coupling. Kindly correct me if I am wrong anywhere.

Example Code:



Please Note: This code works perfectly.



Regarding your first sentence - are you telling this because we couldn't pass the singleton instance dynamically just like we did for DogBreeds.

Regarding your second sentence - whats wrong with being singleton.

All I want to know is why singleton is bad and whats wrong with global access point.

I agree with your last post regarding classloader issue. I hope Tomcat too has seperate classloaders for every context.
[ June 25, 2006: Message edited by: rama murthy ]
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Now I got new doubt



I compiled all three classes and executed
(1)CallSingleton
(2)CallSingletonTwo

in that order.

Output:

D:\>java CallSingleton
Result of i value before modifying: 5
Result of i value after modifying: 160

D:\>java CallSingletonTwo
Result of i value is: 5

If there is ONLY ONE instance of singleton then why do I get the result as 5 while executing CallSingletonTwo? shouldn't it be 160?
 
Stan James
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You started the JVM with the Java command twice. There is only one instance per JVM (as coded) but the two JVMs have their own instances.

To test what you had in mind call your two classes from one JVM:
 
Ranch Hand
Posts: 1170
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Don't think of coupling as the enemy. Its just a part of programming. You can reduce it, but everything has considerations.

In your example code the class CallingTheDog is tightly coupled with DogBreedTwo. If you recompile DogBreedTwo, you must recompile CallingTheDog. However, we can remove this coupling using DogFactory.



Now our CallingTheDog class can be loosely coupled and will not require recompilation.


At first I had used DogFactory directly in CallingTheDog, then realized that DogFactory needs recompilation when any dog is compiled because it uses the dogs directly. So I had to create an interface that will NOT need recompilation since it does not use any other class. Then, create the class dynamically at runtime so no reference to DogFactory will appear in CallingTheDog. Now the coupling is broken. But at the same time, now you can pass any name into the getNewDog method. Some names will fail with exceptions. The compile time system can't check those names for you anymore. This is an unfortunate result of looser coupling. Hopefully I didn't make any big mistakes
[ June 22, 2006: Message edited by: Mr. C Lamont Gilbert ]
 
Frank Carver
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There are soem really interesting points about coupling in this thread. It would be too complex for me to take all these point by point, but I'll try my best to add my thoughts to the mix.

First, I'll agree that coupling itself is not a bad thing. Without it we would have no software, just a loose bag of lonely components. However, there are appropriate and inappropriate places to couple one class to another, and in my exprience, the inappropriate places vastly outnumber the appropriate ones. So I try (as a habit, because it works for me) to reduce or remove coupling wherever I can.

In my designs I typically try to localize explicit coupling to a single place in the delivered system. This might be in the "main" class, or it might be in a "production context" class, or whatever. For all other associations between classes I try to use interfaces to define available methods, and pass in parameters to specify which objects implement these interfaces. In the great bulk of my code you will only ever see the keyword "new" used to create instances of basic classes from the standard APIs, and even that is rare if I can get away with it.

It is important, though, to explain that this is only for the delivered code. I make a lot of use of unit tests (All new code I produce is developed "test first"), and in my test code I make a lot of use of direct calls to "new". My test cases typically create a mix of objects, some Mock or Stub Objects, some instances of domain classes to be tested, and some standard API objects. All of these are used to provoke and verify the behaviour of the domain code.

With all this in mind, and taking the "dog" example as a starting point, I might be more tempted to code something like:



Running the above program as

java CallingTheDog Amber Tarka Pepsi Polly

gives:

Calling for 'Amber' ... I'm 'Amber', I'm a Greyhound: woof!
Calling for 'Tarka' ... I'm 'Tarka', I'm a Border Terrier: yap yap!
Calling for 'Pepsi' ... no answer.
Calling for 'Polly' ... I'm 'Polly', I'm a Border Terrier: yap yap!

The only calls to "new" are in main, except for one which creates a HashMap for a cache to speed up searching.

The main "business" class DogCaller depends only on the interfaces Dog and Fetcher. An object implementing Fetcher is passed in as a constructor parameter, and an object implementing Dog is retrieved from the fetcher. Either of those objects could be substituted for test objects without the knowledge of the DogCaller class.

The DogFetcher class which implements the Fetcher interface only depends on the Dog interface. It knows nothing about the particular dogs or breeds in the system. All it knows is that it is given an array of objects which implement the Dog interface. Any or all of these objects could also be test objects without the knowledge of the DogFetcher class.

For example. To test the behaviour of the DogCaller class I might write a test something like:



Note that specialist test implementations of the two interfaces are created to work in a way more suited to testing (no writing to System.out, for example) and do only what is needed. Note also that the behaviour of the DogCaller class can be tested without the overhead of creating/initializing any other domain classes.

To me, this demonstrates some real advantages of designing for low coupling.
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Look here what I had come up with. An excellent implementation of factory method pattern. All thanks to Head First Design Pattern book authors and Mr. C Lamont Gilbert.

Even though it got nothing to do with Singleton since the code has come up so well explaining decoupling, I am pasting the code here.

 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello Stan James

Thanks for your response. I had this doubt in my mind for quite a long time. Thank you very much.

Hello Mr. C Lamont Gilbert

Thanks for your response. Your code example inspired me to extend and complete a full-fledged Factory method pattern.

Hello Frank Carver

Thanks for you excellent explanation along with code. I had made a note of your code.

--------------------------------------------------------------

Getting back to Singleton pattern

Singleton increases coupling through global access point. Kindly explain me how
(1) How global access point increases coupling
(2) Why global access point is bad

Here is an example that invokes Singleton.

public Class CallSingleton {
public static void main(String[] args) {
Singleton single = Singleton.getInstance();
}
}
 
Frank Carver
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmm.

Personally I still don't like coupling DogFactoryImplOne so closely to the actual Dog classes. This implies to me that you can't compile or test the Factory itself without all the Dog classes in the system in place.

I'm slso surprised that Dog (and indeed DogFactory) are abstract classes rather than interfaces. This approach makes it difficult to re-use existing test framework classes. If Dog is an interface, I could say:



And then test other classes using something like:



If Dog is an abstract class, I don't have that option.

I also really don't like naming classes SomethingImpl - that's implied by the "extends" or "implements", so I always suggest using the name to say what's different about this one - but that's a different issue.
 
Frank Carver
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Kindly explain me how
(1) How global access point increases coupling

A global access point increases coupling because all classes which use the Singleton are forced to use that particular implementation. This is a particular problem if the Singleton implementation relies on the presence of other classes or resources (such as a database, or a web server).

Imagine you wanted to test the behaviour of a class which happens to reference the Singleton. Even though you may not be testing the bit of the class which uses the Singleton, you still need to include the complete, real production implementation in your tests.

Now imagine you want to test how another class uses the Singleton. You can't replace it with one which recodrs which methods were called, or returns pre-specified values to compare against.

(2)Why global access point is bad

For all the reasons above.

Here is an example that invokes Singleton.

public Class CallSingleton {
public static void main(String[] args) {
Singleton single = Singleton.getInstance();
}
}

Sure. But if you are creating it in main, you might as well just call "new", and then pass the created object in to classes which use it. There is no need for it to be a Singleton unless the "getInstance" method is also called from other places in the code, in which case you hit all the coupling problems which we have described above.
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello Frank Carver

Thanks for your response.


I'm also surprised that Dog (and indeed DogFactory) are abstract classes rather than interfaces. This approach makes it difficult to re-use existing test framework classes.



Ok, as of now making DogFactory an interface makes more sense. But I cannot agree with what you had said about Dog class. Yes it is an abstract class. You can see a concrete method implementation - bark(). Currently there are only 3 implementations of DogBreed.

If suppose there are 10 (or) 20 implementations, imagine if there is a small change that I have to do in bark method then I have to goto all the 20 classes to chage it. Instead if I change it in Dog(abstract class) doesn't that chage gets reflected in all the implmentation classes that extends Dog class.

Here I make use of all the good benefits that inheritance offers me.


I also really don't like naming classes SomethingImpl - that's implied by the "extends" or "implements", so I always suggest using the name to say what's different about this one - but that's a different issue.



I agree with you. I never thought a simple example to explain what I understood would turn into such a brief discussion. I will make sure future class names are more meaningful.

Thanks again.
 
Frank Carver
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I cannot agree with what you had said about Dog class. Yes it is an abstract class. You can see a concrete method implementation - bark(). Currently there are only 3 implementations of DogBreed.

If suppose there are 10 (or) 20 implementations, imagine if there is a small change that I have to do in bark method then I have to goto all the 20 classes to chage it. Instead if I change it in Dog(abstract class) doesn't that chage gets reflected in all the implmentation classes that extends Dog class.

Here I make use of all the good benefits that inheritance offers me.

I completely agree that extending your Dog implementations from an abstract base class is good practice. A base class to share behaviour common to a group of classes is a good idea. If you look back to my example a few posts back, that's just what I do.

The difference is that the definition of the methods which must be provided by all Dog implementations is an interface in my version. By doing that I am free to create other completely different classes based on other, different base classes (perhaps a Servlet which is also a Dog, or a MockDog based on a test class as I describe above).

Making the definitive Dog an abstract class prevents this behaviour, and for no obvious gain, since createing an abstract class which implements Dog and provides your shared behaviour is a cheap and simple option.
 
rama murthy
Ranch Hand
Posts: 82
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


The difference is that the definition of the methods which must be provided by all Dog implementations is an interface in my version. By doing that I am free to create other completely different classes based on other, different base classes (perhaps a Servlet which is also a Dog, or a MockDog based on a test class as I describe above).



Thanks.

I was wondering why you had specified an interface first and provided implementation in abstract class.
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Frank Carver:
if you are creating it in main, you might as well just call "new", and then pass the created object in to classes which use it.



So true. The "Just Create One" pattern - I very much prefer that over using a Singleton. With Just Create One, clients simply don't need to know where their instance is coming from -> reduced coupling, easier unit testing and reuse etc. pp.
 
Mr. C Lamont Gilbert
Ranch Hand
Posts: 1170
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes but if you 'just create one' and pass it, then you will have LOTS of code involved in passing around a single object. If this is your only purpose I would much rather use a singleton.

To be fair I have not experienced a situation where a singleton caused me an issue down the road that another implementation would not have caused.

I agree about Dog being an Interface and not an abstract class, even if you want to keep the Abstract class and make it implement the interface.

I don't agree with decoupling the Dogs from their Factory. For me this goes too far and does not achieve much. And in fact loose coupling removes some of the validation the compiler is able to provide. I only decouple on the boundary of a package. Within a package I don't bother decoupling. Everyone will have to draw their own line I suppose.

For instance, generally my packages consist of all package scope classes except one. All methods are public or private. The one class is a factory that is public and returns 'interface's which are defined in some external package.
 
Stan James
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Another thing to consider with a default abstract class plus an interface vs just an abstract base class is: Who owns the interface? You can put the interface in an abstract stable, shrink-wrapped package that never changes, and put the default abstract class in a more dynamic and concrete package. It might be that a generic services team owns the interface and any number of business application teams can have their own default implementations. Even if you write 100% of the code yourself it can be useful to imagine that some parts of the system are purchased binaries that are closed for modification while other parts are the things you modify for business advantage.
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Mr. C Lamont Gilbert:
Yes but if you 'just create one' and pass it, then you will have LOTS of code involved in passing around a single object.



I find that in a good design, most objects actually do not need to be passed around that lot.

If this is your only purpose I would much rather use a singleton.



There are a few situations in which I'd use a singleton, too - loggers come to mind, for example.

But in most cases I find that my designs improve significantly when I think about how to avoid Singletons and still have a design I like to work with. That's why my "default reaction" to them is not to use them.

To be fair I have not experienced a situation where a singleton caused me an issue down the road that another implementation would not have caused.



So how do you unit test the clients of the Singleton?
 
Frank Carver
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ilja: There are a few situations in which I'd use a singleton, too - loggers come to mind, for example.

I don't even use Singleton for this these days. I reckon that if logging is important enough to put in the application, it's important enough to test.

One of the advantages of defining all expected behaviour in interfacs is that it leaves base classes free for application-specific data and behaviour. Typically I address the issue of logging using a combination of two approaches.

Wherever possible I extend my application classes from a class with services common to the application e.g. :



In any given application, this base class may also include other application-common behaviour.

As I mentioned above, I hardly ever use "new" on domain classes inside my production code, instead preferring a single point of setup, so this approach covers most cases.

For domain classes which cannot extend a base class, or situations where there is a lot of shared behaviour which would overcomplicate such a base class, I use a parallel approach of creating an "application context" - a single instance of a facade class, made using "just create one" and passed where needed, e.g.:



By slightly changing the base class to keep/provide a reference to such a context rather than just a logger, and passing it in as a paremeter in the few cases where this is not possible, I am able to "inject" even things which would otherwise seem to need a Singleton.

When used in conjunction with OO techniques such as the "tell, don't ask" principle and the "command object" pattern, this acts to greatly reduce the amount of parameter passing, and thus largely removes the impact on the code of changes and additions to such system-wide services.

Example client code might look like:



Calling mehods directly on the results of other methods can appear a little risky, and "bends" the Law of Demeter, but seems a safe enough compromise in practice compared with tediously adding proxy methods to the context for every method of every class it manages.

Thoughts?
[ June 27, 2006: Message edited by: Frank Carver ]
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Frank, I agree in general - in fact we are using context objects a lot.

I should have said "There are a few situations in which I might sometimes use a singleton, too" - that is, I wouldn't totally rule it out, although I'm always *very* reluctant to introduce one.
 
Frank Carver
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I thought that was what you meant, really. I just relished the chance to appear more "extreme"
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Frank Carver:
I thought that was what you meant, really. I just relished the chance to appear more "extreme"




Hello all, first post for me, be gentle
Don't you bring a dependency problem by using your 'Context'?
An object that used to only need knowledge of some kind of Logger, is now forced to depend on a full 'Context' interface.
I see that as a reusability problem, but maybe i'm wrong
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Ga�tan Remy:



Hello all, first post for me, be gentle
Don't you bring a dependency problem by using your 'Context'?
An object that used to only need knowledge of some kind of Logger, is now forced to depend on a full 'Context' interface.
I see that as a reusability problem, but maybe i'm wrong



Well, yes. I would only do that when it needs more from the context than just the logger, for example. In fact I typically start by passing around single objects, and only when I notice that a cluster of objects all need the same other objects passed into, I create the context object.

I.e. "all those classes that have to do with creating a report not only need the logger, but also the report format and the report variable resolver. So let's create a ReportCreationContext that contains all those 'just create one's."

But even then there is often some dependency introduced that could be avoided by using a Singleton. It's just that those dependencies typically trouble me much less than those introduced by using the Singleton pattern - I think because they are typically more localized and thereby easier to change.
[ June 27, 2006: Message edited by: Ilja Preuss ]
 
Frank Carver
Sheriff
Posts: 7001
6
Eclipse IDE Python C++ Debian Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I agree with Ilja. It's vital to always remember that such patterns and idioms are only to be applied when actually necessary. No such technique is ever useful in all cases, and nothing trumps well-factored code which does exactly what is required and no more.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic