What Makes an API Great? Proven Design Principles from Joshua Bloch

This article explains why APIs are valuable assets, outlines the essential traits of a good API, and provides a step‑by‑step design process—including requirements gathering, naming, documentation, performance considerations, exception handling, and refactoring examples—illustrated with Java code snippets.

21CTO
21CTO
21CTO
What Makes an API Great? Proven Design Principles from Joshua Bloch

As big‑data and public platforms mature, APIs become crucial assets for companies and developers; a well‑designed API can capture users, improve code quality, and boost developer productivity.

Joshua Bloch, Google’s Chief Java Architect and author of Effective Java , presented a PPT titled “How to Design a Good API and Why it Matters,” which is the basis of this translation.

Characteristics of an excellent API:

Simple and easy to learn

Usable even without documentation

Hard to misuse

Readable and maintainable

Powerful enough to meet needs

Easy to extend

User‑friendly

API Design Process Considerations

Gather requirements – Extract real needs from use cases before committing to a solution.

Start with a brief description – Prioritize flexibility over completeness, keep it concise, and refine it as trust grows.

Write the API early – Preserve each implementation, list reasonable rules, and continuously enrich the API.

Write SPI (Service Provider Interface) – Support multiple implementations (e.g., Java Cryptography Extension) and follow the “Rule of Threes” for abstraction.

Maintain realistic expectations – Anticipate possible errors and adopt a growth mindset.

API Design Principles

Each API should focus on a single responsibility; a clear name drives development.

Keep the API lightweight; omit optional parts and favor concepts over size.

Implementation details must not leak into the API (e.g., on‑disk formats).

Minimize accessibility: make classes and members private, avoid public fields.

Use clear, consistent naming without ambiguous abbreviations.

Documentation – Good documentation is as essential as good design; every class, interface, method, constructor, parameter, and exception should be documented.

Performance impact – Design decisions affect performance permanently; poor choices can limit speed, while good design usually aligns with good performance.

Coexistence with the platform

Follow naming conventions and avoid outdated types.

Leverage language features such as generics, var‑args, and enums.

Avoid API traps like finalizers and public static final arrays.

Class design

Minimize mutability; only change a class for strong reasons.

If mutable, keep state small and well‑structured.

Subclassing

Subclasses should be substitutable (Liskov).

Public classes should not inherit from other public classes.

Method design

Clients should not duplicate module functionality.

Avoid long parameter lists; three or fewer parameters are ideal.

Use specific parameter and return types; avoid generic strings for non‑string data.

Maintain consistent parameter order.

Return values – Prefer returning empty strings or collections instead of throwing exceptions for normal cases.

Exception design

Throw exceptions to signal error conditions, not for flow control.

Support unchecked exceptions for programming errors and use checked exceptions sparingly.

Include failure‑capture information in exception messages to aid diagnosis.

Refactoring examples

Sublist operation in Vector vs. List interfaces demonstrates the power of using interfaces to reduce conceptual weight and improve documentation.

Thread‑local variables

Original design uses static set(String key, Object value) and get(String key) methods, which rely on a global namespace. A refactored version introduces a unique Key object to avoid name clashes:

public class ThreadLocal {
    private ThreadLocal() { }
    public static class Key { Key() { } }
    public static Key getKey() { return new Key(); }
    public static void set(Key key, Object value);
    public static Object get(Key key);
}

Another refactor simplifies the API to instance methods:

public class ThreadLocal {
    public ThreadLocal() { }
    public void set(Object value);
    public Object get();
}

These changes remove unnecessary code from the API and client usage.

In summary, API design is a high‑level craft that benefits programmers, end users, and companies. While perfection is unattainable, striving for well‑thought‑out design, clear documentation, and sensible conventions leads to better software.

Original source: http://www.csdn.net/article/2014-02-18/2818441-How-to-design-a-good-API

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaDocumentationAPIDesignBestPracticesexceptionhandling
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.