Hi, fellow innovator (yes, you!). I'm interested i...
# thinking-together
d
Hi, fellow innovator (yes, you!). I'm interested in your driving principles for the work you do in the future of programming/coding. For example, "state and i/o are bad/good", "text is bad/good", "always allow explorable explanations", "programmer must always see the data changing when the code changes", "anything else Bret Victor thinks", "don't allow syntax errors", "programming is about modelling the world", "it's time to break the programmer|corporate|etc priesthood!!", "declarative not imperative", "eliminate accidental complexity", "flappy bird in 10 lines".. What are the fundamental principles you always look to (and have always held to, looking back) when making any technical or design decision, even if only subconsciously?
šŸ’Æ 3
Thread starts here.. šŸ‘šŸ¼šŸ˜ƒ
m
I will try to come around with a more distilled version, since I've a sense of what I'm after but never put it into words, here goes draft 1: • Both data and logic visible • As declarative as possible, as imperative as needed • Visual (no syntax errors) • If one thing is draggable in one place, it should be draggable anywhere else • Highlight valid targets when dragging • Drop the "form" metaphor, no forms, no submits • Changes apply instantly • Undo through history (time traveling versioning) • As few concepts as possible, but no fewer
šŸ‘šŸ¼ 5
d
Cool, thanks! (More distilled is kinda what I'm hoping for, yes! šŸ˜„ )
or more abstract perhaps
t
1. Allow me to organize the source code in the way I want, so that when reading the source code to understand the behavior, the movement of attention can be minized.
i
State is a result of i/o (user interactions + code), so it isn’t good or bad, it’s just an emergent property of code. Scoping it is the tricky part, and keeping it from bubbling up the scope. Text is good, but any text input should be augmented to assist user (autocompletion, refactor, validation etc) by using existing code and predefined/learned knowledge. This doesn’t allow for syntax errors and makes them obvious. We need to focus on writing with computers, not for computers. If we’re the craftsman, the computer is the apprentice and is here to do the mundane tasks and hand us the tools we need when we need them. We don’t need better languages - we need better tools. We need an apprentice that’s going to put the mundane boilerplate behind us. A lot of boilerplate and complexity in software development exists because different worlds collide in a single project - different kinds of developers and designers, each creating their own little universes with their own little stacks and models and processes and standards. Then you add a project manager to connect all those little universes, smashing them together into one and hoping for the best. I believe we should be doing it differently - one universe from the ground up. I believe programming is about expressing ideas and creating universes, and to create a universe for our idea we first must shape the data we want to use, so in a sense it is about modelling a world - you’re setting the laws, boundaries, basic elements of a whole new universe. Sometimes, you model it according to ours and copy over models and abstractions of how things work here. Then you can take a bird’s eye view of that and change it to your will to optimise interactions. Sometimes, you take the power to create from nothing and build the ideal world and then it’s all up to you and your creativity to come up with a solution. So when I’d have to compile it to some fundamental principles, I’d go with: • Model the basic universe structures, then interactions between them • Treat state as an emergent property and recognize it as such, allowing you not to think of it as bad or good but noticing it and managing it. • Write minimal code - template stuff, standardise stuff in your team, use those standards to write small tools, use those tools to generate code. You work with the computer, use the code at your disposal and cut the mundane boilerplate. The boilerplate is where mistakes happen (including human communication when something could be automated). • Be the laziest you can be when designing both developer and user interfaces. Less typing is more productivity. • Don’t let ego effect your code. By that I don’t mean the ā€œthis is the best way to make it and that’s itā€, by that I also mean ā€œi’ll stick with the known because I’m afraid to dive into unknownā€. Keep it balanced. Explore, sketch, rough out the idea, the compare. You can always revert here, there is no fucking up while you’re exploring. • Assist the user in making decisions, but don’t do it for them. • Keep your code structures tree-like. Meaning from the root, it’s easy to see it’s first/second level depth children and interactions between them. Their children’s children should be implementation details and you should dive into them only when needed. If you can’t find ā€œrootā€, look at the code as a dependency graph and you’ll see that it emerges anyways as an interlink of dependencies and interactions. • Everything can be configured and is configurable by the user. Everything. • The samurai technique - minimal movement, maximum effectiveness.
t
2. Allow me to comprehend the runtime behavior without guessing. The linking between source code and runtime behavior is present to me without effort.
d
This is all brilliant stuff. I may have triggered a tsunami though!! Excellent. šŸ˜„
t
@Ian Rumac
modelling a world - you're setting the laws
A majority of software is written just for enforcing business contract, essentially setting some laws. There are two fundermental apporach to setting the law: 1. Own the data, make every write through you. This is called 'Entity'. So that data must have identity. 2. Make the data portable, along with its rules. This is called 'Value Object'. Most of time, Entity is the only way to enforce the contract. Making "master data" partitioned and ownership clear is essential and hard. Delegating reponsibility to manage the data to carry out the logic is an art.
j
Assist the user in making decisions, but don’t do it for them.
I think this is actually a really deep point and can be applied in a fractal (scope-invariant) kind of way. I think this can mean things like making all of the settings configurable, but providing sane defaults. But it can also mean building your app as a composition of pieces in a framework that the user can rewire. Or it can mean building abstractions in code in such a way that they provide value, but can still be decomposed and recombined in ways you didn’t have to account for/expect. Or maybe I’m just reading all of this into it. But it all seems like the same thing to me.
s
Focus on reusability. Find the atoms of form and function.
c
Code is a machine-readable, text-serialized representation of a set of mental models (and not a particularly good representation, at that). Software is just a machine executing that representation with additional context (data). Every complexity in software development follows naturally as a result of that principle.
p
To me its: • Code should never lie • Being able to refactor by adding code without deleting - more like refining.
s
Preface: There is no code. There is no file. There is no program. It's all an illusion. Computing is a game of 'choose your illusions'. I don't like these illusions and I want new ones. Going full abstract: - Meaning over mechanism - Cognitive sympathy - Human provides design, machine provides rigor (not the other way around) - Pervasive provenance - Permeable layers - Seamless composition - Extensive affordances - Universal hypermedia
šŸ‘Œ 1
y
Software needs to be evolvable in order for people to thrive. (I don't think people are thriving)
d
@shalabh some of those are abstract to the point of opacity, to me at least! Can you ground them a little?😃
From Pervasive Provence on
s
Happy to elaborate @Duncan Cragg Pervasive Provenance I should be able to 'inspect element' almost anywhere and follow the chain of provenance - how the thing was constructed - for anything I can see. There are probably multiple aspects to provenance (e.g. version history, execution trace, ...) and I should be able to follow any path. Permeable Layers It should be possible to see under any layer of abstraction, in a safe manner, and see how the inside corresponds to the outside. Seamless Composition When I compose any object A with another object B in my system, the only thing that should matter is the highest level meaning encoded in these objects. The lower level data formats should be irrelevant, adapters should materialize as necessary. This requires that objects carry within them enough information to be tied back to some higher level meaning. Have been discussing this in https://futureofcoding.slack.com/archives/CCL5VVBAN/p1577178650059300. Extensive Affordances All objects should expose (via API/visual features) their abilities - labelled knobs and buttons. Not like Unix shell commands where you can't introspect them in a uniform manner to discover the flags and options. Compare with the Lisp machines (commands are functions with typed arguments, can be introspected, contextually fulfilled). Composition of objects should 'flow through' the affordances. Universal Hypermedia (Never copy paste an id again). Across the whole system, objects have resolvable ids/links. Objects that are related hold resolvable references to each other so their visualization easily provides navigable links to the other objects. Jump from running apps to sources to authors to annotation systems with easy. Allow 'scribbling in the margins' by attaching annotations to any object. No silos.
The higher level principles are in the first few points: Meaning over Mechanism: computers are mechanisms that serve human needs and human values. Twisting our meaning to fit the mechanism must always be looked at as a shortcoming. (Note: Twisting is different from precision) Cognitive Sympathy: The mental models should fit common cognitive abilities. Not having to juggle too many things in your mind, mapping to common metaphors, visualizations to aid comprehension. Human provides design, machine provides rigor (not the other way around). Since the machine can simulate itself very well, humans shouldn't have to simulate the machine. (What do you do when you read code?). We supply ideas (in a precise enough form) and the machine should supply rigor.
šŸ’Æ 1
āž• 1
d
Thanks! That's excellent. šŸ˜„
Those headings did mean what I guessed they meant!
s
This is a great exercise btw. It's always been hard for me to extract these kinds of principles.
g
programming can, should, and must feel like a video game. if your system doesn’t create a flow state as a side effect of expertise, it’s neither learnable nor accessible. direct manipulation refers to domain objects—programs/asts or domain models, not text, forms, or other abstractions over interaction. the primary purpose of programming is to build environments people can thrive, socialize, and accomplish tasks in
šŸ‘šŸ¼ 2
pattern matching and parsers like OMeta can address most programming problems and could be visual/direct manipulation interfaces
c
I forgot to mention, it takes a fair bit of time to actually come up with principles, but it's such a worthwhile exercise. It took me about 6 months of very intense exploration/research to come up with my "mental models" principle, but it's informed everything I've been working on since.
The simplest way I've found is to just start with a statement about something you want to do that really resonates with you (e.g.: "i want to make programming easier") and keep asking "why?" over and over again. At the end of the chain of questioning, you will get to a principle.
d
@crabl šŸ‘šŸ¼ that was something I learned in ThoughtWork
There's a lot of good discussion in this thread, so I'd like to "bump" it again in the main channel to get anyone that missed it the first time around. I won't say who I'm hoping will respond, but will "bump" them directly if they don't! šŸ˜„
šŸ‘ 1
j
My principle: minimize the reference manual. Think about precisely describing how your thing works. Design it to minimize the number of pages it takes to explain it, and minimize the prerequisites to understanding it (particularly mathematical sophistication). A consequence of this principle is that you should be writing the reference manual as you design.
d
↑ Yay! You responded!!
An extreme version of that is "README-Driven Development": Write the README then make it so.
You only have one principle? I'm surprised
j
You want principles? I got lots. Here is from the intro to Subtext: Subtext tries to be simple, transparent, and informal: 1. Simple — easy to learn and easy to use. 2. Transparent — the history of user interaction and program execution are visible in complete detail. 3. Informal — doesn’t require abstraction, premeditation, or mathematical/computational thinking. Subtext rejects: 1. Low level, high performance, or large scale software — being extreme in any dimension. 2. Requiring knowledge of existing software technology and practices beyond using a browser. 3. Appealing to the tastes of professional programmers or computer scientists.
šŸ™ƒ 1
šŸ‘šŸ¼ 1
m
@jonathoda I have a similar principle which is that if I'm giving a demo or explaning the thing and I have to stop to clarify something, next time I should do a change that doesn't require the clarification.
šŸ‘ 1
a simpler rule is to check for superfluous steps in demos and think if I can remove them from the common path