Design¶
Design, Composition and Performance - Rich Hickey [2013]¶
Summary¶
Design is about taking things apart in such a way we can recompose them again. There are numerous concepts we should take apart (needs to problem, information to mechanism, knowns to unknowns, domain to technological solution, benefits and tradeoffs of solutions.) Design is an effective way to reduce the cost of bugs and to test our software as test now embeds the value of our design.
Composition is about constraints and communication. A composition is a design, or a plan for the performer. Bigger scales require more precision and lower scale allows more freedom to the performer.
Performance is about preparation, study and experience. It is the ability to bring our knowledge and our experience to solve the problem on a given context. Most coders stop learning after college which is a contrast to any artistic career who are lifelong learners.
Both activities requires a sensibility about harmony (in a given context, will two things work well together?).
Programming languages are like instruments. As such, we should chose those who are backing some fundamental idea (e.g. immutability, functional programming) and chose those who are aimed to those who have studied the language.
In software engineering, everything is code all the way down. Hence we have a paralysis of choice and distraction (we can improve any part of the problem). Making choices, and hence putting constraints move us forward. Thus, the value of the design is based on the decision made.
In conclusion, good design is about taking things about such that we can put them back together, we should compose by requiring as much constraint as possible, perform by preparing and studying and finally choose and learn simple tools aimed to experts.
Notes¶
Disclamer (joke): analogies are like equivalence, except when they are not.
Design by definition is about to prepare the plans for (a work to be executed), especially to plan the form and the structure of. Execution is interesting as someone or a machine will perform the work. The root is to mark out, to make a plan and write it down.
The value proposition of design: the bugs are the cheapest at design phases, when they are good. What is a good design?
Good design is about taking things apart. We want to separating and break down things into several pieces in such a way that they can be put together again, i.e. recomposed.
Each component should be about one or a few things. We solve a problem by composing the parts and it is iterative.
Design is about taking things apart.
Requirements
move from the want/need to the problems. Take the features and
requirements and break them down into a problems perspective. We can
explicit the knowns to the unknowns (what do we know how to do, from
what we don't know how to do?). Requirement from the domain side (what
does the information encodes and what purpose its transformation will it
serve for the customer) to the solution side (on which technology should
the code run). We can split the cause and the symptom for the problem
(how do you solve a black screen problem?), and explicit the unstated
requirement (e.g. should not destroy the machine or crash), these are
the state we should to avoid. We should transform the set all of
need/features to the intrinsic problems.
Time, order and flow
In which ordering are the operation to happen, can they be commutative?
Queues. Idempotency (redundant activity), transactions (operations have
to happen together at the same time).
Place, participants
Who (developer) is participating into the process? Which processes
(which systems)? Planing about independent development.
Information and mechanism
Which components belongs to the information or business problem, and
which belongs to the technical solution. Information is usually a
logical abstract idea (the sets of users) against a language construct
to represent them (=#{:a :b :c}). It is information against the
mechanics of a program.
Solutions
We have to compare multiple solutions and state their benefits and trade
offs, costs and problem fit (if the solution is not too larger to the
problem).
Why Design? We can understand the system (because design is smaller). Coordination (for writing the code). Extension and reuse (the broken pieces of system become connecting points, and new pieces can be connected to the pieces and thus extend them). As the pieces are independent, they can be reuse in other contexts as well. Testing is facilitated as the design constraints are put into test, in opposition as tests driving the design (quickcheck is interesting we need to think at properties and the computer write the test). Efficiency: the easiest and cheapest way to remove bugs is at design phases, even after shipping, the solution for bugs in the field is to break things even more.
Composition is about addressing self imposed problems and constraints. Learning requires inefficiency. Constraint is a driver of creativity. So we should ask as much constraint as possible when solving a problem. We are forced to take a choice and move on. Composition is designed for performers and is an organizational challenge. In composition, there is a vast variety of specificity and scale (fully orchestrated, arranged, larger scales in opposition to melody and changes, increased latitude for performance and more responsibility).
Most composition are about one or a few things. (melodic, harmonic, rhythmic, timbral ideas). Theme: variations, resolutions, larger works, provides more structural components.
Improvisation (not foreseen or provided). The melody and the changes and provides constraints. The performer provides variations. Improvisation (well executed) requires a tremendous amount of preparation, practice and study. It is about dynamic composition of planned material. The skill is about preparation of plans, material or sensibilities and apply them in the correct situation. Deep knowledge and vocabulary is necessary.
Harmony (accord, congruity, how does things line up in simultaneous combinations). How do things work together when applied at the same time? It might also be the art or science concerned with the structure and combination. Harmonic sensibility is a key design skill. A good designer knows, in a given context, if they make new choices, the pieces will be harmonious (or work together), and the knowledge is acquired through study and experience.
In the context of music, great composer and performers were masters of harmony, and they were students of harmoniousness. They went beyond the rules, they developed their own comprehension. They made new systems that preserver/explore harmonic essences.
Programming languages are more like instruments. Most instrument are about one excitation (pluck, vibrate, strike), combined with control and interface to shape the excitation, with the projection (the problem is how people will hear the sound). They all also have the resonance problem (the body of the instrument will respond to the excitation). Instruments are limited (piano can't play in-between notes, saxophone can only play one note at a time). They are minimal yet sufficient (no missing notes usually). The shortcomings might be overcome by the player.
Instruments are made for people who can play them. But beginners are not players yet. So we should stop designing languages for maximizing the first 5 minutes of experience of a language and we should target long term productivity. (The talk make criticism about cello which should auto-tunes, having green/red lights for good bad notes, or should note make any sound until the whole piece is played perfectly). The first critic is about coercion/javascript and the second one is about IDE, and the third is about static type compile checking (which would not run your program until it is self consistent with the types rules). Learning requires inefficiency.
Players endures pains to overcome and learn instruments. Humans are incredible, good learners and good teachers. Minimizing beginners effort as primary goal will never allow them to reach virtuous abilities with the tools. So teaching and learning are not effort-free. We are all novices (beginner for only a really brief moment). We are permanently students. It takes efforts. Overcoming effort and accomplishing things provides a sense of engagement (effort matters). Instruments (and tools) are usually for one user.
We should practice and plan much more than performing. Coders spend more time performing than studying (unlike other creative people).
In order to be creative you hate to know how to prepare to be creative – Twyla Tharp, The Creative Habit.
There is too much focus and emphasis on how fast a beginner can accomplish some things against what is required to be effective in the real world.
Electronic instruments are at the intersection of art and computer software. In their construction, there are two types of interfaces: machine and human. The instrument makers were smart as they built a human interface on top the machine interface allowing to compose. In contrast in IT, we have two examples where human interface were designed first and brings a lot of problems: SQL and UNIX. When we need to programmatically interface with these, we need to smash strings together or parse the output from a another process.
Design can also be layered and people are concerned with different matters. But for IT: code all the way down, we have the same mechanism at every layer (it does mean we can do filter design). It leads to distraction and unnecessary expansion. It yields the paralysis of choice (we don't know what to do).
We need the impetus of constraint. Constraint drives creativity as it helps to move forward (when we have a few choices, we need to make a choice and move on). We need to quit fidgeting (agglomerating, fiddling, tweakling). Maybe a lot of good ideas does not lead to a good construct.
Design is imagining (potential solutions) and embrace constraints, rush to them, create additional if not enough restrictive. It is optimistic, be positive and imagine a lot. Design is about making decisions. The value conveyed is in decisions made. Admit very little, and ability to say no. Leaving all options open is avoiding design.
Performing is preparing (planning). We should practice and study. Develop sensibilities you can apply on the fly (pattern, techniques, knowledge what works and what not).
Design is about taking things apart in order to be able to pull them back together. Design like Bartok (communicate very well at multiple levels). Code like Coltrane (prepare, study and experience, by doing multiple different things and not the same thing over and over), such that it feels more like improvisation.
Find and choose tools that are like instruments (stable, simple, directed at one thing, and oriented around people who know how to use them). They should express and backing some fundamental idea (or excitation for instruments).
Try to pursue harmony in the design, about the nature of harmoniousness, about what make things work together in a given context.
Source¶
Solving Problems the Clojure Way - Rafal Dittwald [2019]¶
- Pure functions everywhere.
- Minimize the number of mutable state.
- Concentrate the mutable parts into a few objects, like re-frame global state
- Defer side effects to the edge (end) of the program, like re-frame effects.
- Data first, something like configuration driven development. Put parts of your code into configuration.