It is quite concise (about 190 pages), but in my opinion, it includes all the essential information that the other books in that category would teach you. It leaves out a lot of cruft that over the years turned out to be non-issues (code styling, problems that come with object oriented programming, etc.) but occasionally - when the topic is popular and widespread (e.g. Uncle Bob advice) - addresses them as alternative opinions. It was first published in 2018 and is therefore not in the out-of-date category.
So I would recommend it as essential read, hands down.
If you want something a bit more elaborate: "The Pragmatic Programmer" has a 20th Anniversary Edition. It is a timeless classic, worth reading at any rate.
That being said, I wish there was a single consistent resource[1] that summarizes truly modern software design philosophy in the sense that it leaves the object orientation inspired ideas behind that did not turn out to be useful and focusses on typed functional programming. Maybe with examples in Typescript and Rust.
[1] Possibly a book, but not necessarily. For me it would be important that it presents a consistent opinion, so it should be from a single author or small group of authors. The information I have in mind is mostly there, but spread out over many blog posts from people with slightly different takes and ideas about them. The overwhelming majority of recommendations in this thread are from authors I'd consider part of the founding generation. I'd love to read about software design from the perspective of a younger generation.
1. A Philosophy of Software Design is very good. Not the whole of it but it’s short and to the point.
2. Fiction, as diverse as possible. I apologise for making assumptions but many software engineers are secretly lacking in understanding other people, what kind of of life experiences that have, how they think about the world, what is important for them. If you work with people it is going to be useful.
Also, it’ll enrich your life and you’ll have more to talk about during coffee breaks :)
If you're interested in performance, you can read https://algorithmica.org/ and https://people.freebsd.org/~lstewart/articles/cpumemory.pdf
The first are books like Pragmatic Programmer, Mythical Man Month, Code Complete, Design Patterns, talks by Alan Kay on software systems and OOP, even Game Engine Architecture etc. A lot of the content there is distilled experience which is much faster to learn from a book than gain the hard way on the job.
The other books are practical deep dives. Here I would recommend a variety of books like Inside the Machine by Stokes, Computer Architecture by Hennessy, 21st Century C by Klemens, Crafting Interpreters by Nystrom, Compilers by Aho, Effective Java, Nature of Code by Shiffman, Ray Tracing Challenge by Buck, Hands on Hacking by Hickey, and others, depending on your interest and area of focus.
EDIT: An old book (also received an update) I'd add is The Psychology of Computer Programming by Weinberg. More descriptive than prescriptive compared to many other books, written in and about the same period as The Mythical Man-Month.
Here some other recomendations
- Designing Data-Intensive Applications - Tidy First?: A Personal Exercise in Empirical Software Design - A Philosophy of Software Design - Refactoring UI - The Software Engineer's Guidebook - https://blog.rstankov.com/programing-books/
I also have a personal recommendation for when you want to better understand testing, QA, or want to/have to work with QA people. [2]
[1] https://pragprog.com/titles/tpp20/the-pragmatic-programmer-2... [2] https://www.amazon.com/Lessons-Learned-Software-Testing-Cont...
- A Philosophy of Software Design by John Ousterhout - Domain-driven Design: Tackling Complexity in the Heart of Software by Eric Evans
They both manage to explain some ideas that are really important, in a very simple way (which makes me feel like an idiot).
For a good understanding of the basics of architecture: https://www.amazon.com/Web-Application-Architecture-Principl...
https://www.brendangregg.com/systems-performance-2nd-edition...
and
BPF Performance Tools
https://www.brendangregg.com/bpf-performance-tools-book.html
Programming Pearls too would still be worth reading
You’ll just get angry when writing it. We had written down solutions to problems with teams and offices in 50 years ago but just refused to follow them.
Coders at Work: Reflections on the Craft of Programming
https://www.youtube.com/watch?v=tD5NrevFtbU
I also watched clean code videos and used it in practice, and why it _felt_ right my code size blew up and actually it got harder to understand by other people instead of easier.
Nowdays my main guidelines are getting a balance between less lines of code (while still readable), readable variable names and better performance.
Also I may get hate here for it, but I learned a lot from watching George Hotz programming tinygrad (available on YouTube).
“Old” but amazingly relevant today.
https://www.amazon.com/Effective-Engineer-Engineering-Dispro...
If you're experienced (senior or higher), it's still a good read, but fewer things will surprise you.
I’m surprised I don’t see more advice to read a language- or domain-specific book. If you know what type of technology you want to work on and what language(s) you want to use, I’d read a book or two to gain expert-level understanding of those languages or domains. I cannot tell you how beneficial it has been to me to read books covering all the intricacies of C, C++, and Rust. Not to mention countless pages of documentation covering the Linux kernel, shell scripting, etc. Even if you have great general software engineering skill, you still have to be able to quickly read, write, understand, and modify the code you work on. You never know when you might find yourself 50 files deep in an exploration of why some open source software behaves a certain way that’s really boiling your blood, or when you need to parse the code to find an undocumented feature you’re certain exists (or, if not, to hack it in). Knowing the language is very beneficial for this, and getting eyes on open source code to recognize common patterns is very useful.
* measuring things (evidence gathering, performance, comparisons, stats, research). Most developers cannot do this on any level and yet have the balls (stupidity) to advocate so boldly for their opinions.
* data structures. There is a very old best practice: composition over inheritance. That advice runs far deeper than it sounds because all aspects of a good application should be interchangeable and extensible structures. That applies to both theory like functional programming as well as practical like interfaces, APIs, and data in transport.
* writing. Programming, in the brain, is no different than writing an essay in natural language. It requires executive planning, expression, organization, and refactoring. The better you get at writing prose, articles, and proposals the easier it gets to write the first draft of an original application. It’s so much more than just writing documentation and most programmers struggle with all of this.
* transmission. Read the protocol RFCs and attempt to write original implementations. Most programmers cannot do this and yet a deeper understanding of data in movement will provide capabilities you, and your competition, can never before imagine.
"A Philosophy of Software Design" is mentioned a lot, +1
"The Missing README" is full of pragmatic advice to get from 'my code works' to 'my code is in production'. Many of the barriers to success have nothing to do with algorithms and everything to do with the organization running the project. It's marketed to new engineers, but I think anyone who writes software would get something out of it.
"Elements of Clojure" by Zach Tellman is a fantastic high-level architectural philosophy about how we build and compose abstractions. Only wish that the title wasn't tied to the Clojure programming language (most of the book is applicable to any language despite the title) and was a bit longer.
"Tidy First" is the first in a series by Kent Beck, a quick exposition on how to separate structural changes (architecture, paying down tech debt) from behavioral changes (new features, bug fixes). You need both, and you can use economics as a guide for when to invest in one or the other. But you need to treat them differently.
Test-Driven Design by Example is a good (and fun) read.
* “The Design of Everyday Things”. Have you ever pushed on a pull door, or vice-versa, because it was unclear how it worked? Designers call those doors “Norman Doors”, now, after the author of this book Donald Norman so effectively dissected and criticized them (among plenty other objects). Too many APIs suffer similar problems—and if you don’t want yours to, this book is a great place to start.
* “On Writing Well”, by William Zinsser. Good code and good prose have a lot in common: they know what they’re trying to do, are stripped to their clearest components, and have internal structure that supports understanding. Add to that the fact you’ll be writing lots of prose anyway (design docs, postmortems, etc), and the value of writing well should be clear.
Depending on the tech stack you're interested in, I would also strongly suggest reading foundational books that go deep into that platform (e.g. the Java Language Specification if you're into Java [1]). These are not things you necessarily need to read end-to-end or understand completely, but your global understanding of your chosen platform will expand significantly.
Systems Performance by Brendan Gregg is another useful classic. While it's about performance, it touches upon a huge number of important topics (from memory allocation to pretty graphs), perusing it will make you smarter.
Surrounded by Idiots
Meditations
Related to this book is what we call "vertical feature slicing". (I'd be curious to know what other books cover this topic.) There are some Youtube videos on the topic. There was a great 2-hour video from 20 years ago that influenced me. Unfortunately, I don't remember the title and cannot find it today.
The video "Simple Made Easy" had a profound influence on my programming: https://www.infoq.com/presentations/Simple-Made-Easy/
It takes time for them. It takes time for us. The small details are ironed out along the way but the big picture, the concept, is defined/designed before.
Note that I really like the books listed up to now, they are not "dependency injection in Typescript using framework x, y or z" kind of books, more general philosophy of coding (with people). Going to this upper level is for me where you go from good to great. And myself, going to my 50s, I am still learning...
That being said, these have been my favorites:
- designing data intensive applications (a great way of understanding systems + the basics of SRE)
- the senior engineer (I love the prototyping process he lays out)
- the effective engineer (lots of good gems for approaching prioritization)
- debugging (by David agans)- a great resource for a formalized debugging process if you don’t have one
- on writing well (I’m halfway through this, but it has been indispensable for writing tickets + messages at work)
I have no affiliation.
I read this years ago and regularly recommend it, especially when people are all over talking about some special queue or database technology. I find so many people don’t understand even how databases work and it’s crucial to application performance and structuring. Adding queues works to relieve server load but if you get swamped by messages you need to make an active decision on how to handle that - and maybe a queue isn’t the best idea if you can’t lose them.
Another one I found very helpful is Designing Data-Intensive Applications by Martin Kleppmann.
1. The Practice of Programming 2. Programming Pearls 3. Go Programming Language 4. Architecture of Open Source applications - https://aosabook.org/en/
I'm getting an eerie sense of Deja Vu.
I remember reading this exact thread (exact question, exact replies) a few days ago.
But right now it says this question was posted just 6 hours ago (right now the time is 2:35 pm 1st September UTC).
Either I'm going crazy or there's a bug with the time here.
@dang please tell me that I'm not going crazy, or at least that it's just a simple glitch in the matrix.
I've always done well following Don Lancaster's advice: Hit the basics, HARD.
Most modern software "innovations" are really just a restatement of David Parnas' paper from 1971. He suggested programs should be split up so that the data used by modules can't be affected by the other modules. "Data hiding."
Once you get a grounding in the history and literature of programming (which all other professions do without thinking), you'll start to see the "sameness" among all the supposed difference. Once you see the "sameness", you'll know what is truly important to know/master, and what is not.
As a recent grad, I'll tell you that the first thing I learned was to ignore all the "software engineering" stuff that schools teach. The reality is that I would be asked, "Build a tool to do X". So I'd start through the process, building a design and the data flows, starting to build the code. Then I'd get "It also has to do Y." And I'd have to throw away most of what was written.
Eventually, I learned the two rules Ken Thompson taught:
1) give users something useful in two week, not the whole problem solved. 2) when in doubt, use brute force.
That's it. With attention to fundamentals, you can clearly see that "Agile" is just a bunch of fancy words (and vendors selling tools) telling you to do that same thing. Only Ken talked about that in the 70's.
What you'll find is that getting a tool into the hands of users will generate new features based on what it already does. No more blue-sky wishes. And it will allow the tool to evolve into what they really want it to do. Which no one ever knows when they start. All the best software followed that path to greatness. (Which you'll see when you read the history of your chosen profession.)
So learn the history. Learn how computers work (not the "Von Neumann" stuff). Get a computer engineering book and learn about bit-slicing and clocks and microcode. It doesn't matter that you're not a hardware guy; you need to know what your code is actually doing, down on the metal.
Never stop learning. Read constantly. Read books you'll never find a job with, like SICP. (I once had to write a loop in a language without a loop construct. But I had read SICP, so I knew if it supported recursion, I could make a loop. And I did.) Don't read trash. Don't bother with the "current hotness"; if it's good, it's probably just a restatement of the old and if it's bad, it'll go away.
I'll just leave with an ancient aphorism: 40 can't tell 20. There's just a gap between what an older person has learned about the world, and what a younger person imagines the world to be. That different can be called "experience", but the fact is I remember perfectly the pearls of wisdom dropped on my by the "old men"...and 20 years later, I was them. So I offer this small essay, knowing it'll probably be rejected, but hoping that just this once it does some good for someone.
I think the most important chapter is on Simplicity of your build and code.
Definitely worth a read