Mohammad YahiaMohammad Yahia
Handpicked Library

Curated Picks & Deep Dives

A hand-picked selection of standout articles, foundational books, and insightful videos that have shaped my thinking on software design, AI-driven engineering, and the joy of programming.

Type:
Status:
#courseFinishedby LinkedIn Learning
Aug 2026

DDD Thinking vs. Relational Database Design: Same Name, Different Entity

Bounded Contexts vs. Monolithic Global Database Schemas

Analyzing the divergence between relational database normalization (single shared global tables) and Domain-Driven Design (context-specific models where the same noun represents different entities across Bounded Contexts).

Key Takeaways & Reflections
  • The Relational Database Normalization Trap: Traditional DB design tries to create a single canonical table for each entity (e.g., a massive User or Account table with dozens of nullable columns shared across the enterprise). This creates tight schema coupling and high regression risks during database migrations.
  • DDD "Same Name, Different Entity" Principle: In DDD, a noun (like User, Account, or Product) has fundamentally different responsibilities across Bounded Contexts. In Identity, it’s credentials; in Billing, it’s invoices and payment methods; in Logistics, it’s delivery address and tracking slots.
  • Modeling each bounded context with its own purpose-built model and isolated database schema prevents domain contamination and enables autonomous microservice evolution.

"Do not unify domain entities under a single canonical schema just because they share a name. The same real-world noun represents completely different models with distinct invariants across different Bounded Contexts."

— Domain-Driven Design Principles, Software Architecture: DDD
#courseFinishedby LinkedIn Learning
Aug 2026

Software Architecture: Domain-Driven Design

Declarative vs. Imperative Microservices Communication & Orchestrated Systems

A comprehensive synthesis bridging Microservices, Domain-Driven Design (DDD), Declarative vs. Imperative communication, Sync vs. Async patterns, and Agile delivery.

Key Takeaways & Reflections
  • A powerful synthesis uniting Microservices, DDD Bounded Contexts, Declarative vs. Imperative communication, and Sync vs. Async orchestration.
  • Why Imperative RPC Fails in Microservices: In classic DDD microservices, services should not use imperative RPC across the network (e.g., OrderService commanding BillingService.createBill()). Imperative calls create tight behavioral, temporal, and failure coupling—turning microservices into a fragile distributed monolith.
  • The Declarative / Event-Driven Alternative: Emit domain events declaring facts that happened (e.g., OrderPlaced). Downstream bounded contexts listen declaratively and execute their own domain invariants independently, preserving true service autonomy.

"In Domain-Driven microservices, avoid imperative commands over the network. Favor declarative domain events that declare what happened, allowing bounded contexts to remain truly autonomous and decoupled."

— Software Architecture: DDD, LinkedIn Learning
#videoFinishedby Robert C. Martin (Uncle Bob)
Aug 2026

Software Fundamentals in the Age of AI

Agent pipelines, architecture boundaries, and timeless craftsmanship

Uncle Bob delivers a masterclass on how AI agents accelerate coding speed while proving that clean code, deep modules, deterministic verification, and fundamental engineering disciplines matter more than ever.

Key Takeaways & Reflections
  • Engineering with Agents: Constrain agents with deterministic tools (compilers, linters, mutation tests) rather than long, vague prompts. Use single-purpose multi-agent pipelines (Specifier → Coder → Cleaner → Hardener → QA) instead of trying to make one prompt do everything.
  • Architecture Still Wins: What confuses humans still confuses AI models. Strict modular boundaries, deep modules, and clean separation of concerns prevent agent thrashing and context pollution. Full-blown spec-driven upfront planning fails—choose rapid agile iteration.
  • Career & Fundamentals: Learn the fundamentals from the ground up and write code by hand to build deep mental models. Study classic engineering literature to understand historical struggles and the "why" behind architecture.

"What confuses humans still confuses AI agents. Clean architecture, strict modular boundaries, and deterministic verification tools are not obsolete—they are the only way to steer AI at scale without drowning in technical debt."

— Robert C. Martin (Uncle Bob), Software Fundamentals in the Age of AI
#articleFinishedby Uber Engineering
Aug 2026

Revolutionizing Money Movements at Scale with Strong Data Consistency

Double-entry accounting engine & strong consistency in the face of CAP theorem

How Uber re-engineered its global payments platform across 10,000+ cities using immutable double-entry ledger bookkeeping to guarantee financial accuracy and zero downtime under massive scale.

Key Takeaways & Reflections
  • Handling financial balances at global scale cannot tolerate eventual consistency or floating-point rounding errors. Double-entry bookkeeping (every debit paired with an equal credit) provides mathematical invariant checking.
  • Under CAP theorem constraints, money platforms must enforce strict linearizability for balance mutations while offloading reads through read-replicated materialized views.

"To ensure data consistency and accuracy across millions of daily transactions, financial platforms must be founded on immutable ledgers and strict double-entry accounting invariants."

— Uber Payments Engineering, Uber Engineering Blog
#articleFinishedby Uber Engineering
Aug 2026

How Uber Migrated Financial Data from DynamoDB to Docstore

Petabyte-scale zero-downtime migration of trillions of financial records

The multi-year architectural journey of migrating petabytes of immutable financial ledger records from Amazon DynamoDB to Uber’s in-house distributed database, Docstore, saving $6M+ annually.

Key Takeaways & Reflections
  • Migrating trillions of financial records requires shadow writes, dual reads with automated diff reconcilers, and fallback mechanisms to ensure 100% data correctness with zero downtime.
  • Moving from a managed cloud NoSQL store to an internal distributed database (Docstore atop MySQL) provided greater control over transaction semantics, verifiable immutability, and petabyte-scale cost efficiency.

"Migrating petabytes of financial transactions requires transparent dual-read/dual-write verification pipelines with cryptographic immutability guarantees to ensure zero data drift."

— Uber Storage Platform, Uber Engineering Blog
#articleFinishedby Uber Engineering
Aug 2026

How LedgerStore Supports Trillions of Indexes at Uber

Strongly consistent and eventually consistent petabyte-scale indexing architecture

Deep technical dive into LedgerStore’s indexing engine, supporting over 2 trillion unique index entries with two-phase intent indexing for strong consistency alongside materialized views for fast queries.

Key Takeaways & Reflections
  • Strongly Consistent Indexes: Used for critical real-time validation (e.g. credit card authorization) via a two-phase commit intent pattern to prevent duplicate charges.
  • Eventually Consistent Indexes: Powered by change data capture and materialized views for high-throughput analytical and customer lookup queries.
  • Demonstrates how ledger immutability paired with dual-model indexing solves the CAP balance dilemma at planetary scale.

"LedgerStore maintains over 2 trillion unique indexes by bifurcating indexing paths: two-phase commit intent records for strong real-time consistency and asynchronous materialized views for high-volume lookup patterns."

— Uber Data Infrastructure, Uber Engineering Blog
#courseFinishedby LinkedIn Learning
Aug 2026

Behavior-Driven Development: Behavior Before Function

Behavior Before Function & Demystifying BDD vs. Acceptance Testing

Exploring why defining observable behavior must precede function implementation, while clarifying the distinction between writing .feature files as automated acceptance tests and practicing full collaborative BDD.

Key Takeaways & Reflections
  • Behavior Before Function: Traditional development instinctively starts with technical functions and APIs ("how do we code this method?"). BDD flips this paradigm to discover and specify observable system behavior first ("what outcome does the user need?"). Functions exist strictly to fulfill verified behaviors, eliminating speculative abstractions.
  • Writing Feature Files (Specification as Test): A clean, highly readable way to structure automated acceptance tests. It keeps test logic human-readable and decoupled from code implementation, allowing the team to validate the system as a black box based on expected behavior.
  • BDD as a Development Methodology: An evolution of TDD that starts before coding begins. It’s a discovery and alignment practice where engineering, product, and business collaborate on requirements through concrete examples using a shared ubiquitous language.
  • In fast-paced delivery environments, using Cucumber and Gherkin purely for automated acceptance testing brings great structure. Teams doing this can unlock even greater value by embracing the full BDD discovery cycle.

"Focus on behavior before function. BDD is not about tools or syntax; it is about building a shared understanding through conversation, concrete examples, and an executable ubiquitous language."

— Dan North / BDD Community, Behavior-Driven Development
#videoFinishedby Kevlin Henney
Aug 2026

Programming with GUTs

Goodhart’s Law, language idioms, and the pitfalls of software metrics

Kevlin Henney explores the language, terms, and mental models programmers use, explaining Goodhart’s Law and why software engineering metrics collapse when treated as control targets.

Key Takeaways & Reflections
  • Goodhart’s Law in Software: "Once a metric becomes a target, it loses its meaning as a measure." When management turns measures (test coverage percentage, velocity, story points, PR counts) into targets, teams inevitably game the system.
  • A masterclass on engineering terminology, cognitive ergonomics, and how clear language prevents systemic design failure.

"Once a metric becomes a target, it loses its meaning as a measure. Any observed statistical regularity will tend to collapse once pressure is placed upon it for control purposes."

— Kevlin Henney / Charles Goodhart, Programming with GUTs
#videoFinishedby Brian Will
Aug 2026

Object-Oriented Programming is Bad

A foundational critique of object-oriented design and accidental complexity

Brian Will makes a structured, provocative case against OOP, arguing that combining state and behavior into encapsulation graphs produces rigid webs of mutation, complex patterns, and maintenance overhead.

Key Takeaways & Reflections
  • Presents a strong case that OOP’s core promise—bundling mutable state with functions behind encapsulation—often introduces more problems than it solves.
  • Helps clarify why modern enterprise codebases inevitably drift toward procedural/anemic service layers: real-world business pipelines flow naturally as transformations over data records rather than autonomous mutating objects.
  • Advocates for Data-Oriented Programming: keeping data structures dumb/transparent and logic pure, testable, and stateless.

"Object-oriented programming is not just misunderstood or misused; its fundamental ideas create unnecessary complexity and tangled dependency graphs that make code harder to reason about."

— Brian Will, Object-Oriented Programming is Bad
#articleFinishedby bbv Software Services
Jun 2026

Clean Code Principles & Smells Cheat Sheet

Cost of Change (CoC) economics, technical debt curve, and core design smells

A dense, high-value visual reference mapping out why clean code keeps the Cost of Change constant over time, alongside definitions for the 8 core architectural smells.

Key Takeaways & Reflections
  • Cost of Change (CoC) vs. Responsiveness: Writing clean code is an investment in keeping the cost of change constant throughout a project’s lifecycle. Quick and dirty code leads to mounting technical debt where costs skyrocket and responsiveness drops off a cliff.
  • Succinctly catalogs the 8 classic design smells: Rigidity (cascading changes), Fragility (breaking in unrelated places), Immobility (inability to reuse), Viscosity of Design & Environment (shortcuts are easier / slow feedback loops), Needless Complexity, Needless Repetition, and Opacity.

"Code is clean if it can be understood easily – by everyone on the team. With understandability comes readability, changeability, extensibility and maintainability. All the things needed to keep a project going over a long time without accumulating a large amount of technical debt."

— bbv Software Services, Clean Code Cheat Sheet
#articleFinishedby Dave Thomas
Jun 2026

Failing Faster

Technical debt bankruptcy in the age of AI coding

An insightful reflection on how coding with AI generates average code quickly, but without continuous refactoring, tech debt accumulates at 10x speed.

Key Takeaways & Reflections
  • Coding with AI is just coding with a tendency toward average code. Average code is fast and good enough, but you can build much faster.
  • The catch: at some point all these average pieces do not connect together in a resilient, scalable, and modifiable way. With AI, you can reach tech debt bankruptcy so fast.
  • Just like with normal code, we always need continuous refactoring and redesign. AI can help with this too if you actively steer it there.

"Code naturally degrades; you have to invest effort to stop it happening... It’s still just programming, and whether it takes 18 hours or 18 months, untended code will rot. All the things you’ve learned about creating good code still apply: the effect is just amplified."

— Dave Thomas, Pragdave Articles (2026)
#articleFinishedby Dave Thomas
Jun 2026

Castles In The Air

Why programming is thrilling

Nice article from the author of The Pragmatic Programmer, about how and why AI made programming more fun.

Key Takeaways & Reflections
  • I really like the initial quote, I had already came across it from (Mythical Man-Month by Frederick Brooks, 1974), this whole section is very resonating.
  • Working on what is interesting and enjoyable is on a different level.

"Finally there is the delight of working in such a tractable medium. The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. Few media of creation are so flexible, so easy to polish and rework, so readily capable of realizing grand conceptual structures."

— Fred Brooks, The Mythical Man-Month (1975)
#bookIn Progressby Martin Kleppmann
Jan 2026

Designing Data-Intensive Applications

The Big Ideas Behind Reliable, Scalable, and Maintainable Systems

Deep-dive into database engine internals, LSM-trees vs B-Trees, partitioning mechanics, distributed replication, consensus protocols (Raft/Paxos), and stream processing primitives.

Key Takeaways & Reflections
  • The definitive benchmark book for understanding real-world distributed data architectures and storage guarantees.
#articleFinishedby Vlad Mihalcea
Jan 2023

The Spring Data findAll Anti-Pattern

Why default JPA repository query methods degrade enterprise database throughput

A deep technical examination of why extending Spring Data’s default findAll() in entity repositories leads to memory bloat, unindexed table scans, and N+1 query storms.

Key Takeaways & Reflections
  • Inheriting findAll() in Spring Data repositories is a dangerous default for enterprise tables. As dataset sizes grow, accidental findAll() calls trigger out-of-memory errors and excessive JDBC roundtrips.
  • Always favor explicit pagination, keyset pagination, and tailored DTO projections over fetching entire managed entity graphs into memory.

"The problem with findAll is that it makes it very easy to fetch a huge amount of data into memory, which can lead to OutOfMemoryError exceptions and severe performance degradation."

— Vlad Mihalcea, High-Performance Java Persistence