use your type system; write less code - samir talwar
TRANSCRIPT
![Page 1: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/1.jpg)
Use Your Type System;Write Less Code
13th October 2015@SamirTalwar
![Page 2: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/2.jpg)
So I’ve got this website.
![Page 3: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/3.jpg)
![Page 4: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/4.jpg)
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.
![Page 5: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/5.jpg)
Readability
![Page 6: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/6.jpg)
Readability
Tell me what’s more readable.
![Page 7: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/7.jpg)
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
![Page 8: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/8.jpg)
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
![Page 9: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/9.jpg)
Readability readable /ˈ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”
![Page 10: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/10.jpg)
Readability readable /ˈ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”
![Page 11: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/11.jpg)
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
![Page 12: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/12.jpg)
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
![Page 13: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/13.jpg)
Stream<PropertyId> searchForProperties( PurchasingType purchasingType, Budget budget, Area area) { ... }
SearchQuery<PropertyId> searchForProperties( PurchasingType purchasingType, Budget budget, Area area) { ... }
Readability
![Page 14: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/14.jpg)
public interface SearchQuery<T> { public Stream<T> fetch(); public T fetchOne();}
Readability
![Page 15: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/15.jpg)
Readability
OK, the inputs make sense. But the output?
Why bother with a PropertyId?
![Page 16: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/16.jpg)
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
![Page 17: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/17.jpg)
ReadabilityWhat does PropertyId do?
SearchQuery<Property> query (DatabaseConnection connection)
void renderTo(Somewhere else)
new PropertyId(int value)
String toString()
boolean equals(Object other) int hashCode()
![Page 18: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/18.jpg)
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?
![Page 19: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/19.jpg)
Readability
![Page 20: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/20.jpg)
Searchability
![Page 21: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/21.jpg)
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
![Page 22: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/22.jpg)
Searchability
⇧F6
⌥⇧R
⌃R, ⌃R
F2
![Page 23: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/23.jpg)
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
![Page 24: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/24.jpg)
Searchability
⌥F7
⌃G
⌃K, ⌃T
⇧⌥F7
![Page 25: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/25.jpg)
public final class Templating { public void render(PropertyId propertyId) { propertyId.writeTo(output); } ...}
Searchability
![Page 26: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/26.jpg)
Flexibility
![Page 27: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/27.jpg)
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
![Page 28: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/28.jpg)
public final class PropertyId { private final int value; ...}
Flexibility
![Page 29: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/29.jpg)
Flexibility
But our website was slow, so we decided to switch to Cassandra.
![Page 30: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/30.jpg)
public final class PropertyId { private final int value; ...}
public final class PropertyId { private final UUID value; private final int humanRepresentation; ...}
Flexibility
![Page 31: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/31.jpg)
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
![Page 32: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/32.jpg)
Correctness
![Page 33: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/33.jpg)
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.
![Page 34: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/34.jpg)
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
![Page 35: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/35.jpg)
public Stream<Integer> searchForProperties( boolean renting, int monthlyBudget, double latitude, double longitude, double distanceFromCentre) { check(“distance from centre”, distanceFromCentre, is(greaterThan(0))); ...}
Correctness
![Page 36: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/36.jpg)
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
![Page 37: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/37.jpg)
Correctness
I haven’t been totally honest with you.
There’s more code than you thought.
Except it’s not really code.
![Page 38: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/38.jpg)
/** * 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
![Page 39: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/39.jpg)
/** * 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
![Page 40: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/40.jpg)
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
![Page 41: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/41.jpg)
public interface SearchQuery<T> { public Stream<T> fetch() throws DatabaseQueryException; public T fetchOne() throws DatabaseQueryException;}
Correctness
![Page 42: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/42.jpg)
@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
![Page 43: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/43.jpg)
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
![Page 44: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/44.jpg)
![Page 45: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/45.jpg)
Correctness
To paraphrase Nat Pryce and Steve Freeman:
Your types are trying to tell you something.
You should listen to them.
![Page 46: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/46.jpg)
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
![Page 47: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/47.jpg)
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
![Page 48: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/48.jpg)
@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
![Page 49: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/49.jpg)
Correctness
Now, what about all that duplication?
![Page 50: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/50.jpg)
Output process(Input thing) { if (thing == null) { return null; } // process thing and return}
Correctness
![Page 51: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/51.jpg)
Output process(Input thing) { if (thing == null) { return null; } else { // process thing and return }}
Correctness
![Page 52: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/52.jpg)
Output process(Input thing) { Function<Input, Output> processor = value -> { // process value and return }; if (thing == null) { return null; } else { return processor.apply(thing); }}
Correctness
![Page 53: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/53.jpg)
Output process( Function<Input, Output> processor, Input thing) { if (thing == null) { return null; } else { return processor.apply(thing); }}
Correctness
![Page 54: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/54.jpg)
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
![Page 55: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/55.jpg)
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
![Page 56: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/56.jpg)
@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
![Page 57: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/57.jpg)
Efficiency
![Page 58: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/58.jpg)
Efficiency
On BuyMoarFlats.com, we let you short-list properties.
![Page 59: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/59.jpg)
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
![Page 60: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/60.jpg)
List<ShortListedProperty> sortedShortList = shortList.stream() .sorted(comparing(dateTimeAdded)) .collect(toList());
Efficiency
![Page 61: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/61.jpg)
Map<City, List<ShortListedProperty>> shortListsByCity = sortedShortList.stream() .collect(groupingBy(city));
Efficiency
![Page 62: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/62.jpg)
Set<City> cities = shortListByCity.keySet();
Efficiency
![Page 63: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/63.jpg)
List<ShortListedProperty> upForAuctionSoon =shortListsByCity.values().stream() .flatMap(Collection::stream) .filter(property -> property.isUpForAuctionInLessThan( 1, WEEK)) .collect(toList());
Efficiency
![Page 64: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/64.jpg)
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
![Page 65: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/65.jpg)
Efficiency
And we’ve got more features coming every week!
![Page 66: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/66.jpg)
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
![Page 67: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/67.jpg)
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
![Page 68: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/68.jpg)
Efficiency
But we process the original list five times.
![Page 69: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/69.jpg)
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
![Page 70: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/70.jpg)
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.
![Page 71: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/71.jpg)
public final class ShortList { Map<City, List<ShortListedProperty>> byCity; Set<City> cities; List<Property> highlighted; ...}
Efficiency
![Page 72: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/72.jpg)
In Conclusion
![Page 73: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/73.jpg)
We tackled five discrete problems, but the solution was always the same.
Make a new type.
![Page 74: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/74.jpg)
public class CircularArea implements Area { ...}
![Page 75: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/75.jpg)
public final class Optional<T> { ...}
![Page 76: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/76.jpg)
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
![Page 77: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/77.jpg)
1. Passes its tests
2. Minimizes duplication
3. Maximizes clarity
4. Has fewer elements
![Page 78: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/78.jpg)
Jackpot.
Go wrap some data in types.
![Page 79: Use your type system; write less code - Samir Talwar](https://reader030.vdocuments.site/reader030/viewer/2022021419/58ed9c1a1a28ab164b8b4717/html5/thumbnails/79.jpg)
talks.samirtalwar.com
Heckling starts now.
13th October 2015@SamirTalwar