Papers for Software Engineers
A curated list of papers that may be of interest to Software Engineering students or professionals. See the sources and selection criteria below.
List of papers by topic
-
Von Neumann's First Computer Program. Knuth (1970).
Computer History; Early Programming- The Education of a Computer. Hopper (1952).
- Recursive Programming. Dijkstra (1960).
- Programming Considered as a Human Activity. Dijkstra (1965).
- Goto Statement Considered Harmful. Dijkstra (1968).
- Program development by stepwise refinement. Wirth (1971).
- The Humble Programmer. Dijkstra (1972).
- Computer Programming as an Art. Knuth (1974).
- The paradigms of programming. Floyd (1979).
- Literate Programming. Knuth (1984).
-
Computing Machinery and Intelligence. Turing (1950).
Early Artificial Intelligence- Some Moral and Technical Consequences of Automation. Wiener (1960).
- Steps towards Artificial Intelligence. Minsky (1960).
- ELIZA—a computer program for the study of natural language communication between man and machine. Weizenbaum (1966).
- A Theory of the Learnable. Valiant (1984).
-
A Method for the Construction of Minimum-Redundancy Codes. Huffman (1952).
Information Theory- A Universal Algorithm for Sequential Data Compression. Ziv, Lempel (1977).
- Fifty Years of Shannon Theory. Verdú (1998).
-
Engineering a Sort Function. Bentley, McIlroy (1993).
Data Structures; Algorithms- On the Shortest Spanning Subtree of a Graph and the Traveling Salesman Problem. Kruskal (1956).
- A Note on Two Problems in Connexion with Graphs. Dijkstra (1959).
- Quicksort. Hoare (1962).
- Space/Time Trade-offs in Hash Coding with Allowable Errors. Bloom (1970).
- The Ubiquitous B-Tree. Comer (1979).
- Programming pearls: Algorithm design techniques. Bentley (1984).
- Programming pearls: The back of the envelope. Bentley (1984).
- Making data structures persistent. Driscoll et al (1986).
-
A Design Methodology for Reliable Software Systems. Liskov (1972).
Software Design- On the Criteria To Be Used in Decomposing Systems into Modules. Parnas (1971).
- Information Distribution Aspects of Design Methodology. Parnas (1972).
- Designing Software for Ease of Extension and Contraction. Parnas (1979).
- Programming as Theory Building. Naur (1985).
- Software Aging. Parnas (1994).
- Towards a Theory of Conceptual Design for Software. Jackson (2015).
-
Programming with Abstract Data Types. Liskov, Zilles (1974).
Abstract Data Types; Object-Oriented Programming- The Smalltalk-76 Programming System Design and Implementation. Ingalls (1978).
- A Theory of Type Polymorphism in Programming. Milner (1978).
- On understanding types, data abstraction, and polymorphism. Cardelli, Wegner (1985).
- SELF: The Power of Simplicity. Ungar, Smith (1991).
-
Why Functional Programming Matters. Hughes (1990).
Functional Programming- Recursive Functions of Symbolic Expressions and Their Computation by Machine. McCarthy (1960).
- The Semantics of Predicate Logic as a Programming Language. Van Emden, Kowalski (1976).
- Can Programming Be Liberated from the von Neumann Style? Backus (1978).
- The Semantic Elegance of Applicative Languages. Turner (1981).
- The essence of functional programming. Wadler (1992).
- QuickCheck: A Lightweight Tool for Random Testing of Haskell Programs. Claessen, Hughes (2000).
- Church's Thesis and Functional Programming. Turner (2006).
-
An Incremental Approach to Compiler Construction. Ghuloum (2006).
Language Design; Compilers- The Next 700 Programming Languages. Landin (1966).
- Programming pearls: little languages. Bentley (1986).
- The Essence of Compiling with Continuations. Flanagan et al (1993).
- A Brief History of Just-In-Time. Aycock (2003).
- LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation. Lattner, Adve (2004).
- A Unified Theory of Garbage Collection. Bacon, Cheng, Rajan (2004).
- A Nanopass Framework for Compiler Education. Sarkar, Waddell, Dybvig (2005).
- Bringing the Web up to Speed with WebAssembly. Haas (2017).
-
No Silver Bullet: Essence and Accidents of Software Engineering. Brooks (1987).
Software Engineering; Project Management- How do committees invent? Conway (1968).
- Managing the Development of Large Software Systems. Royce (1970).
- The Mythical Man Month. Brooks (1975).
- On Building Systems That Will Fail. Corbató (1991).
- The Cathedral and the Bazaar. Raymond (1998).
- Out of the Tar Pit. Moseley, Marks (2006).
-
Communicating sequential processes. Hoare (1978).
Concurrency- Solution Of a Problem in Concurrent Program Control. Dijkstra (1965).
- Monitors: An operating system structuring concept. Hoare (1974).
- On the Duality of Operating System Structures. Lauer, Needham (1978).
- Software Transactional Memory. Shavit, Touitou (1997).
-
The UNIX Time- Sharing System. Ritchie, Thompson (1974).
Operating Systems- An Experimental Time-Sharing System. Corbató, Merwin Daggett, Daley (1962).
- The Structure of the "THE"-Multiprogramming System. Dijkstra (1968).
- The nucleus of a multiprogramming system. Hansen (1970).
- Reflections on Trusting Trust. Thompson (1984).
- The Design and Implementation of a Log-Structured File System. Rosenblum, Ousterhout (1991).
-
A Relational Model of Data for Large Shared Data Banks. Codd (1970).
Databases- Granularity of Locks and Degrees of Consistency in a Shared Data Base. Gray et al (1975).
- Access Path Selection in a Relational Database Management System. Selinger et al (1979).
- The Transaction Concept: Virtues and Limitations. Gray (1981).
- The design of POSTGRES. Stonebraker, Rowe (1986).
- Rules of Thumb in Data Engineering. Gray, Shenay (1999).
-
A Protocol for Packet Network Intercommunication. Cerf, Kahn (1974).
Networking- Ethernet: Distributed packet switching for local computer networks. Metcalfe, Boggs (1978).
- End-To-End Arguments in System Design. Saltzer, Reed, Clark (1984).
- An algorithm for distributed computation of a Spanning Tree in an Extended LAN. Perlman (1985).
- The Design Philosophy of the DARPA Internet Protocols. Clark (1988).
- TOR: The second generation onion router. Dingledine et al (2004).
- Why the Internet only just works. Handley (2006).
- The Network is Reliable. Bailis, Kingsbury (2014).
-
New Directions in Cryptography. Diffie, Hellman (1976).
Cryptography- A Method for Obtaining Digital Signatures and Public-Key Cryptosystems. Rivest, Shamir, Adleman (1978).
- How To Share A Secret. Shamir (1979).
- A Digital Signature Based on a Conventional Encryption Function. Merkle (1987).
- The Salsa20 family of stream ciphers. Bernstein (2007).
-
Time, Clocks, and the Ordering of Events in a Distributed System. Lamport (1978).
Distributed Systems- Self-stabilizing systems in spite of distributed control. Dijkstra (1974).
- The Byzantine Generals Problem. Lamport, Shostak, Pease (1982).
- Impossibility of Distributed Consensus With One Faulty Process. Fisher, Lynch, Patterson (1985).
- Implementing Fault-Tolerant Services Using the State Machine Approach: A Tutorial. Schneider (1990).
- Practical Byzantine Fault Tolerance. Castro, Liskov (1999).
- Paxos made simple. Lamport (2001).
- Paxos made live - An Engineering Perspective. Chandra, Griesemer, Redstone (2007).
- In Search of an Understandable Consensus Algorithm. Ongaro, Ousterhout (2014).
-
Designing for Usability: Key Principles and What Designers Think. Gould, Lewis (1985).
Human-Computer Interaction; User Interfaces- As We May Think. Bush (1945).
- Man-Computer symbiosis. Licklider (1958).
- Some Thoughts About the Social Implications of Accessible Computing. David, Fano (1965).
- Tutorials for the First-Time Computer User. Al-Awar, Chapanis, Ford (1981).
- The star user interface: an overview. Smith, Irby, Kimball (1982).
- Design Principles for Human-Computer Interfaces. Norman (1983).
- Human-Computer Interaction: Psychology as a Science of Design. Carroll (1997).
-
The anatomy of a large-scale hypertextual Web search engine. Brin, Page (1998).
Information Retrieval; World-Wide Web- A Statistical Interpretation of Term Specificity in Retrieval. Spärck Jones (1972).
- World-Wide Web: Information Universe. Berners-Lee et al (1992).
- The PageRank Citation Ranking: Bringing Order to the Web. Page, Brin, Motwani (1998).
-
Dynamo, Amazon’s Highly Available Key-value store. DeCandia et al (2007).
Internet Scale Data Systems- The Google File System. Ghemawat, Gobioff, Leung (2003).
- MapReduce: Simplified Data Processing on Large Clusters. Dean, Ghemawat (2004).
- Bigtable: A Distributed Storage System for Structured Data. Chang et al (2006).
- ZooKeeper: wait-free coordination for internet scale systems. Hunt et al (2010).
- The Hadoop Distributed File System. Shvachko et al (2010).
- Kafka: a Distributed Messaging System for Log Processing. Kreps, Narkhede, Rao (2011).
- CAP Twelve Years Later: How the "Rules" Have Changed. Brewer (2012).
- Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases. Verbitski et al (2017).
-
On Designing and Deploying Internet Scale Services. Hamilton (2007).
Operations; Reliability; Fault-tolerance- Ironies of Automation. Bainbridge (1983).
- Why do computers stop and what can be done about it? Gray (1985).
- Recovery Oriented Computing (ROC): Motivation, Definition, Techniques, and Case Studies. Patterson et al (2002).
- Crash-Only Software. Candea, Fox (2003).
- Building on Quicksand. Helland, Campbell (2009).
-
Thinking Methodically about Performance. Gregg (2012).
Performance- Performance Anti-Patterns. Smaalders (2006).
- Thinking Clearly about Performance. Millsap (2010).
-
Bitcoin, A peer-to-peer electronic cash system. Nakamoto (2008).
Crytpocurrencies- Ethereum: A Next-Generation Smart Contract and Decentralized Application Platform. Buterin (2014).
-
A Few Useful Things to Know About Machine Learning. Domingos (2012).
Machine Learning- Statistical Modeling: The Two Cultures. Breiman (2001).
- The Unreasonable Effectiveness of Data. Halevy, Norvig, Pereira (2009).
- ImageNet Classification with Deep Convolutional Neural Networks. Krizhevsky, Sutskever, Hinton (2012).
- Playing Atari with Deep Reinforcement Learning. Mnih et al (2013).
- Generative Adversarial Nets. Goodfellow et al (2014).
- Deep Learning. LeCun, Bengio, Hinton (2015).
- Attention Is All You Need. Vaswani et al (2017).
Top-level papers only
- Von Neumann's First Computer Program. Knuth (1970).
- Computing Machinery and Intelligence. Turing (1950).
- A Method for the Construction of Minimum-Redundancy Codes. Huffman (1952).
- Engineering a Sort Function. Bentley, McIlroy (1993).
- A Design Methodology for Reliable Software Systems. Liskov (1972).
- Programming with Abstract Data Types. Liskov, Zilles (1974).
- Why Functional Programming Matters. Hughes (1990).
- An Incremental Approach to Compiler Construction. Ghuloum (2006).
- No Silver Bullet: Essence and Accidents of Software Engineering. Brooks (1987).
- Communicating sequential processes. Hoare (1978).
- The UNIX Time- Sharing System. Ritchie, Thompson (1974).
- A Relational Model of Data for Large Shared Data Banks. Codd (1970).
- A Protocol for Packet Network Intercommunication. Cerf, Kahn (1974).
- New Directions in Cryptography. Diffie, Hellman (1976).
- Time, Clocks, and the Ordering of Events in a Distributed System. Lamport (1978).
- Designing for Usability: Key Principles and What Designers Think. Gould, Lewis (1985).
- The anatomy of a large-scale hypertextual Web search engine. Brin, Page (1998).
- Dynamo, Amazon’s Highly Available Key-value store. DeCandia et al (2007).
- On Designing and Deploying Internet Scale Services. Hamilton (2007).
- Thinking Methodically about Performance. Gregg (2012).
- Bitcoin, A peer-to-peer electronic cash system. Nakamoto (2008).
- A Few Useful Things to Know About Machine Learning. Domingos (2012).
All papers in chronological order
- As We May Think. Bush (1945).
- Computing Machinery and Intelligence. Turing (1950).
- The Education of a Computer. Hopper (1952).
- A Method for the Construction of Minimum-Redundancy Codes. Huffman (1952).
- On the Shortest Spanning Subtree of a Graph and the Traveling Salesman Problem. Kruskal (1956).
- Man-Computer symbiosis. Licklider (1958).
- A Note on Two Problems in Connexion with Graphs. Dijkstra (1959).
- Recursive Programming. Dijkstra (1960).
- Some Moral and Technical Consequences of Automation. Wiener (1960).
- Steps towards Artificial Intelligence. Minsky (1960).
- Recursive Functions of Symbolic Expressions and Their Computation by Machine. McCarthy (1960).
- Quicksort. Hoare (1962).
- An Experimental Time-Sharing System. Corbató, Merwin Daggett, Daley (1962).
- Programming Considered as a Human Activity. Dijkstra (1965).
- Solution Of a Problem in Concurrent Program Control. Dijkstra (1965).
- Some Thoughts About the Social Implications of Accessible Computing. David, Fano (1965).
- ELIZA—a computer program for the study of natural language communication between man and machine. Weizenbaum (1966).
- The Next 700 Programming Languages. Landin (1966).
- Goto Statement Considered Harmful. Dijkstra (1968).
- How do committees invent? Conway (1968).
- The Structure of the "THE"-Multiprogramming System. Dijkstra (1968).
- Von Neumann's First Computer Program. Knuth (1970).
- Space/Time Trade-offs in Hash Coding with Allowable Errors. Bloom (1970).
- Managing the Development of Large Software Systems. Royce (1970).
- The nucleus of a multiprogramming system. Hansen (1970).
- A Relational Model of Data for Large Shared Data Banks. Codd (1970).
- Program development by stepwise refinement. Wirth (1971).
- On the Criteria To Be Used in Decomposing Systems into Modules. Parnas (1971).
- The Humble Programmer. Dijkstra (1972).
- A Design Methodology for Reliable Software Systems. Liskov (1972).
- Information Distribution Aspects of Design Methodology. Parnas (1972).
- A Statistical Interpretation of Term Specificity in Retrieval. Spärck Jones (1972).
- Computer Programming as an Art. Knuth (1974).
- Programming with Abstract Data Types. Liskov, Zilles (1974).
- Monitors: An operating system structuring concept. Hoare (1974).
- The UNIX Time- Sharing System. Ritchie, Thompson (1974).
- A Protocol for Packet Network Intercommunication. Cerf, Kahn (1974).
- Self-stabilizing systems in spite of distributed control. Dijkstra (1974).
- The Mythical Man Month. Brooks (1975).
- Granularity of Locks and Degrees of Consistency in a Shared Data Base. Gray et al (1975).
- The Semantics of Predicate Logic as a Programming Language. Van Emden, Kowalski (1976).
- New Directions in Cryptography. Diffie, Hellman (1976).
- A Universal Algorithm for Sequential Data Compression. Ziv, Lempel (1977).
- The Smalltalk-76 Programming System Design and Implementation. Ingalls (1978).
- A Theory of Type Polymorphism in Programming. Milner (1978).
- Can Programming Be Liberated from the von Neumann Style? Backus (1978).
- Communicating sequential processes. Hoare (1978).
- On the Duality of Operating System Structures. Lauer, Needham (1978).
- Ethernet: Distributed packet switching for local computer networks. Metcalfe, Boggs (1978).
- A Method for Obtaining Digital Signatures and Public-Key Cryptosystems. Rivest, Shamir, Adleman (1978).
- Time, Clocks, and the Ordering of Events in a Distributed System. Lamport (1978).
- The paradigms of programming. Floyd (1979).
- The Ubiquitous B-Tree. Comer (1979).
- Designing Software for Ease of Extension and Contraction. Parnas (1979).
- Access Path Selection in a Relational Database Management System. Selinger et al (1979).
- How To Share A Secret. Shamir (1979).
- The Semantic Elegance of Applicative Languages. Turner (1981).
- The Transaction Concept: Virtues and Limitations. Gray (1981).
- Tutorials for the First-Time Computer User. Al-Awar, Chapanis, Ford (1981).
- The Byzantine Generals Problem. Lamport, Shostak, Pease (1982).
- The star user interface: an overview. Smith, Irby, Kimball (1982).
- Design Principles for Human-Computer Interfaces. Norman (1983).
- Ironies of Automation. Bainbridge (1983).
- Literate Programming. Knuth (1984).
- A Theory of the Learnable. Valiant (1984).
- Programming pearls: Algorithm design techniques. Bentley (1984).
- Programming pearls: The back of the envelope. Bentley (1984).
- Reflections on Trusting Trust. Thompson (1984).
- End-To-End Arguments in System Design. Saltzer, Reed, Clark (1984).
- Programming as Theory Building. Naur (1985).
- On understanding types, data abstraction, and polymorphism. Cardelli, Wegner (1985).
- An algorithm for distributed computation of a Spanning Tree in an Extended LAN. Perlman (1985).
- Impossibility of Distributed Consensus With One Faulty Process. Fisher, Lynch, Patterson (1985).
- Designing for Usability: Key Principles and What Designers Think. Gould, Lewis (1985).
- Why do computers stop and what can be done about it? Gray (1985).
- Making data structures persistent. Driscoll et al (1986).
- Programming pearls: little languages. Bentley (1986).
- The design of POSTGRES. Stonebraker, Rowe (1986).
- No Silver Bullet: Essence and Accidents of Software Engineering. Brooks (1987).
- A Digital Signature Based on a Conventional Encryption Function. Merkle (1987).
- The Design Philosophy of the DARPA Internet Protocols. Clark (1988).
- Why Functional Programming Matters. Hughes (1990).
- Implementing Fault-Tolerant Services Using the State Machine Approach: A Tutorial. Schneider (1990).
- SELF: The Power of Simplicity. Ungar, Smith (1991).
- On Building Systems That Will Fail. Corbató (1991).
- The Design and Implementation of a Log-Structured File System. Rosenblum, Ousterhout (1991).
- The essence of functional programming. Wadler (1992).
- World-Wide Web: Information Universe. Berners-Lee et al (1992).
- Engineering a Sort Function. Bentley, McIlroy (1993).
- The Essence of Compiling with Continuations. Flanagan et al (1993).
- Software Aging. Parnas (1994).
- Software Transactional Memory. Shavit, Touitou (1997).
- Human-Computer Interaction: Psychology as a Science of Design. Carroll (1997).
- Fifty Years of Shannon Theory. Verdú (1998).
- The Cathedral and the Bazaar. Raymond (1998).
- The anatomy of a large-scale hypertextual Web search engine. Brin, Page (1998).
- The PageRank Citation Ranking: Bringing Order to the Web. Page, Brin, Motwani (1998).
- Rules of Thumb in Data Engineering. Gray, Shenay (1999).
- Practical Byzantine Fault Tolerance. Castro, Liskov (1999).
- QuickCheck: A Lightweight Tool for Random Testing of Haskell Programs. Claessen, Hughes (2000).
- Paxos made simple. Lamport (2001).
- Statistical Modeling: The Two Cultures. Breiman (2001).
- Recovery Oriented Computing (ROC): Motivation, Definition, Techniques, and Case Studies. Patterson et al (2002).
- A Brief History of Just-In-Time. Aycock (2003).
- The Google File System. Ghemawat, Gobioff, Leung (2003).
- Crash-Only Software. Candea, Fox (2003).
- LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation. Lattner, Adve (2004).
- A Unified Theory of Garbage Collection. Bacon, Cheng, Rajan (2004).
- TOR: The second generation onion router. Dingledine et al (2004).
- MapReduce: Simplified Data Processing on Large Clusters. Dean, Ghemawat (2004).
- A Nanopass Framework for Compiler Education. Sarkar, Waddell, Dybvig (2005).
- Church's Thesis and Functional Programming. Turner (2006).
- An Incremental Approach to Compiler Construction. Ghuloum (2006).
- Out of the Tar Pit. Moseley, Marks (2006).
- Why the Internet only just works. Handley (2006).
- Bigtable: A Distributed Storage System for Structured Data. Chang et al (2006).
- Performance Anti-Patterns. Smaalders (2006).
- The Salsa20 family of stream ciphers. Bernstein (2007).
- Paxos made live - An Engineering Perspective. Chandra, Griesemer, Redstone (2007).
- Dynamo, Amazon’s Highly Available Key-value store. DeCandia et al (2007).
- On Designing and Deploying Internet Scale Services. Hamilton (2007).
- Bitcoin, A peer-to-peer electronic cash system. Nakamoto (2008).
- Building on Quicksand. Helland, Campbell (2009).
- The Unreasonable Effectiveness of Data. Halevy, Norvig, Pereira (2009).
- ZooKeeper: wait-free coordination for internet scale systems. Hunt et al (2010).
- The Hadoop Distributed File System. Shvachko et al (2010).
- Thinking Clearly about Performance. Millsap (2010).
- Kafka: a Distributed Messaging System for Log Processing. Kreps, Narkhede, Rao (2011).
- CAP Twelve Years Later: How the "Rules" Have Changed. Brewer (2012).
- Thinking Methodically about Performance. Gregg (2012).
- A Few Useful Things to Know About Machine Learning. Domingos (2012).
- ImageNet Classification with Deep Convolutional Neural Networks. Krizhevsky, Sutskever, Hinton (2012).
- Playing Atari with Deep Reinforcement Learning. Mnih et al (2013).
- The Network is Reliable. Bailis, Kingsbury (2014).
- In Search of an Understandable Consensus Algorithm. Ongaro, Ousterhout (2014).
- Ethereum: A Next-Generation Smart Contract and Decentralized Application Platform. Buterin (2014).
- Generative Adversarial Nets. Goodfellow et al (2014).
- Towards a Theory of Conceptual Design for Software. Jackson (2015).
- Deep Learning. LeCun, Bengio, Hinton (2015).
- Bringing the Web up to Speed with WebAssembly. Haas (2017).
- Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases. Verbitski et al (2017).
- Attention Is All You Need. Vaswani et al (2017).
Sources
This list was inspired by (and draws from) several books and paper collections:
- Papers We Love
- Ideas That Created the Future
- The Innovators
- The morning paper
- Distributed systems for fun and profit
- Readings in Database Systems (the Red Book)
- Fermat's Library
- Classics in Human-Computer Interaction
- Awesome Compilers
- Distributed Consensus Reading List
- The Decade of Deep Learning
Meta reads
A few interesting resources about reading papers from Papers We Love and elsewhere:
- Should I read papers?
- How to Read an Academic Article
- How to Read a Paper. Keshav (2007).
- Efficient Reading of Papers in Science and Technology. Hanson (1999).
- On ICSE’s “Most Influential Papers”. Parnas (1995).
Selection criteria
- The list should stay short. Let's say no more than 30 papers.
- The idea is not to include every interesting paper that I come across but rather to keep a representative list that's possible to read from start to finish with a similar level of effort as reading a technical book from cover to cover.
- I tried to include one paper per each major topic and author. Since in the process I found a lot of noteworthy alternatives, related or follow-up papers and I wanted to keep track of those as well, I included them as sublist items.
- The papers shouldn't be too long. For the same reasons as the previous item, I try to avoid papers longer than 20 or 30 pages.
- They should be self-contained and readable enough to be approachable by the casual technical reader.
- They should be freely available online.
- Although historical relevance was taken into account, I omitted seminal papers in the cases where I found them hard to approach, when the main subject of the paper wasn't the thing that made them influential, etc.
- Examples of this are classic works by Von Neumann, Turing and Shannon.
- That being said, where possible I preferred the original paper on each subject over modern updates or survey papers.
- I tended to prefer topics that I can relate to my professional practice, typically papers originated in the industry
or about innovations that later saw wide adoption.
- Similarly, I tended to skip more theoretical papers, those focusing on mathematical foundations for Computer Science, electronic aspects of hardware, etc.
- I sorted the list by a mix of relatedness of topics and a vague chronological relevance, such that it makes sense to read it in the suggested order. For example, historical and seminal topics go first, contemporary internet-era developments last, networking precedes distributed systems, etc.