Happy with incomplete understanding of API provided your app seems to work?
Or do you feel you must understand everything completely to have reasonable confidence in the correctness of your code?
4 comments
If you're using an API all the time, it's easy to justify investing the time in understanding it to the next level.
API defines an abstraction - I assume you're askng about understanding that abstraction completely, not the specifics of how it is implemented. An abstraction can include changes of (abstract) state, and it can include performance characteristics/gotchas (as in Joel's "Leaky Abstractions").
An API can be designed for learning, by forming a series of nested abstractions, such that you can completely understand each well-defined subset independent of understanding all the other subsets. Perhaps an example is a String object in Java or Python. Understanding creation and assignment is a completely self-contained subset of its functionality, without using any of its methods (as such). A deeper level of understanding includes performance characteristics.
To answer the question: I feel I must understand the subset of the abstraction that I am using, in order be confident in the correctness of my code.
But many APIs are not designed this way. Designing APIs for usability is hard, and most programmers prioritize features, performance and internal elegance over it. I suffered to write this. Now it's your turn.
And, worse, the implementations of many APIs have bugs (well, all of them do). It's just that more users find more bugs, so more popular libraries usually have fewer bugs (in their mature parts).
I find a constant pressure between writing the best possible code - and getting things done (one advantage of getting something done is it puts you at a vantage point where you can see more - and becoming part of the process of understanding).
API defines an abstraction - I assume you're askng about understanding that abstraction completely, not the specifics of how it is implemented. An abstraction can include changes of (abstract) state, and it can include performance characteristics/gotchas (as in Joel's "Leaky Abstractions").
An API can be designed for learning, by forming a series of nested abstractions, such that you can completely understand each well-defined subset independent of understanding all the other subsets. Perhaps an example is a String object in Java or Python. Understanding creation and assignment is a completely self-contained subset of its functionality, without using any of its methods (as such). A deeper level of understanding includes performance characteristics.
To answer the question: I feel I must understand the subset of the abstraction that I am using, in order be confident in the correctness of my code.
But many APIs are not designed this way. Designing APIs for usability is hard, and most programmers prioritize features, performance and internal elegance over it. I suffered to write this. Now it's your turn.
And, worse, the implementations of many APIs have bugs (well, all of them do). It's just that more users find more bugs, so more popular libraries usually have fewer bugs (in their mature parts).
I find a constant pressure between writing the best possible code - and getting things done (one advantage of getting something done is it puts you at a vantage point where you can see more - and becoming part of the process of understanding).
The title is a bit confusing... perhaps it should read:
"Are you happy with incomplete understanding of API, provided that your app seems to work?"
For me, the answer is "not always". When the topic is security or performance, I definitely prefer to have as much knowledge of the API as possible.
I remember reading an interesting article about Java's File and how the internal implementation used null terminated strings (which ultimately meant that you could bypass a string-based check (such as 'filename.endsWith(".jpg")' and have the subsequent new File(filename) call open a different file than you'd expect.
On a different story, I was able to speed-up a web-app speed significantly because I knew (from reading the js library's source code) that the DOM querying functions we were using so extensively were very inefficient.
With those anedoctes out of the way, I'll say that knowing how every single function in every single API ticks is probably overkill. I usually only dig deeper when
a) I have to because something needs to be fixed b) It's a very specific area of expertise that happens to interest me
For me, the answer is "not always". When the topic is security or performance, I definitely prefer to have as much knowledge of the API as possible.
I remember reading an interesting article about Java's File and how the internal implementation used null terminated strings (which ultimately meant that you could bypass a string-based check (such as 'filename.endsWith(".jpg")' and have the subsequent new File(filename) call open a different file than you'd expect.
On a different story, I was able to speed-up a web-app speed significantly because I knew (from reading the js library's source code) that the DOM querying functions we were using so extensively were very inefficient.
With those anedoctes out of the way, I'll say that knowing how every single function in every single API ticks is probably overkill. I usually only dig deeper when
a) I have to because something needs to be fixed b) It's a very specific area of expertise that happens to interest me
There is really no reason that I can see to try and figure out why API methods do what they do. You send it something, it sends what you want back. That's basically the nature of object oriented programming, and why it's so popular. You don't need to know the workings of an internal combustion engine to drive a car, and you don't need or want to know what your API is doing behind the scenes in my humble opinion.
I think the obvious reason is that understanding why the API works as it does allows you to understand more about what your program is doing, and thus lets you write better software. For example, you can just think of malloc() as a magical "give me a block of memory!" API, which is perfectly sufficient for a novice who wants to write working programs. Alternatively, you can understand some (not all!) of the details behind virtual memory and how a typical heap allocator works. In the long run, that helps you write better software (e.g. by gaining an intuition for the relative costs of manual memory management, or debugging heap corruption).
So I think it's part of the difference between being a journeyman and an expert. That said, not all APIs are worth understanding, and you don't need to go into exhaustive detail with everything; it's a question of deciding what's worth learning in the long-run.
So I think it's part of the difference between being a journeyman and an expert. That said, not all APIs are worth understanding, and you don't need to go into exhaustive detail with everything; it's a question of deciding what's worth learning in the long-run.
With frameworks, there's a design that it imposes on your application. Are you generally happy with an incomplete understanding of this design provided that your app seems to work?
what more can you ask for? regardless of whether you know how the system works, the nature of an API will impose certain things that you have to design with or around.
I must understand everything thoroughly before I use that API in an "application". In the meanwhile, I try to make as many little sample toy apps as possible. Having said that, learning a new API is made easy if you understand its application doman; see one 2D bitmap graphics API and you have seen them all, for example.