You Cant Encapsulate Everything

But you can get damn close

Take your typical static singleton.

 class Service{
public static void doFoo(){
...
}
 }
Not great, you can't control access in any way shape or form. Heck, you need editor support to simply find access in any codebase larger than a couple classes. So we change it to a singleton instance, hide the constructor, and make a static method to access it:
 class Service{
public static Service instance(){
return instance;
}

static private Service instance = new Service();

private Service(){};

public void doFoo(){ ... } }
Better, you can programmatically control access through the 'instance()' method. But what if the Service is to, say, launch a nuclear strike... okay okay, say it's to edit a live customer database. How do you test this? Send test data to your live database? Ya donta wanna be doin dat, do ya? Cheesy examples and accents aside, that's just asking for trouble. But we're good... create a method to allow us to pass in a mock instance.
 class Service{
public static Service instance(){
return instance;
}

public static void setInstance(Service newInstance){ instance = newInstance; }

static private Service instance = new Service();

private Service(){};

public void doFoo(){ ... } }
Getting better still, but we still have that static method. Now supposing the live code (not under test) caches their reference to the instance. This is good... they're unaffected by the switch, and all's well. Now, suppose they call the static method each time? Not good; for the duration of the test, real live calls will get passed to the mock service instead of the real one. Well, you can wrap it in a factory object... to be honest, you can really do anything you like with it.

What I'm getting at is you can always add the extra layer of indirection, for the sake of testing, 'simplicity', or whatever... but somewhere, there's going to be a static method, or the equivalent of a static method, and you're not going to be able to control access, and therefore there will be that single untested point.

And ya know what? Don't sweat it! Make that single call as clear and as transparent as possible, and then forget about it. Don't let it spread, but don't go overboard. If, after you've done everything you can do to make it simple, clear and obvious, you can't tell if it's correct, well, perhaps you should consider alternate employment :).

Case in point:

 System.out.println("TESTING");
If that doesn't spit out 'TESTING' in the console, it'll take 2 seconds to find out that it isn't the static method call (in this case, the static reference to 'out'), and you can start looking elsewhere.

I offer this... please pick it to pieces and correct my youthful exaggerations (HaHaOnlySerious)

-- WilliamUnderwood


EditText of this page (last edited April 21, 2010) or FindPage with title or text search