The most fundamental problem in computer science is problemdecomposition
Problem decomposition = how to take a problem and break it down into smaller problems that can be solved independently
2 general approaches to fighting complexity:
Make code simpler and more obvious
Encapsulate the complexity
Red flags that suggest code is more complicated than it needs to be are your hint that you haven’t found the right design yet
Complexity = anything related to the structure of the software system that makes it hard to understand and modify the system
Complexity of code is more apparent to readers of the code than writers
If a reader of your code thinks it is complicated then it is complicated. They decide not you
Symptoms of complexity:
Change amplification
Cognitive load
Unknown unknowns
Change amplification as a sign of complexity is when changing code in one place requires you to change code in many places
Cognitive load as a symptom of complexity is when developers need to know a lot and hold it all in their head in order to change some code
Unknown unknowns as a symptom of complexity is when it’s not obvious which pieces of code must be modified to complete the task
Unknown unknowns are the worst symptom of complexity because at least with the other two the programmer knows what they need to do to complete the task
A well designed system makes things obvious
Complexity is caused by:
Dependencies
Obscurity
A dependency exists when a given piece of code cannot be understood and modified in isolation
Obscurity exists in a system when important information is not obvious
Complexity is usually caused by lots of small decisions instead of one big decision
Tactical programming = when you get something working as fast as possible without consideration for its impact on the systems complexity
Tactical tornado = a prolific programmer who pumps out code faster than others but that works in a totally tactical fashion
Good programmers know that writing working code is not enough, it needs to also minimise system complexity
Strategic programming is when you don’t just care about the code working but you try to produce a great design that minimises system complexity
Strategic programming requires a more long-term investment mindset
The author suggests spending 10-20% of regular development time on investments that reduce system complexity
Strategic programming pays off over the long-term
Every module has an interface and an implementation
An interface described what a module does but not how it does it
An implementation is the code that carries out the promises of the interface
The best modules are ones whose interfaces are much simpler than their implementations
Clear interfaces can help reduce unknown unknowns
Abstraction = a simplified view of an entity which omits unimportant details
An abstraction can go wrong in two ways:
by including details that are unimportant
by omitting details that are important
Deep modules are better
Deep modules provide powerful functionality yet have simple interfaces
The benefit provided by a module is its functionality and its cost in terms of system complexity is its interface
Shallow modules are a red flag
A shallow module is one whose interface is complicated relative to the functionality it provides
Many people mistakenly believe classes should always be small, but instead the author thinks they should be deep
Interfaces should be designed to make the common path in particular as simple as possible
Interfaces should not reveal unimportant information to the user and instead should hide that information
Information hiding reduces complexity in 2 ways:
Simplifies the interface
Reduces dependencies on the information so makes it easier to evolve the system