Back to index

Coders at Work

Authors: Peter Seibel

Overview

In “Coders at Work”, I set out to explore the world of programming through the eyes of fifteen highly accomplished practitioners. These individuals represent a diverse range of experiences and perspectives within the field, from systems hackers who built the foundations of the internet to language designers who shaped the way we write code today. I wanted to get at the heart of what it means to be a programmer, to understand the challenges they face and the techniques they use to overcome them. I asked them about their learning journeys, their design philosophies, their approaches to debugging, their thoughts on the future of programming, and much more. What emerged from these conversations is a rich tapestry of insights into the craft of programming. While there is no one “right” way to program, there are recurring themes that resonate throughout the book. Almost everyone stressed the importance of writing clear, readable code; many have grappled with the complexities of concurrency; and nobody believes that programming is a solved problem. There is a persistent desire to find better ways to write software, whether through new tools, techniques, or languages. I also explored the relationship between academic computer science and industrial practice, finding both synergy and tension between these worlds. While academic research often pushes the boundaries of what’s possible, it can sometimes feel divorced from the practical concerns of shipping real-world software. Conversely, the pressure to deliver products can lead to neglecting foundational principles that could ultimately lead to better solutions. I hope that “Coders at Work” offers valuable insights for programmers at all levels of experience. By sharing the stories and wisdom of these accomplished individuals, I aim to shed light on the challenges and rewards of this fascinating field, offering a glimpse into the minds of those who shape the digital world we live in.

Book Outline

1. Jamie Zawinski

Jamie Zawinski’s introduction to programming was a trial by fire, starting with Lisp in an AI lab at age 15. He learned by doing, surrounded by more experienced programmers, and developed a habit of digging into code to understand how it works. He emphasizes the importance of writing code you can understand later, an area where he admits he initially struggled.

Key concept: “Ptthh, wrong!”

2. Brad Fitzpatrick

Early experiences with commercial web development instilled in Brad Fitzpatrick the importance of both deadlines and scalability. He emphasizes learning by reading other people’s code, starting with small, achievable changes before tackling larger tasks. He also highlights the value of testing and the necessity of designing for future migrations when dealing with data that may not always fit into one database.

Key concept: “We’re absolutely 100 percent committed to quality. We’re going to ship the highest-quality product we can on March 31st.”

3. Douglas Crockford

Douglas Crockford, creator of JSON, champions simplicity and readability in code. He advocates for subsetting languages, using only the best parts and avoiding those that add little value. He stresses the importance of code reading as a team activity to identify problems and learn from each other’s code.

Key concept: “The subset idea is really important, especially for JavaScript because it contains so many bad features. But it’s true for all languages.”

4. Brendan Eich

Brendan Eich, the creator of JavaScript, believes that programming language performance and tooling will allow higher-level programmers to work closer to the metal. He advocates for a hybrid type system and static analysis to catch errors without sacrificing the rapid prototyping benefits of dynamic languages. He highlights the need for better debugging tools and criticizes the separation between academic computer science research and industrial practice.

Key concept: “You don’t want to be a programmer associated with that sort of thing.”

5. Joshua Bloch

Joshua Bloch, author of Effective Java, emphasizes API design as a core programming skill. He advocates for writing client code that uses an API before writing the code that implements it, ensuring the API is usable and meets the use cases. He also believes in writing clean, readable code and using the right tools for the job provided by each language.

Key concept: “The fundamental theorem of API design is, when in doubt, leave it out.”

6. Joe Armstrong

Joe Armstrong, creator of Erlang, sees programming as a process of understanding rather than just typing code. He stresses the importance of thinking through a problem thoroughly before writing code, using diagrams and discussions with colleagues to solidify the design before implementation. He also criticizes the overabundance of choice and the reliance on black boxes in modern software development.

Key concept: “Programming is about understanding.”

7. Simon Peyton Jones

Simon Peyton Jones, one of the creators of Haskell, highlights the value of laziness in functional programming, both for modularity and for enabling powerful programming idioms like generators. He advocates for using type systems and partial specifications, checked either statically or dynamically, to increase confidence in program correctness. He also favors Software Transactional Memory (STM) over traditional locks and condition variables for managing concurrent programs.

Key concept: “Avoid success at all costs.”

8. Peter Norvig

Peter Norvig, Director of Research at Google, underscores the importance of knowing the right algorithms and understanding their trade-offs. He believes that clear system design documentation is crucial for larger projects, and that prototypes are valuable for exploring potential solutions and identifying areas where deeper understanding is needed. He also notes the increasing role of assembling existing components rather than writing everything from scratch in modern software development.

Key concept: “It’s also important to know what you’re doing.”

9. Guy Steele

Guy Steele, co-creator of Scheme and Common Lisp, emphasizes the importance of code readability, even prioritizing it over performance. He advocates for consistent code presentation, meaningful variable names, and clear program organization. He highlights the value of reading well-written code to learn from other programmers and advocates for “literate programming,” where code is written in an order designed for human understanding, interspersed with prose explanations.

Key concept: “Readability of code is now my first priority.”

10. Dan Ingalls

Dan Ingalls, a key figure in Smalltalk’s development, values interactive programming environments and rapid prototyping. He believes in building dynamic, changeable systems and adding constraints later rather than starting with rigid systems. He also discusses the importance of understanding the core concepts of a domain, like the relationship between screen pixels and their representation in memory, to enable effective programming.

Key concept: “You ‘breadboard’ it — you just do what you need to do to put a structure in place that’s the structure you think you’re going to want to interpret and then try to make it work.”

11. L Peter Deutsch

L Peter Deutsch, creator of Ghostscript, sees managing detail as a fundamental challenge in software development. He advocates for carefully designing interfaces and separating concerns to manage complexity. Deutsch also argues for treating software as a capital asset, requiring ongoing investment and maintenance, rather than as an immediate expense.

Key concept: “Software is a discipline of detail.”

12. Ken Thompson

Ken Thompson, inventor of Unix, emphasizes simplicity in software design, prioritizing clear algorithms and avoiding unnecessary complexity. He advocates for rewriting code when it becomes difficult to work with, even if it means discarding existing code. He expresses skepticism about modern programming practices that rely on layers of abstraction.

Key concept: “Modern programming scares me in many respects, where they will just build layer after layer after layer that does nothing except translate.”

13. Fran Allen

Fran Allen, a pioneer in optimizing compilers, believes that programming languages should focus on expressing high-level intent and leave low-level optimizations to the compiler. She criticizes the C programming language for hindering advancements in compiler technology and for its negative impact on the study of computer science.

Key concept: “C has destroyed our ability to advance the state of the art in automatic optimization, automatic parallelization, automatic mapping of a high-level language to the machine.”

14. Bernie Cosell

Bernie Cosell, one of the programmers of the original ARPANET IMPs, emphasizes the importance of writing clear, readable code that requires minimal commenting. He believes in rewriting convoluted code rather than patching it and highlights the value of design reviews with experienced engineers to identify potential problems early on. He also argues that programming languages should aid understanding by providing clear and intuitive syntax.

Key concept: “This code sorts the table”

15. Donald Knuth

Donald Knuth, author of The Art of Computer Programming, champions “literate programming,” a method of writing code designed for human understanding, interspersed with prose explanations. He believes in writing code bottom-up, focusing on units that correspond to natural thought processes, and emphasizes the importance of understanding existing algorithms and data structures before creating new ones.

Key concept: “So literate programming is based on this idea that the best way to communicate is to say things both informally and formally that are related.”

Essential Questions

1. How do these expert programmers approach understanding a large, unfamiliar codebase?

Throughout the book, each programmer discusses their preferred methods for navigating unfamiliar codebases. Some, like Zawinski, advocate for an immersive approach, diving into specific tasks or gutting existing modules to understand the structure. Others, like Bloch, prefer a more structured top-down approach, seeking high-level overviews before delving into individual modules. Common to all approaches is the emphasis on active engagement, utilizing tools like debuggers and profilers to gain a deeper understanding of the code’s behavior and underlying structure. The interviews highlight the importance of adapting one’s approach based on the size, complexity, and context of the codebase.

2. To what extent do these programmers rely on formal methods for ensuring code correctness?

The programmers interviewed offer diverse perspectives on the role of formal methods like assertions, invariants, and proofs in ensuring code correctness. While some, like Bloch, advocate for integrating assertions into the code itself to catch potential errors early, others, like Thompson, rely more on intuition and a deep understanding of the code’s behavior. This reflects a broader tension in the field between advocating for rigorous formal verification versus relying on more practical, experience-driven approaches. There’s a general consensus that perfect correctness is often elusive, and that increasing confidence in the code’s behavior, through a combination of techniques, is a more realistic goal.

3. How do these programmers approach the design of software? Do they prefer a top-down or bottom-up approach?

The role of design in programming is a recurring theme. Some, like Bloch, advocate for a structured API design process involving use cases and skeletal APIs that are iteratively refined. Others, like Thompson, lean more on intuition and experience, allowing the design to emerge organically as they work on the code. Common to both approaches is the emphasis on understanding the problem deeply and choosing the right level of abstraction to manage complexity. The book highlights the need for careful consideration of how the design will impact maintainability, readability, and future evolution of the software, especially in large-scale projects.

4. How do these programmers prefer to work with others? What are their thoughts on code ownership and collaborative coding practices like pair programming?

This question delves into the human aspect of software development and how individual working styles impact collaboration. The interviewees offer diverse perspectives, ranging from buddy programming (Zawinski and Weissman) to more independent work with code reviews (Norvig). Some, like Fitzpatrick, highlight the challenges of managing programmers with differing levels of experience and varying degrees of adherence to coding standards. The book ultimately suggests that successful collaboration requires a balance between individual freedom and shared understanding, facilitated through effective communication and a shared commitment to the project’s goals.

5. What are these programmers’ perspectives on the future of programming? What challenges and opportunities do they foresee?

This question explores the programmers’ perspectives on the future of their field in the context of rapidly evolving technology and shifting demands. Some, like Armstrong, express concern about the growing complexity of software systems and the increasing reliance on black boxes. Others, like Eich, see opportunities for new languages and tools to empower programmers to tackle increasingly complex tasks. There’s a general sentiment that the field will continue to evolve rapidly, requiring programmers to constantly adapt and learn new technologies while maintaining a strong understanding of core principles.

Key Takeaways

1. Embrace Rewriting When Necessary

Programmers should avoid clinging to existing code solely due to familiarity. While there’s value in understanding and maintaining existing systems, there are also benefits to exploring new approaches and rewriting code when it becomes difficult to work with or when a more efficient or scalable solution emerges.

Practical Application:

For AI product engineers, this translates to choosing the right algorithms and data structures for the task at hand, understanding their trade-offs, and being willing to adapt or rewrite code if a more efficient or scalable solution emerges.

2. Prioritize Code Readability

Code readability is crucial, especially for large or long-lived projects. Writing code that is easy to understand for both yourself and others increases maintainability, reduces the risk of errors, and facilitates collaboration.

Practical Application:

In the AI domain, where code clarity is crucial for collaborating on complex models and algorithms, this could involve choosing meaningful variable names, writing clear and concise functions, and providing comprehensive documentation.

3. Acknowledge Ethical Responsibilities

Programmers have a responsibility to consider the broader impact of their work. As software plays an increasingly important role in society, ethical considerations such as user privacy, data security, and the potential for misuse of technology should be at the forefront of a programmer’s mind.

Practical Application:

For AI product engineers, this means considering the ethical implications of their work, particularly in areas like bias in training data, potential misuse of AI systems, and the broader societal impact of AI technologies.

4. Never Stop Learning

The field of programming is constantly evolving. Programmers should continually expand their knowledge and skills, exploring new languages, paradigms, and tools. Active engagement in the programming community, through conferences, online forums, and reading research papers, is crucial for staying ahead of the curve.

Practical Application:

This takeaway encourages AI product engineers to embrace lifelong learning, staying abreast of new algorithms, techniques, and frameworks in AI to ensure they are utilizing the most effective tools and approaches.

5. Recognize the Value of Collaboration

Effective collaboration is essential in software development. Recognizing that individual programmers have different strengths and weaknesses allows for creating diverse teams that can leverage their collective expertise to tackle complex problems more effectively.

Practical Application:

In AI, this could involve collaborating with other researchers and engineers who bring different areas of expertise, such as machine learning, natural language processing, or computer vision, to solve complex problems.

Memorable Quotes

Chapter 1: Jamie Zawinski. 23

“When you’re debugging something and then you figure out that not only is the map wrong but the tools are broken—that’s a good time.”

Chapter 2: Brad Fitzpatrick. 59

“At this point I was always spraying memory all over just by taking a hash of the key and picking the shard. Why can’t we do this with files? “

Chapter 3: Douglas Crockford. 98

“At the end of the day, ship the fucking thing! It’s great to rewrite your code and make it cleaner and by the third time it’ll actually be pretty. But that’s not the point—you’re not here to write code; you’re here to ship products.”

Chapter 4: Brendan Eich. 149

“Academia has not been helpful in leading people toward a better model.”

Chapter 5: Joshua Bloch. 178

“The fundamental theorem of API design is, when in doubt, leave it out.”

Comparative Analysis

While “Coders at Work” shares the theme of exploring the programming landscape with books like “Beautiful Code” and “Founders at Work”, it distinguishes itself by delving deeper into the individual philosophies and experiences of its subjects. Unlike the more problem-solution focused approach of “Programming Pearls”, “Coders at Work” prioritizes understanding the individuals’ journeys and thought processes, offering a more philosophical perspective on the craft. This approach aligns more with Weinberg’s “The Psychology of Computer Programming”, emphasizing the human element in software development. However, “Coders at Work” stands out by capturing the voices of a diverse group of modern programmers, offering a contemporary perspective on the field’s evolution.

Reflection

In “Coders at Work”, I sought to capture the essence of programming through the lived experiences of fifteen accomplished practitioners. The book sheds light on the enduring challenges of software development, like managing complexity, ensuring correctness, and adapting to evolving technologies. It highlights the importance of skills often overlooked in traditional computer science curricula, like the ability to communicate effectively, collaborate with others, and learn continuously. However, the book’s focus on individual experience leads to a potential blind spot: it doesn’t fully address the systemic issues that shape the programming landscape, like the influence of corporate interests on software development practices. Additionally, the book was written before the rise of machine learning and deep learning, which have significantly impacted the field. Despite its limitations, “Coders at Work” remains a valuable resource for understanding the core principles of programming and the evolving challenges faced by those who build the software that shapes our world.

Flashcards

Who was Jamie Zawinski?

Jamie Zawinski, known for his work on Netscape Navigator and XScreenSaver, was one of the original developers of the Unix version of the Netscape browser.

What is one piece of advice that Brad Fitzpatrick gives for self-taught programmers?

Brad Fitzpatrick, creator of LiveJournal, believes that programmers should always push themselves to attempt projects outside their comfort zones, and emphasizes the value of learning by reading other people’s code.

Why does Douglas Crockford think that “The subset idea is really important”?

“The subset idea is really important” because it focuses on using the best parts of a language while avoiding features that add complexity or are poorly designed.

What is Brendan Eich’s perspective on abstractions in programming?

Brendan Eich believes that abstractions are powerful for simplifying complex tasks, but that programmers should understand the underlying mechanisms to avoid performance issues and be able to debug effectively.

What is Joshua Bloch’s “fundamental theorem of API design”?

“When in doubt, leave it out.” This encourages programmers to design APIs that are as simple as possible while still meeting the necessary use cases, avoiding unnecessary complexity.

How does Joe Armstrong define programming?

Joe Armstrong, the creator of Erlang, describes programming as “a process of understanding” rather than simply typing code, emphasizing the importance of thorough design and problem-solving before implementation.

What is Haskell’s unofficial motto, as coined by Simon Peyton Jones?

Simon Peyton Jones uses the phrase “Avoid success at all costs.” to describe the philosophy of Haskell’s development, allowing the language to evolve and adapt without becoming burdened by legacy code or backwards compatibility constraints.

What does Peter Norvig believe about the relationship between code clarity and performance?

Peter Norvig emphasizes the importance of writing clear, maintainable code, arguing that “the cleaner and nicer the program, the faster it’s going to run.” This encourages programmers to prioritize clarity and simplicity over premature optimization.

What does Guy Steele say about identifying logical errors in code?

Guy Steele highlights the importance of recognizing the distinction between a logical error and a typographical error when debugging. He emphasizes the value of understanding the programmer’s intent behind the code to identify errors effectively.

What is the importance of “immediate gratification” in programming environments, according to Dan Ingalls?

Dan Ingalls emphasizes the value of “immediate gratification” in programming environments, arguing that systems that provide quick feedback and allow for rapid prototyping are more engaging and encourage experimentation.