Software Engineering for Self-Directed Learners »

Implementation → Reuse →

APIs

What

Can explain APIs

An Application Programming Interface (API) specifies the interface through which other programs can interact with a software component. It is a contract between the component and its clients.

A class has an API (e.g., API of the Java String class, API of the Python str class) which is a collection of public methods that you can invoke to make use of the class.

The GitHub API is a collection of web request formats that the GitHub server accepts and their corresponding responses. You can write a program that interacts with GitHub through that API.

When developing large systems, if you define the API of each component early, the development team can develop the components in parallel because the future behavior of the other components are now more predictable.

Exercises



Designing APIs

Can design reasonable quality APIs

An API should be well-designed (i.e. should cater for the needs of its users) and well-documented.

When you write software consisting of multiple components, you need to define the API of each component.

One approach is to let the API emerge and evolve over time as you write code.

Another approach is to define the API up-front. Doing so allows us to develop the components in parallel.

You can use UML sequence diagrams to analyze the required interactions between components in order to discover the required API. Given below is an example.

Example:

As you analyze the interactions between components using sequence diagrams, you discover the API of those components. For example, the diagram above tells us that the MSLogic component API should have the methods:

  • new()
  • getWidth:int
  • getHeight():int
  • getRemainingMineCount():int

More details can be included to increase the precision of the method definitions before coding. Such precision is important to avoid misunderstandings between the developer of the class and developers of other classes that interact with the class.

  • Operation: newGame(): void
  • Description: Generates a new WxH minefield with M mines. Any existing minefield will be overwritten.
  • Preconditions: None
  • Postconditions: A new minefield is created. Game state is READY.

Preconditions are the conditions that must be true before calling this operation. Postconditions describe the system after the operation is complete. Note that postconditions do not say what happens during the operation. Here is another example:

  • Operation: clearCellAt(int x, int y): void
  • Description: Records the cell at x, y as cleared.
  • Parameters: x, y coordinates of the cell
  • Preconditions: game state is READY or IN_PLAY. x and y are in 0..(H-1) and 0..(W-1), respectively.
  • Postconditions: Cell at x, y changes state to ZERO, ONE, TWO, THREE, …, EIGHT, or INCORRECTLY_CLEARED. Game state changes to IN_PLAY, WON or LOST as appropriate.