What does a module promise its callers?
Try replacing a module whose callers rely on its incidental return order. Start with what the interface says, then trace the decisions it hides and the behaviors people have learned to expect.
Questions in this reading · 13
- Which choices should an API leave out?
- How much can a small interface hide?
- Small objects or small interfaces?
- When does a module boundary freeze a decision?
- When does an implementation detail become a promise?
- When does an implementation detail become a promise?
- Can two versions coexist under the same name?
- Which operations is the caller buying?
- Does a valid signature settle which history to keep?
- Where did the hidden cost go?
- Is starting the old program enough for compatibility?
- Who migrates when a field becomes mandatory?
- How long must “it heats” hold to count as delivery?
Which choices should an API leave out?
Removing an uncertain feature reduces what clients must learn. Separating tangled concerns reduces how many choices they must consider together.
Compare original passages and timestamps · 2
When it doubt, leave it out.start seeing interconnections between things that could be independentHow much can a small interface hide?
A small API reduces the concepts callers must learn. A deep module makes that small surface useful by hiding substantial implementation behind it.
Compare original passages and timestamps · 2
When it doubt, leave it out.very simple interface with a very large amount of functionality underneath itSmall objects or small interfaces?
One talk breaks code into smaller responsibilities. The other limits what callers must learn. Count the decisions exposed to callers as well as the objects inside the implementation.
Compare original passages and timestamps · 2
make smaller thingsWhen it doubt, leave it out.When does a module boundary freeze a decision?
An interface can shelter callers from a changing implementation. Once clients depend on its behavior, changing the interface itself becomes more expensive.
Compare original passages and timestamps · 2
the higher the cost of communication the less iteration will happen therenot be able to take it out once you put it into an API.When does an implementation detail become a promise?
Callers can depend on observable behavior that was never documented. Changing an interpreter or a library then becomes a compatibility decision.
Compare original passages and timestamps · 2
people actually depend in very bizarre ways on some of the internalsanything a user can observe about the implementation of your APIWhen does an implementation detail become a promise?
Interpreter behavior, hash tables and public APIs illustrate how callers come to rely on what they can observe. Observable behavior need not have been formally guaranteed.
Compare original passages and timestamps · 3
people actually depend in very bizarre ways on some of the internalsthey will rely upon
it, given enough users.not be able to take it out once you put it into an API.Can two versions coexist under the same name?
A module name can force a choice between versions. Identifying content by its hash gives each version a separate address.
Compare original passages and timestamps · 2
we would have to make S modules also have a version identifierthen it would be perfectly fine to allow as many different versions of the same library in our code baseWhich operations is the caller buying?
A caller using a square root can leave the improvement of successive guesses inside the procedure. A tree interface promising constant-time parent lookup makes a second commitment. The succinct-structures lecture encodes the tree as bits and relies on rank and select for navigation. Write down separately what the operation returns, how much time it may take, and how much extra index space that time requires. Replacing the representation can preserve one promise while breaking another.
Passages and timestamps · 3
using black-box abstraction to suppress detail.If I have rank and select in constant time, now I can do left child, right child, parent in constant time.all I'm allowed for rank and select is little o of n space.Does a valid signature settle which history to keep?
Send one payment to two nodes. Each can check the signature, but if two individually valid histories conflict, the signature does not choose between them. Gensler asks who appends the next block; the Bitcoin walkthrough introduces cumulative work as part of the rule for choosing a valid history. The 256-bit calculation instead estimates generic trials to hit a particular hash target. That measures one computational task. It cannot certify the separate rules for authorizing messages, validating ledger entries and selecting a history.
Passages and timestamps · 3
how do you decide who appends that next block?the one with the most work put into iton average, 2 to the 256 guessesWhere did the hidden cost go?
One hash lookup may probe a dense run of entries; another may chase pointers to distant addresses. Carruth’s data-structures talk follows the actual accesses. Carry that question into his talk on abstractions: tidy instructions at one call site can coexist with compilation costs or a calling-convention penalty at another boundary. A performance promise needs a workload, a boundary and an account of who pays.
Passages and timestamps · 2
maximize the cache locality of of handling a collisionit just means the cost is paid somewhere elseIs starting the old program enough for compatibility?
Rename a field in a message and the producing service may still compile. Hickey points out that names crossing a process boundary have other readers. Goetz distinguishes linking an old binary, recompiling old source and preserving behavior at runtime. Keep an old artifact, old source and an old message, then exercise them separately. Each tests a different promise.
Passages and timestamps · 2
as your names start escaping out of your processes, that they are global namesexisting class files will continue to linkWho migrates when a field becomes mandatory?
In Hickey’s terms, a mandatory field raises the caller’s obligations. Winters’s diamond dependencies explain why two teams may not move together: each reaches a shared component through a different intermediary. Wright supplies a migration order: offer the replacement while retaining the old default, move callers in batches, then end the transition. A version number can identify the two interfaces but cannot supply the missing data for an unmigrated caller.
Passages and timestamps · 3
if you require more than somebody who's giving less now is not going to get what they wantIf everyone in your infrastructure doesn't upgrade at the same time, then we have version skew.Usually you add the new thing without making it the default.How long must “it heats” hold to count as delivery?
Thwaites counts hundreds of pieces in a cheap toaster. His own device heats briefly before its element melts. As interface promises, “produces heat when switched on” and “continues heating for a useful interval” give different verdicts on the same device. To test the latter, include the duration and the state after failure in the acceptance example.
Passages and timestamps · 2
that, inside this object, which I'd bought for just 3.49 pounds, there were 400 different bits made out of a hundred-plus different materials.And for about five seconds, the toaster toasted, but then, unfortunately, the element kind of melted itself.Try it on your own example
For an interface you plan to change, which behaviors are guaranteed and which have merely stayed the same?