3 ms·
It's not like we embrace complexity for its own sake. The harsh reality is that things like file paths, dates and times, phone numbers and even people's names a
by catnaroek 11y ago
It's not like we embrace complexity for its own sake. The harsh reality is that things like file paths, dates and times, phone numbers and even people's names are already intrinsically complex; and you can either acknowledge this complexity in your code, or ignore it at your own peril. If you want to blame anyone anyone for the complexity, blame those who design file systems, or ISO-standardize date and time formats, or even humanity as a whole for coming up with all sorts of naming customs! A programmer (or any other given single person) has only so much control over the complexity of their environment.
Also, you seem to think typeful programming is just for those who either want to show off (“to your geek programmer friends”) or don't trust other programmers (“to the other [extreme] of "never trust the programmer"”). This plainly untrue. Typeful programming is for those who embrace code as a communication medium (“my data structure has these complex invariants, which I can communicate either with three lines of code, or with two long English paragraphs in comments than might even get out of sync”) and want to include the type checker in the conversation (“this code is rather tricky, and I made lots of changes to it, could you check for me if I missed anything?”). Of course, the effectiveness of code as a communication medium is contingent on your ability to understand code.
- bjz_ 11y agoExactly. The complexity is inherent in the domain, and making it seem simpler by sweeping it under the carpet is not solving the problem, and it will result in hard to find bugs when working at scale.
- dllthomas 11y agoThere's abstraction, leaky abstraction, and brokenness. Making things seem simpler by finding an abstraction over them is great! Making things seem simpler by finding an abstraction that leaks some details so you sometimes need to handle them at a high level is... less great. But sometimes still a win. Making things seem simpler but neither handling the complexity nor allowing your users to handle the complexity is technical debt at best.
- catnaroek 11y agoMaybe this is just a sign of my lack of experience, but I don't think implementing leaky abstractions is ever justified outside of systems programming. (Implementing a runtime system for a manged language counts as “systems programming” in my book.) Here are some examples of justified leaky abstractions: (0) Memory is infinite, and memory allocation will always succeed. If it doesn't, aborting the entire process is the right course of action. (1) Communication over a network is reliable and data will arrive in the same order in which it was sent. And here are some examples of unacceptably leaky abstractions: (0) A few basic data structures [in particular, growable arrays and hashtables] suffice to implement every algorithm you might ever want to implement. (1) Strings are arrays of characters, and thus you can efficiently index them by character. (2) Every [nonempty] string is a valid file name or URL. (3) Every external resource can be manipulated using an API that presents it as a sequence of bytes. (4) An event loop is the universal solution to all asynchronous I/O problems.
- dllthomas 11y agoI don't see how your examples line with "systems programming" vs "not systems programming". I think in general, building on top of leaky abstractions is a form of technical debt, and you have to be aware of how much you're accumulating and what you're getting in exchange. Also, complexities stack super-linearly. I'm tempted to say, additionally, that building shallowly atop a leaky abstraction is less problematic than pushing leaks further down in a tall stack... but on reflection I have no idea how I'd support that.
- catnaroek 11y agoBuilding on top of leaky abstractions isn't necessarily a form of technical debt. Some leaky abstractions are actually better than their non-leaky counterparts. For example, not worrying about the possibility of running out of memory lets you concentrate on whatever your program is actually supposed to do, rather than micromanaging a very improbable situation. So, what I meant to say in my previous post is that, as far as I can tell, good leaky abstractions only arise when doing systems programming, or, more precisely, at the boundary between low-level system services (e.g. runtime systems for managed languages) and the applications that consume them. Abstraction leaks in high-level application code are likely to be bad.