One of the little-appreciated consequences of subclassing or alternative implementations of Java interfaces is to reduce or eliminate “future bugs”.
“Future bugs” are bugs that are currently not wrong, but will cause problems in the future. Every conditional ( if, ? :, or switch ) is a “future bug”.
For example, in this simplistic example code, there are multiple checks for this.enableLogging. If new code is added then the developer has to constantly remember to check for the this.enableLogging.
public class Foo {
private final boolean enableLogging;
public Foo(boolean enableLogging) {
this.enableLogging = boolean enableLogging; }
public void stuff1() {
.....
if ( this.enableLogging ) {
Log.warning("here in stuff1");
}
.....
if ( this.enableLogging ) {
Log.debug("still here in stuff1");
}
}
public void stuff2() {
.....
if ( this.enableLogging ) {
Log.info("here in stuff2");
}
.....
if ( this.enableLogging ) {
Log.debug("still here in stuff2");
}
}
}
Of course sane developers will say that this is silly code, follow the DRY principle and have something like this:
public class Foo {
private final boolean enableLogging;
public Foo(boolean enableLogging) { this.enableLogging = boolean enableLogging; }
public void stuff1() {
.....
warning("here in stuff1");
.....
debug("still here in stuff1");
....
}
public void stuff2() {
.....
info("here in stuff2");
.....
debug("still here in stuff2");
}
private void warning(String message) {
if (this.enableLogging) {
Log.warning(message);
}
}
private void info(String message) {
if (this.enableLogging) {
Log.info(message);
}
}
private void debug(String message) {
if (this.enableLogging) {
Log.debug(message);
}
}
}
This is good enough for this simplistic example. However, consider a more realistic case with complex conditionals:
public class Foo {
private final boolean enableCall;
private final boolean enableEmail;
public Foo(boolean enableCall, boolean enableEmail) {
this.enableCall = enableCall;
this.enableEmail = enableEmail; }
public void stuff1() {
.....
if ( this.enableCall || this.enableEmail) {
doThing1();
} else if (this.enableEmail || this.bigCheck() ) {
... lots of stuff1 lines .....
} else {
.. some different things here....
}
}
public void stuff2() {
.....
if ( this.enableCall || !this.enableEmail ) {
doThing1();
} else if (this.enableEmail || this.bigCheck() ) {
... lots of stuff2 lines .....
} else {
.. some different things for stuff2() here....
}
}
private void doThing1() { ... }
private boolean bigCheck() { .... }
}
...
public class Bar() {
....
Foo foo = new Foo(true, false);
....
Foo foo1 = new Foo(false, true);
}
Do you see the bugs?
- Notice that in stuff2() the first conditional is different than the first conditional in stuff1(). Is this a bug? Who knows? ( Lets assume it is )
- Because the only users of Foo set either enableCall or enableEmail, the only actual code paths through Foo.stuff1() and Foo.stuff2() result in calls to doThing1()
A developer just inspecting Foo can find neither issue easily.
Subclassing/alternative interface implementations solve this problem. The subclass created decides, at object creation, all the conditionals.
So the above code becomes:
public interface Foo {
void stuff1();
void stuff2();
}
// this.enableCall || this.enableEmail case ( The original stuff2() check was wrong )
public class Foo1Impl() implements Foo {
public void stuff1() { doThing1(); }
public void stuff2() { doThing1(); }
private void doThing1() { .... }
}
// !this.enableCall && this.enableEmail case
public class Foo2Impl() implements Foo {
public void stuff1() { if (bigCheck() ) { ... lots of stuff1 lines ..... } }
public void stuff2() { if (bigCheck() ) { ... lots of stuff2 lines ..... } }
private boolean bigCheck() { .... }
}
public class Foo3Impl() implements Foo {
public void stuff1() {
.. some different things for stuff1() here.... }
public void stuff2() {
.. some different things for stuff2() here.... }
}
public class Bar() {
....
Foo foo = new Foo1Impl();
....
Foo foo1 = new Foo1Impl();
}
Note the consequences of this division,
- doThing1() can only be called by a Foo1Impl.
- bigCheck() is isolated to Foo2Impl
- depending on bigCheck()’s implementation, bigCheck() may be could be called once to determine if Foo2Impl or Foo3Impl is created.
- There is no question about the stuff2() check being correct or incorrect. ( the conditional no longer exists! )
- And it is now obvious that only Foo1Impl’s code path is used. If this is a bug, the bug is now obvious. If not then the Foo2Impl and Foo3Impl code can be eliminated.




Privacy is best offline
Art PettyEric Rodriguez has a blog post about being fired for what is said on Facebook.:ArtEric Rodriguez is repeating “and the sky is blue” reminders and unfortunately people do need to be reminded that the “sky is blue”. And that things “are not fair”.<snark>Zuckerberg would be very upset with
ArtEric Rodriguez. After all, you should want to share, and share, and share!</snark>My solution is very simple. I am very minimalist online. I don’t create content online. This is especially true on something like Facebook.
I am not about to put my career in the hands of the never-ending privacy policy changes coming from Facebook or any other website owner.
Look at the questions asked by Facebook:
Most of the content that I create is on my blog, hosted on my server. When I say something online, if it is longer than a paragraph, then I just write a overview and a link to my blog. If I ever decide to delete the content, it is deleted.
Sure someone could go through the effort to copy my blog, but at least its a *manual* effort on their part.
In an age where google searches are easy, there are only a few defenses. The best one is to not post content on external sites. Quite simply anything written down can be held against you.
I find it incredibly revealing that the people who loudly proclaim that privacy is dead are well-off and able to financially deal with the impacts of private information being public.
Eric Schmidt, former CEO of Google, is a good example. But even he reacted strongly when his privacy was invaded. In 2005, Cnet reporters were banned access to Google.
Five years later, Eric Schmidt seems little changed:
If this is so true, then why is Eric still sensitive about all his private information?
For me, I am help with a very common name including very famous people with an identical name. Google searching me turns up bad information. And that is just fine by me.
Update ( 18 March 2011): Brad Feld, a VC, seems to have rediscovered the value of privacy:
Brad describes a repeated call and then concludes: