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

Simple Report on Village visit
Simple Report on Village visitSimple Report on Village visit
Simple Report on Village visitAmitKumar7283
 
Role of Science and Technology in Swach Bharat Abhiyan
Role of Science and Technology in Swach Bharat AbhiyanRole of Science and Technology in Swach Bharat Abhiyan
Role of Science and Technology in Swach Bharat AbhiyanUpamanyu Ray
 
RURAL SKILL DEVELOPMENT PRESENTATION BY AMAN DWIVEDI
RURAL SKILL DEVELOPMENT PRESENTATION BY AMAN DWIVEDIRURAL SKILL DEVELOPMENT PRESENTATION BY AMAN DWIVEDI
RURAL SKILL DEVELOPMENT PRESENTATION BY AMAN DWIVEDIAman Dwivedi
 
Final rural-development-in-india
Final rural-development-in-indiaFinal rural-development-in-india
Final rural-development-in-indiaKartikeya Pandey
 
Role of ict in AKM
Role of ict  in AKMRole of ict  in AKM
Role of ict in AKMKrishna Vala
 
Mgnrega an overview
Mgnrega  an overviewMgnrega  an overview
Mgnrega an overviewAlkesh Patel
 
Public-Private Partnership in Market-led Extension:Case Studies
Public-Private Partnership in Market-led Extension:Case StudiesPublic-Private Partnership in Market-led Extension:Case Studies
Public-Private Partnership in Market-led Extension:Case StudiesAttaluri Srinivasacharyulu
 
National Five year plans for rural development
National Five year plans for rural developmentNational Five year plans for rural development
National Five year plans for rural developmentFarhana Farhath
 
Integrated Rural Development Programme
Integrated Rural Development ProgrammeIntegrated Rural Development Programme
Integrated Rural Development ProgrammePrashant Sharma
 
Role of non-governmental organizations (NGOs) in rural development
Role of non-governmental organizations (NGOs) in rural  development Role of non-governmental organizations (NGOs) in rural  development
Role of non-governmental organizations (NGOs) in rural development Devegowda S R
 

What's hot (20)

Village Profile data collection format
Village Profile data collection formatVillage Profile data collection format
Village Profile data collection format
 
Simple Report on Village visit
Simple Report on Village visitSimple Report on Village visit
Simple Report on Village visit
 
Final ppt
Final pptFinal ppt
Final ppt
 
Role of Science and Technology in Swach Bharat Abhiyan
Role of Science and Technology in Swach Bharat AbhiyanRole of Science and Technology in Swach Bharat Abhiyan
Role of Science and Technology in Swach Bharat Abhiyan
 
RURAL SKILL DEVELOPMENT PRESENTATION BY AMAN DWIVEDI
RURAL SKILL DEVELOPMENT PRESENTATION BY AMAN DWIVEDIRURAL SKILL DEVELOPMENT PRESENTATION BY AMAN DWIVEDI
RURAL SKILL DEVELOPMENT PRESENTATION BY AMAN DWIVEDI
 
Case study on village devp.
Case study on village devp.Case study on village devp.
Case study on village devp.
 
Final rural-development-in-india
Final rural-development-in-indiaFinal rural-development-in-india
Final rural-development-in-india
 
Pre-Independence Programs
Pre-Independence ProgramsPre-Independence Programs
Pre-Independence Programs
 
Role of ict in AKM
Role of ict  in AKMRole of ict  in AKM
Role of ict in AKM
 
Village report
Village reportVillage report
Village report
 
Village Survey
Village SurveyVillage Survey
Village Survey
 
Mgnrega an overview
Mgnrega  an overviewMgnrega  an overview
Mgnrega an overview
 
Smile Foundation
Smile FoundationSmile Foundation
Smile Foundation
 
Public-Private Partnership in Market-led Extension:Case Studies
Public-Private Partnership in Market-led Extension:Case StudiesPublic-Private Partnership in Market-led Extension:Case Studies
Public-Private Partnership in Market-led Extension:Case Studies
 
Participatory Rural Appraisal.pptx
Participatory Rural Appraisal.pptxParticipatory Rural Appraisal.pptx
Participatory Rural Appraisal.pptx
 
National Five year plans for rural development
National Five year plans for rural developmentNational Five year plans for rural development
National Five year plans for rural development
 
SPECIAL AREA DEVELOPMENT
SPECIAL AREA DEVELOPMENTSPECIAL AREA DEVELOPMENT
SPECIAL AREA DEVELOPMENT
 
fd.pdf
fd.pdffd.pdf
fd.pdf
 
Integrated Rural Development Programme
Integrated Rural Development ProgrammeIntegrated Rural Development Programme
Integrated Rural Development Programme
 
Role of non-governmental organizations (NGOs) in rural development
Role of non-governmental organizations (NGOs) in rural  development Role of non-governmental organizations (NGOs) in rural  development
Role of non-governmental organizations (NGOs) in rural development
 

Similar to Use your type system; write less code

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#Juan Pablo
 
1. DSA - Introduction.pptx
1. DSA - Introduction.pptx1. DSA - Introduction.pptx
1. DSA - Introduction.pptxhara69
 
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?Kevin Pilch
 
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évostWeb à Québec
 
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 ComponentsAleksandar Ilić
 
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 ComponentsPSTechSerbia
 
Practices For Becoming A Better Programmer
Practices For Becoming A Better ProgrammerPractices For Becoming A Better Programmer
Practices For Becoming A Better ProgrammerSrikanth Shreenivas
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme SwiftMovel
 
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 useSharon Rozinsky
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionKent Huang
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side JavascriptJulie Iskander
 
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 & STMMario Fusco
 
Android training day 5
Android training day 5Android training day 5
Android training day 5Vivek Bhusal
 

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

Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 

Recently uploaded (20)

Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
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
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 

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.