I often use the notion of interface and implementation dependencies, where interface dependencies are mostly always smaller. I think this is a very important concept to understand for Java developers, and although it seems obvious and self evident, many developers do not think along those lines and still couple classes too tightly.
Take this example:
class CassandraStorage { public void store(String key, String value) { otherPartOfApp.doSomething(); yetAnotherPart.doSomethingElse(); cassandraClient.store(key,value); } } class MyApp { @Inject CassandraStorage storage = null; public void myCode() { ... } }
The dependency chain for MyApp
is:
MyApp -> CassandraStorage -> Cassandra Framework -> Many many more -> Many other parts of application
The problem with this are the many dependencies the implementation of the Storage
class introduces. When we add an interface, decoupling the usage from the implementation, we can decrease the numbers of dependencies significantly.
interface Storage { void store(String key, String value); } class MyApp { @Inject Storage storage = null; public void myCode() { ... } }
The dependency chain now only includes
MyApp -> Storage
broken away from
CassandraStorage -> Storage
with some benefits:
- This breaks dependency chains early
- Speeds up compilation
- Easier to modularize
- Helps break cycles
So use the concept of interface and implementation dependencies, where interface dependencies are mostly always smaller. I think this is a very important concept to understand for Java developers, and although it seems obvious, many do not think along those lines.