Learning
  • Software Engineering Golden Treasury
  • Trail Map
  • Caching
    • Alternatives to use before using cache
    • Caching Architecture
    • Cache Invalidation and Eviction
    • Cache Patterns
    • Cache
    • Consistency
    • Distributed Caching
    • Issues with caching
    • Types of caches
  • Career
    • algo types
    • Backend Knowledge
    • Burnout
    • consultancy
    • dev-level
    • Enterprise Developer
    • how-to-get-in-tech-from-other-job
    • how-to-get-into-junior-dev-position
    • induction
    • Interview
    • junior
    • mid
    • New Job
    • paths
    • Principle/staff Engineer
    • Requirements for job
    • Senior Dev capabilities
    • learning
      • automating-beginner
      • company1
        • analyst-progression
        • core-eng-progression
        • dev-progression
        • perf-eng-progression
        • soft-deliv-progression
    • mentoring
      • mentor-resources
    • recruitment
      • questions
      • Spotting posers
  • Computer Science
    • boolean-algebra
    • Compiler
    • Finite State Machine
    • Hashing
    • Algorithms
      • Breadth Firth Search
      • complexity
      • Depth First Search
      • efficiency
      • Sliding Window
      • sorting
    • data-structures
      • AVL Trees
      • data-structures
      • Linked List
    • machines
      • Intel Machine
      • Turing Machine
      • von neumann machine
      • Zeus Machine
  • devops
    • The 5 Ideals
    • microservice
    • Artifact repository
    • Bugs and Fixes
    • Build police
    • cloud-servers
    • Deployments
    • Environments
    • GitOps
    • handling-releases
    • infrastructure-as-code
    • System Migrations
    • SDP
    • On Premises Hosting
    • Properties/configuration
    • Release process
    • Release
    • Roll Outs
    • serverless
    • Serverless
    • Cloud Services
    • Versioning
    • AWS
      • deploy-docker-esc
      • cloud-practitiioner-essentials-notes
        • Module 1 - Intro to AWS
        • Module 2 Compute in the cloud
        • Module 3 Global Infrastructure and Reliability
        • Module 4 Networking
        • Module 5 Storage and Databases
        • Security
        • 7 Monitoring and Aanlytics
        • 8 Pricing and Support
        • 9 Migration and Innovation
      • developer-associate
        • AWS Elastic Beanstalk
    • build-tools
      • Managing dependecies
      • Apache ANT
      • Gradle
        • Custom Plugins
        • local-jars
      • Project Management - maven
        • Archtypes
        • Build Lifecycles
        • Customising build lifecycle
        • Dependencies
        • Directory layout
        • jar-files
        • one-to-one
        • Modules
        • Phases
        • Maven Plugins
        • POM
        • profiles
        • setup
        • Starting a maven project
        • wrapper
    • CI/CD
      • Continuous Delivery
      • zookeeper
      • Continuous Integration (CI)
      • github-actions
      • Pipeline
      • Teamcity
    • Cloud computing
      • Overview
      • Service Models
      • Cloud Services
    • containers
      • Best Practices
      • Docker
    • Infrastructure
      • IT Infrastructure Model
      • Non functional Attributes (Quality Attributes)
        • Infrastructure Availability
        • Performance
        • Secruity
    • monitoring
      • Alerting
      • Monitoring & Metrics
      • Metrics
      • Ready pages
      • Splunk
      • Status pages
      • notes-devops-talk
      • logging
        • logging
        • issues
        • Logging
        • Logging
    • Service mesh
      • Service Discovery
      • Istio
    • Terraform
    • container-management
      • Kubernetes
        • commands-glossary
        • OLTP
        • config-maps
        • Links
        • ingress
        • SDP
        • minikube
        • filter
        • indexes
        • sidecar
        • continuous-deployment
  • General Paradigms
    • CAP theorem
    • designing data-intensive applications summary
    • a-philosophy-of-software-design-notes
    • Aspect oriented Programming (AOP)
    • Best Practice
    • Cargo Cult
    • Clean Code
    • Coding reflections
    • Cognitive Complexity
    • Complexity
    • Conventions
    • Design discussions
    • Design
    • Error Handling Checklist
    • Exceptions
    • Feature Flags/toggle
    • Functional requirements
    • Last Responsible Moment
    • Lock In
    • Named Arguments
    • Naming
    • Performance Fallacy
    • Quality
    • Redesign of a system
    • Resuse vs Decoupling
    • Rules for software designs
    • Sad Paths
    • Scaling Webservices
    • Scientific Method
    • stream-processing
    • Upstream and Downstream
    • Patterns
      • Client-SDK-Pattern
      • ORM
      • Api gateway
      • Business Rules Engine
      • cache
      • Composition Root
      • Dependency Injection Containers
      • Dependency Injections
      • Double Dispatch
      • Exception Handling
      • Gateway pattern
      • Humble Object
      • Inheritance for reuse
      • Null Object Pattern
      • Object Mother
      • Patterns
      • Collection pipeline pattern
      • Service Locator
      • Setter constructor
      • Static factory method
      • Step Builder Pattern
      • telescopic constructors
      • Toggles
      • API
        • Aims of API designs
        • Avoid Checked Exceptions
        • Avoid returning nulls
        • Be defensive with your data
        • convience-methods
        • Fluent Interfaces
        • Loan Pattern
        • prefer-enums-to-boolean-returns
        • return-meaningful-types
        • Small intefaces
        • Support Lambdas
        • Weakest type
      • Gang of Four
        • Builder
        • Factory Pattern
        • Strategy Pattern
        • Template
        • abstract Factory
        • Adapter
        • Bridge Pattern
        • Chain of responsibility
        • Command Pattern
        • Composite Design Pattern
        • Decorator Pattern
        • Facade Pattern
        • Flyweight pattern
        • Guard Clause
        • Interpreter
        • html
        • Mediator Pattern
        • Memento Pattern
        • Observer
        • Prototype
        • Proxy
        • Singleton
        • State Pattern
        • Visitor Pattern
    • Architecture
      • Entity Component System
      • Integration Operation Segregation Principle
      • Adaptable Architecture
      • Architecture
      • C4 Modelling
      • cell-based
      • Clean/Hexagonal Architecture
      • Codifying architecture
      • Correct By configuration
      • Cost Base Architecture
      • Data Oriented Design
      • deliberate
      • Domain oriented DOMA
      • Event Driven Architecture
      • Evolutionary Architecture
      • examples
      • Feature Architecture
      • Framework and Libraries
      • functional-core-imperative-shell
      • Layered Architecture
      • Micro services
      • monoliths-to-services
      • Multi tiered Architecture
      • Multi tenant application
      • Resilient Architecture
      • stage event driven architecture (SEDA)
      • links spring rest app
      • Tomato Architecture
      • Tooling
      • Types of architecture
      • checklist
        • Checklist for new project
        • Back end Architecture Checklist
        • Front end Architecture Checklist
        • Mobile Architecture Checklist
      • Cloud Patterns
        • Command and Query Responsibility Segregation (CQRS)
        • Event Sourcing & CQRS
        • Asynchronous Request and Reply
        • Circuit Breaker
        • Retry
        • Sidecar
        • Strangler pattern
      • Domain driven design
        • value & entity
      • Microservices
        • Alternatives to choosing microservices first when scaling
        • Consistency in distributed systems
        • 12 Factor applications
      • Modularity
        • Module monolith vs Microservices
        • Spring Moduilth
      • Architecture Patterns
        • Hexagonal architecture
        • Inverting dependencies
        • Layering & Dependency Inversion Principle
        • Mappings
        • Vertical Slice architecture
        • Web Client Server
        • domain
          • Business and Data Layers Separation
          • DTO
          • Domain Model Pattern
          • Domain Object
          • Transaction Script/ Use Case pattern
        • Enterprise Patterns
          • Concurrency
          • Distribution strategies
          • Domain layer patterns
          • Layering/organisation of code
          • Mapping to datasource
          • Session State
        • Usecases
          • Use case return types
      • Serverless
        • Knative
    • Design architecture aims
      • back of envelope
      • Design ideas
      • Design mistakes
      • high-volume-design
      • ISO Quality Attributes
      • Non functional requirements
      • “Designing for Performance” by Martin Thompson
      • High Performance
      • Qaulity Attributes
        • Availability
        • System Availability
        • Fault Tolerance
        • interoperability
        • Latency
        • Maintability
        • Modifiability
        • Performance
        • Readability
        • Reliability
        • Scalability vs performance
        • Scalability
        • Scaling
        • statelessness
        • Testability
        • Throughput
      • System Design
      • web-scalability-distributed-arch
        • scalable-and-distributed-web-architecture
    • README
      • Conflict-free Replicated Data Type
      • Fallacies
      • Load balancing
      • Rate Limiting
      • Transactions
    • Patterns of Enterprise Application Architecture
      • Repository Pattern
      • Rules Engines
      • scatter-gather
      • Specification Design Pattern
      • Table Driven Development
      • Workflow Design Patterns
        • Triggers
    • Principles
      • Do It Or Get Bitten In The End
      • Dont Repeat Yourself
      • Habitability
      • Keep it simple
      • Responsibility Driven Design
      • Ya Ain’t Gonna Need It
      • Conceptual Overhead
      • CUPID
      • Reuse existing interfaces
      • Facts and Fallacies
      • locality of behaviour
      • Separation of Concerns
      • Simplicity
      • SLAP principle
      • Step down rule
      • Unix Philosophy
      • Wrong abstractions
      • SOLID
        • 1. Single Responsibility Principle
        • 2. Open Close Principle
        • 3. Liskov Substitution Principle
        • 4. Interface Segregation Principle
        • 5. Dependency Inversion Principle
        • GRASP (General Responsibility Assignment Software Principles)
        • Solid for packages
          • jobs
          • CCP
          • CRP
          • REP
          • egress
          • gossip-protocol
        • STUPID
    • programming-types
      • Coding to Contract/Interface
      • Links
      • Declarative vs Imperative Programming Languages
      • defensive-programming
      • Design by contract
      • Domain Specific Languages (DSL)
      • Event Driven
      • file-transfers
      • Logical Programming
      • Mutability
      • Self Healing
      • Simplicity
      • Type Driven Design
      • Value objects
      • Aspect Oriented Programming
      • Concurrent and Parallel Programming
        • Actor Model
        • Asynchronous and Synchronous Programming
        • Batch processing
        • Concurrency Models
        • SAP
        • Multithreading
        • Non Blocking IO
        • Optimistic vs Pessimistic Concurrency
        • Thread per connection or request model
        • Actor
        • aysnchronous-tasks
          • Computational Graphs
          • Divide and conquer
          • Future
          • Thread Pool
        • barriers
          • Barriers
          • Race conditions
        • design
          • agglomeration
          • Communication
          • Mapping
          • Partitioning
        • Liveness
          • Abandoned Lock
          • Deadlocks
          • Livelock
          • Starvation
        • locks
          • Read write lock
          • Reentrant lock
          • Try Lock
        • Mutual Exclusion
          • Data Races
          • Mutual Exclusion AKA Locks
        • performance
          • Amdahl's Law
          • Latency, throughput & speed
          • Measure Speed up
        • synchronization
          • Condition variable
          • producer consumer pattern
          • Semaphore
        • Threads and processes
          • Concurrent and parallel programming
          • Daemon Thread
          • Execution Scheduling
          • sequential-parallel
          • Thread Lifecycle
          • threads-and-processes
      • Functional Programming
        • Currying
        • design-patterns-to-func
        • imperative-programming
        • First class functions
        • Functional Looping
        • Higher Order Functions
        • Immutability
        • Issues with functional Programming
        • Lambda calculus
        • Lazy & Eager
        • map
        • Monad
        • Railway Programming
        • Recursion
        • Reduce
        • referential-transparacy
        • Referential transparency
        • Supplier
      • oop-design
        • Issues with object oriented code
        • Aggregation
        • Anti Patterns
        • Association
        • class-and-objects
        • Composition
        • general-laws-of-programming
        • general-notes
        • Getters and Setters
        • Inside out programming
        • Inversion of control
        • oop-design
        • Other principles
        • Outside in programming
        • Readability
        • Why OO is bad
        • README
          • abstraction
          • encapsulation
          • inheritance
          • Polymorphism
        • clean-code
          • Code Smells
          • Comments
          • Naming
          • CLEAN design
            • code is assertive
            • Cohesion
            • Connascence
            • Coupling
            • Encapsulation
            • Loose Coupling
            • Nonredundant code
      • Reactive Programming
        • reactive-programming
    • Projects and Software types
      • Applicatoin Development
      • Buying or creating software
      • Console Applications
      • Embedded Software development
      • Enterprise
      • Framework Development
      • Games
      • Library development
      • Rewriting
      • White Label Apps
    • State Machines
      • Spring State Machine
  • Other
    • 10x devs
    • Aim of software
    • Choosing Technologies
    • Coding faster
    • Component ownership
    • developer-pain-points
    • Developer Types
    • Effective Software design
    • Full Stack Developer
    • Good coder
    • Issues with Software Engineering and Engineers
    • Learning
    • Logic
    • Role
    • Software Actions
    • Software craftmanship
    • Software Designed
    • Software Engineering
    • Software
    • article-summaries
      • General notes
      • Summary of The Grug Brained Developer A layman's guide to thinking like the self-aware smol brained
      • improve-backend-engineer
      • Optimising Api
      • Simple and Easy
    • README
  • Hardware
    • Cpu memory
    • Storage
  • Integration
    • GRPC
    • API
    • Apis and communications between apps
    • asynchronous and synchronous communications
    • Batch Processing
    • Communications between apps
    • Delivery
    • Distributed Computing
    • Entry point
    • Event Source
    • SDP
    • egress
    • Graphql
    • Idempotency
    • Libraries
    • Long Polling
    • Multiplexing & Demultiplexing
    • Publish Subscribe
    • Push
    • Request & Response
    • REST
    • Remote Method Invocation
    • Remote Procedure Calls
    • Server Sent Events
    • Short Polling
    • Sidecars
    • SOAP
    • Stateless and Stateful
    • Streams
    • Third Party Integrations
    • wdsl
    • Web Services
    • Webhooks
    • repository
    • Kafka
      • Kafka Streams
    • message-queues
      • ActiveMQ
      • Dead Letter Queue
      • JMS
      • Messaging
  • Languages
    • C
    • Choosing A Language
    • cobol
    • Composite Data Types
    • creating
    • Date time
    • Numbers
    • Pass by value vs Pass by reference
    • Primitive Data Types
    • REST anti-patterns
    • Rust
    • Scripting
    • Static typing
    • string
    • Task Oriented Language
    • assembly
    • Getting started
      • Functional Concepts
    • cpp
    • Java
      • Code style
      • Garbage Collection
      • Intellij Debugging
      • Artifacts, Jars
      • Java internals
      • Java resources
      • Java versions
      • JShell
      • Libraries
      • opinionated-guide
      • Starting java
      • Java Tools
      • Why use java
      • Advanced Java
        • Annotations
        • API
        • Database and java
        • Debugging Performance
        • Files IO
        • Finalize
        • JDBC
        • jni
        • Libraries
        • Logging
        • SAP
        • Memory Management
        • Modules
        • OTher
        • Packaging Application
        • Pattern matching
        • performance
        • Properties
        • Reference
        • reflection
        • Scaling
        • Scheduling
        • secruity
        • Serilization
        • Time in Java
        • validation
        • Vector
        • Concurrency and Multithreaading
          • Akka
          • ExecutorCompletionService
          • Asynchronous Programming
          • Concurrency and Threads
          • CountDownLatch
          • Conccurrent Data Structures
          • Executor Service
          • Futures
          • reactive
          • Semaphore
          • structured concurrency
          • Threadlocal
          • Threads
          • Virtual Threads
          • Mutual Exclusion
            • Atomic
            • Synchronized
            • Thread safe class
            • Threads
        • debug
          • heap-dumps
          • thread-dumps
        • functional
          • Collectors
          • Exception Handling
          • Flatmap
          • Functional Programming
          • Generators
          • Immutability
          • issues
          • Optional
          • Parallel Streams
          • Reduce
        • networks
          • HTTP client
          • servlet-webcontainers
          • sockets
          • ssl-tls-https
      • Basics of java
        • compilation
        • computation
        • Conditonal/Flow control
        • Excuting code
        • Instructions
        • Looping/Iterating
        • memory-types-variables
        • methods
        • Printing to screen/debugging
        • Setup the system
        • Data structures
          • Arrays
          • Arayslist/list
          • Map
      • Effective Java notes
        • Creating and Destroying Objects
        • Methods Common to All Objects
        • best-practice-api
        • Classes and Interfaces
        • Enums and Annotations
        • Generics
      • framework
        • aop
        • bad
        • Dagger
        • Databases
        • Lombok
        • Mapstruct
        • netty
        • resliance4j
        • RxJava
        • Vert.x
        • Spring
          • Spring Data Repositories
          • actuator
          • cloud-native
          • H2 Db in Spring
          • Initializrs
          • JDBC Template
          • Java Persistence API (JPA)
          • kotlin
          • Pitfalls and advice
          • PRoxies
          • Reactive
          • spring security
          • spring-aop
          • Spring Boot
          • spring-jdbc
          • Spring MVC
          • Spring Testing
          • Testing
          • Transaction
          • patterns
            • Component Scan Patterns
            • Concurrency
            • Decorator Pattern in Spring
        • Micronaut
          • DI
        • Quarkus
          • database
          • Links
      • Intermediate level java
        • String Class
        • Assertions
        • Casting
        • Clonable
        • Command line arguments
        • Common Libraries/classes
        • Comparators
        • Where to store them?
        • Shallow and Deep Copy
        • Date and Time
        • Enums
        • Equals and Hashcode
        • Equals and hashcode
        • Exceptions
        • Final
        • Finally
        • Generics
        • incrementors
        • Null
        • packages and imports
        • Random numbers
        • Regex
        • Static
        • toString()
        • OOP
          • Accessors
          • Classes
          • Object Oriented Programming
          • Constructors
          • Fields/state
          • Inheritence
          • Interfaces
          • Methods/behaviour
          • Nested Classes
          • Objects
          • Static VS Instance
          • Whether to use a dependency or static method?
        • Other Collections
          • Other Collections
          • Arraylist vs Linkedlist
          • LinkedHashMap
          • Linked List
          • Priority queue
          • Sequenced Collections
          • Set
          • Shallow vs Deep Copy
          • Time Complexity of Collections
          • What Collection To use?
    • kotlin
      • Domain Specific Language
      • learning
      • Libraries
      • Personal Roadmap
      • Links
    • Nodejs
      • Performance
  • Management & Workflow
    • Agile
    • Take Breaks
    • # Communication
    • Engineering Daybook
    • Estimates
    • Feedback Loops
    • Little's law
    • Managing Others
    • poser.
    • Presentations
    • self-improvement
    • software-teams
    • Task List
    • trade-off
    • Types of devs
    • Type of work
    • Waterfall Methodology
    • coding-process
      • Bugs
      • Code Review
      • Code Reviews
      • Documentation
      • Done
      • Handover
      • Mob Programming
      • Navigate codebase
      • Pair Programming
      • Pull Requests
      • How to do a story
      • Story to code
      • Trunk based development
      • Xtreme Programming (XP)
      • debugging
        • 9 Rules of Thumb of Dubugging
        • Debugging
        • using-debugger
      • Legacy code
        • Legacy crisis
        • Working with legacy code
    • Managing work
      • Theory of constraints
      • Distributed Teams
      • estimations
      • Improving team's output
      • Kanban
      • Kick offs
      • Retrospectives
      • Scrum
      • Sign offs
      • Stand ups
      • Time bombs
      • Project management triangle
    • Notion
    • recruitment
      • In Person Test
      • Interviews
      • Unattended test
  • Networks
    • Content Delivery Network - CDN
    • DNS
    • cache control
    • Cookies and Sessions
    • Docker Networking
    • Duplex
    • Etags
    • HTTP Cache
    • HTTP - Hyper Text Transfer Protocol
    • HTTP/2
    • Http 3
    • Internet & Web
    • iptables
    • Keep alive
    • Leader Election
    • Load balancer
    • long-polling
    • Network Access Control
    • Network Address Translation (NAT)
    • Network Layers
    • Nginx
    • OSI network model
    • Persistent Connection
    • Polling
    • Proxy
    • Quic
    • reverse-proxy
    • servers
    • Server sent events (SSE)
    • SSH
    • Streaming
    • Timeouts
    • Url Encoding
    • Web sockets
    • WebRTC (Web Real-Time Communication)
    • Wireshark
    • tcp/ip
      • Congestion
      • IP - Internet Protocol
      • TCP - Transmission Control Protocol
  • Operating Systems
    • Cloud Computing
    • Distributed File Systems
    • Distributed Shared Memory
    • Input/Output Management
    • Inter-Process Communication
    • Threads and Concurrency
    • Virtualization
    • Searching using CLI
    • Bash and scripting
    • Booting of linux
    • makefile
    • Memory Management
    • Processes and Process Management
    • Scheduling
    • Scripting
    • Links
    • Ubuntu
    • Unix File System
    • User groups
    • Linux
  • Other Topics
    • Finite state machine
    • Floating point
    • Googling
    • Setup
    • Unicode
    • Machine Learning
      • Artificial Intelligence
      • Jupyter Notebook
    • Blockchain
    • Front End
      • Single Page App
      • cqrs
      • css
      • Debounce
      • Dom, Virtual Dom
      • ADP
      • htmx
      • Island Architecture
      • Why use?
      • Java and front end tech
      • mermaidjs
      • Next JS
      • javascript
        • Debounce
        • design
        • Event loop
        • testing
        • Typescript
        • react
          • Design
          • learning
          • performance
          • React JS
          • testing
      • performance
      • Static website
    • jobs
      • Tooling
      • bash text editor - vim
      • VS code
      • scaling
        • AI Assistant
        • Debugging
        • General features and tips and tricks
        • IDE - Intellij
        • Plugins
        • Spring usage
  • persistance
    • ACID - Atomicity, Consistency, Isolation, Durability
    • BASE - Basic Availability, Soft state, Eventual Consistency
    • Buffer
    • Connection pooling
    • service
    • Database Migrations - flywaydb
    • Databases
    • Eventual Consistency
    • GraphQL
    • IDs
    • indexing
    • MongoDB
    • Normalisation
    • ORacle sql
    • Partitioning
    • patterns
    • PL SQL
    • Replication and Sharding
    • Repository pattern
    • Sharding
    • Snapshot
    • Strong Consistency
    • links
    • Files
      • Areas to think of
    • hibernate
      • ORM-hibernate
    • Indexes
      • Elastisearch
    • relationships
      • many-to-many
      • SDP
      • serverless
      • x-to-x-relationships
    • sql
      • Group by
      • indexes
      • Joins
      • Common mistakes
      • operators
      • performance
    • types
      • maven-commands-on-intellij
      • in-memory-database-h2
      • Key value database/store
      • Mongo DB
      • NoSQL Databases
      • Relational Database
      • Relational Vs Document Databases
  • Security
    • OAuth
    • API Keys
    • Certificates and JKS
    • Cluster Secruity
    • Communication Between Two Applications via TLS
    • Cookies & Sessions
    • CORS - Cross-Origin Resource Sharing
    • csrf
    • Encryption and Decryption
    • Endpoint Protection
    • JWT
    • language-specific
    • OpenID
    • OWASP
    • Secrets
    • Secruity
    • Servlet authentication and Authorization
    • vault
  • Testing, Maintainablity & Debugging
    • Service-virtualization and api mocking
    • a-test-bk
    • Build Monitor
    • Builds
    • Code coverage
    • consumer-driven contract testing
    • Fixity
    • Living Documentation
    • Mocks, Stubs & Doubles
    • patterns
    • Quality Engineering
    • Reading and working with legacy code
    • Reading
    • remote-debug-intellij
    • simulator
    • Technical Debt
    • Technical Waste
    • Test cases
    • Test Data Builders
    • Test Pyramids
    • Test Types
    • Testing Good Practice
    • Testing
    • What to prime
    • What to test
    • Debugging
      • Debugging in kubernetes or Docker
    • fixing
      • How to Deal with I/O Expense
      • How to Manage Memory
      • How to Optimize Loops
      • How to Fix Performance Problems
    • Legacy Code
      • Learning
      • Legacy code
      • techniques
    • libraries
      • assertj
      • Data Faker
      • Junit
      • mockito
      • Test Containers
      • Wiremock
      • Yatspec
    • Refactoring
      • Code Smells
      • refactoring-types
      • Refactoring
      • Technical Debt
      • pyramid-of-refactoring
        • Pyramid of Refactoring
    • Test first strategies
      • Acceptance Testing Driven Developement (ATDD)
      • Behaviour Driven Development/Design - BDD
      • Inside out
      • Outside in
      • Test driven development (TDD)
    • testing
      • Acceptance tests
      • How Much Testing is Enough?
      • Approval Testing
      • Bad Testing
      • End to end tests
      • Honeycomb
      • Testing Microservices
      • Mutation testing
      • Property based testing
      • Smoke Testing
      • social-unit-tests
      • solitary-unit-tests
      • Static Analysis Test
      • Unit testing
  • Version Control - Git
    • Branch by Abstraction
    • feature-branching
    • Git patches
    • Trunk Based Development
Powered by GitBook
On this page
  • Summary
  • From youtube talk
  • Nature of complexity
  • Working code is not enough
  • Modules should be deep
  • Information Hiding
  • General purpose modules are deeper
  • Different layer, different abstraction
  • Pull complexity downwards
  • Better together or better appart
  • Define Errors out of existence

Was this helpful?

  1. General Paradigms

a-philosophy-of-software-design-notes

Previousdesigning data-intensive applications summaryNextAspect oriented Programming (AOP)

Last updated 8 months ago

Was this helpful?

  • https://tigerabrodi.blog/a-philosophy-of-software-design

  • https://lethain.com/notes-philosophy-software-design/

Summary

  • Red flags

  • 𝗦𝗵𝗮𝗹𝗹𝗼𝘄 𝗺𝗼𝗱𝘂𝗹𝗲: the interface for a class or method isn't much more straightforward than the implementation

  • 𝗜𝗻𝗳𝗼𝗿𝗺𝗮𝘁𝗶𝗼𝗻 𝗹𝗲𝗮𝗸𝗮𝗴𝗲: a design decision is reflected in multiple modules

  • 𝗧𝗲𝗺𝗽𝗼𝗿𝗮𝗹 𝗱𝗲𝗰𝗼𝗺𝗽𝗼𝘀𝗶𝘁𝗶𝗼𝗻: the code structure is based on the order in which operations are executed, not on information hiding

  • 𝗢𝘃𝗲𝗿𝗲𝘅𝗽𝗼𝘀𝘂𝗿𝗲: An API forces callers to be aware of rarely used features to use commonly used features

  • 𝗣𝗮𝘀𝘀-𝘁𝗵𝗿𝗼𝘂𝗴𝗵 𝗺𝗲𝘁𝗵𝗼𝗱: a method does almost nothing except pass its arguments to another method with a similar signature

  • 𝗥𝗲𝗽𝗲𝘁𝗶𝘁𝗶𝗼𝗻: a nontrivial piece of code is repeated over and over

  • 𝗦𝗽𝗲𝗰𝗶𝗮𝗹-𝗴𝗲𝗻𝗲𝗿𝗮𝗹 𝗺𝗶𝘅𝘁𝘂𝗿𝗲: special-purpose code is not cleanly separated from general-purpose code

  • 𝗖𝗼𝗻𝗷𝗼𝗶𝗻𝗲𝗱 𝗺𝗲𝘁𝗵𝗼𝗱𝘀: two methods have so many dependencies that it's hard to understand the implementation of one without understanding the implementation of the other

  • 𝗖𝗼𝗺𝗺𝗲𝗻𝘁 𝗿𝗲𝗽𝗲𝗮𝘁𝘀 𝗰𝗼𝗱𝗲: all of the information in a comment is immediately obvious from the code next to the comment

  • 𝗜𝗺𝗽𝗹𝗲𝗺𝗲𝗻𝘁𝗮𝘁𝗶𝗼𝗻 𝗱𝗼𝗰𝘂𝗺𝗲𝗻𝘁𝗮𝘁𝗶𝗼𝗻 𝗰𝗼𝗻𝘁𝗮𝗺𝗶𝗻𝗮𝘁𝗲𝘀 𝗶𝗻𝘁𝗲𝗿𝗳𝗮𝗰𝗲: an interface comment describes implementation details not needed by users of the thing being documented

  • 𝗩𝗮𝗴𝘂𝗲 𝗻𝗮𝗺𝗲: the name of a variable or method is so imprecise that it doesn't convey much useful information

  • 𝗛𝗮𝗿𝗱 𝘁𝗼 𝗽𝗶𝗰𝗸 𝗮 𝗻𝗮𝗺𝗲: it isn't easy to come up with a precise and intuitive name for an entity

  • 𝗛𝗮𝗿𝗱 𝘁𝗼 𝗱𝗲𝘀𝗰𝗿𝗶𝗯𝗲: to be complete, the documentation for a variable or method must be extended.

𝗡𝗼𝗻𝗼𝗯𝘃𝗶𝗼𝘂𝘀 𝗰𝗼𝗱𝗲: the behavior or meaning of a piece of code cannot be understood

From youtube talk

https://www.youtube.com/watch?v=bmSAYlu0NcY

course : https://web.stanford.edu/~ouster/cgi-bin/cs190-winter18/lectures.php

https://lethain.com/notes-philosophy-software-design/

  • Most important concept in this field is decomposition of a problem and build it relatively easily.

  • Idea of software design is doing things today to make it easier to develop in the future

  • One thing that determines high and low performers is practise

  • Iterative process of building a system, use code reviews to edit and improve, then build from scratch

  • General list

    • Working code is not enough, must minimise complexity

    • complexity comes from dependencies and obscruity

    • strategic vs tactical Programming

    • Classes should be deep

    • General purpose classes are deeper

    • new layer new abstraction

    • Comments should describe things that are not obvious from the code

    • Define errors out of existance

    • pull complexity downwards

  • Class should not have large interface or lots of dependencies or side effects (this is the complexity) and not much funcitionality (impementation)

  • Class should have small interface and deep functionality.

    • Apply to methods/classes/modules

  • Shallow classes are an example of just calling another dependency's method

    • Issue with advice that classes/methods should be small, this leads to shallow classes

    • EG filestream, buffered stream in java library. Need to create lots of objects instead of using one object

    • IT is not about length of class, it is about lots of abstractions

  • Example of deep interface, Unix file i/o, wiht five methods

    • Lots of implementation details hidden

  • Define errors out of existence

    • https://web.stanford.edu/~ouster/cgi-bin/cs190-winter18/lecture.php?topic=exceptions

    • Huge source of complexity

    • Common wisdom: detect and throw as many exceptions

    • OVerall goal: minimise number of places where exceptions must be handled

    • Aim redefine the exception, so it does not exist, make normal behavour do the right things

      • ie java substring, throws lots of exceptions, instead better to return empty string if some error, if indexs are wrong sort it out (use correctly)

    • program defensively, but dont let exceptions be thrown

    • WHat matters in throwing an exception

    • Best to throw exceptions isntead of error code if it is propagate up, if caught immediately then use error code.

    • Crashing best for out of memory exceptions, to hard to catch

  • Tactical vs strategic (mindset)

    • wrong approach is tactical

      • results in bad design, high complexity

      • quick fixes, shortcuts

      • short termism, get it working

      • problems start off small, and become speghetti exponentially

    • Workign code is not enough

    • Strategic

      • goal: produce great design

      • simplify future dev

      • minimise complexity

      • must sweat the small stuff

      • Take extra time today, will pay off in future

    • Complexity is inevitable, can slow it down

    • Most startups are tactical

      • get product out as fast as possible

      • hard to repair

      • Facebook

        • move fast break things

        • unstable hard to use codebase

        • mantra change to move fast with solid infrastructure

    • Get product out fast is to get best programmers, programmers want to work with clean code bases

    • How much to invest

      • 10 -20 %

      • Make small changes

        • For new codebase

          • careful design

          • good documentation

        • existing codebase

          • look for improvements

          • dont settle for few modified lines of code

          • Goal: After change, system should be the way it would have been if designed from the start

    • Layers are good for handling abstraction

      • problem is having too many skinny layers

Quotes

  • Complexity is anything that makes software hard to understand or to modify.

  • Isolating complexity in places that are rarely interacted with is roughly equivalent to eliminating complexity.

  • Complexity is more apparent to readers than to writers. If other people think a piece of code is complex, it is.

  • Change amplification is when making a local change requires many changes elsewhere, and is best prevented when you reduce the amount of code that is affected by each design decision, so design changes don't require very many code modifications.

  • Complexity is caused by obscurity and dependencies.

  • Dependency is when code can't be understood in isolation.

  • Obscurity is when important information is not obvious.

  • This can often be due to lack of documentation.

  • Complexity is incremental, the result of thousands of choices. Which makes it hard to prevent and even harder to fix

  • Tactical mindset is focused on getting something working, but makes it nearly impossible to produce good system design.

  • Strategic programming is realizing that working code isn't enough. The primary goal is a good design that also solves your problem, not working code.

  • you should be doing lots of incremental design improvement work over time.

  • different than just "doing Agile", because Agile is too focused with features, whereas

    • The increments of development should be abstractions, not features.

    • Ideally, when you have finished with each change, the system will have the structure it would have had if you had designed it from the start with that change in mind.

  • payoff for good design comes quickly. It's unlikely that tactical approach is faster even for the first version, let alone the second.

    • arguemnet against yagni

  • The most important way to manage complexity is by shifting it from interfaces and into implementation:

    • Modules are interface and implementation.The best modules are where interface is much simpler than implementation.

    • It's more important for a module to have a simple interface than a simple implementation.

  • An abstraction is a simplified view of an entity that omits unimportant details. Omitting details that are important leads to obscurity, creating a false abstraction.

  • Each module should encapsulate a few pieces of knowledge, which represent design decisions. This knowledge should not appear in its interfaces,and hence are restricted to its implementation.Simpler interfaces correlate with better information hiding.

  • The opposite of information hiding is information leakage:

    • When a design decision is used across multiple modules, coupling them together.

  • Design it twice, taking radically different approaches.

  • If you're not making the design better, you are probably making it worse.

Nature of complexity

  • Aim of software design is to minimise Complexity

  • The skill of recognising complexity is essential

    • Choose good from a range of options

    • identify problems before investing a lot of time iin them

  • Complexity is anything related to a system that makes it hard to understand or modify

  • Complexity is found from the reader than the writer.

  • Symptons of Complexity

    • Change amplification

      • Simple change in system, requires many modifications in many places

      • Goals is to reduce the amount of code that is affected by each design decision

    • Cognitive Load

      • How much a dev need to konw in order to complete a task

      • high load, more learning, more risk of bugs

      • Examples : apis with many methods, global variables, inconsistencies, dependencies between Modules

      • Number lines does not equaly complexity

    • Unknown unknowns

      • which part of the system to makes the changes to, or what info does the dev need to complete the task

      • consequence occurs when bugs are raised

  • Aim: A make the system obvious

  • What causes complexity: Dependencies and obscruity

    • dependency is when a given part of the system cannont be changed or understood isolation.

    • Goal: reduce dependencies, make them simple and obvvious

    • Obscruity occurs when important info is not obvvious

      • generic variable names

      • variables names wihtout units

      • Not obvious that dependencies exist

      • inconsistencies, ie same variable name used for two different purposes

      • Occurs from inadequate documentation

        • Clean design, less need for documentation

  • Complexity is incremental

  • In large systems and as they get bigger complexity increases naturally

Working code is not enough

  • Tactical mindset - promtoted by organisations

    • focus on getting as many features out as possible

  • Strategic mindset - takes time, to get good design and fix problems

    • focus on long term

  • Tactical programmning

    • get feature or bug fix, but hard to produce good design

    • short sighted

    • leads to complexity

  • Stategic programming

    • understand working code is not enough

    • not acceptable to introduc Complexity

    • Most code in a system is written by extending the codebass, so need to be able to facilitate This

    • focus on different ways the system will change and how you will facilitate this

    • good documentation and tests

    • when design problem is found, fix it

  • How much to invest

    • Waterfall (design upfront) is not effective

    • Better to make small investments on a continual basis

      • leads to longer time to complete

      • benefits will occur later on

    • Tactical programming, will be faster at first but slower later on

  • Startups and investments

    • a lot of pressure on startups to get features out

    • They become tactical, and hope to hire more engineers as they get more successful

    • Once code turns to speghetti it becomes harder to work with

    • quality engineers leads to success

      • As they care about good design

    • Bad code base, hard to hire and retain engineers

    • Example facebook

Modules should be deep

  • Design systems so devs only need faces a small fraction of the overal complexity at any given time.

  • Modular design

    • Defn: system is decomposed into a collection of modules that are relatively independent.

    • Examples of modules: classes, subsystems, services

    • Ideal: all modules completely independent, deve can work on one without knowledge of the others

    • The complexity of a system is that of the complexity of the worst module

    • Ideal impossible, as modules must be able to work together and call each others functions/methods

      • Thus must know about the other modules

      • thus dependencies will form

        • if one module changes, other modules dependent on it will need to change

        • ie arguments in a method chagne, then any other module usin this method will need to change too

    • Aim: minimise dependencies between modules

    • A module has a

      • Interface

        • has everything that you need to know about a module that you will use ie signatures of methods

        • What a module does

      • Implementation

        • The code that carries out the promise made by the interface

    • Methods withing a classs that is not oo is a module in itself

    • Higher levels subsystems or services, have interfaces of different forms

      • kernal calls or http requests

    • Best Modules: interfaces are simpler than implementation

      • simple interfaces -> minimises Complexity

      • If module changes without changes to interface, other modules will not be affected

  • Whats an inteface

    • Contains formal

      • signature, names and types of params and return value, exception throw for the public methods

      • enforced by language

    • informal

      • high level behaviour, what it does ie naming

      • constraints on usage ie one method should be called before another

      • Derived by name or comments

  • Abstractions

    • defn: a simplified view of an entity which omits unimportant details

      • helpl think and manipulate complex things

    • Each module provides abstraction by its interface

    • More unimportant details ommitted the Better

    • Can wrong

      • include details that are not unimportant -> abstractions become more complex

      • omits details that are important -> obscruity,not info to use it correctly

  • Deep modules

    • Provide powerful functionality with simple interface

    • eg unix io and garbage collection

  • Shallow modules

    • complex inteface simple implementation

    • ie java i/o need many classes, dependencies to work with filestream

  • Interface should be designed to make common case as simple as possible

  • Having lots of options (ie use of lots of classe, decorators) is useful too, a way to disable the default

Information Hiding

  • Create deep modules

  • Info hiding

    • each module should encapsulate a few pieces of knowledge which represent design decision

    • Includes algorithm and data structures

    • Reduces complexity of interface

    • Makes it easier to evolve system

      • If algorithm changes, the interface does not need to only impl

    • Using private modifier is not info hiding but can help

      • But using getters/setters can still expose private members

  • Information leakage

    • opposite of hidding

    • design design is represented in a lot of Modules

      • creates dependencies between those modules, and changes need to occur in them all

    • info leaked in interface

    • different classe know about file Information

    • Pull info out of affected class into new class, which has a simple interface

      • otherwise replace backdoor leakage with leakage through interface

  • Temporal Decomposition

    • structure of system corresponds to the time order in which operations occur

    • Calling multiplemethods from different classses in specific order

      • better to put them in one class

    • In module design, focus on knowledge thats needed to perform task not theorder tasks Occurs

  • Lots of classes can lead to info leakage

  • Info hiding can be imporved by making class larger

    • All info that is needed to do the job of the interface is in here

    • Rather than have separate methods for each step (and thus have complex interface)

  • Avoid exposing external data structures

General purpose modules are deeper

  • A module has two purposes

    • general - address a broad range of problems

      • Build for future

      • what about yagni?? features not used as hard to tell the future

      • Being too general purpose, might not actually solve the problem

    • special - only a few

      • YAGNI

      • what is needed

      • can always refactor later

      • For incremental development

  • MAke classes somewhat special purpose

    • The module implementation should reflect your current needs, your interface should be general

    • general purpose approach allows for reuse and save time in future

    • general purpose better for simplicity even if it is used in one place

  • Questions to ask

    • what is the simplest interface taht will cover my current needs?

      • can reduce number of methods without reducing overall functionality.

      • if have to introduce lots of params to reduce no. of methods not changing things

    • In how many situations will this method be used?

      • If several methods can be replaced with one

    • Is api easy to use for my current needs?

      • STop you from going to far

      • Having to write a lot more code to make it general is not a good thing

Different layer, different abstraction

  • systems are composed of layers

    • higher layers use lower layers functionalities

  • Each layer provides different abstraction to the layers above and below

  • Red flag: adjacent layers with similar abstraction. Decompositon problem

  • Pass through methods

    • red flag

    • defn: has little implementation and invoke another method whose signature is similar/identical to that of the calling method

      • delegating all implementation to another method

    • not a clean division of responsibilities between classe

    • Make classes shallow (bad), increase interface complexity, not increase in functionality

    • Create dependecies between modules

    • The interface to a piece of functionality should in the same class that implements the functionality

    • There is an overlap of responsibilities between two classes

    • ACtion: Refactor so both clases has distinct responsibilities

      • expose lower level class directly to the callers of the high level class

      • Redistribute features between classes

      • merge classes if cannot be distangled

  • When is interface duplication ok

    • Same signature methods is alright if each method has significant different functionality.

    • Dispatcher (type of pass through but good)

      • uses arg/s to select on of which of several methods to invoke, then passes most/all of its args to choosen method, which implements specific algorithm

    • interfaces with multiple implementations

      • strategy pattern

  • Decorators

    • Api duplication across layers

    • Defn: decorator object takes an existing obj and extends its funcitionality

      • it provides an api similar/identical to the underlying obj

      • its methods invoke the underlying object methods

      • decorator adds new methods when wrapping the underlying object

    • Why?

      • separate special purpose extensions of a class from a more generic core

    • Shallow , lots of boiler plate, lots of pass through methods

    • java i/o

    • Alternatives

      • add the functionality to the underlying class

        • if the functionality is general purpose or logically connected to class or it will be used often from this class

      • Merge into same class which it will be called if only used in this in class

      • Merge into exisiting decorator

      • Does it need to wrap exisiting functionality? Be a stand alone class to inject into another

  • Interface versus implementation

    • The interface of class should be different to its implementation

      • internal should be different to external

      • What it does and how it does it should not be shown to be the Same

  • Pass through variables

    • variables that passed down through long chain of methods

    • Add complexity as intermediate methods must be aware of its existence, even if they dont use it.

    • Make changes hard to do if that variable that is passed is now used differently

    • ACtion

      • see if there is shared object between the methods, and just pass that object

        • but again this will be passed through

      • store in global variable

        • issues: cannot store create two independent instances of the same system in the same process, globals will conflict ie in testing

      • use context object pattern.

        • stores all of the applications global state

        • one context object per instance of the system

        • Issue needed in many places and can end up being a pass through

        • a reference to the context can be saved in most of systems major objects

          • When it is needed, the object that needs it upon instantiation it passed it to its constructor

          • wiring

        • properties

Pull complexity downwards

  • In module have unavoidable complexity , options:

    • let users of module deal with it

    • If complexity is related to functionality of the module -> handle complexity internally within the module

  • Most modules have more users than developers -> developers to suffer for user

  • dev to make life easier for user of module

    • simple interface over simple implementation

  • Dont give the hard problems to someone else

  • If dont know how to handle it -> throw exception for caller to handle it

  • have config/properties setting to decide what is best for them

  • Amplifies problems

    • exception thrown ->every caller will deal with it

    • exports config, SAs will need to implement for each env

  • Config params

    • moving complexity upwards instead of downwards

    • tuning the system for their system for requirements or workloads or env

    • The user might know better than the code what the best policy is

    • Can avoid dealing with issues and passing the on

      • imposssible to know these values

      • or can be determined automatically in codebase

    • config can end up out of date

    • Will a user be able to determine a better value than we can determine?

    • Can provide prop but with default in code

  • TAking it too far

    • Too far, pulling all functionality down to one class

    • Only pull down functionality:

      • if it is closely related to the class's exisiting functionality

      • if it will result in many simplifications else in module/app

      • if it will simplify the interface

Better together or better appart

  • Fundamental Question:

    • given two pieces of functionality, should they be implemented together in the same place, or should tehir implementation be seperated?

  • Applies at all levels of system: func, methods, classes and services

  • Idea: split into small components, the smaller they are, the simpler they are

    • problem:

      • More components, harder to keep track of them. More interfaces, every new interface -> increase complexity

      • More code to manage.

      • Creates seperation. components will be further apart. Harder to see components and logic at same time, or aware of existence.

        • If truly independent then seperation is good.

        • If there is a dependency, then seperation is bad as fliping between components. Not aware of dependecies -> bugs

      • lead to duplication

  • when to bring pieces together, if cloesly related:

    • they share information.

    • they are used together at the same time. Only if bi directional

      • ie disk block cache uses hash table, but hash table is not only used by it

    • OVerlap conceptually, there is a higher level category that includes both components

    • Hard to understand if both are not together

  • Info is shared

    • to do implementation of both. put together and reduces duplicaiton

  • Simplify interface

    • Simplifies interface of module, when combing modules, if original modules only implement part of the solution

    • Can do things automatically, without user having to do it (ie call one method insted of several in certain order etc)

      • Can have flags to decide to turn off or switch out default behavour to custom behavour

  • Elimntate duplication

    • extract method refactor

      • if replacement code is long, and method have simple signature

    • Snippet only has to be executed in one place.

      • ISsues with goto statement

      • call method, extract method

  • Seperate general purpose and special case code

    • If module contains code used in several differen places, then it should support general purpose mechanism.

    • Special purpose code associated with general purpose mechanism should go in a different module, typically one associated with smae purpose.

    • In general, lower layers tend to be more general purpose and the upper layers more special purpose

      • Top most layers have featurs totally specific to the application

      • ie layered architecture, upper layers is core, lower layers is infrastructure and presentation. If used in both, ie usecase, then have interface for lower layers used instead of implementation in dependency.

  • Splitting and joining methods

    • length of method is not a criteria for splitting

    • splitting creates more interfaces -> increase complexity

    • Only split if makes it simpler

    • if blocks of code have complex interaction, keep together

    • if simple to read then length is not a problem

    • having to flip between methods is Harder

    • Each method should do one thing and do it completely

    • Methods should have clean and simple interface, and should be deep

    • Refactor by extracting subtask

      • subtask should be independent of parent

      • parent should know nothing of how the child works

      • subtask should be general purpose

    • Refactor by splitting into two separate methods each visible to the calling method of the original

      • do when original has a complex interface or does too many thigns

      • should not need to call both split methods

    • Join methods if original methods are shallow or simpler interface

    • Red flag: Conjoined methods

      • cannot understand one method without understanding the other

Define Errors out of existence

  • exceptions can lead to complexity

  • reduce number of places where exceptions must be handled

  • End up not throughing exceptions by dealing with them

  • Why exceptions add complexity

    • Def: Exception is any uncommon condition that alter the normal flow of control of a program

    • fault tolerant systems need to be able to deal with exceptions, without breaking the system

    • Ways of dealing wiht exceptions

      • Move forward and deal with work despite the exception

      • abort the process and report it upwards

    • exception handling code must restore consistency to the system ie rewinding any partial state changse

    • One exception can lead to another one, especially during recovery from first exception.

  • Too many exceptions

    • Being too over defensive and defining too many exceptions is bad

    • Exceptions increase Complexity

    • People use exceptions to avoid dealing with difficult design decisions

      • thus it must be handled by the caller

    • Exception thrown by a class is part of the interface, thus increase complexity of interface

    • Reduce number of places where exceptions have to be handled

  • Define errors out of existence

    • Define api so there are no exceptions to handle

    • Define the implementation to avoid throwing exception

  • Example

    • When deleting do it async so that no need to check for other processes that are using it. Rather, mark it for deletion and no other process can use it and wait for the file to be finished if being used, then delete.

a-philosophy-of-software-design-notes
From you tube talk
Summary
Nature of complexity
Working code is not enough
Modules should be deep
Information Hiding
General purpose modules are deeper
Different layer, different abstraction
Pull complexity downwards
Better together or better appart
Define Errors out of existence