Two large technology companies are disputing a case before the United States Supreme Court over whether a set of software interfaces can be copyrighted. To the layman that does not understand software or what an Application Programming Interface (API) is or what it is used for, this case may seem meaningless; however, the stakes are very high. Not only does the suit involve potentially billions of dollars in damages, it also will clarify how copyright is applied to software with broad ramifications for the tech. industry, the economy and the future of innovation.
So, let’s begin with the key foundational question:
What is an API?
We must take our time here and define this correctly because most legal material around this court case does a poor job of answering that simple question. In turn, that weakness in this case (possibly caused by being intimidated by the technical nature of the subject matter), does injury to the central arguments in the case by reducing APIs to their lowest common denominator. So, here we will use a careful, building-block approach to properly define and demonstrate the term “Application Programming Interface”.
An Application Programming Interface is a type of specification, written in a programming language, that defines the operational interface between an application and a set of services (either hardware services or software services). This operational interface forms a contract between these two bodies of code that defines how one interacts with the other. Let’s further break down this definition by defining all the specific terms used in the definition in Table 1.
Table 1 Defining an Application Programming Interface
Term |
Definition |
Application |
a user-level program that is run by an operating system of a computer. Examples of user-level programs are Microsoft Word and the Firefox web browser. |
Programming Language |
A Programming language is set of English-like keywords that are strung together into larger groups called statements and stored in a text file (called a source code file). These source code files are compiled into binary instructions and packaged as an executable (which is another name for a program). Executables are run by an operating system on computer hardware. Examples of popular programming languages are Java, Python and C#. The programming language in question in this case is the Java Programming Language, originally created by Sun Microsystems and later bought by Oracle. |
Operational Interface |
An interface is a specific method of operation for invoking one or more services. For example, the operational interface for a car is the gas pedal, steering wheel and gear shift. You use the interface (press the gas, turn the steering wheel) to invoke a service (accelerate, turn, stop). In software an operational interface is defined as a set of methods. A “method” in software is a named block of code that takes input, executes a set of instructions and produces an output. |
Software Services |
A software service is a set of methods (defined above) that provide functionality to a client program. A good example is the services an operating system (like Microsoft Windows or Mac OS) that provide services to client programs to draw on the screen, access the file system or communicate across a network. Software services are often called “back-end” services while the client program often has a user interface and is considered the “front-end” program. This “front-end” versus “back-end” distinction in analogous to a retail establishment, like a restaurant, that has front-end services (seating guests, taking orders) and back-end services (cooking food, washing dishes). |
The smallest build block in an API is what we defined above as a “method”. As depicted in Figure 1, a method is a named body of code that takes some input, executes a set of instructions and generates an output.
Figure 1 “split” method as a Black Box
In figure 1 we have a method called “split” that has the following purpose: take the input string and a delimiter character (a delimiter is a separator character like a comma or colon) and split the large string into all the words that are separated by the delimiter. For example if the input string was “one : two : three” and the delimiter was the colon character (‘:’) then the result would be a group (or list) of strings: [one, two, three]. Another common way to think of a method is as a “black box” that receives inputs and produces outputs. How you implement the “split” method would consist of the set of instructions inside the box. One can use a black box without knowing the details inside (in fact it is called a “black” box because it is opaque and you cannot see inside it). At this point you should understand what a method is and what it is used for. A client program would invoke such a method by calling its name, providing it with the right input parameters and assigning its results to a named memory location (called a variable) like this:
input = “one:two:three”
delimiter = ‘:’
output = split(input, delimiter)
Listing 1. Snippet of client code calling the split method
The above code would be called “pseudo-code” because it omits some details that a programming language like Java would need. See Listing 5, at the end of this article for a complete sample of this code written in Java. You should note the pattern for calling a method is as follows (and similar in almost all programming languages):
Return-variable = method_name(input-param1, input-paramN)
At this point, we have explained the acronym API and demonstrated its simplest form, a single method call. A single method call would provide a single service to a client program. Remember that almost all APIs are much more complicated than a single method call and instead contain dozens and even hundreds of method calls. We will build our way up to such an example by the end of this article. In his initial ruling against Oracle’s copyright claim, Judge Alsup used a single function Math.max() to demonstrate an API and he even asserted that “The foregoing completes the facts necessary to decide the copyrightability issue…”[i]. As the rest of this article will demonstrate, a single method call is a trivial example of an API that, while technically correct, does a disservice to the complexity, careful design and artistry of non-trivial APIs. This fact cannot be understated: in the real world (and thus from a practical perspective), 99.9% of the time there are no APIs consisting of a single method. Having written numerous books[ii] on Java and dozens of real-world software systems, I would assert that Judge Alsup’s one method example of an API reveals a dangerous naivete regarding the technical issues involved in this case. Furthermore, basing his ruling on such a shaky foundation undermines all his conclusions in that ruling. In this article and the articles to come, I hope to clear up those technical issues so that the Supreme Court can have a much stronger basis to make its decision.
Besides a single-method call being non-representative of APIs, another problem with using it as an example is that such a simple case can only be used in what is called a “procedural” language; whereas, Java (the programming language in question in this case) is an object-oriented language. So, again we see that over-simplification damages a complete understanding of the facts. An object-oriented language is more complex than a procedural language because it attempts to represent the problem space by mimicking the way things exist in the real world. In the real world, we have objects (like a Car, a House, a Person) that have specific behaviors and characteristics. Given that, Object-Oriented Programming attempts to mirror that modeling paradigm by creating software objects that bind together (or encapsulate) the methods (the behaviors) and the data (the characteristics) together into a single item called an object. The source code template that describes a class of these objects and how to create them is called a “class”. So, to summarize, in the Java Programming language we create “classes” of objects that encapsulate the behavior (methods) and characteristics (data) of named objects. Listing 2 demonstrates a simple Person class:
public class Person
{
private String fullName;
private LocalDate birthDate;
public Person(String name, LocalDate bday)
{
fullName = name;
birthDate = bday;
}
public int getAge()
{
LocalDate today = LocalDate.now();
Period p = Period.between(birthDate, today);
return p.getYears();
}
}
Listing 2. A Person class in Java
A few things are worth noting in Listing 2 but you should not get bogged down by the details of the language syntax (like the use of curly braces in place of “begin” and “end” or the use of semicolons at the end of statements). The public and private keywords in front of things determine how that thing is either exposed to other code or protected from other code. The basic idea behind the code in Listing 2 is that we have a class called “Person” that has two attributes (the full name of the person and the birth date of the person) and two methods. One method is a special method called a constructor that is run when the object is first created in memory in order to initialize its data and a second method called “getAge” which calculates the person’s age in years from the current time. The notion of encapsulating data with methods and protecting data from other code is a core principle for object-oriented programming and changes how you create an API for such a language. This is very important because an API for a procedural language is different than an API for an object-oriented language. This is yet another reason why simplifying the concept of an API by watering down its complexity cheapens the tremendous effort required to create good APIs. It is also worth noting that the getAge() method in Listing 2 uses a new Java LocalDate API that is the second replacement for the original Date API that was available with the original incarnation of Java. The original Date API was mostly deprecated (marked as “to be replaced in the future) by a Calendar API and now again superceded by the LocalDate API. It is easy for one to argue that Sun Microsystems (the original creator of Java prior to Oracle buying Sun in 2010), messed up the Java Date API and thus competitors stepped in with better alternatives forcing Sun to keep trying to get it right. There is ample evidence of this with many third party alternatives to the Java Date API to include JodaTime[iii], Apache’s Time package[iv] in its Commons API and the CalendarDate[v] API. This is not the only example of the “standard library” provided for Java is not the best or chosen library of the Java development community (other well known examples are the logging APIs and the Enterprise Java Beans API). This highlights the fact that if an API is designed poorly then it will not gain traction in the developer community and is ripe for competition. Java’s overall popularity of its APIs is a testament to the fact that most of its APIs are well-designed and effective. Now we can move on to a more object-oriented example of a non-trivial API. Let’s examine the Java API for communicated with databases which is called the Java Database Connective API (or JDBC). It is worth noting that the JDBC API is a Java redesign of a Microsoft API called ODBC (Object Database Connectivity[vi]). There are many articles on the differences between JDBC and ODBC on the internet.
Figure 2 depicts one key method in the JDBC API called “executeQuery”. As you can see from the diagram, the execute Query method accepts a Java object called “String” which is an Structured Query Language (SQL) command to the database and returns the results of that query in another Java object called a ResultSet. The method name in this example is different due to the fact that this is an Object Oriented API. The executeQuery method is not a standalone method but instead it is part of a Statement object. A Statement object is an abstraction that represents a Structured Query Language statement to the database. There are various ways to form this statement. The second important difference is that you are passing in an object and returning an object from the method. Finally, since the JDBC API was carefully designed to support “plug-in” implementations where each different database vendor could make an implementation for its database, Statement and ResultSet are not classes. They are called “interfaces” because they represent a pure procedural contract that any class can implement. A class implements an interface by using the “implements” keyword so if I wanted to create a class that can be used as a Statement the code would be “class myClass implements Statement”. The JDBC API is a good example of a case where the designer of the API both expects and invites third-party Implementations of the API and even designs an easy method to load the alternative APIs into the Java client programs. This makes sense because Java is creating a client API to access third-party databases. Of course, vendors are free to implement a custom (non-JDBC) interface to their database and many have done so[vii].
Figure 2 The "executeQuery" method
In terms of functionality, Figure 2 depicts a method call that would be used by a client program to communicate and invoke a specific service in a relational database. Specifically, the executeQuery method queries a relational database and receives back the query results (called the “result set”) to the client program. An example of a database query would be a textual command (called an SQL statement) that returns sales data across all the stores in a region.
Listing 3 below is one small example of a Java API that Google copied for their Android Operating Platform that runs on smart phones and competes with an Oracle branded smart phone Operating Platform called J2ME (The Java 2 Micro Edition). While it is 47 lines long, that is considered a small example because most API are more complex and require many more classes and data to perform their essential functions. Additionally, the example in Listing 3 does not include the documentation that accompanies each method call to explain, in detail, its function, its input parameters and its resulting output. Finally, the example in Listing 3 is not even the completed JDBC API, it is only one Interface of that API that consists of a total of 22 interfaces, 7 classes and 17 special subclasses about possible errors (these are called Exceptions in Java).
In the JDBC API, the “Connection” Interface are the methods that a establish an active connection between the desktop client and the third-party database. Most databases work as servers running on a remote computer that a client connects to, sends a set of statements to, and then disconnects from. A single server serves many clients. In Listing 3 below, each row of the API listing contains three parts: first, a class or interface that represents output data. The second column is the method name which is unique (within its Class and Package) and finally, inside the method name parenthesis, is one or more input parameters. Those parameters within parenthesis are the data that is passed into the method.
Output Data Method Name (One or more Data Input Parameters)
void clearWarnings()
void close()
void commit()
Array createArrayOf(String typeName, Object[] elements)
Blob createBlob()
Clob createClob()
NClob createNClob()
SQLXML createSQLXML()
Statement createStatement(int resultSetType, int resultSetConcurrency)
Statement createStatement()
Statement createStatement(int resultSetType, int resultSetConcurrency, int
resultSetHoldability)
Struct createStruct(String typeName, Object[] attributes)
boolean getAutoCommit()
String getCatalog()
String getClientInfo(String name)
Properties getClientInfo()
int getHoldability()
DatabaseMetaData getMetaData()
int getTransactionIsolation()
Map<String, Class<?>> getTypeMap()
SQLWarning getWarnings()
boolean isClosed()
Boolean isReadOnly()
boolean isValid(int timeout)
String nativeSQL(String sql)
CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
CallableStatement prepareCall(String sql)
CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int
resultSetHoldability)
PreparedStatement prepareStatement(String sql, String[] columnNames)
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int
resultSetHoldability)
PreparedStatement prepareStatement(String sql, int[] columnIndexes)
PreparedStatement prepareStatement(String sql)
PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
void releaseSavepoint(Savepoint savepoint)
void rollback()
void rollback(Savepoint savepoint)
void setAutoCommit(boolean autoCommit)
void setCatalog(String catalog)
void setClientInfo(Properties properties)
void setClientInfo(String name, String value)
void setHoldability(int holdability)
void setReadOnly(boolean readOnly)
Savepoint setSavepoint(String name)
Savepoint setSavepoint()
void setTransactionIsolation(int level)
void setTypeMap(Map<String, Class<?>> map)
Listing 2. Listing of API Methods in the Connection interface that are part of the java.sql package.
Now, let’s specifically address the Connection part of the API in listing 2. The purpose of the Connection interface in listing 2 is to create one of three types of Statements (a regular statement, a prepared statement or a callable statement). A statement is an interface that a vendor creates a class to implement that represents an SQL statement that the client wants to send to the database (over the connection) to be executed. That, of course, brings us directly to the executeQuery method we already covered in Figure 2.
Now, let’s go up a level and think about the entire JDBC API. As we have stated, the high level objective of the JDBC API is to provide classes and interfaces to communicate with a relational database by inserting records, querying the database and retrieving results back from the database. There are literally thousands of ways those operations can be performed and thousands of ways you can format the input and output data to be sent to the database or received from the database. The API designer makes choices for everything in the API including how the data is structured, how the operations are sequenced, what operations depend upon other operations and how to handle potential errors. Going up one more level to the platform level, this package may take advantage of and interact with other packages (like networking or utilities) to accomplish its objective. So not only must the package be designed carefully but the entire platform as a whole is taken into consideration when designing APIs.
What can this API example teach us about APIs that a single method call cannot? First, these classes, interfaces and methods should be considered as part of a whole and not examined individually because they were designed as part of a whole to elegantly, efficiently and effectively perform a set of functions. Second, it should now be obvious that APIs are not small lists of commands, instead they are a large set of classes which contain data and methods to expose a set of functionality to client programs in the most intuitive way possible. That objective to make an API “intuitive” represents the core design objective for an API and it is almost always difficult to achieve. Donald Norman in the book, The Design of Everyday Things, states that a good design is one where the conceptual model of how something should work in your head maps well to how the device works. If we have a natural mapping between the two then the operation of the device is considered “intuitive”. The final point about an API is that there are many competing ways to design a API that vie for developer attention and adoption. For communicating with databases, there are other options like Java Data Objects (JDO)[viii] and the Java Persistence API (JPA)[ix]. So, the popularity and adoption of any API is far from assured and there are often competing APIs in every domain. The final topic for this article to cover then is what are the elements of API design that make it so challenging and important to winning the hearts and minds of developers?
Good API design is hard. I remember attending one of the first JavaOne conferences in San Francisco and marveling at how fast the Java Community was moving to expand the number of APIs in order to answer the growing needs of its developer community. The Sun Microsystems Java architects compared their growing set of APIs as the software equivalent to Integrated Circuits. The lesson here is that the Java Architects at Sun Microsystems were aware that good APIs were helping to drive the popularity and growth of the Java language. To that end, there was a keen desire to insure that they designed the APIs right the first time. This was especially important for a platform that was doubling or tripling in adoption each year because replacing or changing an API after mass adoption is very difficult and pisses off many developers. An early lesson of that was when Sun Microsystems drastically revised the AWT API from Java 1.0 to Java 1.1[x]. That major change to a low-level API broke a lot of existing code but that early lesson highlighted the importance of getting it right the first time by adopting a strong set of API design principles. The golden rule of API design is to make “easy things easy and hard things possible”[xi]. While that sounds simple enough, let me assure you that it is not. Let’s examine some evidence of that by looking at the number of books, search results and videos on the subject of API design. A search for books with “api design” in the title on Amazon.com returns a total of 956 results[xii]. A listing of the Top books on the subject can be found at the end of this article. A google search for “api design” (in quotes which preserves the exact order of words) returned 1,130,000 hits[xiii]. A listing of the top articles on the subject can be found at the end of this article. Finally, a search on youtube for “api design” returned 20,400 videos[xiv]. Even a cursory search of the first several pages of any of these sources will make it quite evident that designing good APIs is difficult enough that many people need help to do it well.
In closing, let me summarize the key points in this article and briefly discuss the subject of the next article in this series.
· An Application Programming Interface is a type of specification, written in a programming language, that defines the operational interface between an application and a set of services.
· A single method is a poor example of an API. Furthermore, Judge Alsup’s one method example of an API in his ruling reveals a dangerous naivete regarding the technical issues involved in this case.
· A procedural API is not the same as an Object-Oriented API.
· Every developer is free to write their own API if they believe they can do it better. There are many examples of poor APIs being superseded by new APIs that become more popular.
· The breadth and depth of the Java APIs were instrumental in the growth of the language’s popularity.
· Good APIs are difficult to create as is evidenced by the numerous books, articles and videos on designing APIs.
My hope is that now you understand what an API is and understand a non-trivial example (JDBC) of a popular API. In the next article, we will examine the legal issues that are in question and the history of the case up to this point. I’ll be back soon as my goal is to complete the entire series of these articles before the Supreme Court rules on this case in the Fall of 2020.
Here are the additional listings mentioned in the article:
1. The Design of Web APIs by Arnaud Lauret
2. Design and Build Great Web APIs: Robust, Reliable and Resilient by Mike Amundsen
3. Designing Web APIs: Building APIs That Developers Love by Brenda Jin, Sarabh Sahni
4. Restful API Design: Best Practices in API Design with REST by Matthias Biehl
5. API Design for C++ by Martin Reddy
6. Django for APIs: Build web APIs with Python & Django
7. REST API Design Rulebook: Designing Consistent RESTful Web Service Interfaces by Mark Masse
8. Practical API Design: Confessions of a Java Framework Architect by Jaroslav Tulach
9. The REST API Design Handbook by George Reese and Christian Reilly
10. Enterprise API Management: Design and Deliver valuable business APIs by Luis Weir and Zdenek “Z” Nemec
Listing 3. Top Books on API Design
1. API Design guidance – Best practices for cloud applications; https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design
2. What is API Design (And Why Does it Matter?); https://swagger.io/blog/api-design/what-is-api-design/
3. Best Practices for Designing a Pragmatic RESTful API; https://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
4. Best Practices for REST API design; https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/
5. REST API Design Tutorial; https://restfulapi.net/rest-api-design-tutorial-with-example/
6. Web API Design: 5 Best Practices to Know; https://www.toptal.com/api-developers/5-golden-rules-for-designing-a-great-web-api
7. RESTful API Design – Step by Step Guide; https://hackernoon.com/restful-api-design-step-by-step-guide-2f2c9f9fcdbf
8. REST: Good Practices for API Design; https://medium.com/hashmapinc/rest-good-practices-for-api-design-881439796dc9
9. What is API Design?; https://api-university.com/blog/what-is-api-design/
10. API Design Guide; https://stoplight.io/api-design-guide/basics/
Listing 4. Top Articles on API Design.
package googlevsoracle;
import java.time.LocalDate;
import java.time.Month;
import java.time.Period;
import java.util.Calendar;
import java.util.Date;
/**
*
* @author mdaconta
*/
public class Person {
private String fullName;
private LocalDate birthDate;
public Person(String name, LocalDate bday) {
fullName = name;
birthDate = bday;
}
public int getAge() {
LocalDate today = LocalDate.now();
Period p = Period.between(birthDate, today);
return p.getYears();
}
public String getName() {
return fullName;
}
public LocalDate getBirthDate () {
return birthDate;
}
public static void main(String[] args) {
LocalDate bday = LocalDate.parse("1962-10-10");
Person p = new Person("Joe", bday);
System.out.println("The Person named " + p.getName() + " is "
+ p.getAge());
}
}
Listing 5. Program to split a String in the Java Programming Language.
[i]http://www.groklaw.net/pdf3/OraGoogle-1202.pdf
[ii] I have authored the following books on Java:
· More Java Pitfalls, published in June 2003 by John Wiley & Sons, Inc..
· XML Development with Java 2, published in September 2000 by Sams publishing.
· Java Pitfalls, published in May 2000 by John Wiley & Sons, Inc. One of the best-selling titles at JavaOne and selected as a feature book for the Library of Computer and Information Sciences (LCIS) book club.
· Java 2 and JavaScript for C and C++ Programmers, published in May 2000 by John Wiley & Sons, Inc.
· Java 1.2 and JavaScript for C and C++ Programmers, published in December 1997 by John Wiley & Sons, Inc. Selected as a Main Selection for the Small Computer Book Club (SCBC). Currently updating this book to cover the Java 2 Platform.
· Java for C/C++ Programmers, published in March 1996 by John Wiley & Sons,Inc. Declared a "must-read" by PC Magazine, Information Week and the JavaReport. Also the Main selection of the Library of Computer and Information Science Book Club (LCIS).
[iii] Joda Time API. https://www.joda.org/joda-time/
[iv] Apache Commons API. https://commons.apache.org/
[v] CalendarDate API. http://calendardate.sourceforge.net/
[vi] Open Database Connectivity article on Wikipedia: https://en.wikipedia.org/wiki/Open_Database_Connectivity
[vii] An example of a Non-JDBC interface is the Neo4J interface available at https://neo4j.com/
[viii]Java Data Objects <<< link here >>>
[ix]Java Persistence API <<< link here >>>
[x] Java 1.0 to 1.1 compatibility. See: https://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/guide/awt/HowToUpgrade.html
[xi] Generally attributed to the creator of the Perl language, Larry Wall. See: https://www.amazon.com/Learning-Perl-Making-Things-Possible/dp/1491954329 though I remember hearing this spoken by a Java Architect at a JavaOne conference.
[xii]Search for “api design” was run on amazon.com on 8/3/2020.
[xiii]The google search for “api design” was run on google.com on 8/3/2020.
[xiv] While youtube does not show result counts on youtube.com, a search of google.com with the terms “api design” and youtube.com under the videos tab displayed the result of 20,400 videos.