I'm about to write a Java library. Basically, this library provides something like this to its user:
interface Foo {
void doA();
boolean aWorked();
void doB(int value);
}
The user is not supposed to implement this interface (obviously). Thus, user code will look something like this:
Foo f = Library::SomeFactory();
if (someDecison()) {
f.doA();
if (!f.aWorked()) {
f.doB(21);
}
} else {
f.doB(42);
}
I can make sure that neither preconditions nor postconditions of the methods in the interface change in the future. But there might be a new method, say doC()
.
Now, various resources including Orcale's Docs suggest that just adding this doC()
to above interface is a bad idea. They propose different solutions from extending the interface ...
interface Foo2 : extends Foo {
void doC();
}
... to blowing the code up with command patterns and what not. But the supporting reason is always that "all implementing classes must be changed". That's not an issue in my case, as all implementing classes are "under my control" and will need to be changed either way (when there's a doC()
).
Is simply adding the method to Foo
really a bad idea? And if so, why? Is there anything that I'm not taking into account here? My primary goal is to not break any user code written against that interface.
// That's what I'm planning
interface Foo {
void doA();
boolean aWorked();
void doB(int value);
void doC();
}
This source supports my feeling that it can be as simple as that:
[..] If the method is added to a class (interface) which Clients are not allowed to subclass (to implement), then it is not a breaking change. [..]
foo1.Foo
,foo2.Foo
, .. perhaps I'm also over thinking this.f.doA(); if(f.aWorked()) f.doB(21);
? Or will those statements always execute one right after the other?