Computer Science

Share this article:

Computer Science

  • Join our comunity:

The #1 Rule of API Design

By: , Posted on: November 15, 2013

API Design for C++ CoverApplication Programming Interfaces (APIs) are software components that package up re-usable chunks of code. Traditionally, APIs are used by linking code into your program, from built-in libraries like the C++ Standard Template Library (STL), to open source APIs like libpng or zlib, and user interface frameworks like Qt or the Windows API. More recently, the term API has been popularized to mean Web API, most often meaning a web-based service that can be accessed over HTTP, where requests are sent and returned using a file format like JSON or XML.

Regardless of the particular form of the API, the most important rule you should start from when designing an API is to hide all implementation details. An API should present an abstract interface to a given a problem (in fact some people prefer to define API as Abstract Programming Interface), and as such you should be thinking about how to provide a generic solution that’s unclouded by the specifics of any particular implementation. If you keep this principle of information hiding in mind, then many good things will flow from it.

For example, your interface will be less likely to have to change over time because you’ve found a logical description of your problem area. Also, by hiding the details of your specific implementation, you are free to change that implementation or make optimizations later without affecting your users. After all, one of the most difficult aspects of maintaining a good API is managing change over time and striving to maintain backward compatibility.

In the remainder of this article, I present aspects of several different programming languages that can help you to keep implementation details out of your APIs.

C++ and the Pimpl Idiom

C++ provides access control keywords of public, private, and protected that let you logically hide implementation details. However, any private members are still physically located in your public header files. This can expose implementation headers that add extra dependencies and increase build times. It also increases the temptation for programmers to expose a private method that they see in the header by simply making it public, without giving due consideration to the information hiding and logical design implications.

The pimpl idiom (pointer to implementation) provides a great solution to this situation by using an opaque pointer to a class that’s defined in your .cpp file. This is also referred to as a d-pointer in some libraries, such as Qt and KDE.

.h file
.cpp file

// public class
class AudioPlayer
{
public:
AudioPlayer();
~AudioPlayer();

bool Play(const std::string &uri);
bool IsPlaying() const;

private:
// Make noncopyable because of pointer
AudioPlayer(const AudioPlayer &);
const AudioPlayer &operator =(const AudioPlayer &);

// Opaque pointer to implementation
class Impl;
Impl *mImpl;
};
// implementation class
class AudioPlayer::Impl
{
public:
bool PlayLocal();
bool PlayHttpStream();

std::string mUrl;
bool mIsPlaying;
};

AudioPlayer::AudioPlayer() :
mImpl(new Impl)
{
}

AudioPlayer::~AudioPlayer()
{
delete mImpl;
}

The Pimpl Idiom is described in greater detail in Chapter 3 of my book, API Design for C++. Here’s a sample of that chapter so you can read more about this useful technique:

Download (PDF, 1.68MB)

Like what you’ve read so far? You can purchase your very own copy of Martin’s book, API Design for C++ at a 40% discount. Just enter discount code “CBA123” at checkout!

Objective-C and Class Extensions

Objective-C offers similar access control mechanisms via @public, @private, and @protected. These come with the same issue of having to define all of these in your public headers. However, you can use the concept of class extensions (also known as anonymous categories) to hide your implementation details within your .m files.

.h file
.m file
// public class
@interface AudioPlayer
{
}

- (bool) play: (NSString *) uri;
- (bool) isPlaying;

@end
// class extension
@interface AudioPlayer ()
{
    NSString *mUri;
    bool mIsPlaying;
}

- (bool) playLocal: (NSString *) uri;
- (bool) playHttpStream: (NSString *) uri;

@end

// implementation section
@implementation AudioPlayer

...

@end

 

Python and Private Symbol Names

As a final example, let’s consider a modern scripting language. Python has no true notion of private members: everything is effectively public. This is a cultural difference between Python and languages like C++ or Java. However, Python’s PEP8 style guide defines the convention that any symbol prefixed with a double underscore should be considered private, e.g., __play_local(). Python helps enforce this convention by mangling these symbol names, e.g., a function __func inside of a class MyClass must be referred to as _MyClass__func externally.  Other developers can still access the symbol if they use the mangled name, but you should still use this convention to signal to the users of your API which parts are public and which are implementation details.

class AudioPlayer(object):
    def __init__(self):
        self.__uri = ""
        self.__is_playing = False

    def __play_local(self, uri):
        ...

    def __play_http_stream(self, uri):
        ...

    def play(self, uri):
        ...

    def is_playing(self):
        ...

About Martin Reddy

Martin ReddyMartin Reddy (twitter: @Martin_Reddy) is co-founder and CTO at ToyTalk, Inc. where he works on building conversation-driven entertainment for families. He holds a Ph.D. in Computer Science, has published over 40 peer-reviewed articles, and authored two books, including API Design for C++.

Martin spent 5 years in the Artificial Intelligence Center at SRI International and then 6 years at Pixar where he led the development of the studio’s internal filmmaking software for films such as Finding Nemo, The Incredibles, Cars, Ratatouille, and WALL-E.

Connect with us on social media and stay up to date on new articles

Computer Science

Computing functionality is ubiquitous. Today this logic is built into almost any machine you can think of, from home electronics and appliances to motor vehicles, and it governs the infrastructures we depend on daily — telecommunication, public utilities, transportation. Maintaining it all and driving it forward are professionals and researchers in computer science, across disciplines including:

  • Computer Architecture and Computer Organization and Design
  • Data Management, Big Data, Data Warehousing, Data Mining, and Business Intelligence (BI)
  • Human Computer Interaction (HCI), User Experience (UX), User Interface (UI), Interaction Design and Usability
  • Artificial intelligence (AI)
Morgan Kaufmann companion resources can be found here You can also access companion materials and instructor’s resources for all our new books on the Elsevier Store. Search by author, title or ISBN, then look for the “Resources” tab on any book page. Looking for companion materials or instructor’s resources for these titles? Connect below:

Social Media Auto Publish Powered By : XYZScripts.com