Using Documentation-Driven Design to Guide API Decisions

A woman working on a computer
Image of a person writing and working on a computer by Danai via Adobe

As software design evolves, so do the thought processes behind the design decisions we make as engineers. Some of these development practices are widely known and talked about, such as Test-Driven Design, where changes to code are made in programmatic tests before they’re implemented in actual business logic.

These design practices are helpful for our future selves and for our teammates, because they help us keep our code well-maintained and easily extendable. How do these practices help external audiences, or audiences that aren’t as technical, understand our code? When designing a new API or making impactful changes to an existing API, a Documentation-Driven Design approach can be helpful in guiding the design decisions you make, too.

open books showing text
Image by Patrick Tomaso via Unsplash

What is Documentation-Driven Design?

Documentation-Driven Design (DDD) is the practice of writing your technical documentation first, and then using those docs to steer your eventual code implementation.

All developers want to work with simple APIs. But when the source material that’s driving API design is not simple, we want an API that makes a dense subject easier to understand. This is where DDD is especially helpful because it forces you to think about how an outsider understands and uses your work. Because the crux of DDD is based on thinking through your code as an outsider, it’s also important to know your audience when writing your docs.

For many of us at PayPal, our main audience are developers working for merchants to implement ecommerce websites, reconcile money disbursements, and manage customer transactions. When we take a DDD approach to our work, we write guides for an audience that reads our Developer Docs website. This means we write for developers of all levels, working in many languages.

person holding a debit or credit card while working on a computer.
Image by rupixen.com via Unsplash

Example of Documentation-Driven Design

Let’s assume we have an API that takes credit card information and securely stores it so merchants can safely keep customers on file (like, say, a Vault 😊). There are several types of cards that can be stored — Visa, Amex, prepaid/gift cards, HSA/FSA cards — and they all may have different rules around when and how they are stored. Let’s use DDD to draft a simple example of how a user might create a card with our API.

This example will be pseudo-coded, but the final draft should be syntactically and functionally correct for the programming language it uses.

card({
Card-number: “411111111111111”,
Expiration: “122023”
}).then(response) => (
// do something with the response
).catch => (
error.message
)

On first read, this seems straightforward, and a developer can move on to implementing this in their API. But let’s take a deeper look at our code and think through this from the perspective of someone who is not familiar with the subject. When reading pseudo-code with that lens, the following questions come to mind:

  • Does the name of the function card make sense? Would it be easier to understand if this function was renamed to createCard? Some languages follow different naming conventions, depending on the language a developer would be working in, this name might need updating.
  • expirationseems fairly generalized, too. Is this info expected in a specific format? Will this field expect both expiration month and expiration year? Should they be separate fields? Would people based in different countries expect to use this in a different format?
  • There is a lot of regulation around handling sensitive data like a card’s primary account number (PAN). Does this implementation assume the developer using this API knows those requirements?

Now we have questions that require deeper thought and more careful implementation. Let’s take this feedback and update our docs accordingly:

createCard({
tokenizedCardNumber: “token”,
expirationMonth: “MM”,
expirationYear: “YYYY”,
}).then(card) => (
// charge card
).catch(error) => (
error.message
)

We’ve clarified our API by splitting expiration into two different fields: expirationMonth and expirationYear. We’ve also changed our API to indicate that we expect to receive a string that is a tokenization of the card’s PAN, instead of the PAN itself, which is a more secure way for folks to use our API. But how does a user get a tokenized string? Looks like we should create a way for users to tokenize card data, too:

tokenize(response, error).then => (
createCard({
tokenizedCardNumber: “response.token”,
expirationMonth: “MM”,
expirationYear: “YYYY”,
}).then(response).then => (
// send the response to server
).catch(error) => (
error.message
)
A person wearing headphones writing code
Image by Nubelson Fernandes via Unsplash

Conclusion

DDD creates an opportunity to look at your code from a different lens, which helps you write code with greater clarity and empathy. With the above example, we walked through some ways that DDD can drive your API design, as well. I hope this brief walkthrough helps you in your doc-driven ventures!

The PayPal Technology Blog

Recommended from Medium

Webify PDF Files in AEM using Adobe Cloud APIs

The Road to Graphql

Making a DotA2 Bot Using ML

Building a Successful Modern Data Analytics Platform in the Cloud

The three layers of a modern data analytics platform

Hello Quarkus: Supersonic Subatomic Java

Development of a New Language for Information Architecture

How agile paradigm differs from traditional project style software development?

Combining strict order with massive parallelism using Kafka

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Holly Stotelmyer

Holly Stotelmyer

Software Engineer @PayPal, podcaster, dovahkiin. https://hollabaq86.github.io/

More from Medium

Credit-Based Pricing vs. Fixed Pricing for Mobile CI/CD Platforms (Appcircle, Bitrise, Codemagic)

PaaS vs FaaS

PandaDoc API Enhancements

MVP Vs Microservices