###### tags: `design`
# Software Design and the Physics of Software - Carlo Pescio
https://www.youtube.com/watch?v=WPgYju3KnIY
{%youtube WPgYju3KnIY %}
Why it's important this talk?
* to have new perspectives
* to find new shapes, new ways of structuring your software based on understanding the forces that act on it, and its properties.
* making informed decisions vs design by habits
Modern software developers are like old alchemists, they had a good practical knowledge of the matter, but an imprecise model of reality and an imprecise and not useful language to describe. As a consequence, a lot of time is spent in philosophical debates.
Do we have
* rational conversations about design?
* analytical conversations about design?
No. We argue, and the guy with the best rhetoric (not with the best design!) wins the argument.
The way we speak and think about software is not helping us!
We want to describe properties of our software, because the properties are the final goal of our design: we want our software to expose some properties...
E.g. "viscosity" is not a clear definition: it's not defined in a constructive way.
The actual language draws a dichotomy: good vs bad. Modular is good, rigid is bad, extensible is good, viscous is bad

Viscosity in nature is not always bad.
:::info
Ideally a property should be neutral, and the effect of that property should be considered in a context.
:::
That does not happen in software: it's a polarized language => confrontational language.
We humans are good at doing (e.g. build) even without a precise understanding of things (thinks about a greek temple).
But a good understanding of things is really important!
So, a bold question: **what if we got a sub-optimal language for software design?**
We need to look at software from a different perspective!
A better model?
The properties are central.
We want some given properties in our software.
In physics properties are commonly defined as reaction to forces (e.g. compressibility)
We need to look at software and understand which forces are at play and understand which "material" is reacting to these forces.
:::warning
More: observation
Less: speculation
:::
Understand forces and define properties
---
The 3 spaces:
* the run-time space
* the artifact space
* the decision space
## Run-time Space
The Runtime Space is where the source code is being executed.
It's the runtime behavior of the code on real computers.
The force will evolve as tech evolve. RAM is slow, we have several levels of cache.
* The behavior belongs to the runtime space.
* Instances belong to the runtime space.
* Scalability, immutability, partition tolerance are properties in the runtime space.
* CAP theorem lives here.
## Artifact space
The domain where the source code and the models are living here.
Types and functions live here.
Properties that belongs here: readability, reusability, ...
## Decision space
Technical and management choices and "requirements" live here.
Design is about making choices. The decisions does not appear in our artifacts: we rather see the result of the decisions there.
The decision space is the key for properties like
* Information hiding is about hiding a design decision
* Abstraction
---
## An example: Viscosity vs Friction
Viscosity is resistance to movement.
The neutral property is "friction".
In the artifact space we have friction, when we move things around (e.g. extract some lines of code in a new function).
Movement may incur in resistance: you spend energy
* naming the function
* finding params to pass to the new function
* finding types that needs to be imported
* finding results that needs to be returned
(a refactoring tool can help, but the work is still there)
Asymmetry in size is a smell.
Extracting the function in the same class may create less friction than to move into a different class!
What we can observe:
* Every non-local id is resisting movements (something that is declared or used outside that scope: function names, variable names, members, a base class, etc)
* The resisting force is different depending on where we want to move the code (inside the same class vs into a different class)
* this is true in every programming paradigm (scopes and ids exists everywhere).

=> we can define a "coefficient of friction".
Isn't that just **coupling**??
No, because coupling is BAD.
While friction could be good or bad depending on the context.
In some context we just don't want to experience friction.
But, between different logical layers we may want some friction, because we don't want e.g. to move easily business logic to the presentation layer or to the persistence layer. That's where friction can be good!
## Entanglement
Things that must change at the same time to preserve coherence in the system.
Two information particles (e.g. classes, functions, ...) `P1` and `P2` are `A-B entangled` when performing action `A` to `P1` implies that action `B` must be performed on `P2`.
A,B may be CRUD operations.
E.g.
* I create a class (C) and I have to update a factory (U)
* I delete a class (D) and I have to update a factory (U)
Isn't that **coupling**?
No, it's a different concept: it's not just good or bad, it's just there and depends on the context, like gravity.
### Locality
Devs like **locality**: when we need to change code, we like locality, we like that code that needs to be changed is all nearby and not scattered in the codebase.
Runtime space: CPU likes locality also (see caches).
Locality can influence entanglement.
:::warning
Entangled particles must be kept near if we want locality.
:::
(=> COHESION!)
* Changing small code is good
* Reading small code is good
Things should not be kept together without necessity!
So un-entangled particles should be kept apart to reduce volume of changes, volume of read, etc ("small is good").
If you want high locality, you should keep entangled particles close together and un-entangled particles far away.
E.g. if two classes are U-U entangled (if I update one, I have to update the other too to preserve coherence in the system), they should be kept close together in the artifact space.
It's not a matter of "moral judgement" (_you are bad if you don't design cohesive code_), it's a matter of the consequences you have: you cannot have high locality, so changes will be hard to make in that part of the codebase.
But if you use layers and if you have a cross-cutting concern that cuts all the layers, you cannot do much to avoid entanglement.
## Entanglement may create a chain of reactions!

### Entanglement between artifact space and decision space
**Artifacts tend to be entangled with decisions**: when you change a decision, you potentially have to change a bunch of artifacts too.
This is why exist DRY and Information Hiding principles => it's about localizing these form of entanglements, so that when you change decision you have to change just one class or function.