# ROSE Compiler Framework/Good API Design

Google: "How to Design a Good API and Why it Matters" by Joshua Bloch
TODO: convert from Markdown

## Characteristics of a Good API

* Easy to learn
* Easy to use, even without documentation
* Hard to misuse
* Easy to read and maintain code that uses it
* Sufficiently powerful to satisfy requirements
* Easy to extend
* Appropriate to audience

## The Process of API Design

* Gather true requirements in the form of use-cases
* Start with a short 1-page specification
** Agility trumps completeness
** Collect a lot of feedback
* Use your API early and often
** [Test-Driven Development (TDD)](http://en.wikipedia.org/wiki/Test-driven_development)
   [T]he repetition of a very short development cycle: first the developer writes a failing automated test case that defines a desired improvement or new function, then produces code to pass that test and finally refactors the new code to acceptable standards.
** Doubles as examples/tutorials and unit tests
* Maintain realistic expectations
** You won't be able to please everyone... aim to displease everyone equally
** Expect to evolve API; mistakes happen; real-world usage is necessary

## General Principles

* When in doubt, leave it out. You can always add, but you can never remove.
* Just because you can doesn't mean you should
* [Power-to-weight ratio](http://en.wikipedia.org/wiki/Power-to-weight_ratio)
* Don't give users a gun to shoot themselves with
** Information hiding: minimize the accessibility of everything

### Documentation Matters

* Class: what an instance represents
Pre- and Post- Conditions
* The precondition statement indicates what must be true before the function is called.
* The postcondition statement indicates what will be true when the function finishes its work.

### API vs. Implementation

Implementation details should not impact the API. Don't let implementation details "leak" into the API.
Performance
* Design for usability, refactor for performance
* Do not warp the API to gain performance
* Effects of API design decisions on performance are real and permanent:
** Component.getSize returns Dimension
** Dimension is mutable
** Each getSize call must allocate Dimension
** Causes millions of needless object allocations

### "Harmonize"

* API must coexist peacefully with platform
** Do what is customary (standard)
** Avoid obsolete parameter and return types
** Mimic patterns in core APIs and language
** Take advantage of API-friendly features: generics, varargs, enums, default arguments
* Don't make the client do anything the module could do
** Reduce need for boilerplate code
* Don't violate the [Principle of Least Astonishment](http://en.wikipedia.org/wiki/Principle_of_least_astonishment)
* Provide programmatic access to all data available in string form => no client string parsing necessary
* Overload with care: ambiguous overloadings

### Names Matter

* Largely self-explanatory (avoid cryptic abbreviations)
* Be consistent (e.g. same word means same thing)
* Strive for symmetry
* Should read like [prose](http://en.wikipedia.org/wiki/Prose)

### Input Parameters

* interface types over classes: flexibility, performance
* most specific possible type: moves error from runtime to compile time
* use double (64 bits) rather than float (32 bits): precision loss is real, performance loss negligible
* consistent ordering:
* short parameter lists: 3 or fewer; more and users will have to refer to docs; identically typed params harmful
** Two techniques for shortening: 1) break up method, 2) create helper class to hold parameters

### Return Values

* Avoid values that demand exceptional processing

### Exceptions

* don't force client to use exceptions for control flow
* don't fail silently
* favor unchecked exceptions
* include failure-capture diagnostic information
* Fail fast: report errors ASAP
** Compile time: static typing, generics
** Run time: error on first bad method invocation (should be failure-atomic)