Home

Awesome

Papers for Software Engineers workflow

A curated list of papers that may be of interest to Software Engineering students or professionals. See the sources and selection criteria below.

<br/> <details open> <summary>List of papers by topic</summary> <br/>
  1. Von Neumann's First Computer Program. Knuth (1970).
    <sub>Computer History; Early Programming</sub>

  2. Computing Machinery and Intelligence. Turing (1950).
    <sub>Early Artificial Intelligence</sub>

    • 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).
  3. A Method for the Construction of Minimum-Redundancy Codes. Huffman (1952).
    <sub>Information Theory</sub>

  4. Engineering a Sort Function. Bentley, McIlroy (1993).
    <sub>Data Structures; Algorithms</sub>

  5. A Design Methodology for Reliable Software Systems. Liskov (1972).
    <sub>Software Design</sub>

  6. Programming with Abstract Data Types. Liskov, Zilles (1974).
    <sub>Abstract Data Types; Object-Oriented Programming</sub>

  7. Why Functional Programming Matters. Hughes (1990).
    <sub>Functional Programming</sub>

  8. An Incremental Approach to Compiler Construction. Ghuloum (2006).
    <sub>Language Design; Compilers</sub>

  9. No Silver Bullet: Essence and Accidents of Software Engineering. Brooks (1987).
    <sub>Software Engineering; Project Management</sub>

  10. Communicating sequential processes. Hoare (1978).
    <sub>Concurrency</sub>

  11. The UNIX Time- Sharing System. Ritchie, Thompson (1974).
    <sub>Operating Systems</sub>

  12. A Relational Model of Data for Large Shared Data Banks. Codd (1970).
    <sub>Databases</sub>

  13. A Protocol for Packet Network Intercommunication. Cerf, Kahn (1974).
    <sub>Networking</sub>

  14. New Directions in Cryptography. Diffie, Hellman (1976).
    <sub>Cryptography</sub>

  15. Time, Clocks, and the Ordering of Events in a Distributed System. Lamport (1978).
    <sub>Distributed Systems</sub>

  16. Designing for Usability: Key Principles and What Designers Think. Gould, Lewis (1985).
    <sub>Human-Computer Interaction; User Interfaces</sub>

  17. The anatomy of a large-scale hypertextual Web search engine. Brin, Page (1998).
    <sub>Information Retrieval; World-Wide Web</sub>

  18. Dynamo, Amazon’s Highly Available Key-value store. DeCandia et al (2007).
    <sub>Internet Scale Data Systems</sub>

  19. On Designing and Deploying Internet Scale Services. Hamilton (2007).
    <sub>Operations; Reliability; Fault-tolerance</sub>

  20. Thinking Methodically about Performance. Gregg (2012).
    <sub>Performance</sub>

  21. Bitcoin, A peer-to-peer electronic cash system. Nakamoto (2008).
    <sub>Decentralized Distributed Systems; Peer-to-peer systems</sub>

  22. A Few Useful Things to Know About Machine Learning. Domingos (2012).
    <sub>Machine Learning</sub>

</details> <br/> <details> <summary>Top-level papers only</summary> <br/>
  1. Von Neumann's First Computer Program. Knuth (1970).
  2. Computing Machinery and Intelligence. Turing (1950).
  3. A Method for the Construction of Minimum-Redundancy Codes. Huffman (1952).
  4. Engineering a Sort Function. Bentley, McIlroy (1993).
  5. A Design Methodology for Reliable Software Systems. Liskov (1972).
  6. Programming with Abstract Data Types. Liskov, Zilles (1974).
  7. Why Functional Programming Matters. Hughes (1990).
  8. An Incremental Approach to Compiler Construction. Ghuloum (2006).
  9. No Silver Bullet: Essence and Accidents of Software Engineering. Brooks (1987).
  10. Communicating sequential processes. Hoare (1978).
  11. The UNIX Time- Sharing System. Ritchie, Thompson (1974).
  12. A Relational Model of Data for Large Shared Data Banks. Codd (1970).
  13. A Protocol for Packet Network Intercommunication. Cerf, Kahn (1974).
  14. New Directions in Cryptography. Diffie, Hellman (1976).
  15. Time, Clocks, and the Ordering of Events in a Distributed System. Lamport (1978).
  16. Designing for Usability: Key Principles and What Designers Think. Gould, Lewis (1985).
  17. The anatomy of a large-scale hypertextual Web search engine. Brin, Page (1998).
  18. Dynamo, Amazon’s Highly Available Key-value store. DeCandia et al (2007).
  19. On Designing and Deploying Internet Scale Services. Hamilton (2007).
  20. Thinking Methodically about Performance. Gregg (2012).
  21. Bitcoin, A peer-to-peer electronic cash system. Nakamoto (2008).
  22. A Few Useful Things to Know About Machine Learning. Domingos (2012).
</details> <br/> <details> <summary>All papers in chronological order </summary> <br/>
  1. As We May Think. Bush (1945).
  2. Computing Machinery and Intelligence. Turing (1950).
  3. The Education of a Computer. Hopper (1952).
  4. A Method for the Construction of Minimum-Redundancy Codes. Huffman (1952).
  5. On the Shortest Spanning Subtree of a Graph and the Traveling Salesman Problem. Kruskal (1956).
  6. Man-Computer symbiosis. Licklider (1958).
  7. A Note on Two Problems in Connexion with Graphs. Dijkstra (1959).
  8. Recursive Programming. Dijkstra (1960).
  9. Some Moral and Technical Consequences of Automation. Wiener (1960).
  10. Steps towards Artificial Intelligence. Minsky (1960).
  11. Recursive Functions of Symbolic Expressions and Their Computation by Machine. McCarthy (1960).
  12. Quicksort. Hoare (1962).
  13. An Experimental Time-Sharing System. Corbató, Merwin Daggett, Daley (1962).
  14. Programming Considered as a Human Activity. Dijkstra (1965).
  15. Solution Of a Problem in Concurrent Program Control. Dijkstra (1965).
  16. Some Thoughts About the Social Implications of Accessible Computing. David, Fano (1965).
  17. ELIZA—a computer program for the study of natural language communication between man and machine. Weizenbaum (1966).
  18. The Next 700 Programming Languages. Landin (1966).
  19. Goto Statement Considered Harmful. Dijkstra (1968).
  20. How do committees invent? Conway (1968).
  21. The Structure of the "THE"-Multiprogramming System. Dijkstra (1968).
  22. Von Neumann's First Computer Program. Knuth (1970).
  23. Space/Time Trade-offs in Hash Coding with Allowable Errors. Bloom (1970).
  24. Managing the Development of Large Software Systems. Royce (1970).
  25. The nucleus of a multiprogramming system. Hansen (1970).
  26. A Relational Model of Data for Large Shared Data Banks. Codd (1970).
  27. Program development by stepwise refinement. Wirth (1971).
  28. On the Criteria To Be Used in Decomposing Systems into Modules. Parnas (1971).
  29. The Humble Programmer. Dijkstra (1972).
  30. A Design Methodology for Reliable Software Systems. Liskov (1972).
  31. Information Distribution Aspects of Design Methodology. Parnas (1972).
  32. A Statistical Interpretation of Term Specificity in Retrieval. Spärck Jones (1972).
  33. Computer Programming as an Art. Knuth (1974).
  34. Programming with Abstract Data Types. Liskov, Zilles (1974).
  35. Monitors: An operating system structuring concept. Hoare (1974).
  36. The UNIX Time- Sharing System. Ritchie, Thompson (1974).
  37. A Protocol for Packet Network Intercommunication. Cerf, Kahn (1974).
  38. Self-stabilizing systems in spite of distributed control. Dijkstra (1974).
  39. The Mythical Man Month. Brooks (1975).
  40. Granularity of Locks and Degrees of Consistency in a Shared Data Base. Gray et al (1975).
  41. The Semantics of Predicate Logic as a Programming Language. Van Emden, Kowalski (1976).
  42. New Directions in Cryptography. Diffie, Hellman (1976).
  43. A Universal Algorithm for Sequential Data Compression. Ziv, Lempel (1977).
  44. The Smalltalk-76 Programming System Design and Implementation. Ingalls (1978).
  45. A Theory of Type Polymorphism in Programming. Milner (1978).
  46. Can Programming Be Liberated from the von Neumann Style? Backus (1978).
  47. Communicating sequential processes. Hoare (1978).
  48. On the Duality of Operating System Structures. Lauer, Needham (1978).
  49. Ethernet: Distributed packet switching for local computer networks. Metcalfe, Boggs (1978).
  50. A Method for Obtaining Digital Signatures and Public-Key Cryptosystems. Rivest, Shamir, Adleman (1978).
  51. Time, Clocks, and the Ordering of Events in a Distributed System. Lamport (1978).
  52. The paradigms of programming. Floyd (1979).
  53. The Ubiquitous B-Tree. Comer (1979).
  54. Designing Software for Ease of Extension and Contraction. Parnas (1979).
  55. Access Path Selection in a Relational Database Management System. Selinger et al (1979).
  56. How To Share A Secret. Shamir (1979).
  57. The Semantic Elegance of Applicative Languages. Turner (1981).
  58. The Transaction Concept: Virtues and Limitations. Gray (1981).
  59. Tutorials for the First-Time Computer User. Al-Awar, Chapanis, Ford (1981).
  60. The Byzantine Generals Problem. Lamport, Shostak, Pease (1982).
  61. The star user interface: an overview. Smith, Irby, Kimball (1982).
  62. Design Principles for Human-Computer Interfaces. Norman (1983).
  63. Ironies of Automation. Bainbridge (1983).
  64. Literate Programming. Knuth (1984).
  65. A Theory of the Learnable. Valiant (1984).
  66. Programming pearls: Algorithm design techniques. Bentley (1984).
  67. Programming pearls: The back of the envelope. Bentley (1984).
  68. Reflections on Trusting Trust. Thompson (1984).
  69. End-To-End Arguments in System Design. Saltzer, Reed, Clark (1984).
  70. Programming as Theory Building. Naur (1985).
  71. On understanding types, data abstraction, and polymorphism. Cardelli, Wegner (1985).
  72. An algorithm for distributed computation of a Spanning Tree in an Extended LAN. Perlman (1985).
  73. Impossibility of Distributed Consensus With One Faulty Process. Fisher, Lynch, Patterson (1985).
  74. Designing for Usability: Key Principles and What Designers Think. Gould, Lewis (1985).
  75. Why do computers stop and what can be done about it? Gray (1985).
  76. Making data structures persistent. Driscoll et al (1986).
  77. Programming pearls: little languages. Bentley (1986).
  78. The design of POSTGRES. Stonebraker, Rowe (1986).
  79. No Silver Bullet: Essence and Accidents of Software Engineering. Brooks (1987).
  80. A Digital Signature Based on a Conventional Encryption Function. Merkle (1987).
  81. The Design Philosophy of the DARPA Internet Protocols. Clark (1988).
  82. Why Functional Programming Matters. Hughes (1990).
  83. Implementing Fault-Tolerant Services Using the State Machine Approach: A Tutorial. Schneider (1990).
  84. SELF: The Power of Simplicity. Ungar, Smith (1991).
  85. On Building Systems That Will Fail. Corbató (1991).
  86. The Design and Implementation of a Log-Structured File System. Rosenblum, Ousterhout (1991).
  87. The essence of functional programming. Wadler (1992).
  88. World-Wide Web: Information Universe. Berners-Lee et al (1992).
  89. Engineering a Sort Function. Bentley, McIlroy (1993).
  90. The Essence of Compiling with Continuations. Flanagan et al (1993).
  91. Software Aging. Parnas (1994).
  92. Software Transactional Memory. Shavit, Touitou (1997).
  93. Human-Computer Interaction: Psychology as a Science of Design. Carroll (1997).
  94. Fifty Years of Shannon Theory. Verdú (1998).
  95. The Cathedral and the Bazaar. Raymond (1998).
  96. The anatomy of a large-scale hypertextual Web search engine. Brin, Page (1998).
  97. The PageRank Citation Ranking: Bringing Order to the Web. Page, Brin, Motwani (1998).
  98. Operational transformation in real-time group editors: issues, algorithms, and achievements. Sun, Ellis (1998).
  99. Rules of Thumb in Data Engineering. Gray, Shenay (1999).
  100. Practical Byzantine Fault Tolerance. Castro, Liskov (1999).
  101. QuickCheck: A Lightweight Tool for Random Testing of Haskell Programs. Claessen, Hughes (2000).
  102. Paxos made simple. Lamport (2001).
  103. Statistical Modeling: The Two Cultures. Breiman (2001).
  104. Recovery Oriented Computing (ROC): Motivation, Definition, Techniques, and Case Studies. Patterson et al (2002).
  105. Kademlia: A Peer-to-Peer Information System Based on the XOR Metric. Maymounkov, Mazières (2002).
  106. A Brief History of Just-In-Time. Aycock (2003).
  107. The Google File System. Ghemawat, Gobioff, Leung (2003).
  108. Crash-Only Software. Candea, Fox (2003).
  109. Incentives Build Robustness in BitTorrent. Cohen (2003).
  110. LLVM: A Compilation Framework for Lifelong Program Analysis & Transformation. Lattner, Adve (2004).
  111. A Unified Theory of Garbage Collection. Bacon, Cheng, Rajan (2004).
  112. TOR: The second generation onion router. Dingledine et al (2004).
  113. MapReduce: Simplified Data Processing on Large Clusters. Dean, Ghemawat (2004).
  114. A Nanopass Framework for Compiler Education. Sarkar, Waddell, Dybvig (2005).
  115. Church's Thesis and Functional Programming. Turner (2006).
  116. An Incremental Approach to Compiler Construction. Ghuloum (2006).
  117. Out of the Tar Pit. Moseley, Marks (2006).
  118. Why the Internet only just works. Handley (2006).
  119. Bigtable: A Distributed Storage System for Structured Data. Chang et al (2006).
  120. Performance Anti-Patterns. Smaalders (2006).
  121. The Salsa20 family of stream ciphers. Bernstein (2007).
  122. Paxos made live - An Engineering Perspective. Chandra, Griesemer, Redstone (2007).
  123. Dynamo, Amazon’s Highly Available Key-value store. DeCandia et al (2007).
  124. On Designing and Deploying Internet Scale Services. Hamilton (2007).
  125. Bitcoin, A peer-to-peer electronic cash system. Nakamoto (2008).
  126. Building on Quicksand. Helland, Campbell (2009).
  127. The Unreasonable Effectiveness of Data. Halevy, Norvig, Pereira (2009).
  128. ZooKeeper: wait-free coordination for internet scale systems. Hunt et al (2010).
  129. The Hadoop Distributed File System. Shvachko et al (2010).
  130. Thinking Clearly about Performance. Millsap (2010).
  131. Kafka: a Distributed Messaging System for Log Processing. Kreps, Narkhede, Rao (2011).
  132. Conflict-free Replicated Data Types. Shapiro et al (2011).
  133. CAP Twelve Years Later: How the "Rules" Have Changed. Brewer (2012).
  134. Thinking Methodically about Performance. Gregg (2012).
  135. A Few Useful Things to Know About Machine Learning. Domingos (2012).
  136. ImageNet Classification with Deep Convolutional Neural Networks. Krizhevsky, Sutskever, Hinton (2012).
  137. Playing Atari with Deep Reinforcement Learning. Mnih et al (2013).
  138. The Network is Reliable. Bailis, Kingsbury (2014).
  139. In Search of an Understandable Consensus Algorithm. Ongaro, Ousterhout (2014).
  140. IPFS - Content Addressed, Versioned, P2P File System. Benet (2014).
  141. Ethereum: A Next-Generation Smart Contract and Decentralized Application Platform. Buterin (2014).
  142. Generative Adversarial Nets. Goodfellow et al (2014).
  143. Towards a Theory of Conceptual Design for Software. Jackson (2015).
  144. Deep Learning. LeCun, Bengio, Hinton (2015).
  145. Bringing the Web up to Speed with WebAssembly. Haas (2017).
  146. Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases. Verbitski et al (2017).
  147. Attention Is All You Need. Vaswani et al (2017).
  148. Local-First Software: You Own Your Data, in spite of the Cloud. Kleppmann et al (2019).
</details>

Sources

This list was inspired by (and draws from) several books and paper collections:

Meta reads

A few interesting resources about reading papers from Papers We Love and elsewhere:

Selection criteria

  1. 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.
  2. 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.
  3. They should be self-contained and readable enough to be approachable by the casual technical reader.
  4. They should be freely available online.
  5. 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.
  6. 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.
  7. 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.