Hacker News new | ask | show | jobs
by ATMLOTTOBEER 881 days ago
His idea to keep interfaces small and powerful bothered me - I don’t think it expresses any truth about programming despite being a good rule of thumb. I kept feeling frustrated while reading. The lambda calculus has the best interface to functionality ratio possible but you don’t see humans using it to program. This objection led me to the conclusion that a better heuristic would be: programs should try to communicate intent primarily to another reader, and then to the computer. He does touch on this a little by saying aim for ease of reading over ease of writing, but I don’t think it was a main point. I agreed with almost everything else he had to say including the “taking it too far” chapter (I don’t actually think we should be using lambda calculus to program lol). Curious to know which parts you disagreed with. I am only 2yoe
3 comments

Most so the book is meant to be taken as a rule of thumb. I personally think simple interface hiding deep functionality is a really good one. I was looking at the langchain codebase last year after having read the book and the point was struck home. Many of the functions in Langchain are one line wrappers of other functions. I try to think of functions as atomic units of knowledge. Very short functions are a good indicator that you're not organizing that knowledge effectively. When you have a simple interface with deep logic, you're encapsulating logic in a single place. This is very good for reducing the cognitive load of a developer. Shallow functions fragment that knowledge across multiple classes/functions/files. The developer needs to hold more of the world in their head to make sense of things. This increases complexity.

Additionally, you can sort of intuit this by looking at very successful commercial products like Google Search, the iPhone, and ChatGPT. Search is a single text input. The iPhone is a screen with a very small number of buttons. Chatgpt has a simple chat interface. All of these systems are incredibly complex, but they're able to present a simple interface to the public to allow most people to leverage that complexity without having to think about it.

Just my 2 cents.

To people who are experienced in writing out the full interface of modules, ie their assumptions and guarantees, it's quite clear that being a "deep module" in Ousterhout's sense is quite rare and often undesirable, and that Ousterhout's examples of deep modules are actually shallow. See https://www.pathsensitive.com/2018/10/book-review-philosophy...

He gets a lot of other stuff right though. Love his writing on comments

I think I might be missing something from that article, but I don't think they're in so much disagreement with Ousterhout.

Ousterhout's core argument is this: consider a module as its interface (measured, say, in # of edge cases) multiplied by its effect (measured, say, in # of features achieved). When comparing two modules, we should prefer modules with smaller interfaces and larger implementations, i.e. of two modules with equally sized interfaces, prefer the one which does more, and of two modules which do the same thing, choose the one with the simpler interface.

Narrow vs wide in this context seems to me to mainly be a point of comparison - in practice, narrow and wide don't make much sense when talking about a module on its own, because the dimensions of interface and implementation are not comparable.

However, this article seems to mainly be about comparing interface to implementation and arguing that, because interfaces can be very complex, often as complex or more as the implementation itself, then Ousterhout is wrong. Or in other words, if we convert "# of edge cases" and "# of features achieved" to a single comparable unit like "# of lines of code", then for Ousterhout's advice to hold, then the implementation must be more lines of code than the interface.

To me, that's kind of missing the point of the advice, which is less to do with the amount of code needed to implement something, and more to do with the capability of code vs its interface. Yes, lines of code can be a useful proxy for both dimensions, but the dimensions aren't meant to be directly comparable.

I might be missing something, though.

As one example, I think his formula for overall complexity is mostly correct: Total Complexity = Sum[ componentComplexity x timeSpentWorkingOnThatPart] However I would replace the timeSpentWorkingOnThatPart with the sum of the square roots of all separate times. i.e. Working on a component for 2 days straight versus working on it 1 hour every 2 weeks are quite different. But heh I'm sure there's other refinements and if I was writing a book I wouldn't necessarily include them. It slightly goes against the point of the book to nitpick these things as it's trying to help us think abstractly at a higher level.
If you've never used lambda calculus I would highly recommend trying haskell.