SlideShare a Scribd company logo
1 of 79
Download to read offline
UseYour Type System;
Write Less Code
13th October 2015
@SamirTalwar
So I’ve got this website.
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.
Readability
Readability
Tell me what’s more readable.
public Stream<Integer> searchForProperties(

boolean renting,

int monthlyBudget,

double latitude,

double longitude,

double distanceFromCentre) { ... }
public Stream<PropertyId> abc(

PurchasingType def,

Budget ghi,

Coordinate jkl,

Radius mno) { ... }
Readability
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
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”
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”
Stream<Integer> searchResults =

searchForProperties(

true, 500, 51.525094, -0.127305, 2);
Stream<PropertyId> searchResults =

searchForProperties(

PropertyType.RENTAL,

MonthlyBudget.of(500, GBP),

Coordinate.of(51.525094, -0.127305),

Radius.of(2, MILES));
Readability
Stream<PropertyId> searchResults =

searchForProperties(

PropertyType.RENTAL,

MonthlyBudget.of(500, GBP),

Coordinate.of(51.525094, -0.127305),

Radius.of(2, MILES));
Stream<PropertyId> searchResults =

searchForProperties(

PropertyType.RENTAL,

MonthlyBudget.of(500, GBP),

CircularArea.around(Coordinate.of(

51.525094, -0.127305))

.with(Radius.of(2, MILES)));
Readability
Stream<PropertyId> searchForProperties(

PurchasingType purchasingType,

Budget budget,

Area area) { ... }
SearchQuery<PropertyId> searchForProperties(

PurchasingType purchasingType,

Budget budget,

Area area) { ... }
Readability
public interface SearchQuery<T> {

public Stream<T> fetch();



public T fetchOne();

}
Readability
Readability
OK, the inputs make sense. But the output?
Why bother with a PropertyId?
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
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()
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?
Readability
Searchability
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
Searchability
⇧F6
⌥⇧R
⌃R, ⌃R
F2
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
Searchability
⌥F7
⌃G
⌃K, ⌃T
⇧⌥F7
public final class Templating {

public void render(PropertyId propertyId) {

propertyId.writeTo(output);

}



...

}
Searchability
Flexibility
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
public final class PropertyId {

private final int value;



...

}
Flexibility
Flexibility
But our website was slow, so we decided to switch to
Cassandra.
public final class PropertyId {

private final int value;



...

}
public final class PropertyId {

private final UUID value;

private final int humanRepresentation;



...

}
Flexibility
public SearchQuery<PropertyId> searchForProperties(

PurchasingType purchasingType, Budget budget, Area area)
{

Area rectangle = area.asRectangle();

return connection

.query(select().from(“property”)

.where(eq(“purchasing_type”, purchasingType.name()))

.and(lte(“budget”, budget.inGBP()))

.and(gte(“longitude”, rectangle.minX()))

.and(lte(“longitude”, rectangle.maxX()))

.and(gte(“latitude”, rectangle.minY()))

.and(lte(“latitude”, rectangle.maxY())))

.filter(row ->

area.contains(row.getDouble(“latitude”),

row.getDouble(“longitude”)))

.map(row -> new PropertyId(

row.getUUID(“id”),

row.getInt(“human_representation”)));

}
Flexibility
Correctness
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.
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
public Stream<Integer> searchForProperties(

boolean renting,

int monthlyBudget,

double latitude,

double longitude,

double distanceFromCentre) {



check(“distance from centre”,

distanceFromCentre,

is(greaterThan(0)));

...

}
Correctness
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
Correctness
I haven’t been totally honest with you.
There’s more code than you thought.
Except it’s not really code.
/**

* 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
/**

* 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
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
public interface SearchQuery<T> {

public Stream<T> fetch()

throws DatabaseQueryException;



public T fetchOne()

throws DatabaseQueryException;

}
Correctness
@Path("/properties")

public final class PropertiesResource {

private final Template PropertyTemplate =

Template.inClassPath("/com/buymoarflats/website/property-details.html");



@GET

@Path("/{propertyId}")

public Response propertyDetails(@PathParam("propertyId") int id) {

try {

return propertyResponse(new PropertyId(id));

} catch (DatabaseQueryException e) {

return Response.serverError().entity(e).build();

}

}



private Response propertyResponse(PropertyId id) throws DatabaseQueryException {

Output output = formattedProperty(id);

if (output == null) {

return Response.notFound().entity(id).build();

}

return Response.ok(output).build();

}



private Output formattedProperty(PropertyId id) throws DatabaseQueryException {

Property property = retrieveProperty(id);

if (property == null) {

return null;

}

return PropertyTemplate.format(property);

}



private Property retrieveProperty(PropertyId id) throws DatabaseQueryException {

return id.query(connection).fetchOne();

}

}
Correctness
public Response propertyDetails(@PathParam("propertyId") int id) {

try {

return propertyResponse(new PropertyId(id));

} catch (DatabaseQueryException e) {

return Response.serverError().entity(e).build();

}

}



private Response propertyResponse(PropertyId id)

throws DatabaseQueryException {

Output output = formattedProperty(id); ...

}



private Output formattedProperty(PropertyId id)

throws DatabaseQueryException {

Property property = retrieveProperty(id); ...

}



private Property retrieveProperty(PropertyId id)

throws DatabaseQueryException {

return id.query(connection).fetchOne();

}
Correctness
Correctness
To paraphrase Nat Pryce and Steve Freeman:
Your types are trying to tell you something.
You should listen to them.
public Response propertyDetails(@PathParam("propertyId") int id) {

try {

return propertyResponse(new PropertyId(id));

} catch (DatabaseQueryException e) {

return Response.serverError().entity(e).build();

}

}



private Response propertyResponse(PropertyId id)

throws DatabaseQueryException {

Output output = formattedProperty(id); ...

}



private Output formattedProperty(PropertyId id)

throws DatabaseQueryException {

Property property = retrieveProperty(id); ...

}



private Property retrieveProperty(PropertyId id)

throws DatabaseQueryException {

return id.query(connection).fetchOne();

}
Correctness
public Response propertyDetails(@PathParam("propertyId") PropertyId id) {

try {

return propertyResponse(

id, formattedProperty(retrieveProperty(id)));

} catch (DatabaseQueryException e) {

return Response.serverError().entity(e).build();

}

}



private Response propertyResponse(PropertyId id, Output output) {

...

}



private Output formattedProperty(Property property) {

...

}



private Property retrieveProperty(PropertyId id)

throws DatabaseQueryException {

return id.query(connection).fetchOne();

}
Correctness
@Path("/properties")

public final class PropertiesResource {

private final Template PropertyTemplate =

Template.inClassPath("/com/buymoarflats/website/property-details.html");



@GET

@Path("/{propertyId}")

public Response propertyDetails(@PathParam("propertyId") int id) {

try {

return propertyResponse(

id, formattedProperty(retrieveProperty(id)));

} catch (DatabaseQueryException e) {

return Response.serverError().entity(e).build();

}

}



private Response propertyResponse(PropertyId id, Output output) {

if (output == null) {

return Response.notFound().entity(id).build();

}

return Response.ok(output).build();

}



private Output formattedProperty(Property property) {

if (property == null) {

return null;

}

return PropertyTemplate.format(property);

}



private Property retrieveProperty(PropertyId id)

throws DatabaseQueryException {

return id.query(connection).fetchOne();

}

}
Correctness
Correctness
Now, what about all that duplication?
Output process(Input thing) {

if (thing == null) {

return null;

}

// process thing and return

}
Correctness
Output process(Input thing) {

if (thing == null) {

return null;

} else {

// process thing and return

}

}
Correctness
Output process(Input thing) {

Function<Input, Output> processor =

value -> {

// process value and return

};



if (thing == null) {

return null;

} else {

return processor.apply(thing);

}

}
Correctness
Output process(

Function<Input, Output> processor,

Input thing) {



if (thing == null) {

return null;

} else {

return processor.apply(thing);

}

}
Correctness
public final class Optional<T> {

private final T value;



public <U> Optional<U> map(

Function<? super T, ? extends U> mapper) {

if (value == null) {

return empty();

} else {

return Optional.ofNullable(mapper.apply(value));

}

}

}
Optional<Output> process(

Function<Input, Output> processor,

Optional<Input> thing) {



return thing.map(processor);

}
Correctness
public Response propertyDetails(@PathParam("propertyId") PropertyId id) {

try {

return propertyResponse(

id, retrieveProperty(id).map(this::formattedProperty));

} catch (DatabaseQueryException e) {

return Response.serverError().entity(e).build();

}

}



private Response propertyResponse(PropertyId id, Optional<Output> maybeOutput) {

return maybeOutput

.map(output -> Response.ok(output).build())

.orElse(Response.notFound().entity(id).build());

}



private Output formattedProperty(Property property) {

return PropertyTemplate.format(property);

}
private Optional<Property> retrieveProperty(PropertyId id)

throws DatabaseQueryException {

return id.query(connection).fetchOne();

}
Correctness
@GET

@Path("/{propertyId}")

public Response propertyDetails(

@PathParam("propertyId") PropertyId id) {



try {

return id.query(connection).fetchOne()

.map(PropertyTemplate::format)

.map(Response::ok)

.orElse(Response.notFound().entity(id))

.build();

} catch (DatabaseQueryException e) {

return Response.serverError()

.entity(e).build();

}

}
Correctness
Efficiency
Efficiency
On BuyMoarFlats.com, we let you short-list properties.
Set<ShortListedProperty> shortList =

connection

.query(“SELECT * FROM short_list”

+ “ JOIN property”

+ “ ON short_list.property_id = property.id”

+ “ WHERE short_list.user_id = ?”,

user.id())

.map(row -> propertyFrom(row))

.fetch()

.collect(toSet());
Efficiency
List<ShortListedProperty> sortedShortList =

shortList.stream()

.sorted(comparing(dateTimeAdded))

.collect(toList());
Efficiency
Map<City, List<ShortListedProperty>>

shortListsByCity =

sortedShortList.stream()

.collect(groupingBy(city));
Efficiency
Set<City> cities = shortListByCity.keySet();
Efficiency
List<ShortListedProperty> upForAuctionSoon =

shortListsByCity.values().stream()

.flatMap(Collection::stream)

.filter(property ->

property.isUpForAuctionInLessThan(

1, WEEK))

.collect(toList());
Efficiency
Stream<Property> randomPromotedAuction =

connection

.query(“SELECT * FROM property”

+ “ WHERE sale_type = ?”

+ “ AND promoted = true”

+ “ LIMIT 1”,

PropertySaleType.AUCTION.name())

.fetch();



List<Property> highlighted =

Stream.concat(randomPromotedAuction,

upForAuctionSoon.stream())

.collect(toList());
Efficiency
Efficiency
And we’ve got more features coming every week!
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
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
Efficiency
But we process the original list five times.
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
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.
public final class ShortList {

Map<City, List<ShortListedProperty>> byCity;

Set<City> cities;

List<Property> highlighted;



...

}
Efficiency
In Conclusion
We tackled five discrete problems, but the solution was
always the same.
Make a new type.
public class CircularArea implements Area {

...

}
public final class Optional<T> {

...

}
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
1. Passes its tests
2. Minimizes duplication
3. Maximizes clarity
4. Has fewer elements
Jackpot.
Go wrap some data in types.
talks.samirtalwar.com
Heckling starts now.
13th October 2015
@SamirTalwar

More Related Content

What's hot

Educational technology vs technology in education
Educational technology vs technology in educationEducational technology vs technology in education
Educational technology vs technology in education
jmmendoza21
 
Resources of Teaching Mathematics
Resources of Teaching MathematicsResources of Teaching Mathematics
Resources of Teaching Mathematics
vidyaj7
 

What's hot (20)

Innovation in Education
Innovation in EducationInnovation in Education
Innovation in Education
 
Lesson plan
Lesson planLesson plan
Lesson plan
 
Mathematics Laboratory,Club,Library
Mathematics Laboratory,Club,LibraryMathematics Laboratory,Club,Library
Mathematics Laboratory,Club,Library
 
Project method
Project methodProject method
Project method
 
Educational technology vs technology in education
Educational technology vs technology in educationEducational technology vs technology in education
Educational technology vs technology in education
 
21ம் நூற்றாண்டில் இணையக் கல்வியின் முக்கியத்துவம்
21ம் நூற்றாண்டில் இணையக் கல்வியின் முக்கியத்துவம்21ம் நூற்றாண்டில் இணையக் கல்வியின் முக்கியத்துவம்
21ம் நூற்றாண்டில் இணையக் கல்வியின் முக்கியத்துவம்
 
Innovative teaching methodologies
Innovative teaching methodologiesInnovative teaching methodologies
Innovative teaching methodologies
 
Model lesson plan i &amp; ii
Model lesson plan i &amp; iiModel lesson plan i &amp; ii
Model lesson plan i &amp; ii
 
Aims & objectives of Teaching Social Science,
Aims & objectives of Teaching Social Science,Aims & objectives of Teaching Social Science,
Aims & objectives of Teaching Social Science,
 
Innovative lesson plan aswathy
Innovative lesson plan aswathyInnovative lesson plan aswathy
Innovative lesson plan aswathy
 
Innovative approaches for Teaching and Learning
Innovative approaches for Teaching and LearningInnovative approaches for Teaching and Learning
Innovative approaches for Teaching and Learning
 
Innovative lesson plan
Innovative lesson planInnovative lesson plan
Innovative lesson plan
 
Work Education.pptx
Work Education.pptxWork Education.pptx
Work Education.pptx
 
3. team teaching
3. team teaching3. team teaching
3. team teaching
 
Resources of Teaching Mathematics
Resources of Teaching MathematicsResources of Teaching Mathematics
Resources of Teaching Mathematics
 
Socialised methods ppt
Socialised methods pptSocialised methods ppt
Socialised methods ppt
 
Drill and Practice Instructional Software
Drill and Practice Instructional SoftwareDrill and Practice Instructional Software
Drill and Practice Instructional Software
 
Innovative lesson plan
Innovative lesson planInnovative lesson plan
Innovative lesson plan
 
Neuro Linguistic Programming
Neuro Linguistic ProgrammingNeuro Linguistic Programming
Neuro Linguistic Programming
 
primary education Subhanulla,ppt 2
 primary education Subhanulla,ppt 2 primary education Subhanulla,ppt 2
primary education Subhanulla,ppt 2
 

Similar to Use your type system; write less code

1. DSA - Introduction.pptx
1. DSA - Introduction.pptx1. DSA - Introduction.pptx
1. DSA - Introduction.pptx
hara69
 
Constance et qualité du code dans une équipe - Rémi Prévost
Constance et qualité du code dans une équipe - Rémi PrévostConstance et qualité du code dans une équipe - Rémi Prévost
Constance et qualité du code dans une équipe - Rémi Prévost
Web à Québec
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Mario Fusco
 

Similar to Use your type system; write less code (20)

Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#Lo Mejor Del Pdc2008 El Futrode C#
Lo Mejor Del Pdc2008 El Futrode C#
 
Understanding linq
Understanding linqUnderstanding linq
Understanding linq
 
1. DSA - Introduction.pptx
1. DSA - Introduction.pptx1. DSA - Introduction.pptx
1. DSA - Introduction.pptx
 
What's New In C# 7
What's New In C# 7What's New In C# 7
What's New In C# 7
 
devLink - What's New in C# 4?
devLink - What's New in C# 4?devLink - What's New in C# 4?
devLink - What's New in C# 4?
 
Using the Windows 8 Runtime from C++
Using the Windows 8 Runtime from C++Using the Windows 8 Runtime from C++
Using the Windows 8 Runtime from C++
 
Constance et qualité du code dans une équipe - Rémi Prévost
Constance et qualité du code dans une équipe - Rémi PrévostConstance et qualité du code dans une équipe - Rémi Prévost
Constance et qualité du code dans une équipe - Rémi Prévost
 
Function in C program
Function in C programFunction in C program
Function in C program
 
Java Svet - Communication Between Android App Components
Java Svet - Communication Between Android App ComponentsJava Svet - Communication Between Android App Components
Java Svet - Communication Between Android App Components
 
Java Svet - Communication Between Android App Components
Java Svet - Communication Between Android App ComponentsJava Svet - Communication Between Android App Components
Java Svet - Communication Between Android App Components
 
Practices For Becoming A Better Programmer
Practices For Becoming A Better ProgrammerPractices For Becoming A Better Programmer
Practices For Becoming A Better Programmer
 
Functional concepts in C#
Functional concepts in C#Functional concepts in C#
Functional concepts in C#
 
Python basic
Python basicPython basic
Python basic
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
 
Java 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually useJava 8 new features or the ones you might actually use
Java 8 new features or the ones you might actually use
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side Javascript
 
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STMConcurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
 
Android training day 5
Android training day 5Android training day 5
Android training day 5
 
Functional Programming with C#
Functional Programming with C#Functional Programming with C#
Functional Programming with C#
 

Recently uploaded

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 

Recently uploaded (20)

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 

Use your type system; write less code

  • 1. UseYour Type System; Write Less Code 13th October 2015 @SamirTalwar
  • 2. So I’ve got this website.
  • 3.
  • 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.
  • 7. public Stream<Integer> searchForProperties(
 boolean renting,
 int monthlyBudget,
 double latitude,
 double longitude,
 double distanceFromCentre) { ... } public Stream<PropertyId> abc(
 PurchasingType def,
 Budget ghi,
 Coordinate jkl,
 Radius mno) { ... } Readability
  • 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”
  • 11. Stream<Integer> searchResults =
 searchForProperties(
 true, 500, 51.525094, -0.127305, 2); Stream<PropertyId> searchResults =
 searchForProperties(
 PropertyType.RENTAL,
 MonthlyBudget.of(500, GBP),
 Coordinate.of(51.525094, -0.127305),
 Radius.of(2, MILES)); Readability
  • 12. Stream<PropertyId> searchResults =
 searchForProperties(
 PropertyType.RENTAL,
 MonthlyBudget.of(500, GBP),
 Coordinate.of(51.525094, -0.127305),
 Radius.of(2, MILES)); Stream<PropertyId> searchResults =
 searchForProperties(
 PropertyType.RENTAL,
 MonthlyBudget.of(500, GBP),
 CircularArea.around(Coordinate.of(
 51.525094, -0.127305))
 .with(Radius.of(2, MILES))); Readability
  • 13. Stream<PropertyId> searchForProperties(
 PurchasingType purchasingType,
 Budget budget,
 Area area) { ... } SearchQuery<PropertyId> searchForProperties(
 PurchasingType purchasingType,
 Budget budget,
 Area area) { ... } Readability
  • 14. public interface SearchQuery<T> {
 public Stream<T> fetch();
 
 public T fetchOne();
 } Readability
  • 15. Readability OK, the inputs make sense. But the output? Why bother with a PropertyId?
  • 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
  • 25. public final class Templating {
 public void render(PropertyId propertyId) {
 propertyId.writeTo(output);
 }
 
 ...
 } 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
  • 29. Flexibility But our website was slow, so we decided to switch to Cassandra.
  • 30. public final class PropertyId {
 private final int value;
 
 ...
 } public final class PropertyId {
 private final UUID value;
 private final int humanRepresentation;
 
 ...
 } Flexibility
  • 31. public SearchQuery<PropertyId> searchForProperties(
 PurchasingType purchasingType, Budget budget, Area area) {
 Area rectangle = area.asRectangle();
 return connection
 .query(select().from(“property”)
 .where(eq(“purchasing_type”, purchasingType.name()))
 .and(lte(“budget”, budget.inGBP()))
 .and(gte(“longitude”, rectangle.minX()))
 .and(lte(“longitude”, rectangle.maxX()))
 .and(gte(“latitude”, rectangle.minY()))
 .and(lte(“latitude”, rectangle.maxY())))
 .filter(row ->
 area.contains(row.getDouble(“latitude”),
 row.getDouble(“longitude”)))
 .map(row -> new PropertyId(
 row.getUUID(“id”),
 row.getInt(“human_representation”)));
 } 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
  • 42. @Path("/properties")
 public final class PropertiesResource {
 private final Template PropertyTemplate =
 Template.inClassPath("/com/buymoarflats/website/property-details.html");
 
 @GET
 @Path("/{propertyId}")
 public Response propertyDetails(@PathParam("propertyId") int id) {
 try {
 return propertyResponse(new PropertyId(id));
 } catch (DatabaseQueryException e) {
 return Response.serverError().entity(e).build();
 }
 }
 
 private Response propertyResponse(PropertyId id) throws DatabaseQueryException {
 Output output = formattedProperty(id);
 if (output == null) {
 return Response.notFound().entity(id).build();
 }
 return Response.ok(output).build();
 }
 
 private Output formattedProperty(PropertyId id) throws DatabaseQueryException {
 Property property = retrieveProperty(id);
 if (property == null) {
 return null;
 }
 return PropertyTemplate.format(property);
 }
 
 private Property retrieveProperty(PropertyId id) throws DatabaseQueryException {
 return id.query(connection).fetchOne();
 }
 } Correctness
  • 43. public Response propertyDetails(@PathParam("propertyId") int id) {
 try {
 return propertyResponse(new PropertyId(id));
 } catch (DatabaseQueryException e) {
 return Response.serverError().entity(e).build();
 }
 }
 
 private Response propertyResponse(PropertyId id)
 throws DatabaseQueryException {
 Output output = formattedProperty(id); ...
 }
 
 private Output formattedProperty(PropertyId id)
 throws DatabaseQueryException {
 Property property = retrieveProperty(id); ...
 }
 
 private Property retrieveProperty(PropertyId id)
 throws DatabaseQueryException {
 return id.query(connection).fetchOne();
 } Correctness
  • 44.
  • 45. Correctness To paraphrase Nat Pryce and Steve Freeman: Your types are trying to tell you something. You should listen to them.
  • 46. public Response propertyDetails(@PathParam("propertyId") int id) {
 try {
 return propertyResponse(new PropertyId(id));
 } catch (DatabaseQueryException e) {
 return Response.serverError().entity(e).build();
 }
 }
 
 private Response propertyResponse(PropertyId id)
 throws DatabaseQueryException {
 Output output = formattedProperty(id); ...
 }
 
 private Output formattedProperty(PropertyId id)
 throws DatabaseQueryException {
 Property property = retrieveProperty(id); ...
 }
 
 private Property retrieveProperty(PropertyId id)
 throws DatabaseQueryException {
 return id.query(connection).fetchOne();
 } Correctness
  • 47. public Response propertyDetails(@PathParam("propertyId") PropertyId id) {
 try {
 return propertyResponse(
 id, formattedProperty(retrieveProperty(id)));
 } catch (DatabaseQueryException e) {
 return Response.serverError().entity(e).build();
 }
 }
 
 private Response propertyResponse(PropertyId id, Output output) {
 ...
 }
 
 private Output formattedProperty(Property property) {
 ...
 }
 
 private Property retrieveProperty(PropertyId id)
 throws DatabaseQueryException {
 return id.query(connection).fetchOne();
 } Correctness
  • 48. @Path("/properties")
 public final class PropertiesResource {
 private final Template PropertyTemplate =
 Template.inClassPath("/com/buymoarflats/website/property-details.html");
 
 @GET
 @Path("/{propertyId}")
 public Response propertyDetails(@PathParam("propertyId") int id) {
 try {
 return propertyResponse(
 id, formattedProperty(retrieveProperty(id)));
 } catch (DatabaseQueryException e) {
 return Response.serverError().entity(e).build();
 }
 }
 
 private Response propertyResponse(PropertyId id, Output output) {
 if (output == null) {
 return Response.notFound().entity(id).build();
 }
 return Response.ok(output).build();
 }
 
 private Output formattedProperty(Property property) {
 if (property == null) {
 return null;
 }
 return PropertyTemplate.format(property);
 }
 
 private Property retrieveProperty(PropertyId id)
 throws DatabaseQueryException {
 return id.query(connection).fetchOne();
 }
 } Correctness
  • 49. Correctness Now, what about all that duplication?
  • 50. Output process(Input thing) {
 if (thing == null) {
 return null;
 }
 // process thing and return
 } Correctness
  • 51. Output process(Input thing) {
 if (thing == null) {
 return null;
 } else {
 // process thing and return
 }
 } Correctness
  • 52. Output process(Input thing) {
 Function<Input, Output> processor =
 value -> {
 // process value and return
 };
 
 if (thing == null) {
 return null;
 } else {
 return processor.apply(thing);
 }
 } Correctness
  • 53. Output process(
 Function<Input, Output> processor,
 Input thing) {
 
 if (thing == null) {
 return null;
 } else {
 return processor.apply(thing);
 }
 } Correctness
  • 54. public final class Optional<T> {
 private final T value;
 
 public <U> Optional<U> map(
 Function<? super T, ? extends U> mapper) {
 if (value == null) {
 return empty();
 } else {
 return Optional.ofNullable(mapper.apply(value));
 }
 }
 } Optional<Output> process(
 Function<Input, Output> processor,
 Optional<Input> thing) {
 
 return thing.map(processor);
 } Correctness
  • 55. public Response propertyDetails(@PathParam("propertyId") PropertyId id) {
 try {
 return propertyResponse(
 id, retrieveProperty(id).map(this::formattedProperty));
 } catch (DatabaseQueryException e) {
 return Response.serverError().entity(e).build();
 }
 }
 
 private Response propertyResponse(PropertyId id, Optional<Output> maybeOutput) {
 return maybeOutput
 .map(output -> Response.ok(output).build())
 .orElse(Response.notFound().entity(id).build());
 }
 
 private Output formattedProperty(Property property) {
 return PropertyTemplate.format(property);
 } private Optional<Property> retrieveProperty(PropertyId id)
 throws DatabaseQueryException {
 return id.query(connection).fetchOne();
 } Correctness
  • 56. @GET
 @Path("/{propertyId}")
 public Response propertyDetails(
 @PathParam("propertyId") PropertyId id) {
 
 try {
 return id.query(connection).fetchOne()
 .map(PropertyTemplate::format)
 .map(Response::ok)
 .orElse(Response.notFound().entity(id))
 .build();
 } catch (DatabaseQueryException e) {
 return Response.serverError()
 .entity(e).build();
 }
 } Correctness
  • 58. Efficiency On BuyMoarFlats.com, we let you short-list properties.
  • 59. Set<ShortListedProperty> shortList =
 connection
 .query(“SELECT * FROM short_list”
 + “ JOIN property”
 + “ ON short_list.property_id = property.id”
 + “ WHERE short_list.user_id = ?”,
 user.id())
 .map(row -> propertyFrom(row))
 .fetch()
 .collect(toSet()); Efficiency
  • 62. Set<City> cities = shortListByCity.keySet(); Efficiency
  • 63. List<ShortListedProperty> upForAuctionSoon =
 shortListsByCity.values().stream()
 .flatMap(Collection::stream)
 .filter(property ->
 property.isUpForAuctionInLessThan(
 1, WEEK))
 .collect(toList()); Efficiency
  • 64. Stream<Property> randomPromotedAuction =
 connection
 .query(“SELECT * FROM property”
 + “ WHERE sale_type = ?”
 + “ AND promoted = true”
 + “ LIMIT 1”,
 PropertySaleType.AUCTION.name())
 .fetch();
 
 List<Property> highlighted =
 Stream.concat(randomPromotedAuction,
 upForAuctionSoon.stream())
 .collect(toList()); Efficiency
  • 65. Efficiency And we’ve got more features coming every week!
  • 66. 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
  • 67. 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
  • 68. Efficiency But we process the original list five times.
  • 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
  • 73. We tackled five discrete problems, but the solution was always the same. Make a new type.
  • 74. public class CircularArea implements Area {
 ...
 }
  • 75. public final class Optional<T> {
 ...
 }
  • 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
  • 78. Jackpot. Go wrap some data in types.