📓 Cabinet of Ideas

My Software Bookshelf Olano.dev

My Software Bookshelf | olano.dev #

Excerpt #

The easiest way to make a to-read pile grow is to read a book from it.


Here are books I have read twice
and books I expect to read again in time.
Here are books I hope I’ll read
and books I wish I had but never will.

1

Back in college, I learned about circuits in a physics class. I learned about boolean algebra in a math class; binary code in a programming class; logic gates and CPU architecture in an electronics class, and information theory in a data organization class. Some of these courses were years apart from each other. I always felt I was missing the big picture, an unifying thread to tie all this disparate knowledge together. I wish I had a book like Code to follow along. Not only does it build the computer from the lowest to the highest level of abstraction, but it throws in historical context along the way. Code is compact and interesting enough that I frequently take it out and make plans to read it cover to cover, just out of curiosity and entertainment, even all these years after first learning about its material. And then I put it back.

2

If knowledge in Code was “stacked” chapter by chapter, The New Turing Omnibus is a bag of loosely connected topics, a perfect sample of all Computer Science. Its structure makes it better at sparking curiosity than as a means to master its contents. This is a book I would have recommended to myself, when I was starting out, to get excited about all the places my career could take me; a book I would recommend for other professionals to get a taste of the field; a book that could sit on the coffee table of mad man and casually shake the thoughts of a seasoned engineer.

3

The Innovators does with computing what Fermat’s Last Theorem did with math, The Age of Uncertainty with physics, Replay with video games and It’s All a Game with board games: it tells the history of a field like a thriller. Every other book in this list is a pin on the timeline that The Innovators lays out.

4

Have you ever been part of a highly motivated, self-absorbed engineering team? Have you lost your sleep and put everything you’ve got into a project, and forgot the point of it all but just kept going, out of respect for your teammates? Imagine it’s the ’70s, during the minicomputer era, before PCs and the internet, before most people had even seen a computer—let alone use one. Imagine a professional journalist sitting in with the team, documenting the process, trying to capture that trance engineers seem to get into, trying to explain to himself what it is about this stuff that makes them care almost to the point of self-destruction. That’s The Soul of a New Machine.

5

The interview is such an entertaining literary form; I wonder why it isn’t frequented in our field. Is it because the idea of the genius hacker has gone out of fashion, in favor of the voiceless team? Are the rockstar CEOs now hogging all the spotlight? Have we become so self-absorbed that we can only write in the first person? Whatever the case, there’s a lot to like about Coders at Work, even if it’s now hard to relate to its war stories. This book introduced me to The Paris Review interviews; it pushed me to finally try Emacs—which I’m using to write this—; it provided me with indisputable proof that there’s no single right way of programming. In this sample you’ll read about those who favor teamwork and those who prefer working alone; proponents of bottom-up or top-down or middle-out; some who skip comments and some who practice literate programming; some that polish interfaces and others that shove everything into a single file. All of them were successful; all of them are exemplary.

6

I was lucky to get a full-time job at a software company right after starting college. That certainly delayed my graduation but, in exchange, armed me with perspective for the rest of my career: I would take both what I saw in class and at the office with a grain of salt. I remember, from those first couple of years at work, being overwhelmed by the amount of things that I so obviously didn’t know. It was hard to prioritize, to tell what was important to really understand, what I just needed to get familiar with, and what I could just ignore. I think that The Missing README would have been a lifesaver back then. Project management methodologies are the perfect example: chapter 12 and the Agile Manifesto should be all you need to know; beware of whoever says otherwise—they may be trying to make you join a cult.

7

One source of impostor syndrome is that I never had to struggle with an algorithms textbook when I was at college. The teachers of the Algorithms and Data Structures course were young and too eager to jump from abstract data types to object-oriented programming, which was the topic of a different class. Years later, I read the Aho-Hopcroft-Ullman book on my own, but I guess these things aren’t of much use if you don’t bother doing the exercises. I chose to add the Skiena book to my shelves because its structure makes it look more approachable than the alternatives: 300 hundred pages to cover the fundamentals, favoring war stories over demonstrations, and a catalog of algorithmic problems to wrap it up. I sincerely want to read this thing, I swear, it’s just life—and other books in this list—keep getting in the way.

8

I like how Programming Pearls takes what could be the syllabus of a Computer Science class and gives it a craftsman’s treatment. It’s not so much about the specific techniques but about the problem-solving mindset you need to get into to use them. It’s also, as its title suggests, about these little jewels that don’t make your everyday work but that, when you come across them, remind you why you fell in love with this thing.

9

Text is the stuff of programming. Writing is an important skill, even when only applied to READMEs and PR descriptions. Strunk & White’s Elements of Style is the standard recommendation, but I find it too low level, too focused on preventing errors that can be detected by a computer. If, as suggested in The Pragmatic Programmer, we treat English as just another programming language, then Elements of Style deals with syntax, and On Writing Well deals with design. This book will push you to be deliberate about the many little choices involved in composing a nonfiction text; it will make you think about how to start and how to finish, who your audience is—what can you expect them to know, what do you need to supply, what will they get from the text. It will show you that, much like programming, writing is about simplifying, clarifying, tidying up, and fixing what has already been written.

10

Several short sentences about writing is an advanced book. I don’t mean it’s dense or hard to read. On the contrary, it’s a light read, in the good sense of the word: ethereal. A book that doesn’t tire the eye, that flows like poetry. (That’s a compliment). (And I’m not a poetry reader). Several short sentences about writing is an advanced book because it took me a decade to be in a position to appreciate why its discussion is relevant for a software engineer. I needed to first acknowledge that programs must be written for people to read, and only incidentally for machines to execute, that English is just another programming language, that we’re in the human communication business: that programming is a form of writing.

11

In college and at the office, I was exposed to a very one-sided view of programming: C was powerful but problematic; C++ solved some of its problems but added new ones; Java fixed C and C++ and was pretty much The End of History when it came to programming languages. Being a good software developer largely meant getting good at Java’s flavor of Object-Oriented Programming. I was suspicious of this mindset; after all, every useful program on my computer was written in C or C++. I became a dissident after teaching myself Python one summer, and a full-on heretic, later that year, when I took a Programming Languages seminar. The first part of the semester followed the Concepts, Techniques, and Models of Computer Programming book, building every major paradigm onto a subset of the Oz language. I wasn’t yet equipped to tell the difference between easy and simple but, awkward as the Oz syntax felt, it was obvious how objects complicated the declarative model and how shared state was trickier than message passing. For the second part of the course, we had to research a programming language. I chose Erlang because I was curious about functional programming and its famous concurrency model but, most of all, because of its telecom roots: this was a platform designed to solve real-world engineering problems. Little did I know that, almost a decade later, I would get the chance to use this weird Scandinavian language at my job and that it would shape the way I reason about software.

12

As you may have by now guessed, I have a soft spot for constraints-based writing. The urtext of creative constraints is Raymond Queneau’s Exercises in Style, where he tells the same trivial story 99 times using different literary forms. Cristina Videira Lopes brings this idea to the software world by solving the same programming problem in 33 different coding styles. The result is not only entertaining but an elegant way to structure a discussion of paradigms and computing history. I think there were some missed opportunities in the style selection, and I’m still not sure about the choice of Python to implement the solutions, but the concept alone makes this book nothing short of genius.

13

The Pragmatic Programmer is one of my favorite software books. It’s a catalog of principles and practices across the discipline and, as such, the discussion just scratches the surface. Many of the topics could fill their own book. And, yet, there’s value in going through this wide overview, item by item; seeing the authors approach different problems in different contexts distills that pragmatic attitude that is the theme of the book. I read the first edition as I was starting out, and the 20th anniversary one as a senior engineer. Some of its advice—be a catalyst for change, don’t live with broken windows, delight users, don’t just deliver code—resounded like a mantra throughout my career.

14

I’m ashamed to admit that I’ve left The Design of Everyday Things unfinished after a couple of chapters. Not because there’s anything wrong with abandoning books, but because I feel I should have absorbed these ideas years ago. I don’t think we programmers fully acknowledge how much of design goes into our work. Not just how much of what we call software design has in common with industrial or graphical design, but how much we could benefit from a human-centered approach to our everyday decisions, from how we display information on the screen to how we order arguments in a function definition.

15

A Philosophy of Software Design is my I Ching. I thought I had a good idea of how to write code, of what a good design was, even if I couldn’t quite put it into words. And then this little unassuming book made me change my mind about things I’d previously thought were obvious—smaller modules are always better, inline comments are a bad smell, etc. Ousterhout removes some of the subjectivity from notions like complexity and abstraction and offers heuristics along with examples of how they can be taken too far. Perhaps the book’s biggest contribution is the advice to strive for modules that are not small or large but deep.

16

As I was putting together this list, I noticed something was missing from my bookshelf. There are books touching on data structures, file systems, database internals, software architecture, and large-scale distributed data systems. But none deals with using databases from a developer’s perspective. Years ago I would have covered that gap with something like Seven Databases in Seven Weeks, to get an overview of the available systems and their trade-offs. But, as I grow older I tend to favor frugality: you’re likely to only need PostgreSQL for most projects, so why not focus on getting good at that? That still doesn’t warrant reading a book dedicated to PostgreSQL, to the SQL language, or to the relational model. Looking around I saw many recommendations of SQL performance explained, which has an online version. This book starts with a bold premise: the only thing developers need to learn is how to index. Far from turning it into a shallow tutorial, this premise provides the book with structure: each chapter is dedicated to a portion of a SQL query, going deep into the processes and data structures that power it.

17

The Erlang language and its platform are so special—the pragmatic take on functional programming, the actor model, the let it crash philosophy, the preemptive scheduler, the OTP behaviors, the built-in observability—that it’s worth studying just for perspective and inspiration. And I can’t think of a better way to study Erlang than by reading Learn You Some Erlang for Great Good!—except perhaps running a system in production while reading it. It’s also one of the best software books I know; beyond Erlang, it can be a fun introduction to functional design, fault tolerance, and distributed systems.

18

Concurrent programming is hard for many reasons. We tend to think sequentially. Concurrent programs are harder to test and their bugs are harder to reproduce. Only occasionally do we need to write concurrent code. But, also, I think the narrative of the discipline, and the tooling, haven’t caught up to the last couple of decades of hardware evolution. Why do we spend so many cycles thinking and talking about sophisticated algorithms and distributed architectures, and so few on concurrent program design? Why does the concurrency model feel like an afterthought in most programming languages, old and new? There are two notable exceptions: the Erlang and Go ecosystems. Erlang is the superior platform but, paraphrasing its author, you can’t get Erlang’s concurrency banana without the OTP gorilla holding the banana and the preemptive scheduler jungle. Golang is the general-purpose alternative: for the most part you work and think as with any other mainstream language but, when you need concurrency, you can rely on message passing. And you can always resort to threads and mutexes if necessary. Hence, Learn Concurrent Programming with Go.

19

One of the things that prompted me to write this list was the realization that some of the books that influenced me the most, and some of those considered canonical when I was in college, didn’t age very well. Even conceptual books, not concerned with specific tools, suffer from being rooted in a pre-internet world. Each former classic seemed to have a modern replacement, except for The Mythical Man Month. We don’t read Borges today like they did in 1951 and we don’t read Brooks like they did in the ’70s or the ’90s. The Mythical Man Month is as relevant today as it was back then, but it’s also a different book: as much about programming, systems design, and project management, as it has become a book of software history—our only true classic.

20

The biggest revelation of my professional life was moving from building software wishfully expected to scale, to maintaining systems that had been running in production, for years, at scale. It wasn’t about easing development; it was about easing operations. It wasn’t about sophisticated components; it was about keeping things simple to reason about. It wasn’t about preventing errors; it was about working despite them. It wasn’t about scalability; it was about stability. While some of the discussion and the war stories show their age, no book that I know of does a better job at imbuing this production-first mindset than Release It!

21

Someone recently told me: “If you are not dealing with legacy systems at work, then you are building someone else’s legacy system”. This is an elegant way to capture the ideas from Kill It With Fire. We spend a disproportionate amount of time discussing greenfield system design if we consider that most of our actual work is old software maintenance. Kill It With Fire didn’t really work for me as a book: something is missing in its organization; I would often get lost in the details. But its many insights and some brilliant passages keep coming back to me when I work and when I write. I think this book hints at a more sustainable future for the software industry.

22

I could try to fool myself into thinking I’ll someday read Operating Systems: Three Easy Pieces, but that day would never come. Instead, I’ve picked up the humbler How Linux Works, a concrete and up-to-date book about the only Operating System I will ever care to learn about. If it could only have 10% or 20% more conceptual background it would be just perfect, thanks.

23

Who isn’t guilty of throwing the “root of all evils” bit around? I am, but these days I feel better represented by Joe Armstrong’s quote than by Knuth’s: “Make it work, then make it beautiful, then if you really, really have to, make it fast. 90% of the time, if you make it beautiful, it will already be fast”. Systems Performance is for the other 10% of the time. This talk and paper are good introductions to the methodology. If that’s not enough, then there’s the book, which is probably the most technical and specialized one on my shelves. I learned about Brendan Gregg’s work through a colleague, during a period when the executives were pushing us to reduce infrastructure costs by optimizing our systems. The book forced me to work against my instincts, looking inside the very things my brain insisted on abstracting away. I was out of my league, clearly, and I didn’t reduce infra costs, but I came out a better engineer from the experience.

24

I just bought Designing Secure Software; I haven’t read it yet. Its inclusion in this list is a statement of intent. Everyone says that security is important, but that usually translates to sanitizing SQL inputs, installing software patches, and completing SOC 2 training. There should be more to it, some holistic approach, some instincts programmers can develop without having to become specialists. Maybe by reading this book I’ll find out.

25

Don’t roll your own crypto, the saying goes. Stay clear from those who do, I might add. As far as I can tell, a deep understanding of cryptography isn’t necessary to use it effectively as a security tool. But it still is an interesting area of human knowledge, a beautiful intersection of math and computer science. Despite the hordes that have raided it. From the few chapters that I’ve read, Real-World Cryptography seems to strike a good balance of conceptual discussion, technical details, and practical insight.

26

There used to be an assumption—there still is, really—that, after reaching the Senior level, engineers had to choose between settling there or jumping to a management position. This has terrible consequences: people who don’t like to manage, or are bad at it, or would just prefer a technical role, switch to management because it seems their only option to grow professionally. (Stability instead of growth is a valid option). The Staff engineer track at some organizations is the solution to that problem. Staff, Principal, and Distinguished engineers are technically-focused individual contributor roles, but with higher responsibilities and impact than Seniors. This doesn’t mean they don’t have to deal with people and politics (we’re in the human communication business, remember?), it means they have organizational perspective and operate beyond the team level. The Staff Engineer’s Path is a very stimulating read, making a great case for this track, with tools and career advice for those who want to pursue it. It’s also a truly modern book, surveying and organizing the industry insights from the past decade.

27

We’re not in the high-tech business, we’re in the human communication business. That idea alone deserves Peopleware a place on my shelves but, while its ideas are still relevant, a good part of the discussion now feels dated—from phone call interruptions to office cubicles. I think, today, The Manager’s Path does a better job of describing a people-first approach to software development. Anyone leading or managing or being managed—that is, anyone—can benefit from the ideas in this book.

28

Team Topologies is not the most fun of reads even for those, like me, interested in development processes and how we organize our work. But it presents some useful principles to escape the pitfalls of ‘this is the only way we know’ and ‘this is what everyone else is doing’ in organizational design. In a nutshell: apply the Conway law, design software architecture and team interactions together, favor flow and autonomous delivery, assign responsibilities to match the team’s cognitive capacity, and remove bottlenecks by offloading specialized work to support teams (e.g. platform).

29

I have mixed feelings about software architecture. I think Architecture, the field, is worth studying, discussing, and working on, but the role of the Software Architect—calling the shots while the devs do the work—shouldn’t exist. That’s why I think the architectural mindset comes second to the organizational perspective promoted by The Staff Engineer’s Path and Team Topologies. That being said, Fundamentals of Software Architecture is a great book, packed with useful concepts, techniques, and patterns. The companion Software Architecture: The Hard Parts presents the same material through a case study.

30

I’m a bit of a reactionary when it comes to microservices. I think they are an organizational pattern rather than an architectural one, and that its scope of application is narrow. I’ve heard about teams suffering because of microservices more often than about teams benefiting from them. But I’m fond of Building Microservices, in part because the author is very explicit about when not to use them, and in part because it was the first software architecture book I read that felt like it had been written for my times, for the post-cloud world. I picked it up after joining a startup that was building a microservices platform and I wanted us to do it right. As it turned out, we were doing it wrong, and we shouldn’t have been doing it at all.

31

I picked up Designing Data-Intensive Applications out of a mix of professional curiosity and fear of missing out. I felt that I needed some academic support to navigate the technological explosion that had taken place in the years after I had graduated. I religiously worked my way through the book for a few months. Kleppmann hits a surprising balance of depth, breadth, length, and readability. Over the years, I’ve read accounts from other engineers who went through a similar process—even though none of us are really designing data-intensive applications or using distributed algorithms in production. I concluded that this book has become a modern classic and reading it is a rite of passage for a certain kind of senior engineer.

32

One thing everybody seems to agree about: the Dragon Book is the definitive reference on compilers and language design. Another one: the Dragon Book is almost impossible to read. Over the last couple of years, I saw a new universal truth emerge: Crafting Interpreters is the book anyone interested in language design should read. So far I’ve only read the introduction but, just by reading about how it was written and diagrammed, I can tell why this is such a praised and loved book. I wonder if, over the next decade, we’ll see a generation of languages influenced by the work of Bob Nystrom. I decided to put this by the end of my list; I’d like to replace the idea that compilers are a tricky subject to struggle with in college with this one: designing a programming language is what our whole career has been preparing us to do.

33

I couldn’t wrap this up without a single mention of Lisp. There are books on my shelves about learning to program with Lisp—about thinking in Lisp—; a book to learn Clojure and another one to master it; a book to configure my editor using a Lisp dialect, and another one to learn how computers learn (using Lisp). But nothing suits Lisp, and Racket in particular, better than language development. I don’t remember where I learned about Essentials of Compilation—it’s a rare book judging by the amount of reviews I can find online. But it seems approachable, building on ideas from popular papers, a good complement to Crafting Interpreters, and the perfect excuse to go nuts on Lisp.


See also: