SlideShare ist ein Scribd-Unternehmen logo
1 von 49
Downloaden Sie, um offline zu lesen
How to Design a Good
    API and Why it Matters



        Joshua Bloch
        Principal Software Engineer

1   _How to Design a Good API and Why it Matters
Why is API Design Important?


    • APIs can be among a company's greatest assets
          _ Customers invest heavily: buying, writing, learning
          _ Cost to stop using an API can be prohibitive
          _ Successful public APIs capture customers

    • Can also be among company's greatest liabilities
          _ Bad APIs result in unending stream of support calls

    • Public APIs are forever - one chance to get it right




2   _
    How to Design a Good API and Why it Matters
Why is API Design Important to You?

    • If you program, you are an API designer
          _ Good code is modular–each module has an API

    • Useful modules tend to get reused
          _ Once module has users, can’t change API at will
          _ Good reusable modules are corporate assets

    • Thinking in terms of APIs improves code quality




3   _
    How to Design a Good API and Why it Matters
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



4   _
    How to Design a Good API and Why it Matters
Outline

        I. The Process of API Design
        II. General Principles
    III. Class Design
    IV. Method Design
        V. Exception Design
    VI. Refactoring API Designs




5   _
    How to Design a Good API and Why it Matters
I. The Process of API Design




6   _
    How to Design a Good API and Why it Matters
Gather Requirements–with a Healthy
    Degree of Skepticism

    • Often you'll get proposed solutions instead
          _ Better solutions may exist

    • Your job is to extract true requirements
          _ Should take the form of use-cases

    • Can be easier and more rewarding to build
        something more general


               Good
7   _
    How to Design a Good API and Why it Matters
Start with Short Spec–1 Page is Ideal

    • At this stage, agility trumps completeness
    • Bounce spec off as many people as possible
           _ Listen to their input and take it seriously

    • If you keep the spec short, it’s easy to modify
    • Flesh it out as you gain confidence
           _ This necessarily involves coding




8   _How to Design a Good API and Why it Matters
Write to Your API Early and Often

    • Start before you've implemented the API
           _ Saves you doing implementation you'll throw away

    • Start before you've even specified it properly
           _ Saves you from writing specs you'll throw away

    • Continue writing to API as you flesh it out
           _ Prevents nasty surprises
           _ Code lives on as examples, unit tests




9   _How to Design a Good API and Why it Matters
Writing to SPI is Even More Important


     • Service Provider Interface (SPI)
            _ Plug-in interface enabling multiple implementations
            _ Example: Java Cryptography Extension (JCE)
     • Write multiple plug-ins before release
            _ If you write one, it probably won't support another
            _ If you write two, it will support more with difficulty
            _ If you write three, it will work fine
     • Will Tracz calls this “The Rule of Threes”
          (Confessions of a Used Program Salesman, Addison-Wesley, 1995)



                   Bad
10   _How to Design a Good API and Why it Matters
Maintain Realistic Expectations

     • Most API designs are over-constrained
            _ You won't be able to please everyone
            _ Aim to displease everyone equally

     • Expect to make mistakes
            _ A few years of real-world use will flush them out
            _ Expect to evolve API




11   _How to Design a Good API and Why it Matters
II. General Principles



12   _
     How to Design a Good API and Why it Matters
API Should Do One Thing and Do it Well


     • Functionality should be easy to explain
            _ If it's hard to name, that's generally a bad sign
            _ Good names drive development
            _ Be amenable to splitting and merging modules




13   _How to Design a Good API and Why it Matters
API Should Be As Small As Possible But
     No Smaller

     • API should satisfy its requirements
     • When in doubt leave it out
           _ Functionality, classes, methods, parameters, etc.
           _ You can always add, but you can never remove

     • Conceptual weight more important than bulk
     • Look for a good power-to-weight ratio



14   _
     How to Design a Good API and Why it Matters
Implementation Should Not Impact API

     • Implementation details
           _ Confuse users
           _ Inhibit freedom to change implementation
     • Be aware of what is an implementation detail
           _ Do not overspecify the behavior of methods
           _ For example: do not specify hash functions
           _ All tuning parameters are suspect
     • Don't let implementation details “leak” into API
           _ On-disk and on-the-wire formats, exceptions



15   _
     How to Design a Good API and Why it Matters
Minimize Accessibility of Everything

     • Make classes and members as private as possible
     • Public classes should have no public fields
          (with the exception of constants)

     • This maximizes information hiding
     • Allows modules to be used, understood, built,
          tested, and debugged independently




16   _How to Design a Good API and Why it Matters
Names Matter–API is a Little Language


     • Names Should Be Largely Self-Explanatory
            _ Avoid cryptic abbreviations
     • Be consistent–same word means same thing
            _ Throughout API, (Across APIs on the platform)
     • Be regular–strive for symmetry
     • Code should read like prose
         if (car.speed() > 2 * SPEED_LIMIT)
            generateAlert("Watch out for cops!");




17   _How to Design a Good API and Why it Matters
Documentation Matters

     Reuse is something that is far easier to say than
     to do. Doing it requires both good design and
     very good documentation. Even when we see
     good design, which is still infrequently, we won't
     see the components reused without good
     documentation.
              - D. L. Parnas, _Software Aging. Proceedings
                of 16th International Conference Software
               Engineering, 1994




18   _
     How to Design a Good API and Why it Matters
Document Religiously

     • Document every class, interface, method,
         constructor, parameter, and exception
           _ Class: what an instance represents
           _ Method: contract between method and its client
                   _ Preconditions, postconditions, side-effects
           _ Parameter: indicate units, form, ownership

     • Document state space very carefully




19   _
     How to Design a Good API and Why it Matters
Consider Performance Consequences of
     API Design Decisions

     • Bad decisions can limit performance
           _ Making type mutable
           _ Providing constructor instead of static factory
           _ Using implementation type instead of interface
     • Do not warp API to gain performance
           _ Underlying performance issue will get fixed,
             but headaches will be with you forever
           _ Good design usually coincides with good performance




20   _
     How to Design a Good API and Why it Matters
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
     • Alternative added in 1.2; old client code still slow




21   _
     How to Design a Good API and Why it Matters
API Must Coexist Peacefully with Platform

     • Do what is customary
            _ Obey standard naming conventions
            _ Avoid obsolete parameter and return types
            _ Mimic patterns in core APIs and language
     • Take advantage of API-friendly features
            _ Generics, varargs, enums, default arguments
     • Know and avoid API traps and pitfalls
            _ Finalizers, public static final arrays




22   _How to Design a Good API and Why it Matters
III. Class Design



23   _
     How to Design a Good API and Why it Matters
Minimize Mutability

     • Classes should be immutable unless there’s a
          good reason to do otherwise
            _ Advantages: simple, thread-safe, reusable
            _ Disadvantage: separate object for each value
     • If mutable, keep state-space small, well-defined
            _ Make clear when it's legal to call which method
     Bad: Date, Calendar
     Good: TimerTask



24   _How to Design a Good API and Why it Matters
Subclass Only Where It Makes Sense


     • Subclassing implies substitutability (Liskov)
           _ Subclass only when is-a relationship exists
           _ Otherwise, use composition
     • Public classes should not subclass other public
         classes for ease of implementation
     Bad:                Properties extends Hashtable
                         Stack extends Vector
     Good: Set extends Collection



25   _
     How to Design a Good API and Why it Matters
Design and Document for Inheritance
     or Else Prohibit it

     • Inheritance violates encapsulation (Snyder, ‘86)
           _ Subclass sensitive to implementation details of
             superclass
     • If you allow subclassing, document self-use
           _ How do methods use one another?
     • Conservative policy: all concrete classes final
     Bad: Many concrete classes in J2SE libraries
     Good: AbstractSet, AbstractMap



26   _
     How to Design a Good API and Why it Matters
IV. Method Design



27   _
     How to Design a Good API and Why it Matters
Don't Make the Client Do Anything the
     Module Could Do

     • Reduce need for boilerplate code
           _ Generally done via cut-and-paste
           _ Ugly, annoying, and error-prone
         import   org.w3c.dom.*;
         import   java.io.*;
         import   javax.xml.transform.*;
         import   javax.xml.transform.dom.*;
         import   javax.xml.transform.stream.*;

         // DOM code to write an XML document to a specified output stream.
         private static final void writeDoc(Document doc, OutputStream out)throws IOException{
           try {
             Transformer t = TransformerFactory.newInstance().newTransformer();
             t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId());
             t.transform(new DOMSource(doc), new StreamResult(out));
           } catch(TransformerException e) {
             throw new AssertionError(e); // Can’t happen!
           }
         }




28   _
     How to Design a Good API and Why it Matters
Don't Violate the Principle of Least
     Astonishment

     • User of API should not be surprised by behavior
            _ It's worth extra implementation effort
            _ It's even worth reduced performance

         public class Thread implements Runnable {
           // Tests whether current thread has been interrupted.
           // Clears the interrupted status of current thread.
           public static boolean interrupted();
         }




29   _How to Design a Good API and Why it Matters
Fail Fast–Report Errors as Soon as
     Possible After They Occur

     • Compile time is best - static typing, generics
     • At runtime, first bad method invocation is best
             _ Method should be failure-atomic
         // A Properties instance maps strings to strings
         public class Properties extends Hashtable {
            public Object put(Object key, Object value);

               // Throws ClassCastException if this properties
               // contains any keys or values that are not strings
               public void save(OutputStream out, String comments);
         }




30   _
     How to Design a Good API and Why it Matters
Provide Programmatic Access to All
     Data Available in String Form

     • Otherwise, clients will parse strings
           _ Painful for clients
           _ Worse, turns string format into de facto API
     public class Throwable {
       public void printStackTrace(PrintStream s);
       public StackTraceElement[] getStackTrace(); // Since 1.4
     }
     public final class StackTraceElement {
       public String getFileName();
       public int getLineNumber();
       public String getClassName();
       public String getMethodName();
       public boolean isNativeMethod();
     }

31   _
     How to Design a Good API and Why it Matters
Overload With Care

     • Avoid ambiguous overloadings
           _ Multiple overloadings applicable to same actuals
           _ Conservative: no two with same number of args
     • Just because you can doesn't mean you should
           _ Often better to use a different name
     • If you must provide ambiguous overloadings,
         ensure same behavior for same arguments
     public TreeSet(Collection c); // Ignores order
     public TreeSet(SortedSet s); // Respects order




32   _
     How to Design a Good API and Why it Matters
Use Appropriate Parameter and Return Types


     • Favor interface types over classes for input
            _ Provides flexibility, performance
     • Use most specific possible input parameter type
            _ Moves error from runtime to compile time
     • Don't use string if a better type exists
            _ Strings are cumbersome, error-prone, and slow
     • Don't use floating point for monetary values
            _ Binary floating point causes inexact results!
     • Use double (64 bits) rather than float (32 bits)
            _ Precision loss is real, performance loss negligible




33   _How to Design a Good API and Why it Matters
Use Consistent Parameter Ordering
     Across Methods

     • Especially important if parameter types identical
         #include <string.h>
         char *strcpy (char *dest, char *src);
         void bcopy   (void *src, void *dst, int n);


         java.util.Collections – first parameter always
         collection to be modified or queried
         java.util.concurrent – time always specified as
         long delay, TimeUnit unit




34   _
     How to Design a Good API and Why it Matters
Avoid Long Parameter Lists

     • Three or fewer parameters is ideal
           _ More and users will have to refer to docs
     • Long lists of identically typed params harmful
           _ Programmers transpose parameters by mistake
           _ Programs still compile, run, but misbehave!
     • Two techniques for shortening parameter lists
           _ Break up method
           _ Create helper class to hold parameters
     // Eleven parameters including four consecutive ints
     HWND CreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName,
           DWORD dwStyle, int x, int y, int nWidth, int nHeight,
           HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
           LPVOID lpParam);


35   _
     How to Design a Good API and Why it Matters
Avoid Return Values that Demand
     Exceptional Processing

     • return zero-length array or empty collection, not null

         package java.awt.image;
         public interface BufferedImageOp {
           // Returns the rendering hints for this operation,
           // or null if no hints have been set.
           public RenderingHints getRenderingHints();
         }




36   _
     How to Design a Good API and Why it Matters
V. Exception Design




37   _
     How to Design a Good API and Why it Matters
Throw Exceptions to Indicate
     Exceptional Conditions

     • Don’t force client to use exceptions for control flow
            private byte[] a = new byte[BUF_SIZE];
            void processBuffer (ByteBuffer buf) {
              try {
                while (true) {
                  buf.get(a);
                  processBytes(tmp, BUF_SIZE);
                }
              } catch (BufferUnderflowException e) {
                int remaining = buf.remaining();
                buf.get(a, 0, remaining);
                processBytes(bufArray, remaining);
              }
            }
     • Conversely, don’t fail silently
             ThreadGroup.enumerate(Thread[] list)

38   _
     How to Design a Good API and Why it Matters
Favor Unchecked Exceptions

     • Checked – client must take recovery action
     • Unchecked – programming error
     • Overuse of checked exceptions causes boilerplate
     try {
         Foo f = (Foo) super.clone();
         ....
     } catch (CloneNotSupportedException e) {
         // This can't happen, since we’re Cloneable
         throw new AssertionError();
     }



39   _
     How to Design a Good API and Why it Matters
Include Failure-Capture Information in
     Exceptions

     • Allows diagnosis and repair or recovery
     • For unchecked exceptions, message suffices
     • For checked exceptions, provide accessors




40   _How to Design a Good API and Why it Matters
VI. Refactoring API Designs




41   _
     How to Design a Good API and Why it Matters
1. Sublist Operations in Vector

     public class Vector {
         public int indexOf(Object elem, int index);
         public int lastIndexOf(Object elem, int index);
         ...
     }


     • Not very powerful - supports only search
     • Hard too use without documentation




42   _How to Design a Good API and Why it Matters
Sublist Operations Refactored

     public interface List {
         List subList(int fromIndex, int toIndex);
         ...
     }


     • Extremely powerful - supports all operations
     • Use of interface reduces conceptual weight
           _ High power-to-weight ratio
     • Easy to use without documentation


43   _
     How to Design a Good API and Why it Matters
2. Thread-Local Variables

     // Broken - inappropriate use of String as capability.
      // Keys constitute a shared global namespace.
      public class ThreadLocal {
          private ThreadLocal() { } // Non-instantiable

               // Sets current thread’s value for named variable.
               public static void set(String key, Object value);

               // Returns current thread’s value for named variable.
               public static Object get(String key);
         }




44   _
     How to Design a Good API and Why it Matters
Thread-Local Variables Refactored (1)

     public class ThreadLocal {
          private ThreadLocal() { } // Noninstantiable

               public static class Key { Key() { } }
               // Generates a unique, unforgeable key
               public static Key getKey() { return new Key(); }
               public static void set(Key key, Object value);
               public static Object get(Key key);
         }


     • Works, but requires boilerplate code to use
         static ThreadLocal.Key serialNumberKey = ThreadLocal.getKey();
         ThreadLocal.set(serialNumberKey, nextSerialNumber());
         System.out.println(ThreadLocal.get(serialNumberKey));




45   _How to Design a Good API and Why it Matters
Thread-Local Variables Refactored (2)


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


     • Removes clutter from API and client code
         static ThreadLocal serialNumber = new ThreadLocal();
         serialNumber.set(nextSerialNumber());
         System.out.println(serialNumber.get());




46   _How to Design a Good API and Why it Matters
Conclusion

     • API design is a noble and rewarding craft
           _ Improves the lot of programmers, end-users,
             companies
     • This talk covered some heuristics of the craft
           _ Don't adhere to them slavishly, but...
           _ Don't violate them without good reason
     • API design is tough
           _ Not a solitary activity
           _ Perfection is unachievable, but try anyway



47   _
     How to Design a Good API and Why it Matters
Shameless Self-Promotion




48   _
     How to Design a Good API and Why it Matters
How to Design a Good
     API and Why it Matters



         Joshua Bloch
         Principal Software Engineer

49   _How to Design a Good API and Why it Matters

Weitere ähnliche Inhalte

Ähnlich wie Keynoteof A P I

How To Design A Good A P I And Why It Matters G O O G L E
How To Design A Good  A P I And Why It Matters    G O O G L EHow To Design A Good  A P I And Why It Matters    G O O G L E
How To Design A Good A P I And Why It Matters G O O G L Eguestbe92f4
 
How to design good api
How to design good apiHow to design good api
How to design good apiOsama Shakir
 
Sap web dynpro – practices for better functionality
Sap web dynpro – practices for better functionalitySap web dynpro – practices for better functionality
Sap web dynpro – practices for better functionalityanjalirao366
 
The Power Of Refactoring (PHPNW)
The Power Of Refactoring (PHPNW)The Power Of Refactoring (PHPNW)
The Power Of Refactoring (PHPNW)Stefan Koopmanschap
 
Dev Learn Handout - Session 604
Dev Learn Handout - Session 604Dev Learn Handout - Session 604
Dev Learn Handout - Session 604Chad Udell
 
MuleSoft Surat Meetup#39 - Pragmatic API Led Connectivity
MuleSoft Surat Meetup#39 - Pragmatic API Led ConnectivityMuleSoft Surat Meetup#39 - Pragmatic API Led Connectivity
MuleSoft Surat Meetup#39 - Pragmatic API Led ConnectivityJitendra Bafna
 
Designing Good API & Its Importance
Designing Good API & Its ImportanceDesigning Good API & Its Importance
Designing Good API & Its ImportanceImran M Yousuf
 
Your API Sucks! Why developers hang up and how to stop that.
Your API Sucks! Why developers hang up and how to stop that.Your API Sucks! Why developers hang up and how to stop that.
Your API Sucks! Why developers hang up and how to stop that.Apigee | Google Cloud
 
API Specifications and Best Practices | MuleSoft Mysore Meetup #4
API Specifications and Best Practices | MuleSoft Mysore Meetup #4API Specifications and Best Practices | MuleSoft Mysore Meetup #4
API Specifications and Best Practices | MuleSoft Mysore Meetup #4MysoreMuleSoftMeetup
 
Trouble with Performance Debugging? Not Anymore with Choreo, the AI-Assisted ...
Trouble with Performance Debugging? Not Anymore with Choreo, the AI-Assisted ...Trouble with Performance Debugging? Not Anymore with Choreo, the AI-Assisted ...
Trouble with Performance Debugging? Not Anymore with Choreo, the AI-Assisted ...WSO2
 
#7 Deep Dive into RAML 1.0 .pptx
#7 Deep Dive into RAML 1.0 .pptx#7 Deep Dive into RAML 1.0 .pptx
#7 Deep Dive into RAML 1.0 .pptxJohnMathewPhilip1
 
Faridabad MuleSoft Meetup Group (1).pdf
Faridabad MuleSoft Meetup Group (1).pdfFaridabad MuleSoft Meetup Group (1).pdf
Faridabad MuleSoft Meetup Group (1).pdfRohitSingh585124
 
[WSO2 API Day Chicago 2019] Sustainable Competitive Advantage
[WSO2 API Day Chicago 2019] Sustainable Competitive Advantage [WSO2 API Day Chicago 2019] Sustainable Competitive Advantage
[WSO2 API Day Chicago 2019] Sustainable Competitive Advantage WSO2
 
Why your APIs should fly first class
Why your APIs should fly first classWhy your APIs should fly first class
Why your APIs should fly first classLibbySchulze
 
Using Artificial Intelligence in Software Engineering
Using Artificial Intelligence in Software EngineeringUsing Artificial Intelligence in Software Engineering
Using Artificial Intelligence in Software EngineeringFaculty of Computer Science
 

Ähnlich wie Keynoteof A P I (20)

How To Design A Good A P I And Why It Matters G O O G L E
How To Design A Good  A P I And Why It Matters    G O O G L EHow To Design A Good  A P I And Why It Matters    G O O G L E
How To Design A Good A P I And Why It Matters G O O G L E
 
How to design good api
How to design good apiHow to design good api
How to design good api
 
Sap web dynpro – practices for better functionality
Sap web dynpro – practices for better functionalitySap web dynpro – practices for better functionality
Sap web dynpro – practices for better functionality
 
How to define an api
How to define an apiHow to define an api
How to define an api
 
The Power Of Refactoring (PHPNW)
The Power Of Refactoring (PHPNW)The Power Of Refactoring (PHPNW)
The Power Of Refactoring (PHPNW)
 
Dev Learn Handout - Session 604
Dev Learn Handout - Session 604Dev Learn Handout - Session 604
Dev Learn Handout - Session 604
 
MuleSoft Surat Meetup#39 - Pragmatic API Led Connectivity
MuleSoft Surat Meetup#39 - Pragmatic API Led ConnectivityMuleSoft Surat Meetup#39 - Pragmatic API Led Connectivity
MuleSoft Surat Meetup#39 - Pragmatic API Led Connectivity
 
The Power of Refactoring
The Power of RefactoringThe Power of Refactoring
The Power of Refactoring
 
Designing Good API & Its Importance
Designing Good API & Its ImportanceDesigning Good API & Its Importance
Designing Good API & Its Importance
 
Your API Sucks! Why developers hang up and how to stop that.
Your API Sucks! Why developers hang up and how to stop that.Your API Sucks! Why developers hang up and how to stop that.
Your API Sucks! Why developers hang up and how to stop that.
 
API presentation
API presentationAPI presentation
API presentation
 
API Specifications and Best Practices | MuleSoft Mysore Meetup #4
API Specifications and Best Practices | MuleSoft Mysore Meetup #4API Specifications and Best Practices | MuleSoft Mysore Meetup #4
API Specifications and Best Practices | MuleSoft Mysore Meetup #4
 
Effective API Design
Effective API DesignEffective API Design
Effective API Design
 
Trouble with Performance Debugging? Not Anymore with Choreo, the AI-Assisted ...
Trouble with Performance Debugging? Not Anymore with Choreo, the AI-Assisted ...Trouble with Performance Debugging? Not Anymore with Choreo, the AI-Assisted ...
Trouble with Performance Debugging? Not Anymore with Choreo, the AI-Assisted ...
 
#7 Deep Dive into RAML 1.0 .pptx
#7 Deep Dive into RAML 1.0 .pptx#7 Deep Dive into RAML 1.0 .pptx
#7 Deep Dive into RAML 1.0 .pptx
 
Faridabad MuleSoft Meetup Group (1).pdf
Faridabad MuleSoft Meetup Group (1).pdfFaridabad MuleSoft Meetup Group (1).pdf
Faridabad MuleSoft Meetup Group (1).pdf
 
[WSO2 API Day Chicago 2019] Sustainable Competitive Advantage
[WSO2 API Day Chicago 2019] Sustainable Competitive Advantage [WSO2 API Day Chicago 2019] Sustainable Competitive Advantage
[WSO2 API Day Chicago 2019] Sustainable Competitive Advantage
 
Why your APIs should fly first class
Why your APIs should fly first classWhy your APIs should fly first class
Why your APIs should fly first class
 
Using Artificial Intelligence in Software Engineering
Using Artificial Intelligence in Software EngineeringUsing Artificial Intelligence in Software Engineering
Using Artificial Intelligence in Software Engineering
 
How to design effective APIs
How to design effective APIsHow to design effective APIs
How to design effective APIs
 

Kürzlich hochgeladen

COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Websitedgelyza
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarPrecisely
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDELiveplex
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintMahmoud Rabie
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfJamie (Taka) Wang
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?IES VE
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemAsko Soukka
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Adtran
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXTarek Kalaji
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAshyamraj55
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024D Cloud Solutions
 

Kürzlich hochgeladen (20)

COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Website
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity Webinar
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership Blueprint
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystem
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBX
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024
 
20150722 - AGV
20150722 - AGV20150722 - AGV
20150722 - AGV
 

Keynoteof A P I

  • 1. How to Design a Good API and Why it Matters Joshua Bloch Principal Software Engineer 1 _How to Design a Good API and Why it Matters
  • 2. Why is API Design Important? • APIs can be among a company's greatest assets _ Customers invest heavily: buying, writing, learning _ Cost to stop using an API can be prohibitive _ Successful public APIs capture customers • Can also be among company's greatest liabilities _ Bad APIs result in unending stream of support calls • Public APIs are forever - one chance to get it right 2 _ How to Design a Good API and Why it Matters
  • 3. Why is API Design Important to You? • If you program, you are an API designer _ Good code is modular–each module has an API • Useful modules tend to get reused _ Once module has users, can’t change API at will _ Good reusable modules are corporate assets • Thinking in terms of APIs improves code quality 3 _ How to Design a Good API and Why it Matters
  • 4. 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 4 _ How to Design a Good API and Why it Matters
  • 5. Outline I. The Process of API Design II. General Principles III. Class Design IV. Method Design V. Exception Design VI. Refactoring API Designs 5 _ How to Design a Good API and Why it Matters
  • 6. I. The Process of API Design 6 _ How to Design a Good API and Why it Matters
  • 7. Gather Requirements–with a Healthy Degree of Skepticism • Often you'll get proposed solutions instead _ Better solutions may exist • Your job is to extract true requirements _ Should take the form of use-cases • Can be easier and more rewarding to build something more general Good 7 _ How to Design a Good API and Why it Matters
  • 8. Start with Short Spec–1 Page is Ideal • At this stage, agility trumps completeness • Bounce spec off as many people as possible _ Listen to their input and take it seriously • If you keep the spec short, it’s easy to modify • Flesh it out as you gain confidence _ This necessarily involves coding 8 _How to Design a Good API and Why it Matters
  • 9. Write to Your API Early and Often • Start before you've implemented the API _ Saves you doing implementation you'll throw away • Start before you've even specified it properly _ Saves you from writing specs you'll throw away • Continue writing to API as you flesh it out _ Prevents nasty surprises _ Code lives on as examples, unit tests 9 _How to Design a Good API and Why it Matters
  • 10. Writing to SPI is Even More Important • Service Provider Interface (SPI) _ Plug-in interface enabling multiple implementations _ Example: Java Cryptography Extension (JCE) • Write multiple plug-ins before release _ If you write one, it probably won't support another _ If you write two, it will support more with difficulty _ If you write three, it will work fine • Will Tracz calls this “The Rule of Threes” (Confessions of a Used Program Salesman, Addison-Wesley, 1995) Bad 10 _How to Design a Good API and Why it Matters
  • 11. Maintain Realistic Expectations • Most API designs are over-constrained _ You won't be able to please everyone _ Aim to displease everyone equally • Expect to make mistakes _ A few years of real-world use will flush them out _ Expect to evolve API 11 _How to Design a Good API and Why it Matters
  • 12. II. General Principles 12 _ How to Design a Good API and Why it Matters
  • 13. API Should Do One Thing and Do it Well • Functionality should be easy to explain _ If it's hard to name, that's generally a bad sign _ Good names drive development _ Be amenable to splitting and merging modules 13 _How to Design a Good API and Why it Matters
  • 14. API Should Be As Small As Possible But No Smaller • API should satisfy its requirements • When in doubt leave it out _ Functionality, classes, methods, parameters, etc. _ You can always add, but you can never remove • Conceptual weight more important than bulk • Look for a good power-to-weight ratio 14 _ How to Design a Good API and Why it Matters
  • 15. Implementation Should Not Impact API • Implementation details _ Confuse users _ Inhibit freedom to change implementation • Be aware of what is an implementation detail _ Do not overspecify the behavior of methods _ For example: do not specify hash functions _ All tuning parameters are suspect • Don't let implementation details “leak” into API _ On-disk and on-the-wire formats, exceptions 15 _ How to Design a Good API and Why it Matters
  • 16. Minimize Accessibility of Everything • Make classes and members as private as possible • Public classes should have no public fields (with the exception of constants) • This maximizes information hiding • Allows modules to be used, understood, built, tested, and debugged independently 16 _How to Design a Good API and Why it Matters
  • 17. Names Matter–API is a Little Language • Names Should Be Largely Self-Explanatory _ Avoid cryptic abbreviations • Be consistent–same word means same thing _ Throughout API, (Across APIs on the platform) • Be regular–strive for symmetry • Code should read like prose if (car.speed() > 2 * SPEED_LIMIT) generateAlert("Watch out for cops!"); 17 _How to Design a Good API and Why it Matters
  • 18. Documentation Matters Reuse is something that is far easier to say than to do. Doing it requires both good design and very good documentation. Even when we see good design, which is still infrequently, we won't see the components reused without good documentation. - D. L. Parnas, _Software Aging. Proceedings of 16th International Conference Software Engineering, 1994 18 _ How to Design a Good API and Why it Matters
  • 19. Document Religiously • Document every class, interface, method, constructor, parameter, and exception _ Class: what an instance represents _ Method: contract between method and its client _ Preconditions, postconditions, side-effects _ Parameter: indicate units, form, ownership • Document state space very carefully 19 _ How to Design a Good API and Why it Matters
  • 20. Consider Performance Consequences of API Design Decisions • Bad decisions can limit performance _ Making type mutable _ Providing constructor instead of static factory _ Using implementation type instead of interface • Do not warp API to gain performance _ Underlying performance issue will get fixed, but headaches will be with you forever _ Good design usually coincides with good performance 20 _ How to Design a Good API and Why it Matters
  • 21. 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 • Alternative added in 1.2; old client code still slow 21 _ How to Design a Good API and Why it Matters
  • 22. API Must Coexist Peacefully with Platform • Do what is customary _ Obey standard naming conventions _ Avoid obsolete parameter and return types _ Mimic patterns in core APIs and language • Take advantage of API-friendly features _ Generics, varargs, enums, default arguments • Know and avoid API traps and pitfalls _ Finalizers, public static final arrays 22 _How to Design a Good API and Why it Matters
  • 23. III. Class Design 23 _ How to Design a Good API and Why it Matters
  • 24. Minimize Mutability • Classes should be immutable unless there’s a good reason to do otherwise _ Advantages: simple, thread-safe, reusable _ Disadvantage: separate object for each value • If mutable, keep state-space small, well-defined _ Make clear when it's legal to call which method Bad: Date, Calendar Good: TimerTask 24 _How to Design a Good API and Why it Matters
  • 25. Subclass Only Where It Makes Sense • Subclassing implies substitutability (Liskov) _ Subclass only when is-a relationship exists _ Otherwise, use composition • Public classes should not subclass other public classes for ease of implementation Bad: Properties extends Hashtable Stack extends Vector Good: Set extends Collection 25 _ How to Design a Good API and Why it Matters
  • 26. Design and Document for Inheritance or Else Prohibit it • Inheritance violates encapsulation (Snyder, ‘86) _ Subclass sensitive to implementation details of superclass • If you allow subclassing, document self-use _ How do methods use one another? • Conservative policy: all concrete classes final Bad: Many concrete classes in J2SE libraries Good: AbstractSet, AbstractMap 26 _ How to Design a Good API and Why it Matters
  • 27. IV. Method Design 27 _ How to Design a Good API and Why it Matters
  • 28. Don't Make the Client Do Anything the Module Could Do • Reduce need for boilerplate code _ Generally done via cut-and-paste _ Ugly, annoying, and error-prone import org.w3c.dom.*; import java.io.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; // DOM code to write an XML document to a specified output stream. private static final void writeDoc(Document doc, OutputStream out)throws IOException{ try { Transformer t = TransformerFactory.newInstance().newTransformer(); t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, doc.getDoctype().getSystemId()); t.transform(new DOMSource(doc), new StreamResult(out)); } catch(TransformerException e) { throw new AssertionError(e); // Can’t happen! } } 28 _ How to Design a Good API and Why it Matters
  • 29. Don't Violate the Principle of Least Astonishment • User of API should not be surprised by behavior _ It's worth extra implementation effort _ It's even worth reduced performance public class Thread implements Runnable { // Tests whether current thread has been interrupted. // Clears the interrupted status of current thread. public static boolean interrupted(); } 29 _How to Design a Good API and Why it Matters
  • 30. Fail Fast–Report Errors as Soon as Possible After They Occur • Compile time is best - static typing, generics • At runtime, first bad method invocation is best _ Method should be failure-atomic // A Properties instance maps strings to strings public class Properties extends Hashtable { public Object put(Object key, Object value); // Throws ClassCastException if this properties // contains any keys or values that are not strings public void save(OutputStream out, String comments); } 30 _ How to Design a Good API and Why it Matters
  • 31. Provide Programmatic Access to All Data Available in String Form • Otherwise, clients will parse strings _ Painful for clients _ Worse, turns string format into de facto API public class Throwable { public void printStackTrace(PrintStream s); public StackTraceElement[] getStackTrace(); // Since 1.4 } public final class StackTraceElement { public String getFileName(); public int getLineNumber(); public String getClassName(); public String getMethodName(); public boolean isNativeMethod(); } 31 _ How to Design a Good API and Why it Matters
  • 32. Overload With Care • Avoid ambiguous overloadings _ Multiple overloadings applicable to same actuals _ Conservative: no two with same number of args • Just because you can doesn't mean you should _ Often better to use a different name • If you must provide ambiguous overloadings, ensure same behavior for same arguments public TreeSet(Collection c); // Ignores order public TreeSet(SortedSet s); // Respects order 32 _ How to Design a Good API and Why it Matters
  • 33. Use Appropriate Parameter and Return Types • Favor interface types over classes for input _ Provides flexibility, performance • Use most specific possible input parameter type _ Moves error from runtime to compile time • Don't use string if a better type exists _ Strings are cumbersome, error-prone, and slow • Don't use floating point for monetary values _ Binary floating point causes inexact results! • Use double (64 bits) rather than float (32 bits) _ Precision loss is real, performance loss negligible 33 _How to Design a Good API and Why it Matters
  • 34. Use Consistent Parameter Ordering Across Methods • Especially important if parameter types identical #include <string.h> char *strcpy (char *dest, char *src); void bcopy (void *src, void *dst, int n); java.util.Collections – first parameter always collection to be modified or queried java.util.concurrent – time always specified as long delay, TimeUnit unit 34 _ How to Design a Good API and Why it Matters
  • 35. Avoid Long Parameter Lists • Three or fewer parameters is ideal _ More and users will have to refer to docs • Long lists of identically typed params harmful _ Programmers transpose parameters by mistake _ Programs still compile, run, but misbehave! • Two techniques for shortening parameter lists _ Break up method _ Create helper class to hold parameters // Eleven parameters including four consecutive ints HWND CreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); 35 _ How to Design a Good API and Why it Matters
  • 36. Avoid Return Values that Demand Exceptional Processing • return zero-length array or empty collection, not null package java.awt.image; public interface BufferedImageOp { // Returns the rendering hints for this operation, // or null if no hints have been set. public RenderingHints getRenderingHints(); } 36 _ How to Design a Good API and Why it Matters
  • 37. V. Exception Design 37 _ How to Design a Good API and Why it Matters
  • 38. Throw Exceptions to Indicate Exceptional Conditions • Don’t force client to use exceptions for control flow private byte[] a = new byte[BUF_SIZE]; void processBuffer (ByteBuffer buf) { try { while (true) { buf.get(a); processBytes(tmp, BUF_SIZE); } } catch (BufferUnderflowException e) { int remaining = buf.remaining(); buf.get(a, 0, remaining); processBytes(bufArray, remaining); } } • Conversely, don’t fail silently ThreadGroup.enumerate(Thread[] list) 38 _ How to Design a Good API and Why it Matters
  • 39. Favor Unchecked Exceptions • Checked – client must take recovery action • Unchecked – programming error • Overuse of checked exceptions causes boilerplate try { Foo f = (Foo) super.clone(); .... } catch (CloneNotSupportedException e) { // This can't happen, since we’re Cloneable throw new AssertionError(); } 39 _ How to Design a Good API and Why it Matters
  • 40. Include Failure-Capture Information in Exceptions • Allows diagnosis and repair or recovery • For unchecked exceptions, message suffices • For checked exceptions, provide accessors 40 _How to Design a Good API and Why it Matters
  • 41. VI. Refactoring API Designs 41 _ How to Design a Good API and Why it Matters
  • 42. 1. Sublist Operations in Vector public class Vector { public int indexOf(Object elem, int index); public int lastIndexOf(Object elem, int index); ... } • Not very powerful - supports only search • Hard too use without documentation 42 _How to Design a Good API and Why it Matters
  • 43. Sublist Operations Refactored public interface List { List subList(int fromIndex, int toIndex); ... } • Extremely powerful - supports all operations • Use of interface reduces conceptual weight _ High power-to-weight ratio • Easy to use without documentation 43 _ How to Design a Good API and Why it Matters
  • 44. 2. Thread-Local Variables // Broken - inappropriate use of String as capability. // Keys constitute a shared global namespace. public class ThreadLocal { private ThreadLocal() { } // Non-instantiable // Sets current thread’s value for named variable. public static void set(String key, Object value); // Returns current thread’s value for named variable. public static Object get(String key); } 44 _ How to Design a Good API and Why it Matters
  • 45. Thread-Local Variables Refactored (1) public class ThreadLocal { private ThreadLocal() { } // Noninstantiable public static class Key { Key() { } } // Generates a unique, unforgeable key public static Key getKey() { return new Key(); } public static void set(Key key, Object value); public static Object get(Key key); } • Works, but requires boilerplate code to use static ThreadLocal.Key serialNumberKey = ThreadLocal.getKey(); ThreadLocal.set(serialNumberKey, nextSerialNumber()); System.out.println(ThreadLocal.get(serialNumberKey)); 45 _How to Design a Good API and Why it Matters
  • 46. Thread-Local Variables Refactored (2) public class ThreadLocal { public ThreadLocal() { } public void set(Object value); public Object get(); } • Removes clutter from API and client code static ThreadLocal serialNumber = new ThreadLocal(); serialNumber.set(nextSerialNumber()); System.out.println(serialNumber.get()); 46 _How to Design a Good API and Why it Matters
  • 47. Conclusion • API design is a noble and rewarding craft _ Improves the lot of programmers, end-users, companies • This talk covered some heuristics of the craft _ Don't adhere to them slavishly, but... _ Don't violate them without good reason • API design is tough _ Not a solitary activity _ Perfection is unachievable, but try anyway 47 _ How to Design a Good API and Why it Matters
  • 48. Shameless Self-Promotion 48 _ How to Design a Good API and Why it Matters
  • 49. How to Design a Good API and Why it Matters Joshua Bloch Principal Software Engineer 49 _How to Design a Good API and Why it Matters