Visual summary of operating lessons from Barbara Liskov.

Lessons from Barbara Liskov

Barbara Liskov turned software development into a discipline by inventing abstract data types and defining the rules for subtyping. This profile covers her work on the CLU and Argus languages, the substitution principle that bears her name, and her practical approach to building reliable distributed systems.

Part 1: The Architecture of Abstraction

  1. On the Discovery of ADTs: "I have no idea how I got that idea. It was ready to be discovered... what's important about this step is that it relates a thing that was just a structural idea to an abstraction." — Source: InfoQ
  2. On the Definition of a Type: "The key idea of data abstraction is that a type is characterized by the operations you can perform on it." — Source: MIT News
  3. On Irrelevant Details: "What we desire from an abstraction is a mechanism which permits the expression of relevant details and the suppression of irrelevant details." — Source: The Morning Paper
  4. On the Venus Operating System: The realization that a module should be a data type rather than just a collection of procedures occurred while designing the Venus system in 1972. — Source: Medium
  5. On Object Logic: A number is characterized by addition and multiplication; a string by concatenation—users of a type should never worry about how values are actually stored. — Source: ACM Turing Award
  6. On Thinking Before Coding: The fundamental difficulty of programming is translating ambiguous requirements into very precise code that is resilient to a lack of dependability. — Source: Mozaic Works
  7. On Design Boundaries: Abstraction encompasses finding the right interface for a system as well as finding an effective design for a system implementation. — Source: ResearchGate
  8. On Procedural Limitations: Before ADTs, procedures were the only way of doing abstraction; people didn't even understand what modules were meant to be. — Source: Alvaro Videla
  9. On Meaningful Naming: If an abstraction's name is so technically-derived that it doesn't explain its role, it might as well be named "X." — Source: Authentic Nerd

Part 2: The Substitution Principle

  1. On the Informal Definition: "If for each object $o_1$ of type $S$ there is an object $o_2$ of type $T$ such that for all programs $P$ defined in terms of $T$, the behavior of $P$ is unchanged when $o_1$ is substituted for $o_2$, then $S$ is a subtype of $T$." — Source: Gersti
  2. On the Formal Definition: "Let $\phi(x)$ be a property provable about objects $x$ of type $T$. Then $\phi(y)$ should be true for objects $y$ of type $S$ where $S$ is a subtype of $T$." — Source: Wikipedia
  3. On Naming the Principle: Liskov did not name the principle herself; she discovered it had been named after her years later when someone emailed her asking if they had "her principle" right. — Source: YouTube
  4. On "Common Sense": Her initial reaction to the formal naming of the Liskov Substitution Principle was: "It's really just common sense." — Source: GitHub
  5. On Subtyping vs. Subclassing: Subtyping is a semantic relation, whereas subclassing is a linguistic mechanism for code reuse—inheritance does not automatically create a valid subtype. — Source: CMU
  6. On the History Constraint: A subtype must not allow state changes that the supertype does not allow; you cannot create a mutable subtype of an immutable parent. — Source: Stackify
  7. On Behavioral Consistency: LSP is about more than matching method signatures; it is about preserving the invariants and contracts of the supertype. — Source: Northeastern University
  8. On Preconditions: A subtype cannot strengthen preconditions; it cannot require more from the caller than the parent type did. — Source: GitConnected
  9. On Postconditions: A subtype cannot weaken postconditions; it cannot promise less to the caller than the parent type promised. — Source: Ersantana
  10. On Client Expectations: The validity of a subtype is determined by the expectations of the client code that relies on the properties of the supertype. — Source: InfoQ

Part 3: Designing for Reliability in CLU

  1. On Modular Organization: In the early 70s, electrical engineers had circuits and wires to organize systems, but programmers lacked an equivalent modularity. — Source: Computer History Museum
  2. On the "Cluster": CLU introduced the Cluster, a module that encapsulated a data type's representation and its operations to ensure strict access control. — Source: Stone River Elearning
  3. On Iterators: CLU pioneered the concept of iterators, allowing programmers to loop over collections without knowledge of their internal data structures. — Source: Wikipedia
  4. On Exception Handling: CLU introduced the `signal` and `except` keywords, requiring exceptions to be handled or re-signaled to prevent silent failures. — Source: Wikipedia
  5. On "Where Clauses": Long before modern generics, CLU used "where clauses" to constrain type parameters, such as requiring a type to have a "less_than" operation. — Source: InfoQ
  6. On Inheritance Omission: CLU intentionally omitted inheritance to focus on composition and polymorphism through interfaces. — Source: Computer History Museum
  7. On Dijkstra's Influence: "There were no GOTOs [in CLU] because I believed Dijkstra." — Source: GitHub
  8. On Static Type Checking: Errors caught at compile-time are essential for building reliable, large-scale systems. — Source: MIT Infinite History
  9. On Language as a Tool: A language should make the things you want to do easy to do; this is a maxim for both language and software design. — Source: ACM Turing Award

Part 4: The Distributed Challenge

  1. On Modularity in Distribution: Distributed computing is an ideal place to apply abstract data types because you are forced to think of components as remote objects. — Source: CRA
  2. On Guardians: The Argus language introduced "Guardians"—autonomous, location-transparent objects that were precursors to the Actor Model. — Source: UBC
  3. On Atomic Actions: Argus brought the database concept of transactions directly into the programming language as "atomic actions." — Source: Wikipedia
  4. On Nested Transactions: Sub-actions in Argus could fail and be retried without aborting the entire top-level distributed operation. — Source: UBC
  5. On Stable State: The `stable` keyword was introduced to mark data that must be written to persistent storage to allow for crash recovery. — Source: UBC
  6. On Viewstamped Replication: Her work on consensus protocols aimed to prove that fault-tolerant systems could perform nearly as well as those that ignored failures. — Source: MIT CSAIL
  7. On PBFT: Practical Byzantine Fault Tolerance assumes that failed nodes can behave arbitrarily or maliciously, not just crash. — Source: YouTube
  8. On "Under False Pretenses": Liskov often tells blockchain audiences she is there "under false pretenses" because she views blockchain as an application of old replicated state machine theory. — Source: YouTube
  9. On Malicious Failures: In the modern era, malicious attacks have become a primary cause of system failure, making Byzantine Fault Tolerance a requirement rather than a curiosity. — Source: YouTube
  10. On RPC Efficiency: Communication across a network must be handled with the same care as local abstraction to maintain system availability. — Source: Developing.dev

Part 5: Software Engineering as a Science

  1. On Performance Obssessions: "You never need optimal performance, you need good-enough performance. Programmers are far too hung up with performance." — Source: GitHub
  2. The "Cockroach" Standard: "If you find a bug in your code, you should be as embarrassed as if you found a cockroach in your kitchen." — Source: Greenspun
  3. On the Software Crisis: The problem of the 1960s was that building big programs that worked required a modularity that simply hadn't been invented yet. — Source: InfoQ
  4. On Reasoning Independently: The ultimate goal of modularity is the ability to reason about a piece of code without knowing its internal implementation. — Source: ACM Turing Award
  5. On Programming as Cooking: Programming is about breaking a job down into steps and organizing the process, much like following a recipe. — Source: YouTube
  6. On Complexity as the Enemy: Her entire body of work is unified by the insight that complexity must be managed through strict encapsulation. — Source: Computer History Museum
  7. On Encapsulation as Security: Without strict encapsulation, modularity is an illusion because external code can always "muck around" with internal state. — Source: Developing.dev
  8. On Computational Thinking: Programming requires a "puzzle-solving" mindset that looks for the logical path through complex requirements. — Source: MIT Infinite History
  9. On the Spirit of the Time: To understand technology, one must understand the history of thought and the problems researchers were trying to solve at the time. — Source: ACM Digital Library

Part 6: Critique of Modern Languages

  1. On Python's Encapsulation: "Python has modules. But it doesn't have encapsulation, so it allows code on the outside to muck around with what's going on on the inside of a module." — Source: YouTube
  2. On Team Integrity: Your team is only as strong as your weakest programmer; it is better if the compiler can enforce rules that make bad behavior impossible. — Source: Developing.dev
  3. On "BeanFacade": The worst abstraction is one like a Java "BeanFacade," where two technical terms are jammed together to create a meaningless concept. — Source: Authentic Nerd
  4. On Java Generics: Her work on CLU's "where clauses" directly influenced the implementation of generics in Java and C#. — Source: InfoQ
  5. On Python's Intended Use: Python's design is well-suited for helping naive programmers learn quickly, but its lack of enforcement is a risk for large systems. — Source: Developing.dev
  6. On Programmer Discipline: Relying on programmer conventions (like the `_` prefix in Python) is insufficient compared to compiler-enforced encapsulation. — Source: Tufts University
  7. On Meaningless Abstractions: A good abstraction should describe what it does in the problem domain, not which design patterns it uses. — Source: Quora
  8. On Cognitive Load: Meaningless abstractions increase the cognitive load because developers must look at the implementation to understand the class's purpose. — Source: Authentic Nerd
  9. On "Consenting Adults": The "we are all consenting adults" philosophy of Python fails to protect system integrity from the least-skilled member of a team. — Source: YouTube

Part 7: Navigating Career and Adversity

  1. On the Princeton Rejection: She was rejected from Princeton’s math PhD program because they didn't admit women; she views this as a "crucial" happy accident. — Source: NPR
  2. On Accidental Programming: She became a programmer at MITRE after being rejected from grad school, despite not even knowing what computers were at the time. — Source: MIT Infinite History
  3. On the First CS PhD: In 1968, Liskov became the first woman in the U.S. to earn a PhD from a computer science department (Stanford). — Source: Stanford Daily
  4. On Strategic Career Tracks: She turned down a non-tenure research associate position at MIT, choosing to return to industry until a faculty role opened. — Source: MIT News
  5. On Ignoring the "Noise": Her strategy for navigating a male-dominated field was to keep a low profile and do the work she was interested in regardless of expectations. — Source: MIT News
  6. On Resilience: "I was very used to being the only woman in the room." — Source: YouTube
  7. On Competence: The best way to handle discrimination is to let the quality and impact of your work speak for itself. — Source: Computer History Museum
  8. On Value of Downtime: Liskov is a strong advocate for hobbies like gardening to clear the mind and help solve complex problems away from the screen. — Source: YouTube
  9. On the "Nerd" Stereotype: She famously used a photo of herself in a dress from the 70s to show that appearance has no bearing on research competence. — Source: YouTube
  10. On Career Success: "Find something you are both good at and genuinely like. If you don't have both, you won't be successful." — Source: Stanford Daily

Part 8: Mentorship and the Path Forward

  1. On Important Problems: Avoid "incremental work"; focus on significant questions that could fundamentally change how software is built. — Source: MIT Infinite History
  2. On Modern Education: "I worry about our current students who may not ever really understand how machines work... they take [data abstraction] for granted." — Source: YouTube
  3. On the "Internet as a Computer": There is a "funny disconnect" in how we write distributed programs; we need better abstractions to treat the global network as a single machine. — Source: ICT
  4. On the Future of Parallelism: New abstractions are desperately needed to handle the complexity of multicore processing and massive parallelism. — Source: ACM Digital Library
  5. On Cross-Chain Deals: Her recent work explores ensuring atomic transactions across different blockchains without a central authority. — Source: YouTube
  6. On BFT Scalability: While PBFT works for permissioned systems, its communication complexity is a hurdle for massive public blockchains. — Source: YouTube
  7. On Legacy: Almost every major programming language used today is a descendant of the concepts first implemented in CLU. — Source: Computer History Museum
  8. On the Craft vs. Science: Programming transitioned from a craft of writing procedures to a science of designing abstractions through formal logic. — Source: ACM Turing Award
  9. On the Long Game: The most influential work often takes decades to be fully recognized and integrated into the industry's daily practice. — Source: MIT CSAIL