The Golden Rule of API Design

From WikiContent

(Difference between revisions)
Jump to: navigation, search
Current revision (21:46, 6 July 2009) (edit) (undo)
 
(4 intermediate revisions not shown.)
Line 1: Line 1:
-
API design is tough, particularly in the large. If you are designing an API which is going to have hundreds or thousands of users, you have to think about how you might change it in the future and whether your changes might break client code.
+
API design is tough, particularly in the large. If you are designing an API that is going to have hundreds or thousands of users, you have to think about how you might change it in the future and whether your changes might break client code. Beyond that, you have to think about how users of your API affect you. If one of your API classes uses one of its own methods internally, you have to remember that a user could subclass your class and override it, and that could be disastrous. You wouldn't be able to change that method because some of your users have given it a different meaning. Your future internal implementation choices are at the mercy of your users.
-
You aren't going to be able to freely refactor your API over time, so there are some decisions that you have to get right in the beginning, because right or wrong you are going to have to live with their consequences for a long while. Above all, you have to protect your API. If one of your API classes uses one of its own methods internally, you have to remember that a user could subclass your class and override it, and that could be disastrous. You wouldn't be able to change that method because some of your users have given it a different meaning. Your future internal implementation choices are at the mercy of your users.
+
API developers solve this problem in various ways, but the easiest way is to lock down the API. If you are working in Java you might be tempted to make most of your classes and methods <code>final</code>. In C#, you might make your classes and methods <code>sealed</code>. Regardless of the language you are using, you might be tempted to present your API through a singleton or use <code>static</code> factory methods so that you can guard it from people who might override behavior and use your code in ways which may constrain your choices later. This all seems reasonable, but is it really?
-
API developers solve this problem in various ways, but the easiest way is to lock down the API. If you are working in Java you might be tempted to make most of your classes and methods final. In C#, you might make your classes and methods sealed. Regardless of the language you are using, you might be tempted to present your API through a singleton or use static factory methods so that you can guard it from people who might override behavior and use your code in ways which may constrain your choices later. This all seems reasonable, but is it really?
+
Over the past decade, we've gradually realized that unit testing is an extremely important part of practice, but that lesson has not completely permeated the industry. The evidence is all around us. Take an arbitrary untested class that uses a third-party API and try to write unit tests for it. Most of the time, you'll run into trouble. You'll find that the code using the API is stuck to it like glue. There's no way to impersonate the API classes so that you can sense your code's interactions with them, or supply return values for testing.
-
Over the past decade, we've gradually realized that unit testing is an extremely important part of practice, but that lesson has not completely permeated the industry. The evidence is all around us. Take an arbitrary class untested class which uses a third-party API and try to write unit tests for it. Most of the time, you'll run into trouble. You'll find that the code using the API is stuck to it like glue. There's no way to impersonate the API classes so that you can sense your code's interactions with them, or supply return values for testing.
+
Over time, this will get better, but only if we start to see testing as a real use case when we design APIs. Unfortunately, it's a little bit more involved than just testing our code. That's where the '''Golden Rule of API Design''' fits in: ''It's not enough to write tests for an API you develop; you have to write unit tests for code that uses your API. When you do, you learn first-hand the hurdles that your users will have to overcome when they try to test their code independently.''
-
Over time, this will get better, but only if we start to see testing as a real use case when we design APIs. Unfortunately, it's a little bit more involved than just testing our code. That's where the '''Golden Rule of API Design''' fits in: ''It's not enough to write tests for an API you develop, you have to write unit tests for code that uses your API. When you do, you learn first-hand the hurdles that your users will have to overcome when they try to test their code independently.''
+
There is no one way to make it easy for developers to test code which uses your API. <code>static</code>, <code>final</code>, and <code>sealed</code> are not inherently bad constructs. They can be useful at times. But it is important to be aware of the testing issue and to do that, you have to experience it yourself. Once you have, you can approach it as you would any other design challenge.
-
There is no one way to make it easy for developers to test code which uses your API. Static, final, and sealed are not inherently bad constructs. They can be useful at times. But it is important to be aware of the testing issue and to do that, you have to experience it yourself. Once you have, you can approach the API user testing challenge as you would any other design issue.
+
By [[Michael Feathers]]
 +
 
 +
This work is licensed under a [http://creativecommons.org/licenses/by/3.0/us/ Creative Commons Attribution 3]
 +
 
 +
 
 +
 
 +
Back to [[97 Things Every Programmer Should Know]] home page

Current revision

API design is tough, particularly in the large. If you are designing an API that is going to have hundreds or thousands of users, you have to think about how you might change it in the future and whether your changes might break client code. Beyond that, you have to think about how users of your API affect you. If one of your API classes uses one of its own methods internally, you have to remember that a user could subclass your class and override it, and that could be disastrous. You wouldn't be able to change that method because some of your users have given it a different meaning. Your future internal implementation choices are at the mercy of your users.

API developers solve this problem in various ways, but the easiest way is to lock down the API. If you are working in Java you might be tempted to make most of your classes and methods final. In C#, you might make your classes and methods sealed. Regardless of the language you are using, you might be tempted to present your API through a singleton or use static factory methods so that you can guard it from people who might override behavior and use your code in ways which may constrain your choices later. This all seems reasonable, but is it really?

Over the past decade, we've gradually realized that unit testing is an extremely important part of practice, but that lesson has not completely permeated the industry. The evidence is all around us. Take an arbitrary untested class that uses a third-party API and try to write unit tests for it. Most of the time, you'll run into trouble. You'll find that the code using the API is stuck to it like glue. There's no way to impersonate the API classes so that you can sense your code's interactions with them, or supply return values for testing.

Over time, this will get better, but only if we start to see testing as a real use case when we design APIs. Unfortunately, it's a little bit more involved than just testing our code. That's where the Golden Rule of API Design fits in: It's not enough to write tests for an API you develop; you have to write unit tests for code that uses your API. When you do, you learn first-hand the hurdles that your users will have to overcome when they try to test their code independently.

There is no one way to make it easy for developers to test code which uses your API. static, final, and sealed are not inherently bad constructs. They can be useful at times. But it is important to be aware of the testing issue and to do that, you have to experience it yourself. Once you have, you can approach it as you would any other design challenge.

By Michael Feathers

This work is licensed under a Creative Commons Attribution 3


Back to 97 Things Every Programmer Should Know home page

Personal tools