KEMBAR78
Add (Syntactic) Sugar To Your Java | PPT
Add  Sugar to your Java “ how we architected from the ground up for testability, and why” Pascal-Louis Perez –  .com Pascal-Louis Perez, kaChing Group Inc. V SYNTACTIC
.com Pascal-Louis Perez, kaChing Group Inc.
our system in 30 seconds Pascal-Louis Perez, kaChing Group Inc.
Overview Components versus Layers Type Driven Development 1:1 principle Family Polymorphism Annotations Meta Information Typing Extensions Object Oriented design replaces Conditionals Delegation State Pattern Declarative Programming Domain Specific Language Factories Pascal-Louis Perez, kaChing Group Inc. τ @ what?
µ-Java Imagine Java deprived of all native types ( boolean ,  int , …) and all control-flow constructs  ( if then else ,  for ,  while , …) How do you encode booleans using only objects? What about integers? Is µ-Java Turing-complete? Pascal-Louis Perez, kaChing Group Inc.
µ-Java: boolean if (condition)   statement1 else   statement2 condition.if(statement1, statement2) Bool class with True and False subclasses in True, if computes statement1 In False, if computes statement2 Statements are instances of  Thunk<Void> Pascal-Louis Perez, kaChing Group Inc.
Growing a Language Pascal-Louis Perez, kaChing Group Inc. expressiveness µ-Java 1 Do not take things for granted 2 Think outside the Language
Testable Code Because… It allows quick iterations It makes it easy to scale the team It is more cost effective than debugging It obsoletes the need for functional QA It facilitates continuous refactoring, allowing the code to get better with age It attracts the right kind of engineers Pascal-Louis Perez, kaChing Group Inc.
It’s a lot of fun! Pascal-Louis Perez, kaChing Group Inc.
And  it can be very geeky! Pascal-Louis Perez, kaChing Group Inc.
Software is Traditionally Layered Examples Jetty Apache HTTP client Pascal-Louis Perez, kaChing Group Inc. STOP
Think about Components Provides Functionality… given Required Services. Yields reusable software Key to testability Pascal-Louis Perez, kaChing Group Inc.
Wireable Puzzle Pieces What if I want only one thread pool in my whole app server? In Scala  (  http://www.scala-lang.org ) new JettyServer with MyThreadPool; new ParallelRpc with MyThreadPool; Pascal-Louis Perez, kaChing Group Inc.
Dependency Injection to the Rescue class UserServiceImpl implements  UserService  { @Inject UserServiceImpl( HttpClient, … ) { … } Pascal-Louis Perez, kaChing Group Inc. required services functionality τ
Add Retrying Logic class MyExtendedUserServiceImpl implements  UserService  { @Inject  UserServiceImpl( UserServiceImpl ) … User  getUser (Id<User> id) { User u = null; for (int i=0; i<5 && u == null; i++) u =  delegate . getUser (id); return u; } Pascal-Louis Perez, kaChing Group Inc.
QueryEngine Software platform to build services quickly Unit of work is a Query query constructors define input parameters queries can request dependencies at run-time queries do work and produce a value which is then post-processed (serialized, stored, …) Soon open-sourced  http://code.google.com/p/queryengine/   Pascal-Louis Perez, kaChing Group Inc.
Shell’s “everything is a process” Pascal-Louis Perez, kaChing Group Inc. process stdin args stdout stderr return code
Shell is a plumbing language if echo $name | grep –q “Jack”; then Pascal-Louis Perez, kaChing Group Inc. echo $name $name grep -q return code if return code
Queries Pascal-Louis Perez, kaChing Group Inc. query dependencies exception arguments value
Query Constructors Similar to dependency injection, you ask for the arguments you need rather than fetch them from the environment Type safe regardless of input format Pascal-Louis Perez, kaChing Group Inc.
Query Constructors AddToWatchlist(Id<User>, Symbol) AddToGroup(Id<User>, Id<Group>, @Optional boolean) PlaceOrder(Id<User>, Action, Symbol, @Positive int) PostMessage(Id<User>, Id<Wall>, Text<Plain>) Pascal-Louis Perez, kaChing Group Inc. @ τ
HelloWorld Query class HelloWorld extends AbstractQuery<String> { HelloWorld(String name) { … @Inject DateTime now; String process() { return now + “: Hello ” + name; } } Pascal-Louis Perez, kaChing Group Inc.
QueryDriver Pascal-Louis Perez, kaChing Group Inc. @ query monitoring retrying transacting injecting scoping V LazyManager
Adapt Queries Backend servers Frontend server for GWT Command-line tools Tests Pascal-Louis Perez, kaChing Group Inc.
Conditionals Complicate Testing if (a) { if (b) { section 1 } else { section 2 } } else { if (b) { section 3 } else { section 4 } } Branch coverage requires a lot of tests Typically, deep conditionals require a lot of obscure setup in tests Ties more closely the test and the implementation Pascal-Louis Perez, kaChing Group Inc.
Thunk<T> abstract class Thunk<T> { private boolean evaluated = false; private T value; public T get() { if (!evaluated) { value = compute(); evaluated = true; } return value; } abstract protected T compute(); } Pascal-Louis Perez, kaChing Group Inc.
Thunk<T> without conditional abstract class Thunk<T> { private Getter  value  = new Getter<T>() { public T get() { final T v = compute(); value  = new Getter<T>() { T get() { return v; } }; return  value .get(); } }; public T get() { return  value .get(); } Pascal-Louis Perez, kaChing Group Inc.
JsonMarshaller Marshalling library converting Java POJOs into JSON and vice-versa. Annotations and persistence ideas inspired by Hibernate “ kaChing’s proto buffers” http://code.google.com/p/jsonmarshaller/   Pascal-Louis Perez, kaChing Group Inc.
JsonMarshaller @Entity class Googler { @Value List<Cafe> favoriteCafes; } createMarshaller(Googler.class).marshall(…); produces {“favoriteCafes”:[“150”, “Charlie’s”]} Pascal-Louis Perez, kaChing Group Inc.
JsonMarshaller @Value ABC enumAbc; @Value(ordinal = true) ABC enumAbc; dedicated code is wired at creation time (almost) no conditionals at run-time Pascal-Louis Perez, kaChing Group Inc. @
JsonMarshaller Conditionals if(annotation.ordinal) marshallOrdinal() else marshallName() Delegation marshall() Pascal-Louis Perez, kaChing Group Inc.
kaChing’s API REST path parsing REST API with paths such as /users/ :id: /users/ :id: /portfolio/trades/ :tradeId: /communities/everyone/insight HTTP parameters Headers (X-KaChing-ApiKey, X-KaChing-RemoteKey) GET, PUT, POST, DELETE Pascal-Louis Perez, kaChing Group Inc.
Express “ what ” instead of Coding “ how ” path( &quot;users&quot;, path( FetchUser.class, path( &quot;watchlist&quot;, QuerySpec. of( FetchUser.class, a sList(UserPart.WATCHLIST)), path( immutableMap( PUT, AddToWatchlist.class, DELETE, RemoveFromWatchlist.class)))), Pascal-Louis Perez, kaChing Group Inc. τ /users/ :id:  handled by  FetchUser.class /users/ :id: /watchlist  handled by  FetchUser.class  with the extra paramater   WATCHLIST PUT /users/ :id: /watchlist  handled by  AddToWatchlist.class what?
I’ll have a big boilerplate for lunch Portfolio p = new Portfolio(…); Stock ko = new Stock(…); p.executeTrade( new BuyStockTrade(ko, …)); p.executeTrade(new Interest(…)); p.executeTrade( new SellStockTrade(ko, …)); Pascal-Louis Perez, kaChing Group Inc.
…  or maybe not Pascal-Louis Perez, kaChing Group Inc. portfolio(now, 90) .buyStock(now, &quot;KO&quot;, 10, 1) .payInterest(later, fedRateRepository) .sellStock(latest, &quot;KO&quot;, 10, 1) .get() what?
Find Managers Pascal-Louis Perez, kaChing Group Inc. order constraint
Constraint, Index, Selector Constraint: search criteria on one dimension e.g.  age = 4 Index: search structure can handle only one kind of constraint Selector: constraint template used to find appropriate index e.g.  age = ? Pascal-Louis Perez, kaChing Group Inc. dimension 1 dimension 2 … order 1 order 2 …
Practice Safe Programming: Use Types Pascal-Louis Perez, kaChing Group Inc. Selector createIndex : Index Index search( Constraint) Constraint getSelector : Selector
Practice Safe Programming: Use Types Pascal-Louis Perez, kaChing Group Inc. τ Selector <M> createIndex : Index <M> Index <M> search( Constraint <M> ) Constraint <M> getSelector : Selector <M>
Summary of the Examples Pascal-Louis Perez, kaChing Group Inc. τ @ dependency injection query constructors query driver thunk JsonMarshaller API paths parsing builder pattern family polymorphism ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ µ-Java ✓ what?
Key Takeaways Build components instead of providing extension points Apply the 1:1 principle Simplify your life with annotations Use delegation instead of conditionals Languages are conveniences, not barriers Pascal-Louis Perez, kaChing Group Inc.
Further Readings TotT: Too Many Tests http://googletesting.blogspot.com/2008/02/in-movie-amadeus-austrian-emperor.html TotT: The Invisible Branch http://googletesting.blogspot.com/2008/05/tott-invisible-branch.html JsonMarshaller http://code.google.com/p/jsonmarshaller/ Real-World Scala: Dependency Injection http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/ Scalable Component Abstraction http://lamp.epfl.ch/~odersky/papers/ScalableComponent.pdf Unifying Type Parameters in Java http://blog.kaching.com/index.php/2009/01/16/unifying-type-parameters-in-java/ Japex: Micro-Benchmarking https://japex.dev.java.net/   The Testability Explorer, Misko Hevery http://misko.hevery.com Growing a Language, by Guy Steele http://video.google.com/videoplay?docid=-8860158196198824415   Type-Safe Builder Pattern in Scala http://blog.rafaelferreira.net/2008/07/type-safe-builder-pattern-in-scala.html  Pascal-Louis Perez, kaChing Group Inc.

Add (Syntactic) Sugar To Your Java

  • 1.
    Add Sugarto your Java “ how we architected from the ground up for testability, and why” Pascal-Louis Perez – .com Pascal-Louis Perez, kaChing Group Inc. V SYNTACTIC
  • 2.
    .com Pascal-Louis Perez,kaChing Group Inc.
  • 3.
    our system in30 seconds Pascal-Louis Perez, kaChing Group Inc.
  • 4.
    Overview Components versusLayers Type Driven Development 1:1 principle Family Polymorphism Annotations Meta Information Typing Extensions Object Oriented design replaces Conditionals Delegation State Pattern Declarative Programming Domain Specific Language Factories Pascal-Louis Perez, kaChing Group Inc. τ @ what?
  • 5.
    µ-Java Imagine Javadeprived of all native types ( boolean , int , …) and all control-flow constructs ( if then else , for , while , …) How do you encode booleans using only objects? What about integers? Is µ-Java Turing-complete? Pascal-Louis Perez, kaChing Group Inc.
  • 6.
    µ-Java: boolean if(condition) statement1 else statement2 condition.if(statement1, statement2) Bool class with True and False subclasses in True, if computes statement1 In False, if computes statement2 Statements are instances of Thunk<Void> Pascal-Louis Perez, kaChing Group Inc.
  • 7.
    Growing a LanguagePascal-Louis Perez, kaChing Group Inc. expressiveness µ-Java 1 Do not take things for granted 2 Think outside the Language
  • 8.
    Testable Code Because…It allows quick iterations It makes it easy to scale the team It is more cost effective than debugging It obsoletes the need for functional QA It facilitates continuous refactoring, allowing the code to get better with age It attracts the right kind of engineers Pascal-Louis Perez, kaChing Group Inc.
  • 9.
    It’s a lotof fun! Pascal-Louis Perez, kaChing Group Inc.
  • 10.
    And itcan be very geeky! Pascal-Louis Perez, kaChing Group Inc.
  • 11.
    Software is TraditionallyLayered Examples Jetty Apache HTTP client Pascal-Louis Perez, kaChing Group Inc. STOP
  • 12.
    Think about ComponentsProvides Functionality… given Required Services. Yields reusable software Key to testability Pascal-Louis Perez, kaChing Group Inc.
  • 13.
    Wireable Puzzle PiecesWhat if I want only one thread pool in my whole app server? In Scala ( http://www.scala-lang.org ) new JettyServer with MyThreadPool; new ParallelRpc with MyThreadPool; Pascal-Louis Perez, kaChing Group Inc.
  • 14.
    Dependency Injection tothe Rescue class UserServiceImpl implements UserService { @Inject UserServiceImpl( HttpClient, … ) { … } Pascal-Louis Perez, kaChing Group Inc. required services functionality τ
  • 15.
    Add Retrying Logicclass MyExtendedUserServiceImpl implements UserService { @Inject UserServiceImpl( UserServiceImpl ) … User getUser (Id<User> id) { User u = null; for (int i=0; i<5 && u == null; i++) u = delegate . getUser (id); return u; } Pascal-Louis Perez, kaChing Group Inc.
  • 16.
    QueryEngine Software platformto build services quickly Unit of work is a Query query constructors define input parameters queries can request dependencies at run-time queries do work and produce a value which is then post-processed (serialized, stored, …) Soon open-sourced http://code.google.com/p/queryengine/ Pascal-Louis Perez, kaChing Group Inc.
  • 17.
    Shell’s “everything isa process” Pascal-Louis Perez, kaChing Group Inc. process stdin args stdout stderr return code
  • 18.
    Shell is aplumbing language if echo $name | grep –q “Jack”; then Pascal-Louis Perez, kaChing Group Inc. echo $name $name grep -q return code if return code
  • 19.
    Queries Pascal-Louis Perez,kaChing Group Inc. query dependencies exception arguments value
  • 20.
    Query Constructors Similarto dependency injection, you ask for the arguments you need rather than fetch them from the environment Type safe regardless of input format Pascal-Louis Perez, kaChing Group Inc.
  • 21.
    Query Constructors AddToWatchlist(Id<User>,Symbol) AddToGroup(Id<User>, Id<Group>, @Optional boolean) PlaceOrder(Id<User>, Action, Symbol, @Positive int) PostMessage(Id<User>, Id<Wall>, Text<Plain>) Pascal-Louis Perez, kaChing Group Inc. @ τ
  • 22.
    HelloWorld Query classHelloWorld extends AbstractQuery<String> { HelloWorld(String name) { … @Inject DateTime now; String process() { return now + “: Hello ” + name; } } Pascal-Louis Perez, kaChing Group Inc.
  • 23.
    QueryDriver Pascal-Louis Perez,kaChing Group Inc. @ query monitoring retrying transacting injecting scoping V LazyManager
  • 24.
    Adapt Queries Backendservers Frontend server for GWT Command-line tools Tests Pascal-Louis Perez, kaChing Group Inc.
  • 25.
    Conditionals Complicate Testingif (a) { if (b) { section 1 } else { section 2 } } else { if (b) { section 3 } else { section 4 } } Branch coverage requires a lot of tests Typically, deep conditionals require a lot of obscure setup in tests Ties more closely the test and the implementation Pascal-Louis Perez, kaChing Group Inc.
  • 26.
    Thunk<T> abstract classThunk<T> { private boolean evaluated = false; private T value; public T get() { if (!evaluated) { value = compute(); evaluated = true; } return value; } abstract protected T compute(); } Pascal-Louis Perez, kaChing Group Inc.
  • 27.
    Thunk<T> without conditionalabstract class Thunk<T> { private Getter value = new Getter<T>() { public T get() { final T v = compute(); value = new Getter<T>() { T get() { return v; } }; return value .get(); } }; public T get() { return value .get(); } Pascal-Louis Perez, kaChing Group Inc.
  • 28.
    JsonMarshaller Marshalling libraryconverting Java POJOs into JSON and vice-versa. Annotations and persistence ideas inspired by Hibernate “ kaChing’s proto buffers” http://code.google.com/p/jsonmarshaller/ Pascal-Louis Perez, kaChing Group Inc.
  • 29.
    JsonMarshaller @Entity classGoogler { @Value List<Cafe> favoriteCafes; } createMarshaller(Googler.class).marshall(…); produces {“favoriteCafes”:[“150”, “Charlie’s”]} Pascal-Louis Perez, kaChing Group Inc.
  • 30.
    JsonMarshaller @Value ABCenumAbc; @Value(ordinal = true) ABC enumAbc; dedicated code is wired at creation time (almost) no conditionals at run-time Pascal-Louis Perez, kaChing Group Inc. @
  • 31.
    JsonMarshaller Conditionals if(annotation.ordinal)marshallOrdinal() else marshallName() Delegation marshall() Pascal-Louis Perez, kaChing Group Inc.
  • 32.
    kaChing’s API RESTpath parsing REST API with paths such as /users/ :id: /users/ :id: /portfolio/trades/ :tradeId: /communities/everyone/insight HTTP parameters Headers (X-KaChing-ApiKey, X-KaChing-RemoteKey) GET, PUT, POST, DELETE Pascal-Louis Perez, kaChing Group Inc.
  • 33.
    Express “ what” instead of Coding “ how ” path( &quot;users&quot;, path( FetchUser.class, path( &quot;watchlist&quot;, QuerySpec. of( FetchUser.class, a sList(UserPart.WATCHLIST)), path( immutableMap( PUT, AddToWatchlist.class, DELETE, RemoveFromWatchlist.class)))), Pascal-Louis Perez, kaChing Group Inc. τ /users/ :id: handled by FetchUser.class /users/ :id: /watchlist handled by FetchUser.class with the extra paramater WATCHLIST PUT /users/ :id: /watchlist handled by AddToWatchlist.class what?
  • 34.
    I’ll have abig boilerplate for lunch Portfolio p = new Portfolio(…); Stock ko = new Stock(…); p.executeTrade( new BuyStockTrade(ko, …)); p.executeTrade(new Interest(…)); p.executeTrade( new SellStockTrade(ko, …)); Pascal-Louis Perez, kaChing Group Inc.
  • 35.
    … ormaybe not Pascal-Louis Perez, kaChing Group Inc. portfolio(now, 90) .buyStock(now, &quot;KO&quot;, 10, 1) .payInterest(later, fedRateRepository) .sellStock(latest, &quot;KO&quot;, 10, 1) .get() what?
  • 36.
    Find Managers Pascal-LouisPerez, kaChing Group Inc. order constraint
  • 37.
    Constraint, Index, SelectorConstraint: search criteria on one dimension e.g. age = 4 Index: search structure can handle only one kind of constraint Selector: constraint template used to find appropriate index e.g. age = ? Pascal-Louis Perez, kaChing Group Inc. dimension 1 dimension 2 … order 1 order 2 …
  • 38.
    Practice Safe Programming:Use Types Pascal-Louis Perez, kaChing Group Inc. Selector createIndex : Index Index search( Constraint) Constraint getSelector : Selector
  • 39.
    Practice Safe Programming:Use Types Pascal-Louis Perez, kaChing Group Inc. τ Selector <M> createIndex : Index <M> Index <M> search( Constraint <M> ) Constraint <M> getSelector : Selector <M>
  • 40.
    Summary of theExamples Pascal-Louis Perez, kaChing Group Inc. τ @ dependency injection query constructors query driver thunk JsonMarshaller API paths parsing builder pattern family polymorphism ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ µ-Java ✓ what?
  • 41.
    Key Takeaways Buildcomponents instead of providing extension points Apply the 1:1 principle Simplify your life with annotations Use delegation instead of conditionals Languages are conveniences, not barriers Pascal-Louis Perez, kaChing Group Inc.
  • 42.
    Further Readings TotT:Too Many Tests http://googletesting.blogspot.com/2008/02/in-movie-amadeus-austrian-emperor.html TotT: The Invisible Branch http://googletesting.blogspot.com/2008/05/tott-invisible-branch.html JsonMarshaller http://code.google.com/p/jsonmarshaller/ Real-World Scala: Dependency Injection http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/ Scalable Component Abstraction http://lamp.epfl.ch/~odersky/papers/ScalableComponent.pdf Unifying Type Parameters in Java http://blog.kaching.com/index.php/2009/01/16/unifying-type-parameters-in-java/ Japex: Micro-Benchmarking https://japex.dev.java.net/ The Testability Explorer, Misko Hevery http://misko.hevery.com Growing a Language, by Guy Steele http://video.google.com/videoplay?docid=-8860158196198824415 Type-Safe Builder Pattern in Scala http://blog.rafaelferreira.net/2008/07/type-safe-builder-pattern-in-scala.html Pascal-Louis Perez, kaChing Group Inc.

Editor's Notes

  • #2 - syntactic sugar refers to convenience features implemented at the urface level of a programming language, for instance i++ in Java is a short hand for increment by 1 plus a cast or foreach added in Java 5 to avoid dealing with iterators directly -in our experience, many of the code we write is to some extent an extension of the language , basically creating a Domain Specific Language to solve a particular problem -talk about how we implemented things rather than what we implemented -cover multiple examples , including our platform the QueryEngine -effort of a whole team presented, many contributions and arguments about how things should be built