System Design Principles
2018-02-16 System Design
SOLID Design Principles
SOLID is an acronym of design principles that help software engineers write solid code within a project.
- S - Single Responsibility Principle. A module should be responsible to one, and only one, actor. a module is just a cohesive set of functions and data structures.
- O - Open/Closed Principle. A software artifact should be open for extension but closed for modification.
- L - Liskov’s Substitution Principle. Simplify code with interface and implementation, generics, sub-classing, and duck-typing for inheritance.
- I - Interface Segregation Principle. Segregate the monolithic interface into smaller ones to decouple modules.
- D - Dependency Inversion Principle. The source code dependencies are inverted against the flow of control. most visible organizing principle in our architecture diagrams.
- Things should be stable concrete, Or stale abstract, not concrete and volatile.
- So use to create volatile concrete objects (manage undesirable dependency.)
- DIP violations cannot be entirely removed. Most systems will contain at least one such concrete component — this component is often called main.
Concurrency Models
- Single-threaded - Callbacks, Promises, Observables and async/await: vanilla JS
- threading/multiprocessing, lock-based concurrency
- protecting critical section vs. performance
- Communicating Sequential Processes (CSP)
- Golang or Clojure’s
core.async
. - process/thread passes data through channels.
- Golang or Clojure’s
- Actor Model (AM): Elixir, Erlang, Scala
- asynchronous by nature, and have location transparency that spans runtimes and machines - if you have a reference (Akka) or PID (Erlang) of an actor, you can message it via mailboxes.
- powerful fault tolerance by organizing actors into a supervision hierarchy, and you can handle failures at its exact level of hierarchy.
- Software Transactional Memory (STM): Clojure, Haskell
- like MVCC or pure functions: commit / abort / retry
AKF Scale Cube
- Horizontal Duplication and Cloning (X-Axis). Having a farm of identical and preferably stateless instances behind a load balancer or reverse proxy. Therefore, every request can be served by any of those hosts and there will be no single point of failure.
- Functional Decomposition and Segmentation - Microservices (Y-Axis). e.g. auth service, user profile service, photo service, etc
- Horizontal Data Partitioning - Shards (Z-Axis). Replicate the whole stack to different “pods”. Each pod can target a specific large group of users. For example, Uber had China and US data centers. Each datacenter might have different “pods” for different regions.