api design done right: some guidelines which every programmer should probably know

Upload: fanzefirl

Post on 13-Apr-2018

242 views

Category:

Documents


1 download

TRANSCRIPT

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    1/25

    API Design Done RightSome guidelines which every programmer should probably know

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    2/25

    API Design Done WRONG

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    3/25

    Copyright Reaktor 2011

    publicintcountBigCustomers() {

    Connection connection = null;

    try{

    connection = DriverManager.getConnection("jdbc:h2:mem:");

    PreparedStatement statement = connection

    .prepareStatement("SELECT COUNT(*) FROM CUSTOMERS WHERE REVENUE > ?");

    // Do indexes start from 0 or 1?

    statement.setLong(1, 1000000L);

    ResultSet resultSet = statement.executeQuery();

    resultSet.next();

    // Do indexes start from 0 or 1?

    intresult = resultSet.getInt(1);

    returnresult;

    } catch(SQLException e) {

    // Checked exception - ouch!

    thrownewRuntimeException(e);

    } finally{

    try{

    if(connection != null&& !connection.isClosed()) {

    connection.close();

    } } catch(SQLException e) {

    // Checked exception - aargh

    thrownewRuntimeException(e);

    }

    }

    }

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    4/25

    Copyright Reaktor 2011

    publicintcountBigCustomers() {

    Connection connection = null;

    try{

    connection = DriverManager.getConnection("jdbc:h2:mem:");

    PreparedStatementstatement = connection

    .prepareStatement("SELECT COUNT(*) FROM CUSTOMERS WHERE REVENUE > ?");

    // Do indexes start from 0 or 1?

    statement.setLong(1,1000000L);

    ResultSet resultSet = statement.executeQuery();

    resultSet.next();

    // Do indexes start from 0 or 1?

    intresult = resultSet.getInt(1);

    returnresult;

    } catch (SQLException e) {

    // Checked exception - ouch!

    thrownewRuntimeException(e);

    } finally {

    try{

    if(connection != null && !connection.isClosed()) {

    connection.close();

    } } catch (SQLException e) {

    // Checked exception - aargh

    thrownewRuntimeException(e);

    }

    }

    }

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    5/25

    Copyright Reaktor 2011 Confidential

    publicintcountBigCustomers() {

    JdbcTemplate jdbc = newJdbcTemplate(newSingleConnectionDataSource(

    "jdbc:h2:mem:", false));

    returnjdbc.queryForInt(

    "SELECT COUNT(*) FROM CUSTOMERS WHERE REVENUE > ?", 1000000L);

    }

    A bit better way

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    6/25

    Copyright Reaktor 2011

    Why API Design Matters

    Usually write-once,

    read/learn many times

    by many different people

    Every piece of code has an API

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    7/25

    Copyright Reaktor 2011

    Why API Design Matters

    Bad API usually leads to bad client code

    Bad API design tends to infect all abovelayers

    http://www.flickr.com/photos/bamshad/1469713774/sizes/s/in/photostream/

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    8/25

    Copyright Reaktor 2011

    API is a User Interface

    The same principles apply

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    9/25

    Copyright Reaktor 2011

    API is a User Interface

    The purpose and usages must be known

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    10/25

    Copyright Reaktor 2011

    API is a User Interface

    Make correct usage easy

    Make wrong usage hard

    (or impossible)

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    11/25

    Copyright Reaktor 2011

    Good API

    Intuitive

    Easy to learn from simple examples

    Self explanatory

    Effort minimizing

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    12/25

    Copyright Reaktor 2011

    Levels of abstraction

    publicintcountBigCustomers() {

    Connection connection = null;

    try{

    connection = DriverManager.getConnection

    ("jdbc:h2:mem:");

    PreparedStatement statement = connection

    .prepareStatement("SELECT COUNT(*)

    FROM CUSTOMERS WHERE REVENUE > ?");

    // Do indexes start from 0 or 1?

    statement.setLong(1, 1000000L);

    ResultSet resultSet = statement.executeQuery();

    resultSet.next();

    // Do indexes start from 0 or 1? intresult = resultSet.getInt(1);

    returnresult;

    } catch(SQLException e) {

    // Checked exception - ouch!

    thrownew RuntimeException(e);

    } finally{

    try{

    if(connection != null&& !

    connection.isClosed()) {

    connection.close();

    }

    } catch(SQLException e) {

    // Checked exception - aargh thrownewRuntimeException(e);

    }

    }

    }

    publicintcountBigCustomers() {

    JdbcTemplate jdbc = newJdbcTemplate(newSingleConnectionDataSource(

    "jdbc:h2:mem:", false));

    returnjdbc.queryForInt(

    "SELECT COUNT(*) FROM CUSTOMERS WHERE REVENUE > ?", 1000000L);

    }

    JDBC API Spring API

    Good abstraction level for low-level library code, bad for

    application code

    Good abstraction level forapplication code

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    13/25

    Copyright Reaktor 2011

    Levels of abstraction

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    14/25

    Copyright Reaktor 2011

    Client perspective with TDD@RunWith(Enclosed.class)

    publicclassOrderBuilderTest {

    publicstaticclassWhenBuildingOrderWithTwoProducts {

    privateOrder order;

    @Before

    publicvoidsetUp() {

    // API as an user interface - how user of the API would

    create an order order= newOrderBuilder(CustomerId.FANBOY_CUSTOMER)

    .with(ProductId.JPHONE_6, 4)

    .with(ProductId.CONSTELLATION_TABLET, 2)

    .build();

    }

    @Test publicvoidorderHasTwoRows() {

    assertThat(order.orderRows().size(), is(2));

    }

    }

    }

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    15/25

    Copyright Reaktor 2011

    Simplicity

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    16/25

    Copyright Reaktor 2011

    Object initialization

    An object should be in valid, usable stateimmediately.

    Component c = newComponent();

    // Here the component cannot be used

    // yet, since it is not initialized,

    // i.e. it is in an invalid state.

    c.initialize(newConfiguration());

    // Only now the component can be used.

    BAD!!!

    Component c = newComponent(new

    Configuration());

    // Now the component can be used

    // immediately. BETTER

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    17/25

    Copyright Reaktor 2011

    Object initialization

    Use builders or factories for more complexinitializations

    order= newOrderBuilder(CustomerId.FANBOY_CUSTOMER)

    .with(ProductId.JPHONE_6, 4)

    .with(ProductId.CONSTELLATION_TABLET, 2)

    .build();

    // default visibility

    // we can only create objects with valid state

    Order(CustomerId customerId, List orderRows) {

    this.customerId= customerId;

    this.orderRows= Collections.unmodifiableList(orderRows);

    }

    publicclassOrderBuilder {

    publicOrderBuilder(CustomerId customerId) { ... }

    publicOrderBuilder with(ProductId productId, intquantity) { ... }

    publicOrder build() { ...}

    }

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    18/25

    Copyright Reaktor 2011

    Object state

    It should be impossible to get an object in anillegal state.

    Object should be in a valid state between

    any method calls.

    Fail fast if the method call would leave the

    object in an invalid state.

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    19/25

    Copyright Reaktor 2011

    Object state

    Prefer immutability

    publicclassOrder {

    privatefinalCustomerId customerId;

    privatefinalList orderRows;

    Order(CustomerId customerId, List orderRows) {

    this.customerId= customerId;

    this.orderRows= Collections.unmodifiableList(orderRows);

    }

    }

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    20/25

    Copyright Reaktor 2011

    Atomic operations

    // User must explicitly begin transaction...c.beginTransaction();

    // ...do their stuff...

    c.doSomething();

    // ...and remember to commit...

    c.commit();

    // ...but what if something fails in between?

    c.doInTransaction(newCallback() {

    @Override

    publicvoidexecute(Component c) {

    // Method doInTransaction() takes

    // care oftransaction management

    // and error handling

    c.doSomething();

    }

    });

    BAD!!!

    BETTER

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    21/25

    Copyright Reaktor 2011

    Visibility and packages in Java

    Domain class name is the package name:packagemyapp.domain.order;

    All services, interfaces and implementation

    related to this domain class in the samepackage.

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    22/25

    Copyright Reaktor 2011

    Visibility and packages in Java

    Public visibility:domain class,

    interfaces for services,

    builders, ...

    publicclassOrder { ...

    public interface OrderRepository { ...

    public class OrderBuilder { ...

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    23/25

    Copyright Reaktor 2011

    Visibility and packages in JavaDefault visibility:

    domain object constructors,

    implementation classes

    // domain object constructor

    Order(CustomerId customerId, List orderRows) { ...

    // repository implementation

    classJdbcOrderRepository implementsOrderRepository { ...

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    24/25

    Copyright Reaktor 2011

    Domain Specific Languages

    Counting two weeks from a given date:

    publicDate twoWeeksFrom(Date beginning) {

    // You have to create a

    // separate Calendar object...

    Calendar calendar = Calendar.getInstance(); // And modify its state...

    calendar.setTime(beginning);

    // And modify its state a little more...

    calendar.add(Calendar.DAY_OF_MONTH, 14);

    // ...before you get the answer.

    returncalendar.getTime();

    }

    publicDateTime twoWeeksFrom(DateTime beginning) {

    returnbeginning.plusWeeks(2);

    }

    Standard Java Calendar API

    Joda-Time

    Monday, September 12, 2011

  • 7/26/2019 API Design Done Right: Some guidelines which every programmer should probably know

    25/25

    Copyright Reaktor 2011

    Thank you!

    Jari Mkel

    Ville Peurala

    mailto:[email protected]:[email protected]:[email protected]:[email protected]