2. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 2
3. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 3
4. Why it matters?
“Software artifacts that
cannot attract programmers
are not reused, and fade
into oblivion.”
Brian Foote
Slide 4
5. Why it matters?
“The impact of API design
choices on users sometimes
shows time penalties of a
factor of 3 to 10.”
Brad Myers
Slide 5
6. Why it matters?
“Public APIs, like
diamonds, are forever. You
have one chance to get it
right so give it your best .”
Joshua Bloch
Slide 6
7. Why it matters?
“A key lesson here is that API
is not just a documented class.
And, APIs don't just happen;
they are a big investment..”
Erich Gamma
Slide 7
8. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 8
9. Consider the perspective of the caller
Implementation focus results in poor APIs:
class ContentInstance
java.lang.Object
extended by DataObject
extended by ManagedObject
extended by ExtensibleObject
extended by ContentItem
extended by ContentInstance
All Implemented Interfaces:
IAttributedObject, IChannelAssociate, IPersistable,
IRelatedAttribute, java.io.Serializable
Slide 9
10. Consider the perspective of the caller
Implementation perspective
class Document {
String getTag();
boolean isTagged(String tag);
void remove(String tag);
void removeTag(String tag);
}
Caller perspective
if(document.getTag().equals(“Best Practices”))
if(document.isTagged(“Best Practices”))
document.remove(“Best Practices”)
document.removeTag(“Best Practices”)
Slide 10
11. Consider the perspective of the caller
Write client code first
Write client code for all major use cases
Ask yourself
Is this code simple?
Is this code intuitive?
Is this code consistent?
Is this code performant?
Does this code reveal any implementation
details?
Not a wasted effort
Code samples reused in tests
Code samples reused in documentation
Slide 11
12. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 12
13. Keep it simple
“Simplicity is the ultimate
sophistication”
Leonardo da Vinci
Slide 13
14. Keep it Simple
Measuring Conceptual Complexity
try {
AuthenticationProvider20 provider = new LocalAuthenticationProvider19();
SearchCriteria18 criteria = new SearchCriteria17(EntityName16.USER15);
criteria.addPropertyToFetch14(PropertyName13.COMMON_NAME12);
criteria.addPropertyToFetch(PropertyName.PHONE11);
criteria.addPropertyToMatch10(PropertyName.DEPARTMENT9, "R&D");
criteria.addPropertyToMatch(PropertyName.LOCATION8, "Waterloo");
criteria.setSortProperty7(PropertyName.COMMON_NAME);
ProfileIterator6 iterator = provider.search5(criteria);
while(iterator.hasNext()4){
Profile3 profile = iterator.next()2;
Property1 commonName = profile.getProperty0(PropertyName.COMMON_NAME);
Property phone = profile.getProperty(PropertyName.PHONE);
System.out.println(commonName.getValue()-1, “ ”, phone.getValue());
}
}
catch(AuthenticationProviderException-2 e) {
}
The higher score is better; less than zero means too complex!
Slide 14
15. Keep it simple
Accidental complexity
Avoid asking callers to extend classes
Avoid asking callers to implement interfaces
Avoid “Gang of Four” design patterns
Provide alternate implementations
Handle change requests carefully
Essential complexity
Organize large APIs into smaller parts
Increase API granularity
Give up some control
Leave functionality out!
Slide 15
16. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 16
17. Strive for consistency
Do the same thing the same way every
time
Rules, patterns, and conventions makes
everyday life more predictable
A consistent API has no frivolous or
unnecessary variations in it
int fscanf(FILE* stream, const char* format,...);
char* fgets(char* str, int num, FILE* stream);
Consistent APIs are easy to
learn, remember and use
Slide 17
18. Strive for consistency
Follow established conventions!
C#: IPublishable, PublishDocument()
Java: Publishable, publishDocument()
Create your own conventions
eliminate unnecessary variations
parameter ordering, error handling, use of
null, etc.
Enforce consistency with code reviews
Use design patterns
Business Service – Business Object
Beware of false consistency
Attributes getAttributes() throws RemoteException
Slide 18
19. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 19
20. Choose memorable names
Avoid silly naming mistakes
antiquated naming conventions
spelling and grammar
synonyms
overly generic terms
inaccurate terms
meaningless terms
Choose names first
Design abstractions are difficult to name
– LLValue, DTree
– DocumentWrapperReferenceBuilderFactory
Best names come from the problem domain
– Familiar, intuitive, accurate, memorable
API as a domain-specific extension
– Establishing a domain vocabulary
Slide 20
21. Choose memorable names
Survey problem domain for suitable names
“In online computer systems terminology, a tag is a non-
hierarchical keyword or term assigned to a piece of
information (such as an internet bookmark, digital
image, or computer file). This kind of metadata helps
describe an item and allows it to be found again by
browsing or searching. Tags are generally chosen
informally and personally by the item's creator or by its
viewer, depending on the system.”
Let names guide design
void assignTag(Item item, String tag);
Metadata describeItem(Item item);
Item[] searchByTag(String tag);
Slide 21
22. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 22
23. Specify the behavior
Consider the class:
TeamsIdentifier
Uniquely identifies an Artesia entity.
Methods:
TeamsIdentifier(String id)
Constructs an identifier from a string.
java.lang.String asString()
Returns the id as a String.
TeamsIdentifier[] asTeamsIdArray()
Convenience method to return this id as an array.
boolean equals(java.lang.Object o)
boolean equalsId(TeamsIdentifier id)
Checks if two ids are equal.
java.lang.String getTeamsId()
Intended for hibernate use only.
java.lang.String toString()
Returns a string representation of the id.
Slide 23
24. Specify the behavior
Try answering the questions:
Expression True or False
TeamsIdentifier id1 = new
TeamsIdentifier(“name”); ?
TeamsIdentifier id2 = new
TeamsIdentifier(“Name”);
id1.equals(id2)
id1.equalsId(id2); ?
id1.toString().equals(“name”) ?
id1.getTeamsId.equals(“name”) ?
TeamsIdentifier id = new
TeamsIdentifier(“a.b.c”) ?
id.asTeamsIdArray().length == 3
TeamsIdentifier id = new
TeamsIdentifier(“a:b:c”) ?
id.asTeamsIdArray().length == 3
AssetIdentifier assetId = new ?
AssetIdentifier(“Donald”)
UserIdentifier userId = new
UserIdentifier(“Donald”)
assetId.equals(userId)
assetId.equalsId(userId) ?
Slide 24
25. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 25
26. Make it safe
Developers make mistakes
Prevent access to dangerous code
Keep implementation code private
Prevent class extension
Control class initialization
Prevent data corruption
Maximize compiler checks
Avoid out and in-out parameters
Check arguments at runtime
Provide informative error messages
Make method calls atomic
Write thread-safe code
Slide 26
27. Make it safe
public Job {
private cancelling = false;
public void cancel() {
...
cancelling = true;
onCancel();
cancelling = false;
...
}
//Override this for custom cleanup when cancelling
protected void onCancel() {
}
public void execute() {
if(cancelling) throw
IllegalStateException(“Forbidden call to execute()
from onCancel()”);
...
}
}
Slide 27
28. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 28
29. Anticipate evolution
Maintain binary backwards compatibility
Clients work without an explicit upgrade
Technology-dependent compatibility rules
– Implemented Java interfaces not extensible
– Java constant values hard-coded in client code
– C++ has more compatibility issues than C
– Adding field or method breaks C++, not Java
Not the same as source-compatibility!
Maintain functional backwards compatibility
Allowed changes
– Weakening preconditions
– Strengthening postconditions
– Strengthening invariants
Testing is essential
SPIs evolve very differently from APIs
Slide 29
30. Anticipate evolution
API versioning cannot be entirely avoided
major technology innovations
unanticipated requirements
quality degradation over time
Incompatible API = major API upgrade
Planned, not accidental
Significant new functionality
Cleanup and reorganization
Removal of deprecated constructs
Old API remains unchanged
must co-exist with the new API
Must be supported for years
often re-implemented as an Adaptor
Slide 30
31. Agenda
Introduction: Why it matters?
Consider the perspective of the caller
Keep it simple
Strive for consistency
Choose memorable names
Specify the behaviour
Make it safe
Anticipate evolution
Write helpful documentation
Slide 31
32. Write helpful documentation
FALSE: APIs are self documenting
Behavior
Design concepts and abstractions
Design patterns and conventions
TRUE: Nobody reads documentation
Just-in-time learning preferred
Documentation is referenced
Information can be hard to find
FALSE: Nobody uses documentation
Adobe Flex Online, July, 2008
24,293 programmers, 101,289 queries
TRUE: Users don’t want documentation
They want assistance (help)
Slide 32
33. Write helpful documentation
Typical question from an online forum
Question: “With java.sql.ResultSet is there a
way to get a column's name as a String by
using the column's index? I had a look
through the API doc but I can't find anything.”
Answer: “See ResultSetMetaData:
ResultSet rs =
stmt.executeQuery("SELECT a, b, c
FROM TABLE2");
ResultSetMetaData rsmd =
rs.getMetaData();
String name =
rsmd.getColumnName(1);”
Slide 33
34. Write helpful documentation
Think like a friend providing assistance
Write short sections (10 minutes or less)
Answer specific questions
Make it easy to find
Forms of API documentation
Developer’s Guide (overview)
Reference manual (details)
Cookbook (usage scenarios, code snippets)
Working code (test drive)
Tutorial (optional)
FAQ or Knowledge Base (ease of update)
Slide 34
35. Summary
1) Consider the perspective of the caller
2) Keep it simple
3) Strive for consistency
4) Choose memorable names
5) Specify the behaviour
6) Make it safe
7) Anticipate evolution
8) Write helpful documentation
Slide 35
36. Further reading:
The Amiable API
http://theamiableapi.com
Slide 36