How do you write code? You just write code.
public static void main(String[] args) {
new WhatDayIsIt().printDay();
}
public class WhatDayIsIt {
void printDay() {
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("cccc")
.withLocale(Locale.UK)
.withZone(ZoneId.of("Europe/London"));
System.out.println(formatter.format(Instant.now()));
}
}
What are the "dependencies" of printDay?
void printDay() {
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("cccc")
.withLocale(Locale.UK)
.withZone(ZoneId.of("Europe/London"));
System.out.println(formatter.format(Instant.now()));
}
What are the "dependencies" of printDay?
void printDay() {
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("cccc")
.withLocale(Locale.UK)
.withZone(ZoneId.of("Europe/London"));
System.out.println(formatter.format(Instant.now()));
}
What are the "dependencies" of printDay?
void printDay() {
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("cccc")
.withLocale(Locale.UK)
.withZone(ZoneId.of("Europe/London"));
System.out.println(formatter.format(Instant.now()));
}
What about formatter?
void printDay() {
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("cccc")
.withLocale(Locale.UK)
.withZone(ZoneId.of("Europe/London"));
System.out.println(formatter.format(Instant.now()));
}
What about formatter?
Key question:
// Given a PrintStream
ByteArrayOutputStream os = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(os);
// And a Thursday in 2019
Clock clock = Clock.fixed(
ISO_INSTANT.parse("2019-09-12T16:04:00Z").query(Instant::from),
ZoneId.of("Europe/London"));
// When we print the day
WhatDayTestable wd = new WhatDayTestable(ps, clock);
wd.printDay();
// Then we printed Thursday!
assert os.toString().equals("Thursday\n");
WhatDayTestable(PrintStream printStream, Clock clock) {..}
void printDay() {
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("cccc")
.withLocale(Locale.UK)
.withZone(ZoneId.of("Europe/London"));
printStream.println(formatter.format(Instant.now(clock)));
}
What about formatter?
Manual injection:
public static void main(String[] args) {
PrintStream ps = System.out;
Clock clock = Clock.systemUTC();
new WhatDayTestable(ps, clock).printDay();
}
Injection via framework:
public static void main(String[] args) {
Injector injector = Guice.createInjector(
new AbstractModule() {
@Override
public void configure() {
bind(PrintStream.class).toInstance(System.out);
bind(Clock.class).toInstance(Clock.systemUTC());
}
}
);
injector.getInstance(WhatDayGuice.class).printDay();
}
Dependency Injection frameworks mean you don't have to write this:
public static void main(String[] args) {
PrintStream ps = System.out;
Clock clock = Clock.systemUTC();
new WhatDayTestable(ps, clock).printDay();
}
Instead you just write this:
public static void main(String[] args) {
Injector injector = Guice.createInjector(
new AbstractModule() {
@Override
public void configure() {
bind(PrintStream.class).toInstance(System.out);
bind(Clock.class).toInstance(Clock.systemUTC());
}
}
);
injector.getInstance(WhatDayGuice.class).printDay();
}
E.g. for constructors:
$ grep 'new WhatDayGuice'
... silence ...
(Also for setters.)
bind(PrintStream.class).toInstance(System.out);
bind(Clock.class).toInstance(Clock.systemUTC());
vs.
PrintStream ps = System.out;
Clock clock = Clock.systemUTC();
What did you do to my unit test?
Injector injector = Guice.createInjector(
new AbstractModule() {
@Override
public void configure() {
bind(Clock.class).toInstance(clock);
bind(PrintStream.class).toInstance(ps);
}
}
);
WhatDayGuiceNoConstr wd = injector.getInstance(
WhatDayGuiceNoConstr.class);
Reasons to use them:
If you are too lazy to write this code:
class MyClass {
MyClass(Dep1 dep1, Dep2 dep2, Dep3 dep3) {
this.dep1 = dep1;
this.dep2 = dep2;
this.dep3 = dep3;
}
}
If you are too lazy to write this code:
class MyClass {
MyClass(Dep1 dep1, Dep2 dep2, Dep3 dep3) {
this.dep1 = dep1;
this.dep2 = dep2;
this.dep3 = dep3;
}
}
Use Kotlin.
Reasons to use them:
If you are too lazy to write this code:
Dep1 dep1 = new Dep1();
Dep2 dep2 = new Dep2(dep1);
Dep3 dep3 = new Dep3(dep1);
MyClass mine = new MyClass(dep1, dep2, dep3);
If you are too lazy to write this code:
Dep1 dep1 = new Dep1();
Dep2 dep2 = new Dep2(dep1);
Dep3 dep3 = new Dep3(dep1);
MyClass mine = new MyClass(dep1, dep2, dep3);
Dragon up.
Dragon up.
A programmer not thinking about dependencies is like a farmer not thinking about irrigation.
Yes, you might grow something.
Or you might not.
Here is our example again:
WhatDayTestable(PrintStream printStream, Clock clock) {..}
void printDay() {
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("cccc")
.withLocale(Locale.UK)
.withZone(ZoneId.of("Europe/London"));
printStream.println(formatter.format(Instant.now(clock)));
}
How about this instead?
String printDay(Instant time) {
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("cccc")
.withLocale(Locale.UK)
.withZone(ZoneId.of("Europe/London"));
return formatter.format(time);
}
static void main(String[] args) {
System.out.println(
new WhatDayBeing().printDay(Instant.now()));
}
printDay converts Instants to day names.
Most of your code should be low-dependency.
Isolate highly-dependent code.
Consider making a distinction between: