4. It’s got a lot of code.
But a little while ago, I started to think it’s not as good
as I thought when we were first getting started.
So I got to work.
Here’s what I found.
8. first second
name searchForProperties
buying or
renting?
boolean renting PurchasingType
monthly budget int monthlyBudget Budget
centre
coordinates
double latitude,
double longitude
Coordinate
maximum
distance
double
distanceFromCentre
Radius
return type Stream<Integer> Stream<PropertyId>
Readability
9. Readabilityreadable
/ˈriːdəb(ə)l/
adjective
1. able to be read or deciphered; legible.
“a code which is readable by a computer”
synonyms:
legible, easy to read, decipherable, easily deciphered,
clear, intelligible, understandable, comprehensible, easy to
understand
“the inscription is still perfectly readable”
antonyms:
illegible, indecipherable
2. easy or enjoyable to read.
“a marvellously readable book”
10. Readabilityreadable
/ˈriːdəb(ə)l/
adjective
1. able to be read or deciphered; legible.
“a code which is readable by a computer”
synonyms:
legible, easy to read, decipherable, easily deciphered,
clear, intelligible, understandable, comprehensible, easy to
understand
“the inscription is still perfectly readable”
antonyms:
illegible, indecipherable
2. easy or enjoyable to read.
“a marvellously readable book”
16. public final class PropertyId {
private final int value;
public PropertyId(int value) {
this.value = value;
}
public SearchQuery<Property> query(
DatabaseConnection connection) { ... }
public void renderTo(Somewhere else) { ... }
// equals, hashCode and toString
}
Readability
17. Readability
What does PropertyId do?
SearchQuery<Property> query
(DatabaseConnection connection)
void renderTo(Somewhere else)
new PropertyId(int value)
String toString()
boolean equals(Object other)
int hashCode()
18. Readabilityaddition
multiplication
subtraction
division
modulus
negation
bit manipulation operations such as &, |, ^ and ~
further bit manipulation functionality from java.lang.Integer (I count 9 separate methods)
equality
hashing
comparison with other integers
treatment as an unsigned integer
treatment as a sign (the Integer.signum function returns a value representing negative, positive or zero)
conversion to and from other number types (such as double)
conversion to and from strings in decimal, hexadecimal, octal and binary
all of the other methods on java.lang.Integer
What does int do?
21. public final class PropertyId {
private final int value;
public PropertyId(int value) {
this.value = value;
}
public SearchQuery<Property> query(
DatabaseConnection connection) { ... }
public void renderTo(Somewhere else) { ... }
// equals, hashCode and toString
}
Searchability
23. public final class PropertyId {
private final int value;
public PropertyId(int value) {
this.value = value;
}
public SearchQuery<Property> query(
DatabaseConnection connection) { ... }
public void writeTo(Somewhere else) { ... }
// equals, hashCode and toString
}
Searchability
27. public SearchQuery<PropertyId> searchForProperties(
PurchasingType purchasingType, Budget budget, Area area)
{
Area rectangle = area.asRectangle();
return connection
.query(“SELECT * FROM property”
+ “ WHERE purchasing_type = ?”
+ “ AND budget <= ?”
+ “ AND longitude BETWEEN ? AND ?”
+ “ AND latitude BETWEEN ? AND ?”,
purchasingType.name(), budget.inGBP(),
rectangle.minX(), rectangle.maxX(),
rectangle.minY(), rectangle.maxY())
.filter(row ->
area.contains(row.getDouble(“latitude”),
row.getDouble(“longitude”)))
.map(row -> new PropertyId(row.getInt(“id”)));
}
Flexibility
28. public final class PropertyId {
private final int value;
...
}
Flexibility
30. public final class PropertyId {
private final int value;
...
}
public final class PropertyId {
private final UUID value;
private final int humanRepresentation;
...
}
Flexibility
33. Correctness
In his book, Understanding the Four Rules of Simple
Design, Corey Haines talks about a really important
concept in software design.
He calls things that embody this concept,
behaviour attractors.
34. public Stream<Integer> searchForProperties(
boolean renting,
int monthlyBudget,
double latitude,
double longitude,
double distanceFromCentre) {
if (distanceFromCentre <= 0) {
throw new IllegalArgumentException(
“The distance from centre must be positive.”
+ “ The value was ” + distanceFromCentre);
}
...
}
Correctness
35. public Stream<Integer> searchForProperties(
boolean renting,
int monthlyBudget,
double latitude,
double longitude,
double distanceFromCentre) {
check(“distance from centre”,
distanceFromCentre,
is(greaterThan(0)));
...
}
Correctness
36. public final class Radius {
public static Radius of(
@NotNull double magnitude,
@NotNull DistanceUnit unit) {
check(“magnitude”,
magnitude, is(greaterThan(0)));
return new Radius(magnitude, unit);
}
private Radius(
@NotNull double magnitude,
@NotNull DistanceUnit unit) { ... }
...
}
Correctness
37. Correctness
I haven’t been totally honest with you.
There’s more code than you thought.
Except it’s not really code.
38. /**
* Searches for properties in the database
* matching the specified parameters.
*
* @param renting True if renting, false if buying.
* ...
* @return A stream of property IDs.
* @throws DatabaseQueryException if there is a connection error.
*/
public Stream<Integer> searchForProperties(
boolean renting,
int monthlyBudget,
double latitude,
double longitude,
double distanceFromCentre) {
check(distanceFromCentre,
is(greaterThan(0)));
...
}
Correctness
39. /**
* Searches for properties in the database
* matching the specified parameters.
*
* @throws DatabaseQueryException
* if there is a connection error.
*/
Stream<PropertyId> searchForProperties(
PurchasingType purchasingType,
Budget budget,
Area area) { ... }
Correctness
40. public interface SearchQuery<T> {
/**
* @throws DatabaseQueryException
* if there is a connection error.
*/
public Stream<T> fetch();
/**
* @throws DatabaseQueryException
* if there is a connection error.
*/
public T fetchOne();
}
Correctness
41. public interface SearchQuery<T> {
public Stream<T> fetch()
throws DatabaseQueryException;
public T fetchOne()
throws DatabaseQueryException;
}
Correctness
69. public final class ShortList {
Set<ShortListedProperty> shortList;
List<ShortListedProperty> sortedShortList;
Map<City, List<ShortListedProperty>> byCity;
Set<City> cities;
List<ShortListedProperty> upForAuctionSoon;
Optional<Property> randomPromotedAuction;
List<Property> highlighted;
...
}
Efficiency
70. Efficiency
Here’s the magic bullet.
We don’t need to optimise our algorithms.
The database author already did that.
We just need to write code that does less.
71. public final class ShortList {
Map<City, List<ShortListedProperty>> byCity;
Set<City> cities;
List<Property> highlighted;
...
}
Efficiency
76. Quoting @jbrains (who was paraphrasing Kent Beck),
“I define simple design this way.
A design is simple to the extent that it:
1. Passes its tests
2. Minimizes duplication
3. Maximizes clarity
4. Has fewer elements”
http://www.jbrains.ca/permalink/the-four-elements-of-simple-design
77. 1. Passes its tests
2. Minimizes duplication
3. Maximizes clarity
4. Has fewer elements