00:00:09.280
All right, so I'm here to talk to you today about API design. So, why am I here to talk about API design? This is an easy question, so I'm going to throw some softballs at you here. How many of you write software for a living? Okay, I'm hoping quite a few of you. Great! And how many of you design APIs for a living? Okay, see? All of your hands should be going up right now! If you write software, you design APIs for a living; you just may not know it yet. That's one of the reasons why I think it's important to talk about it, and it's actually not discussed very often.
00:00:19.480
I don't know; I mean, it may be discussed, but there's very little written about good API design. I suppose we're supposed to just know good API design after we've been developers for a long time, but I think we can do better than that. So my talk today is to get us not only thinking about API design but hopefully to actually inspire some of you to start writing about it and delve a little deeper into it.
00:00:46.879
As software developers, APIs are your product, both internally and externally. For example, anyone who's developing web apps these days probably either already has an external-facing API or will eventually build one. But there are also internal APIs within your applications where different components communicate with each other, or even where classes interact. So there are APIs all over the place, and those are ultimately the products you're developing as you write software.
00:01:10.840
Another reason why it’s important to talk about APIs is because they outlive implementations. Anyone who's used a library that has evolved over time has noticed that while the API is often improved, the implementation behind it can change constantly. Getting the APIs right is a crucial part of making a library really useful; thus, discussing API design is important.
00:01:39.600
Good API design can lead to many other things, like influencing client-level implementation. So, that's another reason it’s important to have this conversation. Now, here are a few principles—some things that come from what's already been written about API design. I'll touch on some presentations and papers that address it. There's really not a lot, but I will share what I can.
00:02:03.840
The first principle is that any API should be easy to learn. An API should be designed around the principle of least astonishment. When you think something should work a certain way, and it does, you feel a sense of satisfaction. The principle of least astonishment is very important in API design. Additionally, what makes something easy to learn often has to do with naming conventions. It's essential to think about naming in the context of your audience—who is going to use and talk about the API.
00:02:29.800
Another principle that contributes to good API design is that it should produce readable code. From a client usage perspective, if you have a class that is communicating with another class within your application and they have a well-designed API, then the client code is going to be straightforward to understand and probably not too difficult to write. I’m not saying it will write itself, but it might get pretty close.
00:02:56.560
Good APIs are also extensible; they should grow with changing requirements. Additionally, they should be designed with future growth in mind. APIs will live a long time; they won’t be something you can just change a couple of weeks after releasing them, as this would make it impossible for anyone to write client code. Therefore, it's vital to design APIs with the potential for growth in mind.
00:03:12.720
Moreover, APIs should be easily splittable into smaller APIs when needed. As APIs grow, they become more complex; this is just a fact of software development. Thus, the better the API design, the easier it will be to take one API and break it into multiple APIs. This could involve breaking it into two or three distinct components as ideas evolve and start to amalgamate into something too complicated.
00:03:58.560
Another vital aspect of good API design is to minimize the risks of misuse. A well-designed API should make it hard to write bad code. This principle ties back into the concept of writing good code. You shouldn't be able to abuse a well-designed API; instead, it should facilitate the writing of correct code. This means that your client code shouldn’t be complex.
00:04:23.000
Good API design avoids depending on side effects and order of execution. For instance, a poor API design might rely on the order of some states you've set up in advance. If that order changes, the API's behavior will change as well, making it a bad design. A well-designed API minimizes side effects and doesn't depend heavily on aspects like order of execution.
00:04:51.839
The final principle from this initial set is that an API should be sufficiently powerful while being as small as possible. This principle suggests that APIs should implement only the necessary functionality required to complete the job without excessive features. You shouldn't add functionalities just because you might need them in the future or because it seems like a fun challenge; adding to an API is much easier than removing functionality later since the latter could break existing dependencies.
00:05:26.560
Now, those are the fundamental principles I want to share—principles inspired by works like those of Joshua Bloch, who discussed good API design, and numerous papers addressing this topic. I'd like to distill these principles into a more memorable set, so I’m going to categorize them under the letter 'C.' The first principle is consistency in APIs. Good APIs should remain consistent with existing APIs. If you follow a particular style for writing your methods or structuring your APIs, related APIs should ideally follow suit to prevent confusion when different APIs behave inconsistently.
00:06:01.520
In addition to consistency, another critical aspect is clarity. Your code and method signatures should provide clear indications of their purpose. This means you want to avoid sending mixed signals that could confuse users. Convenience is another principle; your API should allow users to write code more easily than having to implement everything themselves. The result should be a user-friendly experience that emphasizes usability. Simplifying the user experience leads to better integration of your libraries.
00:07:10.240
Next is conciseness; it’s important for APIs to be brief while still being comprehensive enough to meet user needs. Finally, completeness ensures that the API does what is necessary without introducing superfluous elements.
00:07:40.720
Those are the five 'C's: be consistent, be clear, be convenient, be concise, and be complete. Now, let’s look at some specific examples, specifically in Ruby, which I know is surprising. I'll be using the standard library net/http, which many in the Ruby community often criticize for its design flaws.
00:08:15.360
As I go through this example, I want you to consider the five 'C's: is this library consistent, clear, convenient, concise, and complete? Let's examine several method calls and their behaviors. You’ll notice how the methods can seem confusing, especially when comparing one method over another.
00:08:49.920
For instance, we have multiple variations of the 'get' method that differ only slightly in their parameters, yet it remains unclear how these methods should ideally be used. The signature of these methods often lacks clarity, eliciting questions about what port is being used and how to define options. The library design complicates what could otherwise be straightforward requests.
00:09:40.480
Here's another example of questionable design in the library. Take a look at one particular 'get' method that has three arguments where two are optional. However, it's unclear what these optional parameters should be. The headers are labeled 'init_header' rather than simply 'headers,' which generates confusion. The documentation indicates that the second argument is obsolete, yet it still functions. This leads to ambiguity in how to use the method correctly.
00:10:25.760
The documentation also states that if this method is called with a block, it will yield each fragment of the response body in turn as a string as it is read from the socket, but leaves much to be deciphered about the structure of the response. Moreover, the documentation indicates a significant divergence in behavior depending on the version of the protocol being used, which only adds to the confusion surrounding its usage.
00:11:15.280
As we continue observing the structure of 'get' methods, we can identify many programming smells, such as inconsistencies in expectations from the user and unnecessary complexity. Furthermore, side effects become apparent in certain methods, which must separate concerns more effectively to avoid overwhelming the user with nuances.
00:11:48.400
While this library has managed to exist for some time, admittedly getting the job done, the convoluted design leads to excessive complexity. In comparison, let’s look at some examples of libraries that have better design principles and adhere to the five 'C's. One such example is Typhus, an HTTP library that permits a clean and straightforward construction of requests.
00:12:32.320
Typhus effectively manages parallel requests, requiring clear operations. The API allows straightforward responses from its requests. Additionally, another library worth mentioning is Faraday, which adopts a different yet intuitive approach to conducting HTTP operations, simplifying method calling and embracing clarity in its design.
00:13:32.360
Faraday reduces complication by letting users create a class-level GET method that encapsulates all necessary details, making the API design more user-friendly. Both Typhus and Faraday illustrate the value of easy-to-understand APIs that deliver comprehensive and effective functionality. They demonstrate consistency, clarity, convenience, conciseness, and completeness, thereby providing good examples to aspire to.
00:14:12.600
Turning to more design principles, let’s consider some techniques for developing better APIs. One essential step is to consult with those who will use your API. Understand their needs, and become the client yourself during the design process. This client-first perspective should guide the API design with user interactions driving the final implementation.
00:15:02.679
To ensure your API meets requirements, write sample client code and run through it against your API regularly to identify any issues. The key is to tease out anything that doesn’t fit well from a client perspective and maintain clarity in design as it relates to user experience, even when contemplating implementation details.
00:15:46.480
Make sure to define your APIs with a suitable level of jargon, using specific terms only if your audience is familiar with them. Additionally, choose sensible defaults and ensure to document those conventions. In doing so, balance clarity for novice users against the needs of more experienced users who may expect deeper functionality.
00:16:28.000
Remember that the principles outlined earlier—being consistent, clear, convenient, concise, and complete—should act as foundational guidelines while your API evolves. Leveraging existing patterns to implement an API can often lead to success, making integration smoother and less cumbersome.
00:17:09.480
As I wrap up my talk, I invite software developers everywhere to recognize the inherent API design responsibilities we all share. Designing APIs with purpose and intent is crucial; simply going through the motions isn’t sufficient. I encourage you all to reflect on good examples of APIs around you and continue learning from best practices in API design.
00:17:51.920
When examining your own APIs, consider how you might refactor them for improvement, keeping potential challenges for existing users in mind. Good API design allows for agility and adaptability, and refining that design should be an ongoing process. Insisting on a user-centered design approach while avoiding unnecessary complexity is vital in crafting APIs.
00:18:33.320
Lastly, I want to express gratitude to everyone for attending my talk. The slides I used for this presentation borrowed from various resources, and I have chocolate to share with all of you, which will be available at the front of the stage! Feel free to grab some!
00:19:15.280
With that, I would like to open the floor for questions. If you have any questions, please feel free to ask. My aim is to provide clarity on API design and any challenges you may face throughout implementation.
00:19:40.560
Okay, so the consensus around API design and implementation is significant. One of the important aspects is understanding that all code essentially functions as its own set of APIs. If you're writing methods in a class, those public methods are part of an API. However, private methods serve more as implementations that internally drive the behaviors of your reactions.
00:20:19.200
The question arises often regarding standard libraries; while they provide a foundation, I believe in keeping them lightweight and avoiding unnecessary bulk. My stance is that a smaller set of well-designed libraries is superior to an expansive collection with excessive incongruities.
00:20:50.480
Regarding API versioning, it's a nuanced topic that deserves thorough attention. Others might adopt semantic versioning and facilitate adjustments for API designs over time without harming the user experience. Some might argue in favor of maintaining flexibility for users while ensuring any transformative changes continue to push the API forward.
00:21:35.120
Every API should reflect intended use in ways that allow for progressive enhancements. Users should never feel locked into a particular version, and the best APIs empower their users to evolve alongside them without encountering undue friction.
00:22:05.440
When we talk about Service Provider Interfaces (SPIs), we’re referring to the foundational designs that allow for connections to multiple underlying services while also maintaining a public-facing API. This encapsulated design allows for flexibility while keeping user interactions seamless, which is essential for overall good API design.
00:22:39.440
Are there any final thoughts or questions? I want to ensure everyone feels equipped to engage with API design topics and tackle any obstacles to achieving good practice. If not, I appreciate your participation, and remind you again, feel free to enjoy the chocolates I brought!
00:23:16.640
Thank you! Please enjoy the conference and engage in meaningful dialogues about enhancing our experiences with software development and API design.