Context:
I'm java programmer and reading Uncle Bob Agile Software Development. Regarding ISP Interface Segregation Principle there is given an argument which I understand as:
Lets have:
interface Service {
function doA();
}
class ServiceImpl implements Service {...}
class ServiceClient {
// ServiceImpl is injected; eg either through constructor or setter
private Service service;
function useOnlyDoA() {
service.doA();
}
}
And now, if interface Service changes, e.g. method doB()
is added, then all dependent classes e.g. ServiceClient
have to be recompiled, even if they don't use added method! (really??)
I lived in conviction that regarding java if ServiceClient
is in package e.g. client.jar
, interface Service
in service.jar
and ServiceImpl
in impl.jar
, then client.jar
doesn't have to be recompiled and rebuild if it doesn't use new methods from Service interface and it can be used together with new versions of service.jar
and impl.jar
. It seems to me that things go this way in java.
Is it other in eg c++ or some other languages?
Possibly in c++ much more is broken, eg https://stackoverflow.com/a/4033900/1423685
To make it clear:
I'm not asking about recompiling class implementing changed interface (this is obvious, it class has to implement new added method). But I am asking if I have to recompile class ServiceClient which is using this interface even when class isn't using new added methods. Possibly in c++ BC changes and client really has to be recompiled, but it seems to me that not in java.
Edit:
I implemented a test in java. 4 jars:
public interface Service
public class ServiceImpl implements Service
ClientOfService
taking Service
as a constructor parameter, uses this service in it's doA()
method
public static void main(String[] args) {
Service service = new ServiceImpl();
ClientOfService clientOfService = new ClientOfService(service);
System.out.println("App.main() :: calling clientOfService.doWorkCallingDoAFromService");
clientOfService.doWorkCallingDoAFromService();
System.out.println("App.main() :: end of main");
}
The main in App run successfully after change of interface.jar and implementation.jar (I added some unused methods and removed one old method).
So the challenge is how to change interface (of course without changing doA()
method declaration) and implementation to stop it running successfully? Is it possible? If so, how?
Yes, if you change the interface, you need to recompile the classes that implement it in Java and in C++. This has several reasons, among others:
vtable
if doB() is virtual), and verify if another member function with the same signature but in another base class is not hidden by the newly created one. The whole thing of the ISP is to avoid such situations. So if doB()
has in reality nothing to do with this interface, you'd better go for a segregated interface with just doB()
, and change/recompile only the classes that need to implement it.
Edit: The same principle applies to classes that use the interface. Some of the arguments may of course be implementation dependent:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With