8 ms·
No comment about the Mu itself but: > Our approach to keeping software comprehensible is to reduce information hiding and abstraction, and instead encourage cu
by chenglou 7y ago
No comment about the Mu itself but:
> Our approach to keeping software comprehensible is to reduce information hiding and abstraction, and instead encourage curiosity about internals
YES! Precisely. Most "bicycle for the mind" or "tool for thought" approaches go the completely opposite direction accidentally. Many programming languages and communities nowadays too.
In reality, if you wanna teach, you have to unveil the guts of the system. Sure, it's "scary" and all, but still, initial hand-holding & letting newcomers see the internals, rather than presenting an overly polished surface at the expensive of everything else, is a much better designed learning process. Design is "how it works" after all. *
Related: a common misconception when folks defend abstractions & encapsulation is to raise the issue that letting newcomers explore the internals causes too much trouble. That's an obvious strawman; these methods are not championing everyone writing anything everywhere. They can stay read-only, but public. E.g. an interface can expose its internal data types, without allowing consumers to actually leverage that (enforced through types or something else). This is easily doable, and you don't sacrifice learnability in the service of team programming sanity.
* This point seems to get dismissed quickly by folks who only care about visual polish nowadays. Imo this is naive. I care about visuals a _lot_, and we should definitely aiming for both learning polish and surface polish. But you can't let the latter calcify the former.
My advice for all the "tool for thought"/"bicycle for the mind" projects: all your opaque designs and small interface flourishes falter in the face of a properly exposed and clean-ed up paradigm, in the long run. This applies on a smaller scope to modern libraries too. That boilerplate generator you mega-fine-tuned to the point you delight yourself in guessing the user's mind, ultimately is a roadblock in the learner's thought process. Expose the boilerplate and document how you're automating it instead. You're trying to teach fishing, not to show off your own fish.
Another good analogy I've heard elsewhere is to ask whether you're teaching people how to cook, or just building a microwave. For a tool for thought product ask yourself if you ended up accidentally making "an appliance".
- jacobwilliamroy 7y agoAbstraction to me, just makes it easy to delay implementation. There are sometimes when I need to use an interface now but it won't actually be implemented until next week, when the client gets us our API key, or someone else finds time to do it. Using an abstraction means that I don't have to change any of the code that uses the interface, I just have to change the interface. This is also a good way to make a prototype that is easy to optimize, for example by abstracting a very costly computation, you can just focus on making that computation run faster without having to refactor every line of code where that computation is used.
- bitwize 7y agoMorty: Aw, geez, Rick, don't you think we ought to abstract away the low-level details here? Rick: Listen, Morty. Just bburpecause you wrap something in an abstraction doesn't mean the complexity "goes away". It just means you've put off dealing with it -- usually until it fails. And when it does fail, you now have another layer of shit to dig through to find the root cause. Walk into the fire, Morty. Embrace the suck. And think about how you will handle error conditions before you write the happy path.
- akkartik 7y agoThat's hilarious. Is it a real quote from the show?! (I'm the author of OP.)
- bitwize 7y agoNah, I made it up. I've noticed a tension between two dominant programmer archetypes in my career -- one naïve and inexperienced, but well-meaning and careful (the programmer I'm supposed to be), the other more experienced, but jaded by the passing of frameworks, methodologies, and other trends, who just wants to hack things into working order (the programmer I appear to be becoming as I age). They were pretty good fits for Rick and Morty. Quite coincidentally, the personas Microsoft used for their developer tools were called (in order of increasing experience) Mort, Elvis, and Einstein.
- dkarl 7y agoThis was/is a failure of pedagogy. I was taught abstraction as a virtue, embraced it, learned this lesson, and then noticed that the experienced programmers (not the pedagogists and professional authors) had been saying all along that until you had seen three distinct cases of something in the wild you were in no position to create an abstraction for it.
- quelltext 7y agoBeing curious about internals and giving users the means to understand them doesn't conflict with the goal of a) putting them behind a hiding layer that reduces the aspects a user needs to keep track of and b) avoiding dependence on those internals staying the same. You can still teach people how things work or you can still have a list of potential implementations of an interface. Where the internals matter you would either define very strict contracts or not use abstraction mechanisms that hide internals. But where it matters is not everywhere.
- akkartik 7y agoIn the past (http://akkartik.name/post/libraries http://akkartik.name/post/libraries) I've tried to distinguish between giving things a name to avoid having to work through details over and over again, and relying on something built by others so one never has to think about the details. But this has been a difficult point to communicate. I usually try to avoid the term 'abstraction' because it's gotten so debased. But here for an academic audience I go with the grain of how people use the word.
- Mikhail_Edoshin 7y agoThe original idea of encapsulation was not to rely on arbitrary internal knowledge but provide stable procedures. One of real-world examples was not to rely on Dorothy in marketing putting the red copy into the blue folder because next month Dorothy may be on vacation, red copies become yellow, and the blue folder is replaced with a green one. Instead the procedure should refer to Senior Marketing assistant, marketing copy, and folder for the current year. No excessive hiding, just stability.
- ssivark 7y agoYes, but what if that appearance of stability is unwarranted? After all, the underlying process is just Dorothy moving things around, and when Dorothy's on vacation things might not be working the way they should. This brings up an interesting aside: they right way to build software for "agile" processes might look very different from the right way to build software for "frozen" (non-agile) processes (big corp, stable processes, few surprises if any, etc.). Ideas such as abstraction/encapsulation that work well for the latter situation might be totally out of place in the former.
- atoav 7y agoIt is weird, this made me immidiately think about Rust: when they tried to solve a "hard problem" in the language, instead of hiding it away, they make it front and center and try to give you a comfortable way of dealing with it — but you cannot ignore it. A good example would be that functions of the Std library that deal with the Filesystem often return an OsStr instead of the Str/String Rust uses elsewhere. This means you cannot ignore the fact that the stuff the OS gives you might not be valid UTF-8 bytes. All functions that can be interrupted from the outside or fail, return their values wrapped in a Result Type and make you handle it. I think this is an example of good encapsulation — when something is a hard problem, it doesn't get easy suddenly, there are just clean ways of dealing with it. I learned a lot just by looking at how they did things and reading their explainations why they did it differently than other languages. In fact Rust teaches me so much about programming that it would've been worth to learn for these lessons alone..
- carlmr 7y ago>A good example would be that functions of the Std library that deal with the Filesystem often return an OsStr instead of the Str/String Rust uses elsewhere. This means you cannot ignore the fact that the stuff the OS gives you might not be valid UTF-8 bytes. All functions that can be interrupted from the outside or fail, return their values wrapped in a Result Type and make you handle it. This is the essence of why optional/result types lead to more stable systems than exceptions. With exceptions they can come from anywhere, you don't know if you've handled all of them (depends on the language). It's goto with a new name. With result types you're forced to deal with corner cases, or if you unwrap, you know you've omitted some corner cases, but it's still very visible what you did in your code. With exceptions your code looks clean when it's dirty, with results and optionals your code looks dirty when it's dirty. This is a talk about F#, but it explains the concept of railway oriented programming quite well. It's a paradigm for keeping your data flow clean with result types and optionals. https://www.slideshare.net/ScottWlaschin/railway-oriented-programming https://www.slideshare.net/ScottWlaschin/railway-oriented-pr...
- TheOtherHobbes 7y agoI think it's more like confusing people who just want to cook by expecting them to learn hob design and maintenance. The Jobs "bicycle for the mind" line was about the user experience, not the developer experience. So the fallacy in the argument is that implementation details are relevant to everyone. They aren't. They're relevant to system builders and people who like tinkering because that is a separate domain to the user domain. Most users just want an appliance, because a good appliance - like Hypercard, Excel, and maybe VBA - allows them to concentrate on the things that interest them, not on the things that interested the appliance designer when they were building their product. This is fine for products in the the app store - it's a mark of good design that it reveals exactly as much complexity as it needs to, but no more - but it breaks down when the user domain and the tinkerer domain overlap, as they do in professional software development. The reason it breaks down is because there is no general solution. No library is ever going to be a perfect snap-in tool that solves your problem for you, no language is going to hide OS-level and library-level abstractions with perfect elegance, and no OS is ever going to have perfectly elegant abstractions for file and network operations, simultaneous and synchronous operations, and so on. Everyone has opinions about how software should be designed, the problems are essentially open-ended, tinkerers have a tendency to turn everything into an excuse for tinkering instead of a streamlined product/service pipeline, and the result is the mess we have today. And this is probably how it has to be, given the limitations of human reason.
- nikki93 7y agoI agree for all the 'appliance' stuff; and a lot of times that's what you want. But I think also we should be sure to enable and flood computers with "play" spaces--which are about such 'tinkering' but I think it is much; much more than just tinkering--it's really what enables us to express our humanity IMO. And I think that's actually all types of tinkering; technical or not. And for a lot of 'use' you want to tinker but want the technical part to work; which I agree with. But we still maybe want to keep them open, inviting and friendly somehow. Just some thoughts along this rabbit hole I've been diving into lately--"game studies," "play," etc.-- https://publishup.uni-potsdam.de/frontdoor/index/index/docId/5045 https://publishup.uni-potsdam.de/frontdoor/index/index/docId... collects some references.
- 7y ago