Have You Ever Wondered
From APIDesign
Many people want to know, before they start to read a book, whether it can help them solve some problems they have faced. That is very likely reason why many books start with have you ever wondered sections. Practical API Design book does not contain such section itself, however that in no way means that it is not helping to solve problems! You can bet that there is a lot of useful advices! Practical API Design is a lab journal describing adventures of NetBeans project and as such, it is almost completely stuffed with problem solutions. Here is short online version of have you ever wondered to demonstrate that.
Part I - Philosophy
Have you read many books about design? Have you read some? Do you think you know everything about proper design? Are you asking, "why bother with yet another design book"? The prologue shows you that you should care. Most design books are written for "in-house" development, however, with the rise of code reuse caused mostly by a proliferation of various open source libraries and frameworks, we are entering a world of distributed development. The new coding life style needs a slightly different designing approach. After reading prologue, you'll find out that you need TheAPIBook if you want to code software for the 21st century.
Have you ever considered yourself an artist when coding? Do you think programming is a kind of art? Have you noticed the difference in developing software systems today and twenty years ago? Do you know why people consider ugly solutions wrong? If you've ever asked questions like this, the chapter 1 gives you answers that I found after many years of oscillating between feeling like an artist and behaving as an engineer. Did you ever hopelessly search for new programmers? We do it all the time and it looks like we are constantly running out of good ones. But how good does a programmer have to be to produce good software? Maybe it is enough if one can code HTML.
Maybe you are asking yourself: "Why should I slow myself down by creating an API? Is not that more work?". In the second chapter of TheAPIBook I describe that, overall, it is not more work. Moreover I also reveal that even if you try, you cannot live without APIs. APIs are everywhere, even in in-house systems. In the world of DistributedDevelopment they become inevitable.
Have you ever searched for the root reason of why you like some APIs more than others? Are those APIs that you liked the most also those most easily usable? I was thinking about this a lot. First of all I broaden the meaning of the term API and let chapter 3 define what it means an API, explain why and enumerate various APITypes. Then I also took look at the basic objective criteria to ensure an API's quality is really good.
Are you afraid of upgrading your favorite application to a newer version? I am. Every time I need to upgrade X Window server, I am stressed and ready for problems that almost always appear. Are you asking how this relates to API Design? Easily, the building blocks of our systems which provide some functionality via their APIs (like the X Window server), are expected to evolve compatibly. It is not hard to produce a new version of a framework or library, it is hard to release a new version that remains compatible. This is quite a big difference from in-house software system development and chapter 4 discusses its implications and the actions we need to take to resolve them.
Part II - Practice
Do you want to know some simple trick that will help you design better APIs? The chapter 5 gives you one. It is very elementary, but very powerful. It also shows that the object oriented languages of today are not really optimized for API development and that there are many gotchas one needs to be aware of.
Have you ever participated in a flamewar between people who believe API should be full of interfaces and those who believe it is better to use classes? Was the dispute resolved somehow or people just kept their original views? Yes, I've participated in such discussions few times and yes, they never lead to any conclusions. However then I've managed to look at the old code against interfaces advice in a new light and things started to make sense. Since then I have eliminated flamewars of this kind almost completely. Probably because the revelation is not only surprising, but also backed by rational reasoning. You can find this all in the chapter 6.
OK, so you want to prevent object-oriented spaghetti mess by splitting our systems into into independent modular pieces, however I wonder how to glue them together? Are there some good practices for doing so? Yes, there are and the Chapter 7 gives some. For example to glue pieces together you need some injection to configure all individual components to work together. The Chapter 7 builds the understanding for this by starting with the most straightforward and hand-coded solutions and then enhances them to cover injection as provided by Spring Framework as well as latest releases of JDK.
Have you ever subclassed some API class and started to ask yourself: "Shall I override its particular method or just call it?" Or: "Is this method public because external users shall call it or am I supposed to override it?". Chapter 8 brings you answer to such common worries. It analyses the differences between evolution of APIs targeted to different clients, analyses what kind of messages various Java access modifiers carry and gives a recipe to convert a class full of methods with unclear multiple meanings into an API that carries just one, clear message for every developer using it.
Why did people prefer Spring over EJB 2.x? Is this just a problem of these particular technologies or is there a stronger reason beneath it applicable to any API? In Chapter 9 I'll discuss one, in my opinion very important difference that is getting more and more important in the last few years. Spring has been designed with testability in mind and as such it attracted all those developers who subscribed to agile development. I'll present this as almost necessary feature of every new API and outline a way to make productivity higher while making testability simple.
Did you ever write an application against one version of Java just to find out that it does not work with newer version? I guess everyone faced that situation, however did you ever faced that with your library? Did you change nothing in your library, yet your customers complain that their code using your library classes does not run or even compile with newer version of Java? I guess some of us have been in such situation. This is an inevitable impact caused not only by Java but by cooperating with any APIs created by others. Chapter 10 analyses why we have problems when working with foreign APIs and suggest strategies to deal with such situations.
Have you ever tried to find the border line between the API and its implementation? Is javadoc API? I guess, so. Do names of public classes and methods belong into the API? Are the checks for incorrect parameter types throwing IllegalArgumentException part of API? Are NullPointerExceptions thrown from inside of the API method bodies part of API? And what about the order of callbacks to client code, order of event delivery, identity of threads the callbacks happen in? Is speed of method execution or the amount of allocated memory important for API users? I guess it may be, at least in the real-time world. But then: Where is the border between API and its implementation!? The chapter 11 shows why the APIs do not end at method and class signatures. It explains why these runtime APIs are important and what needs to be done to evolve them in the right way - evolve them compatibly. The chapter 11 does not reveal the holy grail, but it presents a technique proven to work, capable to ensure runtime backward compatibility.
You have just scared us with runtime implications of APIs, is there a way to minimize their impact? Is there a way to prevent race conditions, deadlocks, etc.? Yes, as far as I know there are two ways. Either prevent shared access to data, objects, structures, resources or allow it. The chapter 12 explains how to do that with a little help of Declarative Programming. Declarative Programming!? Is there something like that? Well, that is indeed good question, which the chapter 12 analyses as well and it even suggest some good forms to use for this style of APIs.
Part III - Process
I've just finished reading the theoretical and practical parts of your book, are you telling me that I have to apply all your advices to be successful? No, not at all. One of the the worst things to do is to follow advice completely, to the extreme. The chapter 13 builds on the Considered harmful phrase and expands its meaning into the world of API Design.
Are you asking now why some API design advices feel so unnatural? Why they are so different compared to the best practices that we learned while working on our small projects or on in-house projects of any size? The reason is that even a small shift in the initial conditions may result in completely opposite advice which may seem paradoxical. However that does not mean such advice is not useful and the chapter 14 describes some of them and explains why adhering to them may be beneficial for any software project.
Have you ever been afraid of releasing your API because you knew the implementation behind it is not good enough? Have you been afraid of the API's future? Of numerous bugs, each creating another incompatibility? Chapter 15 explains that you do not have to! If you design your API to be ready for evolution, you can resuscitate even bad design of your broken libraries without doing incompatible changes. All that is needed is to learn the right way to provide alternative behaviour and also how to allow coexistence of similar APIs.
There is a common wisdom among programmers saying that design cannot be done by committee. However how can we design bigger and bigger systems without designing in teams? Does not that hurt consistency? Yes, partially. Most people seem to be able to keep design consistency when they work alone, however software projects of today and of the future are designed by teams. Keeping consistency in such environment is much harder, but it is possible. Chapter 16 describes what aspects need to be verified and checked, and introduces the APIReview process which is capable of doing so.
After getting so far in the book you may ask: "OK, you told us how to write the APIs properly, but how am I supposed to transfer this knowledge to my peers?" The chapter 17 is here to teach you how to learn API Design by playing games. It is simple, entertaining and it really demonstrates the basic principles of backward compatibility and various types of API. Every time I participate in such API Fest I enjoy it very much.
Do you wonder whether knowledge of proper design patterns makes you good API designer? Yes and no. Of course knowing regular design patterns simplifies communication, understanding, etc. However there are hidden catches. Not every design pattern belongs among APIDesignPatterns - it may not be ready for evolution. For example the well known Visitor pattern is really not evolvable easily as analysed by Chapter 18.
Is it not true, that by keeping compatibility we grow the number of APIs we have to maintain? For how long can this be sustained? Will not we all spend our lives maintaining old APIs instead of developing new functionality? Not necessarily. If you know how to use end of life procedures as described in Chapter 19, you can send your old APIs to black hole smoothly while keeping backward compatibility.
Do we need some changes to our programming languages, tools to build APIs more easily? Some changes would be nice, however they are not necessary. It is possible to write good APIs in C, in Java even now. It is just not very clueless right now. One needs to think about the evolution issues related to API too much. As the Epilogue suggests, it would be really much simpler for all of us, if our systems were designed with evolution in mind. I hope this book will provoke discussion of how to do it.