Software has almost no constraints.
We can make pigs fly, if we want to.
Slide 4
Slide 4 text
If you can imagine a system, you can probably
build it in software.
Slide 5
Slide 5 text
The greatest limitation in software is our ability to understand
the systems we are creating.
— John Ousterhout, A Philosophy of Software Design
Slide 6
Slide 6 text
As we add new features, our code evolves and naturally
becomes more complicated.
Subtle dependencies emerge.
Slide 7
Slide 7 text
Over time, this complexity accumulates.
Slide 8
Slide 8 text
It becomes harder and harder for us to keep all of the
relevant information in our minds …
Over time, this complexity accumulates.
Slide 9
Slide 9 text
Because the system is becoming complex and we’re struggling
to keep all the details in our minds:
Slide 10
Slide 10 text
Because the system is becoming complex and we’re struggling
to keep all the details in our minds:
It becomes harder to add new features … it slows us down.
Slide 11
Slide 11 text
Because the system is becoming complex and we’re struggling
to keep all the details in our minds:
We can easily miss some detail and create bugs …
which further slows us down.
It becomes harder to add new features … it slows us down.
Slide 12
Slide 12 text
The effect multiplies and accelerates with every new
contributor to our codebase.
Slide 13
Slide 13 text
Progress starts to stagnate and costs start to grow rapidly.
Slide 14
Slide 14 text
Fighting
Complexity
Its all about:
Slide 15
Slide 15 text
Stamina
Simpler, less complex, designs allow us to build larger more
powerful systems before complexity becomes overwhelming.
Its about building:
Slide 16
Slide 16 text
Complexity
Anything related to the structure of a codebase that makes it hard to
understand or improve that codebase.
Slide 17
Slide 17 text
Change Amplification
Symptom 1:
A seemingly simple change requires code
modification in many places.
Slide 18
Slide 18 text
Cognitive Load
Symptom 2:
How much information does a developer need to
make a change to the system.
Slide 19
Slide 19 text
Unknown unknowns
Symptom 3:
It’s not obvious which pieces of code must be modified to complete
a task, or what information a developer must have to carry out the
task successfully.
Slide 20
Slide 20 text
Complexity is caused by two things
dependencies and obscurity.
Slide 21
Slide 21 text
Tactical Programming
In the tactical approach, our main focus is to get something
working. This is how systems become complicated - one small
compromise at a time.
Slide 22
Slide 22 text
Strategic Programming
The first step towards becoming a good software designer is to realize that working code isn’t
enough. It’s not acceptable to introduce unnecessary complexities in order to finish your
current task faster.
The most important thing is the long-term structure of the system. Our primary goal must be to
produce a great design, which also happens to work. This is strategic programming.
– John Ousterhout. A Philosophy of Software Design
Slide 23
Slide 23 text
No content
Slide 24
Slide 24 text
The Tactical Tornado
Slide 25
Slide 25 text
No content
Slide 26
Slide 26 text
The simple parts of reducing
Cognitive Load …
Good names, good comments, consistency, mix format, credo etc.
Slide 27
Slide 27 text
Modular Design
A developers only need to face a small fraction of the overall
complexity at any given time.
Slide 28
Slide 28 text
Does not mean more modules.
Slide 29
Slide 29 text
Encapsulation
Encapsulate complexity so our team can work on other parts
of the system without being exposed to the complexity
encapsulated in this module.
Slide 30
Slide 30 text
In Elixir we can encapsulate at the function
level and at the module level.
Slide 31
Slide 31 text
Deep Modules
The best modules are those that provide powerful
functionality yet have simple interfaces.
Slide 32
Slide 32 text
No content
Slide 33
Slide 33 text
No content
Slide 34
Slide 34 text
No content
Slide 35
Slide 35 text
With a sufficient number of users of an API, it does not matter
what you promise in the contract: all observable behaviours of
your system will be depended on by somebody.
Hyrum's Law:
Use defp.
Slide 36
Slide 36 text
Loose Coupling
Components in a loosely coupled system can be replaced with
alternative implementations that provide the same services.
Slide 37
Slide 37 text
Polymorphism
The ability to present the same interface for differing underlying forms
Slide 38
Slide 38 text
Messages
Processes can send messages to other processes without
needing to care what the receiver process is or does.
The interface is Process IDs and Kernel.send/2
Slide 39
Slide 39 text
Behaviors
A module that defines a spec which other modules can
implement.
Slide 40
Slide 40 text
No content
Slide 41
Slide 41 text
Protocols
A group of function headers that a data type must implement if it
is considered to be implementing that protocol.
Slide 42
Slide 42 text
No content
Slide 43
Slide 43 text
No content
Slide 44
Slide 44 text
Functions
Slide 45
Slide 45 text
No content
Slide 46
Slide 46 text
Dependency Inversion
High-level modules should not depend on low-level modules.
Both should depend on abstractions (e.g. interfaces).
Abstractions should not depend on details.
Details (concrete implementations) should depend on abstractions..