Some of the most interesting books I've read in support of my software-development work are:
* "Compilers: Principles, Techniques, & Tools" by Aho et al. (i.e., "the dragon book")
* "Data Flow Analysis: Theory and Practice" by Khedker et al.
* "Understanding MySQL Internals" by Sasha Pachev.
* "Transaction Processing: Concepts and Techniques" by Gray and Reuter.
* "Fundamentals of Wireless Communication" by Tse and Viswanath.
* "Genetic Programming: An Intrduction" by Banzhaf et al.
* "Applied Crytography" by Schneier.
EDIT: A few additional comments:
(1) Although these books are problem-domain specific, some of them had benefits outside of their problem domains:
* The Dataflow book has some great coverage of fixpoint algorithms. It's really helpful to recognize when some problems are best solved by fixpoint analysis.
* The "dragon book" takes a lot of the mystery out of compilers. That's somewhat helpful when writing code that needs to be fast. It's super helpful if you want to work with compiler-related technologies such as LLVM.
* Understanding the fundamental challenges of transaction processing helps you avoid massive misadventures when dealing with databases or concurrent / multithreaded systems.
(2) YMMV, but I've found it hard to soldier through these books unless I had a need to for my job or for school.
Don't read the dragon book if you're interested in compilers. It's lex and parse heavy, and is not up to date with more recent best practice on codegen. Further, the lex and parse end of it is focused on the kind of theory you need to build tools like lex and yacc, rather than stuff you need to know if you want to write a compiler.
For a good intro of modern back end development, check out Engineering a Compiler. It's also got the lexical and parsing end of things, but a bit better done, but still quite theoretical.
One of the best books I read on programming is "Concepts, Techniques, and Models of Computer Programming"; it's not strictly speaking language agnostic, based as it is on Oz, but Oz isn't a language you'd ever use in production and is a reasonable base to introduce you to ways of programming that will probably be completely unfamiliar, like constraint programming, dataflow, concurrent logic, etc.
Most people who criticize the Dragon (Compilers etc... by Aho et al.) book seem to focus on chapters 3 and 4 which are the chapters on lexical analysis and parsing. The book has 12 chapters. Whatever your feelings on the parsing techniques, the book covers WAY more than that. It has a really good introduction to code generation, syntax directed translation, control flow analysis, dataflow analysis, and local, global and whole program optimizations.
As someone who has quite a few books on compilers, program analysis, type theory, etc... I find the Dragon book an irreplaceable reference to this day. It has a breadth of content shared by very few other books. For instance, Muchnick's classic "Advanced Compiler Design and Implementation" is really good for analysis and optimization but neglects all front end topics. The only area where I believe the Dragon book is inadequate in is type theory (I recommend Types and Programming languages [TAPL] by Pierce and Semantics with Application by Nielson for a gentler intro).
As to parsing, its chapter on parsing (4) is not as "hip" has some people want. However, it is solid and will teach you how to do parsing. There are newer and fancier techniques not covered in Chapter 4 but in general most people would benefit just having a solid understanding of recursive descent parsing!
Don't read only the Dragon book if you're interested in compilers (or parsing in general). But it should be read, in addition to whatever else you read on the subject. It's classic for a reason.
Most programmers don't understand parsing worth a crap, imho. Some compiler theory would do most of us some good. I read it because I was doing data stream parsing back in the olden days before XML (which was before JSON), when we had to write our own stream formats. It really changed my whole way of thinking about a fundamental class of programming problems.
I found the Dragon Book unbearable---and I am one of those people interested in theory. Pick something better, plenty of choice available.
'Essentials of Programming Languages' and 'Types and Programming Languages' are good choices. (But slightly off-topic for this particular subthread, since they don't deal with parsing.)
The Dragon book is not good at teaching parsing, but is obsessed with the idea and spends 2/3 of the time talking about it, so you'll just be left thinking it's really difficult. The whole thing is extremely boring and lacks confidence.
Try "Parsing Techniques: A Practical Guide" and then a more concise book like Muchnick.
I also found my theory-of-computation course in college to be a wonderful help in understanding parsing.
Being familiar with the Chomsky Hierarchy ([1]), and the kinds of language recognizers required for each level in that hierarchy, can save parser authors a lot of wasted time.
Hey, I seconded this, the Dragons Book is not the best textbook or introduction to the topic, there are a lot of better ones. The Dragons Book is more of a classic. If you want to read a good book on compilers construction then you're better off reading "Engineering a Compiler" by K. Cooper and L. Torczon or "Modern Compiler Implementation in ML" by A. Appel.
If you want more resources on Compilers other than books, such as tutorials, guides, talks and papers, then go ahead and check the Awesome Compilers vertical I compiled a while ago: https://github.com/aalhour/awesome-compilers
The criticism is that the strongest part of the book is focused on writing compiler compilers - that is, writing tools that write parsers - not writing parsers.
Do note that there are multiple editions of the Dragon book and later editions have a far better codegen section.
One of the more famous compiler writers from that era once told me that the Dragon book's original codegen section wasn't even historically how anyone wrote a compiler and it certainly didn't reflect modern practice even back in the 90s.
However, the update significantly improves it with the addition of Monica Lam's contribution. I don't know if it's state of the art for codegen (probably not), but I'm not sure what book is (Muchnick is great too, but this is also quite old now).
I would recommend Schneier's Cryptography Engineering (or its predecessor) Practical Cryptography over Applied Cryptography, given the question. I agree Applied Cryptography is a very interesting book, but that's because I'm a crypto nerd. For someone looking to improve general software engineering skills, I think the other books do a better job of presenting best practices and the understanding behind them, with a bit less mathematical theory, etc.
Also, Applied Cryptography includes a ton of totally obsolete stuff, which tptacek has complained is still leading people astray by giving them seemingly attractive choices that are in fact broken or deprecated. Even at the time, with its focus on breadth of coverage, it presented technology which wouldn't have been a state-of-the-art choice, while today many techniques there are even less appropriate (and some good new crypto has been invented in the interim).
Applied Cryptography was an important political statement that we can and should have access to cryptographic technology, but I don't think it can be recommended as an appropriate introduction to the field in 2017.
Is there a best security book that is even more high level than those? Just like security patterns or something. What you need to know about TLS and securing data at rest, etc.
+1 for the "dragon book". Though the criticism about it being too focused on lex/yacc-era compilers and not being relevant today might have a point, I still find the mix of pragmatism and formal language theory absolutely worth the read, stylish/Unix-y, and even entertaining - for me, truly a hallmark of "American-style" comp.sci. standard literature (as opposed to more theoretical expositions to the topic).
Also, Donald Knuth's "The Art of Programming" (at least the fundamental and sorting/searching algorithms books), plus a book about graph theory and algorithms.
> "Understanding MySQL Internals"
Why this, as opposed to a more general text on databases? MySQL is popular, but few would accuse it of actually being a good database. I feel like the point at which knowing about the internals of MySQL becomes relevant is probably the point at which you should use a better database.
It's definitely a good idea to have prior general knowledge of database internals before reading an "internals" book.
I'm not sure if it's out of date, but my favorite book on the topic was "Database System Implementation" by Garcia-Molina et al. I found it to be super-readable.
What I like about the "internals" book is you get to see a real, specific database up close, warts and all. It gives you a different perspective from an overview book like the one mentioned above.
I think a good book that helps you understand a complex piece of software is a good read for programmers, regardless of the use you make of that software.
Additionally, I don't see how the need to know about the internals of MySQL means one should use a better database. PostgreSQL is normally proposed as the better alternative to MySQL if one sticks to Open Source, and all the good experts at it I have met were familiar with its internals too.
You seem to have misinterpreted my objection. There are better books on databases, and MySQL is not necessarily a good example of a database. It tends to do things in its own way. When you get into the sort of situation where the difference between 'how MySQL does things' and 'how things are supposed to work' matters, then typically it's MySQL that's quirky.
I think your last sentence is what caused me to misinterpret you. I agree with your comment up to "... being a good database.", but I think the point at which you need to know the internals of MySQL are irrelevant to whether you should use a database that is better for the problem you're trying to solve or not.
I would assume that any book about the internals of a database would be suitable. MySQL is plenty real enough to be educational to learn about its internals, yea verily, even its quirks, and to learn a lot about how other databases work. Even the "NoSQL" databases will use many of the same primitives.
An equivalent substitution for another database would be fine; anyone have any suggestions? Then again, such a substitution is really solving a non-problem.
It may very well be the case that looking at the internals of some database other would provide a different set of lessons.
IMHO, MySQL is especially ugly due to an attempt to insert an abstract interface around its storage engines. IIRC that interface is leaky, and its documentation is pretty spotty. Also, the InnoDB storage engine has a lot of complexity that seemingly duplicates what's provided on the storage-engine-agnostic side of that interface.
One of the big lessons I took away from studying MySQL's internals, and partially confirmed by the "internals" book, was this: Be careful when designing a plugible storage-engines framework for a DBMS; MySQL has some examples of what can go wrong.
That's something you're unlikely to find mentioned in a generic DBMS-implementation book, but is very good to know about regardless.
"Transaction Processing" is a great book for thinking about whole systems in a practical way and really covers a lot of stuff that one would otherwise have to learn by bitter experience.
Working Effectively with Legacy Code by Michael Feathers. It's a bit hard to wrap your brain around the Java and C++ examples unless you have experience with them, but the techniques are timeless. You may need to practice them extensively before you understand how important they are, though. In a recent book club we did at work, a common complaint was, "This just looks like common sense". Indeed it does... though the common sense is uncommonly hard to find when you are staring at the actual situations this book helps you with.
I just finished reading this book yesterday. I am not an expert in refactoring but the book seems too old, although most advises could be still useful. Anyway, today I found a new book by the author: Brutal Refactoring: More Working Effectively with Legacy Code. Unfortunately, I couldn't find a good review of the book on the Internet. But I think it could be more useful.
Modern IDEs can deliver many of the recommendations of the book. Our productivity has increased a great deal. Back then there was no intellisense, code navigation through clicking on method names/classes etc. highlighted syntax errors, built-in unit test frameworks etc.
It was written for a different type of developer and a different type of development environment and a specific language, C++.
You haven't looked at C++ lately if you think it's the same as it was in 2004. The ISO has released new versions of the language in 2011, 2014 and ratified a new standard here in 2017. If you're writing C++ code that is consistent with 2004 C++ then you're writing a really bad version of "C with classes", not C++.
Edit:
Modern C++ contains native support for the filesystem, threads, lambda expressions, variants, upcoming networking library, coroutines (at least in Visual Studio), no more new/delete memory management, parallel algorithms and a ton more. This is a completely different language now and the code you write looks nothing like 2004 C++ code.
Our productivity has increased a great deal. Back then there was no intellisense, code navigation through clicking on method names/classes etc. highlighted syntax errors, built-in unit test frameworks etc.
Just about all of these things were around in 2004.
"You haven't looked at C++ lately if you think it's the same as it was in 2004."
"If you're writing C++ code that is consistent with 2004 C++ then you're writing a really bad version of "C with classes", not C++."
I applaud your attempt at an authoritative voice. But you focus on mostly technical trivia that are thin scaffolding on top of the language. I agree modern C++ is nice but it's the same language still.
"This is a completely different language now and the code you write looks nothing like 2004 C++ code."
Are you trolling? This reads like a transcript from a TV commercial.
They sound like they're echoing the kinds of things that are normally said about C++11.
> I agree modern C++ is nice but it's the same language still.
Well...in the same sense that any language is the same language after you add a bunch of things to it that weren't there before and shift to using those new features as idiomatic parts of the language. I would expect C++ written in 2004 to use different patterns than C++ written in 2017. Not "completely different"...but different.
Idiomatic sounds like preference to dogmatism rather than pragmatism which is generally the worse tradeoff.
I would say generally C++ style has evolved through last decades with people understanding class based architecture as an antipattern and data pipelines based on preferably immutable data as the more robust and understandable approach. This has nothing to do with language standards or 'idiomatic' constructs - both can be expressed as perfectly elegant C++, using the '98 or '11 or '17 variant.
But anyway, within this context -
refactoring old code - I would not expect a legacy codebase to resemble 2017 C++ as much as 1997 C++. This is the main reason I find the claim of methods to understand circa 2004 C++ to be outdated to be silly.
> Idiomatic sounds like preference to dogmatism rather than pragmatism which is generally the worse tradeoff.
That's never been the way that I've read it, and it's not how I meant it. New language constructs allow for more-natural ways for the code to express the intent of the programmer, replacing the use of older constructs in the places that they were clumsy.
The entire point is to make the language more practical. Patterns of use in a language aren't idiomatic because of dogma (or at least, they shouldn't be). They're idiomatic because they're a clear and elegant way (or at least the most elegant way available) to implement something.
> I would not expect a legacy codebase to resemble 2017 C++ as much as 1997 C++.
Agreed, but then we come back to the fact that we might refactor a 1997 codebase differently in 2004 than in 2017.
"Agreed, but then we come back to the fact that we might refactor a 1997 codebase differently in 2004 than in 2017."
Well, if the original code is of the worst kind of a mess, Feather's circa 2004 collection of methods to make it more understandable but functionally the same work just fine for the first part of the refactoring. In my experience this is the most difficult part as well. To what dialect of the language the code is ported after it is understandable, is a relatively trivial syntax transform after this.
I speak from experience from having recently had to implement features to a production codebase with millions of lines of code, some of which date back to Fortran, and that took the final step of evolving into C++ sometimes in the late 90's.
I prefer the definition of legacy code that it's any code that does not have unit tests. In this case every transformation to a production codebase needs to retain the original behavior - without exact understanding what that behavior is.
I think this comment should have been my original response to this thread instead of the relatively cheeky responses I wrote earlier.
Intellisense (the MS one) was introduced in 1996. VB6 had good intellisense. I seem to remember having intellisense while working in classic asp vb (as in pre .Net), but could be wrong, it's so long ago now.
Modern IDEs can do many of the refactorings required when modifying code, yes. But you still need to know where to find seams or how to create them. Refactorings are just tools for getting there. It doesn't seem like you have read the book.
Me and a friend continually send IM's to each other, "LEAN ON THE COMPILER!".
That statement alone, one of the sections of the book, recommending you to allow the compiler to find your errors for you, is an example of the "age" of the book.
At the time I read it, when it first came out, I loved it. I still love Michael's work and advice to this day, but this book was written for another time.
I do not understand this. It seems like a perfectly good advice, and in fact it's what I'm doing every day - leaning on my compiler, and in Java world, on my IDE.
And also it seems to be something lots of programmers don't realize for some reason - many times I had to instruct people to crank up their compiler warning settings and actually read them. Especially in C-land, I can't count the number of times I solved someone's problem by appending -Wall to the gcc invocation and telling them to come back after they fixed all the warnings...
My point was that with a modern IDE we can do that without resorting to a full compile, which can be burdensome with large codebases.
The IDE space has improved a lot since 2004, eg. Jetbrains' tools around refactoring and code cleanup suggestions, make things super simple.
Don't get me wrong, I've read this book, multiple times, it's on my bookshelf and think it's a great book, but it was written when the state of development was a much different landscape, IMO.
Just looking at the responses to this comment, I have to say that I agree with both sides. The book is really dated, but the advice is timeless. The biggest problem I've had trying to get people to take the book seriously is that they can not identify with it. I had not realised that Michael Feathers had written a followup. I will definitely take a look. Thanks!!!
That's by Andy Hunt, one of the Pragmatic Programming authors. Pragmatic Programmer, as a publisher, has produced dozens of books. They're like another O'Reilly.
These are indications of the weakness of Java and C, not SICP.
I do not mean this as empty snark; it is something you can see across the board in programming language evolution. It is virtually impossible to propose a new general-purpose programming language today that does not have closure support, which is the biggest thing you're finding missing from C and Java to use the techniques in SICP. (It is not the only thing, but it is the biggest thing.) You'll note Java is going to bolt them on soon, or recently bolted them on, but it'll be another decade before Java is using them fluently either way.
I've often recommend SICP to self-taught programmers; it is not a complete substitute for a computer science education, but it is a concentrated dose of the stuff you're probably missing out on. Expect it to be the work of some months to work through it. However, in the end, a self-taught programmer who has also worked through SICP systematically and carefully is probably a better programmer than 80% of the modern computer science graduates nowadays. (If you want to avoid that fate, oh ye who are still in school, take the freaking compilers course at the very least. Do your peers complain that it is hard? Then maybe it is a good one.)
I don't think a book is "not language agnostic" because two particular languages aren't very good at it. C's lack of closure support is unique among any language still in use, for a variety of reasons. Java... was Java. If you weren't there you may not remember or understand, but at the time OO was at its most dogmatic and either it was an object or it was not included. Anything you could do with a closure could be done with an anonymous inner class. (Which is, technically, true. But the amplification factor on the effort and the sheer quantity of text involved to do so in Java is astonishing.) You can hear some of the echos of this in the older Ruby rhetoric, though I haven't heard it in a while.
Any other general-purpose language you'd be inclined to pick up right now would be fine.
IIRC, you end up implementing a scheme, which you can do nearly in the language of your choice, then the book covers that language you are implementing.
The book is not language agnostic because it's not language agnostic, mostly. The fact that many other languages are a poorer fit for what it's trying to teach is pretty much the definition of 'not language-agnostic'.
I don't know what task could possibly exist for which there are not significantly better and worse languages. Even today's "list of practical projects that anyone can solve in any programming language" [1] I can see at a casual glance that any of them that are not simply trivial will have better and worse languages. A definition of "lanugage agnostic" that either covers no tasks, or covers only very trivial tasks, isn't very useful. (Although in the latter case one can attain some insight by pondering why only such trivial tasks might be considered "lanugage agnostic".)
I'm not sure what any of these logical contortions have to do with SICP being 'language agnostic'. It isn't. The first section of the first chapter talks about why a Lisp dialect is used. This is the first figure.
The "Compiler Design" course at my university was the hardest CS course I've ever taken -- and it was generally taken your very last semester (and was infamous for being a common cause of many senior CS students not graduating on time).
Had it been optional, I would have been sorely tempted to skip it. But, taking it was probably good for me in the long run :)
"I'd find it quite hard to apply lessons from SCIP using java or c"
IMO, you're supposed to write your own Scheme to reap full benefits from SICP.
The book contains a recipe for an interpreter that can be transferred to any other language. Chapter 5.4 : The explicit-control evaluator[0].
Strangely this fact is not advertised that much, I find it to be one of the coollest features of the book.
The implementation is not a direct syntax translation - one needs to figure out how to implement the base susbstrate and how to handle e.g. tokenization, but well rounded software engineer should have some model in ones head how to manage these (so if there are missing pieces this is a good opportunity to brush on those).
After SICP and a little study of functional programming, I started learning about design patterns, and my immediate reaction was, “What’s all the fuss about? I mean ... c’mon ... how else would you solve that problem?”
It took me a while to understand that, if you’ve been raised on Java or C, these things are not obvious at all.
when you start to get to the parts about abstracting a circut, and making it streamy/lazy, you'd find that the impl details of a non-lazy language can make it more difficult than it needs to be.
Also, as a beginner, you don't want both the difficulties of contepts _and_ the difficulties of language to combine to stop you from learning as effectively.
But Scheme isn't a lazy language - granted, you'll need a language that supports first class functions to lift their implementation of a stream though.
>Also, as a beginner, you don't want both the difficulties of contepts _and_ the difficulties of language to combine to stop you from learning as effectively.
Are you referring to the need to learn Scheme to work through SICP? While the asker specifically requested language-agnostic books, Scheme was chosen as a language for SICP for being a "syntax-free" language...
> Are you referring to the need to learn Scheme to work through SICP?
That's not particularly demanding requirement. The class began with a single lecture about how Scheme worked and after that Hal and Gerry assumed you knew all the language you needed to and dove in.
When the course was introduced (early 80s), most incoming MIT freshman had not programmed a computer (!), including those who planned to do course 6 (EE or CS -- 6.001 was a requirement for either degree).
Scheme was chosen as a language for SICP for being a "syntax-free" language...
First-class functions, lambdas, closures, lexical scoping, etc. Abelson wrote, for instance:
"6.001 differs from typical introductory computer science subjects in using Scheme (a block-structured dialect of Lisp) rather than Pascal as its programming vehicle. The subject's developers feel strongly that Pascal is hopelessly constraining, and that important ideas (such as functional programming and object-oriented programming) can be addressed within Pascal only awkwardly, if at all."
Programming Pearls by Joe Bentley. And its followup. It's old but it does get you thinking about things.
I'd also recommend The Linux Programming Interface by Michael Kerrisk as it teaches so much about what makes modern Unix what it is but.. it's arguably quite oriented around C by necessity. It's not a "C book" by any means though.
"The Design of Design: Essays from a Computer Scientist" by Frederick P. Brooks [1] is language-agnostic and worth reading.
It's about software engineering but also about hardware and some different kinds of design outside of IT.
From an interview about the book [2]:
> Eoin: Your new book does talk about software design in places, but it’s really about design generally, and the case studies span buildings, organizations, hardware and software. Who is the book aimed at? Are you still writing primarily for people who design software or are you writing for a broader audience?
> Fred: Definitely for a broader audience. I have been surprised that The Mythical Man-Month, aimed at software engineers, seems to have resonated with a broader audience. Even doctors and lawyers find it speaks to some of their team problems. So I aimed this one more broadly.
Brooks is also the author of The Mythical Man-Month which is often mentioned on HN.
Second the Pragmatic Programmer, however: I read it when I just started programming (like not much more experienced than basic hello world and some fiddling) and, looking back, didn't really get it. I mean, I got the principles, but couldn't apply it as there was just not enough experience for the higher level abstract stuff. I recently read it again and it makes complete sense now, but I ddn't learn much new from it. So I'd suggest that if you read it, do so after a couple of years of programming.
Indeed, the Pragmatic Programmer book's subtitle is "from Journeyman to Master", and that's exactly what journeyman is supposed to mean - someone who's a few years into it, not bad, but not great (yet?).
Yes to Code Complete. I read the first edition at a time I wasn't sure if I'd pursue a career in computer programming. I hadn't used a computer for nearly a month making that decision. After reading and re-reading that book during that time, I pursued programming with a passion. That book struck all the right chords with me.
I read the second edition of Code Complete when I started my first job. Very good book to transition from fresh grad to professional. It has some very dry sections (eg. a chapter on how to name variables) but these are the little things that make a big difference and allows you to 'level up' as an engineer.
It has good parts. But it has some very bad parts too, when it reinforces myths that, IMO, are very wrong (e.g.: cone of uncertainty, X times better programmer, etc).
I'd recommend to read it with care.
> - The Pragmatic Programmer by Andrew Hunt and David Thomas
After many years I still read parts of it, again and again. And I still like it.
No problem. It is surprisingly advanced too and was co-authored by Eben Upton who started the Raspberry Pi. Nice whirlwind tour of computing architecture and history.
This is an amazing book. Hard to describe, and maybe not even all that interesting sounding if you managed to describe it accurately, it’s actually fascinating.
If you don’t know much about hardware (and maybe even if you do) it’ll change the way you think about computing devices.
You hear people say "Computers are all just 0's and 1's", which when you sit down at a modern computer interface is virtually meaningless. In an accurate, but still comprehensible way, 'Code' takes you from the AND's and XOR's and 0's and 1's to the experience you know from a modern computer interface. It is a brilliant book.
Seconded. I'm one of those savages who didn't really find much value in classical tomes like MMM or Code Complete (probably because all their core points have already been distilled into contemporary best practices) - but I love this book, and even recommend it to non-technical friends & family.
- Advanced Programming in the Unix Environment by Stevens
- Operating Systems: Design and Implementation by Tanenbaum
- The Art of Unix Programming by ESR
- Parsing Techniques by Grune and Jacobs
- Applied Cryptography by Schneier
Yes. TAOUP has a lot of good content about Unix programming styles and traditions, much of it useful generally. ESR's writing style is a bit heavy / verbose / uses verbal flourishes, but if you can let that not put you off, the book is worth reading. I've read most of it. One of the good sections is about Rules (of programming in Unix, which are not really rules, of course, but informal guidelines developed over many years of experience by many people - ESR has sort of codified them, a thing he tends to do a lot :)
The Rule about separating the interface from the implementation is a good one. I've seen developers at even enterprise companies sometimes not follow it in practice.
> - Parsing Techniques by Grune and Jacobs
Just saw that there is a new edition of this book:
I'll second The Art of Unix Programming - despite the title, it has many broad programming and software architecture lessons, and "The Unix Philosophy" is applicable far beyond Unix.
I have a pretty negative opinion on ESR these days. I could find technical arguments about many aspects of his good pieces of writing, and much of his writing is not good. His abilities as a coder are not generally remarkable, either. But mostly I don't think he's a good person. I would probably not say "Don't read ESR", but I think it has to be "Read ESR* "
*but be aware that he's a polarizing figure and opinions of his merits differ
(and if you happen to have a differing opinion, please use the reply button instead of the downvote button)
I share your sceptical opinion about ESR, but I concur with the other commenters that The Art of Unix Programming is still worth reading. (In contrast eg to his thing about Bazaar vs Cathedral.)
The Cathedral and the Bazaar was not an excellent piece of writing, but it was sort of necessary at the time. It has served its evangelical purpose well, to the point where it's no longer necessary. Open Source won the day, in no small part due to ESR. (I think it vital to give my enemies their due praise).
TAoUP is a good book on the Unix Philosophy, but it's worth noting that the ultimate expression of these ideas (Plan 9) was a failure, and the 'everything is a file' metaphor is arguably incorrect. I hope I didn't give the impression that it was not worth reading, especially in the sense that there are few other good sources for that information (even using Unix is not likely to teach you much about its whys and wherefores). I just think that it should be read in the proper context, and that recommendations should try to include that context.
- Excellent book that gets into the internals of what developers need to know about SQL and covers each part as it relates to the 4 major SQL databases (Oracle, SQL Server, Postgres, MySQL)
'Implementation Patterns', Kent Beck. A semi-language-agnostic extension of his 'Smalltalk Patterns'for how to clearly and consistently express what you're saying when you code.
'Facts and Fallacies of Software Engineering', Robert Glass. Glass presents a list of things everybody knows, or ought to know, and gives both academic and opinionated support and/or critique for why they are and aren't so.
'Making Software', Oram and Wilson. An edited collection of papers on evidence-based software engineering.
'The Deadline', Tom DeMarco. A thinly disguised commercial for his advice on how to organize software development teams and organizations, packaged as light, light novel.
One that hasn't been mentioned yet: "Coders at Work". A very enlightening book about how some of the best programmers in the world approach the craft in their own words.
Nobody recommended The Phoenix Project yet by Gene Kim?
Unless you have some understanding of your system's architecture, how it's run in production, and why a production environment is Really Different and a Big Freaking Deal, and how operations is supposed to look like, you'll never be an effective programmer, no matter whether you run your own operations in a small start-up or work for a large enterprise with dedicated operations teams.
Not a book per say, but "Out of The Tar Pit" by Moseley and Marks is definitely a must-read.
Abstract:
```
Complexity is the single major difficulty in the successful development
of large-scale software systems. Following Brooks we distinguish
accidental from essential difficulty, but disagree with his premise that
most complexity remaining in contemporary systems is essential. We
identify common causes of complexity and discuss general approaches
which can be taken to eliminate them where they are accidental in
nature. To make things more concrete we then give an outline for
a potential complexity-minimizing approach based on functional programming
and Codd’s relational model of data.
```
I've been thoroughly enjoying "Designing Data-Intensive Applications" by Martin Kleppmann. It primarily deals with the current state of storing data (databases, etc) starting with storing data on one machine and expanding to distributed architectures...but most importantly it goes over the trade-offs between the various approaches. It is at a high level because of the amount of ground it covers, but it contains a ton of references to dig in deeper if you want to know more about a specific topic.
+1. Great for getting a lay of the land on distributed systems problems. I haven't ever studied distributed systems formally though, so I wonder how this differs from that.
- The Elements of Computing Systems: Build the virtual hardware and software from scratch. Software includes writing a compiler in a language of your choice, so agnostic in that sense.
- The Art of Metaobject Protocol: Extremely insightful treatment of OOP! Alan Kay called it as the 'best book in ten years' at OOPSLA 97.
I'd second the Head First Design Patterns. The style of writing is light and fun. There are definitely concepts about abstraction, etc. that may take a while to grok and the different approaches help.
I think that is part of their goal / style. They are meant to be lightweight and fun and easy-to-read intros to topics for beginners, who would get put off by more formal / less joke-y prose.
A bit like the Dummies series of books, in fact. Which is not to say that those books are not good. I've read a few of them, and they have some good matter.
I also emphatically suggest D.Knuth's "The Art of Computer Programming". Super dense, not like a sit down and read from cover to cover, but really good set to have around.
Another Knuth-related one that is less programming that I found rewarding to read was 'Concrete Mathematics.' It is per its own description a lengthier version of the TAOCP, but it's mostly or entirely exempt of actual code. But because of the subject matter it spawned from it tends to cover math of 'what comes later' so there is a very specific perspective of Knuth style that comes from it and its easier to see the eventual application.
I had a professor who would joke that it was called Concrete Mathematics both because it was foundational math for computer science, but also because it was as hard as concrete.
I also heavily recommend this. It was gifted to me from a professor at my university while leaving, and I left it alone for a few years.
But when I finally opened it up, wow. You can appreciate just how dense the information is. It really reads as if no sentence was written without some purpose of conveying information. Definitely go slow reading this series so you can properly ingest what's written.
Yes it's a classic and very well written. When I read this more than 25 years ago it was a real eye-opener and made the workings of recursion clear to me. Curiously acquiring an understanding of recursion in programming allows me to "think recursively" in regard to many other matters as well, so important for thinking "outside the box".
I'd venture that besides recursion, the other key concepts in programming have been pointers and first-class functions. Getting a grasp on these 3 ideas has been essential to learning.
MMM is a must-read, for anyone that wants to effectively engage in the software development lifecycle, IMO. Developer, project manager, doesn't matter.
Definitely, definitely, Kernighan and Plauger's 1976 book _Software Tools_. The code is in RATFOR (a structured dialect of FORTRAN) but all the ideas are language-independent. It remains, four decades on, the best book I have ever read on how to solve the real problems of real program development. Very practical, and covers a vast amount of ground. (As it happens, I am re-reading it right now.)
+1. I have a corner of a bookshelf reserved for everything Kernighan, e.g. both Software Tools editions, both C Language editions, The Unix Programming Environment, The Practice of Programming, The AWK Language, even a copy of The Elements of Programming Style. I, and my employers and clients, may owe more to Mr. Kernighan for his teaching and programming style, than anyone else.
There is also an edition using Pascal, "Software Tools in Pascal" from 1981, which might be a little more accessible than the RATFOR edition. I fully agree with the recommendation as such, though.
The code from "Software Tools in Pascal" mostly just works in FreePascal, too. So it's pretty easy to jump in and work through the examples in the book.
It's a collection of programming exercises I used when I taught introduction to programming. They start out incredibly trivial, ("prompt for a name, print "hello [name]" back to the screen. But the trivial part is, in my opinion, the fun part when you work with a new language.
That program is a two line program in Ruby. But it might be much more complicated if you implemented that as your first GUI app in Swift for iOS.
I wrote the book to teach beginners, but I and others use those exercises to learn new languages. The book has no answers, just the problem statements.
Thinking Forth is a great suggestion since the approach goes way beyond Forth. I also would read the Brad Cox (objc creator) books if you can get them.
The Cuckoo's Egg by Clifford Stoll. This book taught me how important it is to keep a log of events. These logs come in very handy when the problem one trying to debug spawns multiple complex systems.
Seconded. This is also a great read on how to track down a deep problem, going through all of the steps required to figure out where it was coming from. That's on top of it being an entertaining view of early computer networking.
Programming in the 1990s by Edward Cohen. A rather practical introduction to the calculation of programs from their specifications. Plenty of introductions to computer programming involve guessing your program into existence. This is one of those rare books that give a solid, pragmatic approach (with examples) of developing software from solid, mathematically sound specifications and avoiding errors by design.
Even if you don't adopt formal methods in your day-to-day work (often we're not building sky-scrapers) it's a useful book to give you insight into the kinds of questions one should be asking and thinking about when designing software systems.
Agile Software Development, Principles, Patterns, and Practices - by Uncle Bob Martin
One of the most influential programming books I've ever read. The code is in Java, but it's east to follow even for a non-Java developer, and the truths are universal. Learn the most fundamental design and encapsulation patterns. Uncle Bob Martin is a legend. This book has probably made me tens of thousands of dollars.
Introduction to algorithms[1] is a great book to improve how you think about code and the way you implement your solutions. Even if you are a seasoned programmer you'll find it useful.
We used it in my algorithms class in uni, I found it a bit heavy on the math side of things. For me a more code oriented book such as Skiena's The Algorithm Design Manual works better.
Joy of Clojure & SICP. To a lesser extent, Learn You a Haskell. 7 Languages in 7 Weeks is an excellent good baby step book if these are too daunting. 7in7 was my first intro to many new ideas.
Any language worth learning has this property of influencing the way you think forever. TDD, Code Complete &co are all very integrated into mainstream industry and are no longer novel. If you find yourself needing to recommend your colleagues to read Code Complete you might consider working on the skills to get a better job.
An Introduction to General Systems Thinking. Gerald Weinberg. This book, now over 40 years old, addresses the 'core within the core' of the reality of systems. Unbelievably good, with a very light-hearted tone.
If you consider C to be language-agnostic, here are some gems. These are personal favorites as much for their excellent writing as for their content.
The Unix Programming Environment was published in 1984. I read it over 20 years later and was astonished at how well it had aged. For a technical book from the 80's, it is amazingly lucid and well-written. It pre-dates modern unix, so things have changed but much that goes unstated in newer books (for brevity) is explicit in UPE. (Plus, the history itself is illuminating.) It gave me a much deeper understanding of how programs actually run over computer hardware. Examples in C are old-school and take a bit of close reading but oh so rewarding. https://www.amazon.com/Unix-Programming-Environment-Prentice...
+1 to Code (Petzold). I would absolutely start with that. One of my favorite books. The build a computer course from coursera (https://www.coursera.org/learn/build-a-computer) is the natural next step after reading code.
The title seems, well, creepy, in modern language. Like it's manipulative.
It's not.
It was written in the 1930s, and has been continuously in print since then. How many books have achieved that honor? That's because it's one of the best books you will ever read. Absorbing its lessons will make you a better person.
Let Over Lambda. Not entirely agnostic, but delves into Forth, Smalltalk, C, Scheme, and Perl while overall being about Lisp. Fascinating book; really a look at metaprogramming (macros) and closures (that's what "let over lambda" is).
In addition to those already mentioned here, I enjoyed the book 'Algorithms' by Robert Sedgewick & Kevin Wayne.
The algorithms are explained, and demonstrated (in java). But with the knowledge of how the algorithm works you should be able to use them in another language.
(And even though henrik_w already mentioned it, Code Complete2 is a really good book to read!)
Good advice! I have an older version, in which the implementations are explained in Pascal. I understand that newer issues cover java. I'd believe the book goes well with his coursera course:
I see you read Kent Beck's TDD book. A good follow-up might be Roy Osherove's "The Art of Unit Testing." I found it to have a lot of pragmatic, practical advice. It's not the final word, but it is a good next step after Kent Beck's book. It has some C#-specific material, but that stuff is interesting to read about even if you're working in other languages.
Lot's good suggestions in this thread, here's one I didn't see:
"Software Runaways - lessons learned from massive software project failures," by Robert L. Glass.
I have been reading Game Programming Patterns lately. It explains the design patterns with examples from games, and it is really well written by an engineer at Google (Bob Nystrom): http://gameprogrammingpatterns.com/
After I complete this book, I think I'll read his other book: Crafting Interpreters. This one teaches about implementing a programming language from scratch, once in Java and a second time in C.
From its preface: "This book has only one major purpose - to trigger the beginning of a new field of study: computer programming as a human activity, or, in short, the psychology of computer programming."
Still a worthy topic, still worth your time. As was mentioned about 'The Pragmatic Programmer', I think reading this works best once you have a few years of experience.
Practical Object-oriented Design in Ruby is a great read with a lot of advice on approaching design problems, approaching refactoring and thinking about how to model. It's in Ruby but I feel a lot of its advice is general.
aka "Why duck typing is better than inheritance". Yes, great book, but if you're using a language that doesn't support duck typing, some of the concepts will frustrate you and make you wish you were using Ruby instead.
Although the OP seems to be asking for "engineering" not "programming" books, I'm going to second this. Benjamin Pierce's "Types and Programming Languages" will help you get down to what programming is really about. If you are not familiar with lambda calculus and its notation, it may be rough going at first. But lambda calculus is VERY simple, and Pierce takes you through it. The book progresses methodically to the concepts found in most common programming languages.
This is one of the few truly language agnostic books on programming. SICP is close, but it is limited in relevance at times due to the limitations of a particular language (Scheme).
Motulsky's Intuitive Biostatistics - this one goes over all the usual methods used in science from distributions to t-test to ANOVA to regressions etc., the basics, but doesn't introduce the maths (you use R for that) but the assumptions and pitfalls of all of those methods.
Statistics Done Wrong: The Woefully Complete Guide - this is all the stuff that's going wrong in applied statistics, a bit short but enlightening
Discovering Statistics Using R - a whopper of a book (~1000 pages?), it goes through everything while also being funny (the constant humor may not be for everyone). Graphs, correlations, regressions, all the MLMs and GLMs, linear models etc. pp., their assumptions, how to run them in R, how to interpret R's sometimes annoying output, etc. pp. Like Motulsky's, but wayyyyy more in-depth on the language's specifics.
Naked Statistics - an intro to stats for laypeople with a focus on politics/economics, good for interpreting and assessing daily news
If you liked Clean Code, read Clean Coder. A quick summary:
Robert C. Martin introduces the disciplines, techniques, tools, and practices of true software craftsmanship. This book is packed with practical advice–about everything from estimating and coding to refactoring and testing. It covers much more than technique: It is about attitude.
I feel that books like Clean Coder should be recommended reading for people in their first job. I really feel like it made me think about how I do my job in a more professional, quality-focused manner than even Clean Code did.
Sipser's Theory of Computation. It covers automata and languages, computability, and complexity - and is brilliantly written, the proof style in particular: clear 'proof idea's followed by the details that can be easily skipped if you're not interested, or it is clear from the 'idea'.
While he'd been successful writing language-specific books, he stopped writing them in the early 70's, because he recognized that the important principles didn't change. Super important thinker about software and the people who make it.
Growing Object-Oriented Software Guided by Tests, by Steve Freeman and Nat Pryce. The examples are, IIRC, in Java, but the ideas about TDD are applicable to any OO language. It'll make you think more about how you write testable code and the test themselves.
As someone married to an journalist and now EIC and one who prides himself on concise and solid writing, I really detest this book. It's full of terrible recommendations that the authors themselves don't even follow in their own book. I strongly recommend any English authors stay miles away from it.
If you want this sort of thing, read a well-respected publication's style guide (e.g., from the AP, NYT or Economist).
Not a programming book per se, but seeing that you had "The Healthy Programmer" in your list I'll throw it out there:
"The underachievers manifesto" - a short book that does wonders for your mental health in a world that values productivity and superficial, short-sighted goals over everything else.
I've really enjoyed "Dependency Injection in .NET"- despite the name, the book itself is really 95% about Dependency Injection and relatively language agnostic. It exhibits a bottom-up approach to using inversion of control in a way that makes sense and is scalable.
It's not language-agnostic, but it's still a great book: The D Programming Language. The reason I recommend it is because Alexandrescu is a great writer who knows a lot about programming languages and the kinds of tradeoffs that a low-level, practical, and safe programming language like D must do.
Even if you never intend to program in D, I encourage you to read this book to get a different view on metaprogramming, memory safety, and concurrency.
If you can find a copy, get the 1st Edition of Bertrand Meyer's "Object Oriented Software Construction". (1st ed. is a classic; 2nd ed. is much larger and worse for it, IMO.)
If you can, forget about the title and just read it; most of the good stuff in this book is less about objects and much more a fantastic seminar on programming in general.
"The Elements of Computing Systems" and the accompanying course Nand2Tetris on Coursera. It's a course that starts with just nand gates, and leads you through the development of higher level logic gates, then an ALU, then a CPU, the an assembler, then a high level language compiler, and finally an operating system.
I've seen the "dragon book" mentioned several times, and I think it (and similar books) are good if you really do plan to (re-)invent a real world, large scale, programming language. If you really just want to get a feel for what's going on under the hood, the language presented in Nand2Tetris is specifically designed to have the necessary complexity to cover most of the details, but not so many special cases that you end up "chasing dragons". And the course is modular enough that you can jump right in and just implement the compiler if you want.
I really liked "Building Microservices" by Sam Newman. It's a good review on current software architecture and software development process in addition to going over microservices. Honestly microservices are a topic in the book but it could just be called "Software Architecture in 2016".
Learning more and more about imperative programming, OOP, design patterns, etc is good, but branching out into declarative programming and the functional and logic paradigms will stretch your mind for the better.
The great thing, I think, about The Reasoned Schemer is that it tackles a complex topic with almost no prose. The whole book is basically one code example after another, in a Q/A style. "What does this do?" <allow you to think about it> "Here is what it does, and here's why." Rinse and repeat. I think more technical books should try this.
The Reasoned Schemer sounds like it was part of a series, is that right? I remember reading about The Little Schemer and maybe The Seasoned Schemer. Are those all parts of the same series? Haven't read any of them yet, but hope to do so some day.
I like reading the classics of the field. Not only because they are classics, but also because they tend be well-written and hence more readable as well (than your average text). But maybe that is a tautology :) - they are classics because they are well-written ...
It's a nice fiction book that goes into how different people view the world. At least that's what I've gotten out of it so far, I'm only about a quarter of the way through it so I might be missing some of the things it covers.
yes, I assumed that to be the book they meant. I read it 25 years ago. I am just surprised that it would be included in this list. I see no connection to the question posed.
I'm not sure why he included it in his list. However I do think that it does a very good job of bringing to light that your customers/users may not be appreciative of buggy code. They want something that "just works" and to not have to deal with vague error messages.
I started reading the book about a year into my first development job and it really brought to light the frustrations my users were having as I was seeing as it was just another interesting problem to me. As I said in my past post I haven't been diligent in reading it so I'm only a quarter of the way through but here's hoping I'll get more insights out of it when I pick it back up.
I do think that what this book talks about can be discovered in other ways, but for people who are just starting in the technology field it's a good primer to be aware of how others experience what you implement.
In a way, the entire book is about debugging, but the target is the author's thought process rather than code. While Robert Pirsig fictionalizes the story, in fact it's closely based on his own life, in which he sought understanding of values (via zen and academics) but somehow went wrong and ended up catatonic and in shock therapy. The plot is a revisit of the mind trek he was on then and a quest to see where he went wrong. Pirsig approaches this not as a psychologist, but as a reductionist philosopher/scientist, trying to identify what troubled him and caused him to fail -- a debugging of the mind.
IMO, It's more "philosophy" than "programming", but it makes you think about the role of technology in our lives and our role as creators of that technology.
If you are writing code, you are doing yourself (and anyone using your code) a disservice if you do not read something on secure coding. There are not a ton of code agnostic resouces, but you may want to start with "Software Security: Building Security In"
I would then look for language specific options as well, because programming for security can vary a lot amongst languages. Writing securely for native applications running on a system is much different than writing secure web apps.
Understanding the Four Rules of Simple Design by Cory Haines
I like the 4 simple rules, I think he originally got these from Kent Beck. It is easier to keep this system in your mind if it is just a few basic principles.
Working Effectively with Legacy Code by Michael Feathers
As others also mentioned this. I think this is becoming more important as people transition to new jobs where they have to take on existing software. Having a process to deal with code that lacks documentation and tests is really important.
This book is from 1989, but it's a timeless and fascinating look at the minds of Bill Gates, Andy Hertzfeld (apple/mac), Dan Bricklin (visicalc), and 16 others.
Although I liked Effective Java a lot, and it does contain a lot of advice relevant to many OO languages - it is the opposite of language agnostic: It's very Java-specific. Much of the content is irrelevant except in Java itself; and some of it is the opposite of "Effective language X". For example, it has a section named "Prefer lists to Arrays"; any C++ programmer will tell you the opposite (and that goes down to some of the arguments, such as Java not supporting generic arrays while C++ supports them).
But it also tells you why to prefer x over y, every time it gives any recommendations. And it's always explained well. So I think reading this book will help you make conscious decisions while using other languages. It's just a very well written book.. Which is pretty rare..
Of course a lot of it is Java-specific, but there's enough advice that seems relevant to $BOG_STD_OO_LANG that it's probably worthwhile for this purpose.
I haven't read the book, but I guess part of the argument is because ArrayList in Java is backed by an array, and is what is usually called a "vector" in other languages, while the generic List interface is what you would call a "sequence" elsewhere.
I also like to add "Pragmatic Thinking and Learning: Refactor Your Wetware" by Andy Hunt
It can be considered as a followup of pragmatic programmer.
For me the main challenge is to how to stay relevant in days of constant change, and the best answer seems to be constant learning. So, let's learn how to learn! And this is exactly the main topic of this book.
I loved cracking the coding interview, even if you want to practice for an interview or not, with this book you can get a friendly reminder of data structures and algorithms, time complexity and related topics (and you can improve your problem-solving skills too). For me at least it was useful for feeling again a great interest in these topics and to love even more my job.
Not exactly language-agnostic, nor about programming per se, nor a book, but [Google Style Guides](https://github.com/google/styleguide) offer a lot of specific, opinionated, practical advice that you can apply immediately. It's like an MLA manual for programmers.
A really fun read is The New Turing Omnibus. I'd call it fun reading rather than required reading.
Basically, it's a collection of small fun loosely related chapters about various ideas in computer science. It's the kind of book where you can open it up in the middle and start reading.
Over the years, I must have purchased 5 or 6 copies because I keep giving them away.
Great recommendation! His book The Armchair Universe is pretty much what made me want to be a programmer. I enjoy books that keep the fun in programming.
"Practices of an Agile Developer: Working in the Real World" - this book was like the Bible for me when I started my career in IT 10 years ago. I re-read it multiple times and I still stick to the practices described in this book. They are language agnostic, they are pretty clear and easy to follow and they can really improve your skills.
The first thing that will come to mind when seeing that title is “ug, another book on patterns.” Or maybe “I thought it was named Design Patterns - Elements of Reusable Object-Oriented Software”
This isn’t anything like that book. Or maybe it should be. The full title of the book is A Pattern Language: Towns, Buildings, Construction. Yes, this is a book about architecture - but not software architecture. It is about the houses and buildings that we walk live and work in.
The description of A Pattern Language is one that will sound very familiar to people familiar with Design Patterns:
> It is shown [in The Timeless Way of Building], that towns and buildings will not become alive, unless they are made by all the people in society, and unless these people share a common pattern language, within which to make these buildings, and unless this common pattern language is alive itself.
> In this book we present one possible pattern language, of the kind called for in The Timeless Way. This language is extremely practical. It is a language that we have distilled from our own building and planning efforts over the last eight years. You can use it to work with your neighbors, to improve your town and neighborhood. You can use it to design a house for yourself, with your family; or to work with other people to design an office or a workshop or a public building like a school. And you can use it to guide you in the actual process of construction.
> The elements of this language are entities called patterns. Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.
This is the book that inspired Gamma, Helm, Johnson and Vissides.
By reading A Pattern Language you will be able to understand what the authors of Design Patterns were trying to do and how design patterns were intended to work.
It’s a good book too, who knows what else you will find useful in it. Pattern #146 describes a flexible office space. Pattern #148 describes a workspace for small work groups, #151 is about small meeting rooms, #152 is a half private office. Everyone who works in today’s world of computers and cubes, can use these ideas to conceptualize and consider improvements to the office.
You would need a cursory knowledge of ml to be able to understand it, but you can implement the examples in plenty of other languages. The principles taught are fairly universal. (At least for the first half, I haven't made it beyond that yet...)
Yeah, I had a hard time getting into that book the first time around due to a lack of ML knowledge. Once you have some ML or Haskell I'd say it's worth a read.
Though it uses a subset of C++ for the code examples, Elements of Programming by Stepanov and McJones. It shows how algebra can serve as an effective foundation for engineering generic, reusable programs.
Okay, here's some I haven't seen mentioned yet, although these may be pretty far afield for you:
Drift into Failure, by Sidney Dekker. Studies failure analysis in complex systems, and basically argues that our classic reductionist/scientific method approach is the wrong way to study complex engineering failures.
How Buildings Learn, by Stewart Brand. This isn't about programming. It's about architecture, in the build-a-building sense. It studies what happens to buildings over the course of their lives, as opposed to just when they're first built.
Enterprise Integration Patterns, by Gregor Hohpe and Bobby Woolf. Learn how to use message queues and service busses correctly. Honestly, just read the first couple of chapters (65 pages or so), and the rest is reference, to look up as needed, so it's not as imposing as it sounds.
Advanced Programming in the UNIX Environment, by W. Richard Stevens. This book was my bible back in the olden days before http and ssh and stuff (I'm olde). Knowing how sockets really work can be an absolute lifesaver, even in this modern world of giant protocol stacks. Especially in this modern world.
The Art of Computer Programming, vols 1-3, by Donald Knuth. Only a madman would actually read them all, but they're good to have to remind you that there are mountains you can't even begin to climb.
A Deepness in the Sky, by Vernor Vinge. A science fiction novel that is really about hacking, set thousands of years in the future, when Moore's Law is long defeated and programmers are basically archeologists.
Design Patterns (aka Gang of Four), by Gamma/Helm/Johnson/Vlissides. There are lots of good books on design patterns, but you should really read the one that started it all. (For extra credit, read A Pattern Language, by Christopher Alexander - a book about urban architecture that inspired it.)
Continuous Delivery, by Jez Humble and David Farley. Stop thinking about your program in isolation, and learn how to deploy effectively!
Influence: The Psychology of Persuasion, by Robert Cialdini. This is DHH's favorite book. Learn how people think, and how to use that to design better products.
How to Win Friends and Influence People, by Dale Carnegie. Not creepy at all, despite how the title sounds in today's language. This book is the bible of how to get along with others. It's been in continuous print since before WWII, for good reason.
The Lean Startup, by Eric Ries. The best work you do is the work you find you don't need to do. Learn how to fail fast and save time on projects and product development, by building what customers want rather than what you think they need.
Here are my recommendations. Each is a placeholder for a complete discussion :)
Psychology of Programming
=========================
1. "Psychology of Computer Programming" - Gerald M. Weinberg
2. "Software Design – Cognitive Aspect" by Francoise Detienne
3. "Thinking Fast and Slow" by Kahneman and Tversky
4. "Drive: The Surprising Truth About What Motivates U" by Daniel Pink
Book 1 is a really nice read and touches a lot of the social and workplace aspects of computer programming. Book 2 is more focused on modern research of program comprehension in relation to cognition. It's a little older, and often just scratches the surface, but they both nicely show that a lot of social and psychological factors are relevant for programming, independent of the programming languages developers use. 3. and 4. add some more background infos to it if you want to dive deeper.
Career Development
==================
- "Hackers and Painters" - Paul Graham
- "The Passionate Programmer" - Chad Fowler
In addition to the Pragmatic Programmer which has been mentioned in other comments, these books really helped me understand where I wanted to be as a programmer.
- "A Retargetable C Compiler: Design and Implementation" - Hanson, Fraser
I found them more helpful than the Red Dragon Book. The latter is good, but as a beginner I felt a little lost and Terence Parr's book was much more helpful.
Practice & Karate
=================
- "Elegant Objects" by Yegor Bugayenko
- "Working Effectively With Legacy Code" - Michael Feathers
- "Growing OO Software, Guided by tests" - Pryce, Freeman
- "Test Driven Development" by Kent Beck
And, this last one I can't recommend enough:
"XUnit Test Patterns" by Gerard Meszaros
Kent Beck's TDD is good book to start with. Even if you feel like you have got testing figured out, you should try TDD. It has more to do with discipline and getting things done, rather than writing code fast or smart or efficiently. Someone I follow on twitter once called it "thinking at sustainable pace", which is really what TDD is about. A lot of people are simply offended by the idea to "test first". To me, "test first" is roughly equivalent to "think before you code". Maybe this is what others find offensive.
As for an advanced view on testing, Gerard Meszaros's book is really good. It is a catalogue of testing patterns that helps to structure testing code in a nice way.
Depending on OP's skill I would recommend the following: Be very carefull with the following books:
- Design Patterns - Gang of Four
- Patterns of Enterprise Application Architecture
- {Doing Anything with} Domain Driven Design
These books are really valuable, but somewhat problematic. Sometimes they will give you a hammer and make everything look like a nail. Sometimes they make it easy to focus on the wrong things. They come over as precise and clear, but really aren't, which will cause discussions and poor choices. On the surface, they sound nice, simple and friendly, but on a deeper level, they are really difficult to understand.
If you want to read them, I encourage you to do so with your colleague and discuss them critically. Maybe you can have a wednesday afternoon bookclub meeting at your company. We once did that for "Working Effectively with Legacy Code".
I collected some more suggestions on a trello board a while ago, which should be accessible here:
One of the first books I read that led me on to craploads of other books. It mentioned Peopleware, Mythical Man Month and just opened up a whole world of books about programming and being a programmer that were not 'do this then that to achieve Y'.
Gonna have to pick that one up again and see what else I can glean from it years later :)
I've gathered all the book titles in this thread and created Amazon affiliate links (if you don't mind. Otherwise you still have all the titles together :-) )
I saw many comments and had some good programming books to suggest but thought that a little fun would not hurt. but it looks like according to the -4 i got i should have not make that joke. jokes are not allowed here?
* "Compilers: Principles, Techniques, & Tools" by Aho et al. (i.e., "the dragon book")
* "Data Flow Analysis: Theory and Practice" by Khedker et al.
* "Understanding MySQL Internals" by Sasha Pachev.
* "Transaction Processing: Concepts and Techniques" by Gray and Reuter.
* "Fundamentals of Wireless Communication" by Tse and Viswanath.
* "Genetic Programming: An Intrduction" by Banzhaf et al.
* "Applied Crytography" by Schneier.
EDIT: A few additional comments:
(1) Although these books are problem-domain specific, some of them had benefits outside of their problem domains:
* The Dataflow book has some great coverage of fixpoint algorithms. It's really helpful to recognize when some problems are best solved by fixpoint analysis.
* The "dragon book" takes a lot of the mystery out of compilers. That's somewhat helpful when writing code that needs to be fast. It's super helpful if you want to work with compiler-related technologies such as LLVM.
* Understanding the fundamental challenges of transaction processing helps you avoid massive misadventures when dealing with databases or concurrent / multithreaded systems.
(2) YMMV, but I've found it hard to soldier through these books unless I had a need to for my job or for school.