21. Dependency Management
• Put less transitive dependencies
• Do you really need that commons-lang?
• Do you remember about Guava
incompatibilities
Extreme example: OrientDB - zero dependencies!
26. Gadget gadget = new Gadget(name, id, options);!
// Gadget is connected at this point
public Gadget(name, id, options) {!
this.name = name;!
this.id = id;!
this.options = options;!
connect(); // could throw an exception!
}
Gadgets should always be connected
Can not create an instance
for testing
27. Create Gadget by static method or factory class
public Gadget(name, id, options) {!
this.name = name;!
this.id = id;!
this.options = options; !
}!
!
public static Gadget newGadget(name, id, options) {!
Gadget gadget = new Gadget(name, id, options);!
gadget.connect();!
return gadget;!
}!
!
public class GadgetFactory {!
public Gadget newGadget(name, id, options) {!
Gadget gadget = new Gadget(name, id, options);!
gadget.connect();!
return gadget;!
} !
}
28. public static Gadget newGadget(name, id, options) {!
Gadget gadget = new DefaultGadget(name, id, options);!
gadget.connect();!
return gadget;!
}!
!
public interface Gadget {!
void connect();!
}!
!
public class DefaultGadget implements Gadget {!
public void connect() {!
}!
}
Hide your gadget behind interface
Because you could change the implementation
Details are well hidden
29. public static Gadget newGadget(name, id, options) {!
Gadget gadget = new DefaultGadget(name, id, options);!
gadget.connect();!
return gadget;!
}!
!
public interface Gadget {!
void connect();!
}!
!
public final class DefaultGadget implements Gadget {!
DefaultGadget() {!
}!
public void connect() {!
}!
}
Make it final with package-level constructor
Disallow
unsanctioned
modification of
your code
30. Open Closed Principle
"software entities (classes, modules, functions, etc.) !
should be open for extension, but closed for modification"
public final class DefaultGadget implements Gadget {!
public void setStrategy(BehaviorStrategy s) {!
// changes the behavior of this Gadget;!
}!
}
Allowing
sanctioned
modifications
31. Gadget gadget = Gadgets.newGadget(name, id, options);!
// Gadget is connected at this point!
!
!
// Similar APIs!
Files.createFile(...); // JDK 7!
Lists.newArrayList(...); // Guava
Resulting code
32. Method Overloading
Gadget gadget = Gadgets.newGadget(name, id, options);!
Gadget gadget = Gadgets.newGadget(id, options);!
Gadget gadget = Gadgets.newGadget(name, options);!
Gadget gadget = Gadgets.newGadget(id, enabled);!
Gadget gadget = Gadgets.newGadget(id, name, enabled);!
What if different parameter
combinations should be supported?
36. Gadget Service
public final class GadgetService {!
!
private static final GadgetService instance = new GadgetService();!
!
public static void getInstance() {!
return instance;!
}!
!
public void saveGadget(Gadget gadget) {!
...!
}!
}
Static fields may produce memory leaks
Difficult to test code using that
37. Gadget Service
public class GadgetServiceImpl implements GadgetService {!
!
// To be called by factory method/class!
public GadgetServiceImpl() {}!
!
public void saveGadget(Gadget gadget) {!
...!
}!
!
}!
!
!
public class MyClass {!
@Inject!
GadgetService service;!
}
Everyone is using
Dependency
Injection now
38. You do not know which
Dependency Injection
framework
developers will use!
Spring, Guice, CDI, Dagger, PicoContainer etc.
39. Abstract DI
public interface BeanRegistry {!
!
void register(Class<?> type);!
!
<T> T getBean(Class<T> type);!
!
<T> Collection<T> getBeans(Class<T> type);!
!
}
https://github.com/DozerMapper/dozer/blob/master/core/src/main/java/org/dozer/inject/
DozerBeanContainer.java
40. Provide DI Bindings
• Write bindings for other frameworks
• Your beans are accessible
• Ready for the next big thing
public class SpringBeanRegistry implements BeanRegistry {!
public SpringBeanRegistry(ApplicationContext context) {!
//..!
}!
}
41. Make your api Extensible
interface Plugin {!
void init(Context context);!
}
How to allow
people to
contribute
extensions?
57. public Object someServiceMethod() {!
return transactionTemplate.execute(new TransactionCallback() {!
!
// the code in this method executes in a transactional context!
public Object doInTransaction(TransactionStatus status) {!
updateOperation1();!
return resultOfUpdateOperation2();!
}!
});!
}
Same approach in Spring Framework