Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
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...
Readability
Readability
Tell me what’s more readable.
public Stream<Integer> searchForProperties(

boolean renting,

int monthlyBudget,

double latitude,

double longitude,

do...
first second
name searchForProperties
buying or
renting?
boolean renting PurchasingType
monthly budget int monthlyBudget Bu...
Readabilityreadable

/ˈriːdəb(ə)l/

adjective
1. able to be read or deciphered; legible.

“a code which is readable by a c...
Readabilityreadable

/ˈriːdəb(ə)l/

adjective
1. able to be read or deciphered; legible.

“a code which is readable by a c...
Stream<Integer> searchResults =

searchForProperties(

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

searchForProperties(

PropertyType.RENTAL,

MonthlyBudget.of(500, GBP),

Coordinate.of...
Stream<PropertyId> searchForProperties(

PurchasingType purchasingType,

Budget budget,

Area area) { ... }
SearchQuery<Pr...
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;

}



pub...
Readability
What does PropertyId do?
SearchQuery<Property> query

(DatabaseConnection connection)
void renderTo(Somewhere ...
Readabilityaddition
multiplication
subtraction
division
modulus
negation
bit manipulation operations such as &, |, ^ and ~...
Readability
Searchability
public final class PropertyId {

private final int value;



public PropertyId(int value) {

this.value = value;

}



pub...
Searchability
⇧F6
⌥⇧R
⌃R, ⌃R
F2
public final class PropertyId {

private final int value;



public PropertyId(int value) {

this.value = value;

}



pub...
Searchability
⌥F7
⌃G
⌃K, ⌃T
⇧⌥F7
public final class Templating {

public void render(PropertyId propertyId) {

propertyId.writeTo(output);

}



...

}
Sea...
Flexibility
public SearchQuery<PropertyId> searchForProperties(

PurchasingType purchasingType, Budget budget, Area area)
{

Area rect...
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 va...
public SearchQuery<PropertyId> searchForProperties(

PurchasingType purchasingType, Budget budget, Area area)
{

Area rect...
Correctness
Correctness
In his book, Understanding the Four Rules of Simple
Design, Corey Haines talks about a really important
concep...
public Stream<Integer> searchForProperties(

boolean renting,

int monthlyBudget,

double latitude,

double longitude,

do...
public Stream<Integer> searchForProperties(

boolean renting,

int monthlyBudget,

double latitude,

double longitude,

do...
public final class Radius {

public static Radius of(

@NotNull double magnitude,

@NotNull DistanceUnit unit) {



check(...
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,...
/**

* Searches for properties in the database

* matching the specified parameters.

*

* @throws DatabaseQueryException
...
public interface SearchQuery<T> {

/**

* @throws DatabaseQueryException

* if there is a connection error.

*/

public St...
public interface SearchQuery<T> {

public Stream<T> fetch()

throws DatabaseQueryException;



public T fetchOne()

throws...
@Path("/properties")

public final class PropertiesResource {

private final Template PropertyTemplate =

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

try {

return propertyResponse(new PropertyId(id));

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

try {

return propertyResponse(new PropertyId(id));

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

try {

return propertyResponse(

id, formattedP...
@Path("/properties")

public final class PropertiesResource {

private final Template PropertyTemplate =

Template.inClass...
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 (thi...
Output process(

Function<Input, Output> processor,

Input thing) {



if (thing == null) {

return null;

} else {

retur...
public final class Optional<T> {

private final T value;



public <U> Optional<U> map(

Function<? super T, ? extends U> ...
public Response propertyDetails(@PathParam("propertyId") PropertyId id) {

try {

return propertyResponse(

id, retrievePr...
@GET

@Path("/{propertyId}")

public Response propertyDetails(

@PathParam("propertyId") PropertyId id) {



try {

return...
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...
List<ShortListedProperty> sortedShortList =

shortList.stream()

.sorted(comparing(dateTimeAdded))

.collect(toList());
Ef...
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(pr...
Stream<Property> randomPromotedAuction =

connection

.query(“SELECT * FROM property”

+ “ WHERE sale_type = ?”

+ “ AND p...
Efficiency
And we’ve got more features coming every week!
public final class ShortList {

Set<ShortListedProperty> shortList;

List<ShortListedProperty> sortedShortList;

Map<City,...
public final class ShortList {

Set<ShortListedProperty> shortList;

List<ShortListedProperty> sortedShortList;

Map<City,...
Efficiency
But we process the original list five times.
public final class ShortList {

Set<ShortListedProperty> shortList;

List<ShortListedProperty> sortedShortList;

Map<City,...
Efficiency
Here’s the magic bullet.
We don’t need to optimise our algorithms.
The database author already did that.
We just...
public final class ShortList {

Map<City, List<ShortListedProperty>> byCity;

Set<City> cities;

List<Property> highlighte...
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 ...
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
Use your type system; write less code
Use your type system; write less code
Upcoming SlideShare
Loading in …5
×

Use your type system; write less code

1,122 views

Published on

Using your type system to improve the readability, flexibility, correctness and performance of your software.

Published in: Software
  • Nice !! Download 100 % Free Ebooks, PPts, Study Notes, Novels, etc @ https://www.ThesisScientist.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Use your type system; write less code

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

×