practices and tools for building better apis
DESCRIPTION
TRANSCRIPT
Practices and Tools for Building Better APIs
@PeterHendriks80, +PeterHendriks
Objectives of this talk
• API from a Java app developer perspective !
• Why API is important • What makes a better API • Practical tips and tools • Measuring your existing codebase
Some API terminology
• API Consumer: code that uses API • API: the interface • API Implementer: code that implements API
API Consumer API API
Implementer
Data Access Object JDBC Database Driver
We are using a lot of API
Java SE: 45 API’s
Java EE: 37 API’s
Spring: 27 API’s
Bazillion Open Source Web
Framework API’s
Cloud API’s
Public Service API’s
Enterprise Service API’s
Middleware API’s
We are building more of them, too
• API is key to a succesful module design – Essential for agile teams at scale
Shared code
Customer Front-‐End
Warehouse Front-‐End
Order Management
Distance to API implementation is increasing
• API quality increasing important when implementation becomes a black box
Same team
Different team
Open source
Binary only
Other datacenter
The API we use shapes our code
• Most code we write calls an API • Code that calls an API is shaped to fit the API • Therefore, APIs determine the shape of application code – In some ways, even more impactful than high level design, test driven development or code craftsmanship
!http://docs.oracle.com/javaee/1.4/tutorial/examples/jaxp/xslt/samples/TransformationApp04.java !public class TransformationApp04 { public static void main(String[] argv) { if (argv.length != 1) { System.err.println("Usage: java TransformationApp filename"); System.exit(1); } ! // Create the sax "parser". AddressBookReader02 saxReader = new AddressBookReader02(); ! try { File f = new File(argv[0]); ! // Use a Transformer for output TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(); ! // Use the parser as a SAX source for input FileReader fr = new FileReader(f); BufferedReader br = new BufferedReader(fr); InputSource inputSource = new InputSource(fr); SAXSource source = new SAXSource(saxReader, inputSource); StreamResult result = new StreamResult(System.out); transformer.transform(source, result); } catch (TransformerConfigurationException tce) { // Error generated by the parser System.out.println("\n** Transformer Factory error"); System.out.println(" " + tce.getMessage()); ! // Use the contained exception, if any
var json_data = JSON.stringify(obj);
What makes a better API
API Quality: Value
• Value = benefits -‐ costs • Benefits – Features – Data – ...
• Costs – License/pay per use – Performance/footprint – Security – …
API Quality: Usability
• API Design == Human Interface design – Although API is for machine/machine interaction, APIs need to be understood by programmers to write the code
– Programmers are humans
API is not just about capability and structural design, but also about human understanding
A simple model for API Usability
Learnability: How easy is it to accomplish basic tasks the first time? Efficiency: Once users learned the design, how quickly can they perform tasks? Memorability: When users return after a while, how easily can they re-‐establish proficiency? Errors: How many errors do users make, how severe are these errors, and how easily can they recover from the errors? Satisfaction: How pleasant is it to use the design?
Generic usability model by Ben Shneiderman:
API Quality: stability
Able to enhance/grow implementation without breaking existing consumer codeGoogle AppEngine release notes: Version 1.7.5 -‐ February 13, 2013 The Conversion API, which was decommissioned last release, has been removed from the SDK. In a future release, the API will be removed from the runtime and applications that attempt to use it may stop working. Applications in production that import the library should be fixed as soon as possible. Version 1.8.4 -‐ September 9, 2013 The Conversion API, a decommissioned feature, has been removed from the SDK. In the next release, the API will be removed from the runtime and any attempt to import the API will raise an exception. Version 1.8.5 -‐ September 25, 2013 The Conversion API, a decommissioned feature, has been removed from the runtime. Applications in production that import the API should be fixed as soon as possible.
API Quality: A hierarchy of needs
Stability only matters when API is valuable and usable
Valuable
Usable
Stable
Building Better APIs
API Design: start with examples
• Examples most important in API documentation – Concrete use case, usability check
• Make examples exemplary – Example code will be copy-‐pasted
• Create a cheat sheet – Improves learnability – Shows design issues
API Design: multiple perspectives
public class Document { ! private List<Page> pages = new ArrayList<>(); ! public Page addPage() { Page page = new Page(); pages.add(page); page.setPageNumber(pages.size()); return page; } public void report() {...} }
Page page = document.addPage(); page.setContents("Once upon a time...");
Impl:
UML:Names, Completeness,
Grouping
Can it be built?
Is it usable?Consumer:
API practice: Keep it simple
• Try to stick to just methods and constructors – Factories, Delegates, etc. not always necessary !
• “When in doubt leave it out” – Less classes, methods – Less parameters, return values
Josh Bloch, Java API guru
API practice: avoid verbose constructs
• Constructs that create verbose consumer code – Extending class/implementing interface – Checked exception – Required casting – Required generic type – Required if, for, while, try/finally – Required synchronization/locking – Hard coded parameter value
Example: doing some loggin’
• Demo: different styles of logging API
Why Lambdas are so much better than inner classes
• Inner classes, or extending existing classes often needed – Resource handling – Looping/visiting collections – Event handling
• Lambdas provide a much more usable construct – Shorter, safer, better footprint/performance
Example: Lambda benefits
• Demo: Netbeans example
API practice: fail fast, fail hard
• Fail immediately on wrong input • Limit the use of null as valid input/output
public void save(String filename) { if (filename == null) { return; // bad api: error is ignored! } ... // save happens here }
public void save(String filename) { Objects.requireNonNull(filename); // Throws NPE immediately ... // save happens here }
Better
API Tool: checking for null
• Tool: FindBugs, a static code analyzer – Reports errors at compile-‐time
• Annotations for Software Defect Detection (JSR 305: Dormant) – @Nonnull: may never be null – @CheckForNull: should always be checked before dereferenced
– @Nullable: caller decides if null check is needed
• Java 8 will add more annotation options for tools
FindBugs demo in Eclipse
Finding API problems in your code
• People – Team knowledge – Policy, “best practices”, conventions – Elaborate explanation, “hard to do” – Defect lists/exceptions/stack traces
• Tools – Finding most used API: Dependency Structure Matrix (DSM)
How a Dependency Structure Matrix works
Document Page TextBlock
Document -‐Page 2 -‐
TextBlock 10 -‐
Classes/Packages
# of direct dependencies from Document to Page
Demo: SonarQube DSM
API design cheat sheet
A Better API is: 1. Valuable 2. Usable 3. Stable
API usability: • Learnability • Efficiency • Memorability • Error rate • Satisfaction
API Design Perspectives: UML: names, completeness, grouping Implementation: can it be built API usage: how usable is it Examples First
Document Page TextBlock
Document -‐
Page 2 -‐
TextBlock 10 -‐
DSM: finding most used API
JSR 305/FindBugs: @Nonnull: may never be null @CheckForNull: always check @Nullable: caller decides null check
API matters: Reuse 3rd party Modular design Distance to impl.
API Design practices: When in doubt leave it out Limit API consumer code to a minimum • Extending class/interface • Checked Exception • Required casting • Required Generic Type • Hard coded parameter value • Required if, for, while, try • Required synchronization/locking !Be predictable and obvious • Methods calleable in any order • Constructor should only construct • Don’t have surprising side effects • Limit null as input/output • Fail fast, fail hard
@PeterHendriks80, +PeterHendriks
Eval!